Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: upgrade to gpt-vis #1852

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions web/components/chat/agent-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ChatContext } from '@/app/chat-context';
import { IChatDialogueMessageSchema } from '@/types/chat';
import classNames from 'classnames';
import { memo, useContext } from 'react';
import ReactMarkdown from 'react-markdown';
import { GPTVis } from '@antv/gpt-vis';
import markdownComponents from './chat-content/config';
import rehypeRaw from 'rehype-raw';

Expand All @@ -27,10 +27,13 @@ function AgentContent({ content }: Props) {
})}
>
{isView ? (
<ReactMarkdown components={markdownComponents} rehypePlugins={[rehypeRaw]}>
<GPTVis components={markdownComponents} rehypePlugins={[rehypeRaw]}>
{formatMarkdownVal(content.context)}
</ReactMarkdown>
</GPTVis>
) : (
// <ReactMarkdown components={markdownComponents} rehypePlugins={[rehypeRaw]}>
// {formatMarkdownVal(content.context)}
// </ReactMarkdown>
<div className="">{content.context}</div>
)}
</div>
Expand Down
4 changes: 2 additions & 2 deletions web/components/chat/chat-content/agent-messages.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ReactMarkdown from 'react-markdown';
import { GPTVis } from '@antv/gpt-vis';
import markdownComponents from './config';
import { renderModelIcon } from '../header/model-selector';
import { SwapRightOutlined } from '@ant-design/icons';
Expand Down Expand Up @@ -28,7 +28,7 @@ function AgentMessages({ data }: Props) {
</div>
</div>
<div className="whitespace-normal text-sm">
<ReactMarkdown components={markdownComponents}>{item.markdown}</ReactMarkdown>
<GPTVis components={markdownComponents}>{item.markdown}</GPTVis>
</div>
</div>
))}
Expand Down
4 changes: 2 additions & 2 deletions web/components/chat/chat-content/agent-plans.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CaretRightOutlined, CheckOutlined, ClockCircleOutlined } from '@ant-design/icons';
import { Collapse } from 'antd';
import ReactMarkdown from 'react-markdown';
import { GPTVis } from '@antv/gpt-vis';
import markdownComponents from './config';

interface Props {
Expand Down Expand Up @@ -36,7 +36,7 @@ function AgentPlans({ data }: Props) {
)}
</div>
),
children: <ReactMarkdown components={markdownComponents}>{item.markdown}</ReactMarkdown>,
children: <GPTVis components={markdownComponents}>{item.markdown}</GPTVis>,
};
})}
/>
Expand Down
198 changes: 109 additions & 89 deletions web/components/chat/chat-content/config.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { LinkOutlined, ReadOutlined, SyncOutlined } from '@ant-design/icons';
import ReactMarkdown from 'react-markdown';
import { GPTVis, withDefaultChartCode } from '@antv/gpt-vis';
import { Table, Image, Tag, Tabs, TabsProps, Popover } from 'antd';
import { Reference } from '@/types/chat';
import { AutoChart, BackEndChartType, getChartType } from '@/components/chart';
Expand All @@ -16,7 +16,7 @@ import VisPlugin from './vis-plugin';
import VisCode from './vis-code';
import { formatSql } from '@/utils';

type MarkdownComponent = Parameters<typeof ReactMarkdown>['0']['components'];
type MarkdownComponent = Parameters<typeof GPTVis>['0']['components'];

const customeTags: (keyof JSX.IntrinsicElements)[] = ['custom-view', 'chart-view', 'references', 'summary'];

Expand All @@ -32,95 +32,115 @@ function matchCustomeTagValues(context: string) {
return { context, matchValues };
}

const basicComponents: MarkdownComponent = {
code({ inline, node, className, children, style, ...props }) {
const content = String(children);
/**
* @description
* In some cases, tags are nested within code syntax,
* so it is necessary to extract the tags present in the code block and render them separately.
*/
const { context, matchValues } = matchCustomeTagValues(content);
const lang = className?.replace('language-', '') || 'javascript';
const codeComponents = {
/**
* @description
* Custom code block rendering, which can be used to render custom components in the code block.
* Is it defined in gpt-vis, and the default rendering contains `vis-chart`.
*/
code: withDefaultChartCode({
languageRenderers: {
'agent-plans': ({ inline, node, className, children, style, ...props }) => {
const content = String(children);
/**
* @description
* In some cases, tags are nested within code syntax,
* so it is necessary to extract the tags present in the code block and render them separately.
*/
const lang = className?.replace('language-', '') || 'javascript';
try {
const data = JSON.parse(content) as Parameters<typeof AgentPlans>[0]['data'];
return <AgentPlans data={data} />;
} catch (e) {
return <CodePreview language={lang} code={content} />;
}
},
'agent-messages': ({ inline, node, className, children, style, ...props }) => {
const content = String(children);
const lang = className?.replace('language-', '') || 'javascript';
try {
const data = JSON.parse(content) as Parameters<typeof AgentMessages>[0]['data'];
return <AgentMessages data={data} />;
} catch (e) {
return <CodePreview language={lang} code={content} />;
}
},
'vis-convert-error': ({ inline, node, className, children, style, ...props }) => {
const content = String(children);
const lang = className?.replace('language-', '') || 'javascript';
try {
const data = JSON.parse(content) as Parameters<typeof VisConvertError>[0]['data'];
return <VisConvertError data={data} />;
} catch (e) {
return <CodePreview language={lang} code={content} />;
}
},
'vis-dashboard': ({ inline, node, className, children, style, ...props }) => {
const content = String(children);
const lang = className?.replace('language-', '') || 'javascript';
try {
const data = JSON.parse(content) as Parameters<typeof VisDashboard>[0]['data'];
return <VisDashboard data={data} />;
} catch (e) {
return <CodePreview language={lang} code={content} />;
}
},
'vis-chart': ({ inline, node, className, children, style, ...props }) => {
const content = String(children);
const lang = className?.replace('language-', '') || 'javascript';
try {
const data = JSON.parse(content) as Parameters<typeof VisChart>[0]['data'];
return <VisChart data={data} />;
} catch (e) {
return <CodePreview language={lang} code={content} />;
}
},
'vis-plugin': ({ inline, node, className, children, style, ...props }) => {
const content = String(children);
const lang = className?.replace('language-', '') || 'javascript';
try {
const data = JSON.parse(content) as Parameters<typeof VisPlugin>[0]['data'];
return <VisPlugin data={data} />;
} catch (e) {
return <CodePreview language={lang} code={content} />;
}
},
'vis-code': ({ inline, node, className, children, style, ...props }) => {
const content = String(children);
const lang = className?.replace('language-', '') || 'javascript';

if (lang === 'agent-plans') {
try {
const data = JSON.parse(content) as Parameters<typeof AgentPlans>[0]['data'];
return <AgentPlans data={data} />;
} catch (e) {
return <CodePreview language={lang} code={content} />;
}
}

if (lang === 'agent-messages') {
try {
const data = JSON.parse(content) as Parameters<typeof AgentMessages>[0]['data'];
return <AgentMessages data={data} />;
} catch (e) {
return <CodePreview language={lang} code={content} />;
}
}

if (lang === 'vis-convert-error') {
try {
const data = JSON.parse(content) as Parameters<typeof VisConvertError>[0]['data'];
return <VisConvertError data={data} />;
} catch (e) {
return <CodePreview language={lang} code={content} />;
}
}

if (lang === 'vis-dashboard') {
try {
const data = JSON.parse(content) as Parameters<typeof VisDashboard>[0]['data'];
return <VisDashboard data={data} />;
} catch (e) {
return <CodePreview language={lang} code={content} />;
}
}

if (lang === 'vis-chart') {
try {
const data = JSON.parse(content) as Parameters<typeof VisChart>[0]['data'];
return <VisChart data={data} />;
} catch (e) {
return <CodePreview language={lang} code={content} />;
}
}

if (lang === 'vis-plugin') {
try {
const data = JSON.parse(content) as Parameters<typeof VisPlugin>[0]['data'];
return <VisPlugin data={data} />;
} catch (e) {
return <CodePreview language={lang} code={content} />;
}
}

if (lang === 'vis-code') {
try {
const data = JSON.parse(content) as Parameters<typeof VisCode>[0]['data'];
return <VisCode data={data} />;
} catch (e) {
return <CodePreview language={lang} code={content} />;
}
}
try {
const data = JSON.parse(content) as Parameters<typeof VisCode>[0]['data'];
return <VisCode data={data} />;
} catch (e) {
return <CodePreview language={lang} code={content} />;
}
},
},
defaultRenderer({ inline, node, className, children, style, ...props }) {
const content = String(children);
const lang = className?.replace('language-', '') || 'javascript';
const { context, matchValues } = matchCustomeTagValues(content);
return (
<>
{!inline ? (
<CodePreview code={context} language={lang} />
) : (
<code {...props} style={style} className="p-1 mx-1 rounded bg-theme-light dark:bg-theme-dark text-sm">
{children}
</code>
)}
<GPTVis components={markdownComponents} rehypePlugins={[rehypeRaw]}>
{matchValues.join('\n')}
</GPTVis>
</>
);
},
}),
};

return (
<>
{!inline ? (
<CodePreview code={context} language={lang} />
) : (
<code {...props} style={style} className="p-1 mx-1 rounded bg-theme-light dark:bg-theme-dark text-sm">
{children}
</code>
)}
<ReactMarkdown components={markdownComponents} rehypePlugins={[rehypeRaw]}>
{matchValues.join('\n')}
</ReactMarkdown>
</>
);
},
const basicComponents: MarkdownComponent = {
...codeComponents,
ul({ children }) {
return <ul className="py-1">{children}</ul>;
},
Expand Down
9 changes: 4 additions & 5 deletions web/components/chat/chat-content/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PropsWithChildren, ReactNode, memo, useContext, useMemo } from 'react';
import { CheckOutlined, ClockCircleOutlined, CloseOutlined, CodeOutlined, LoadingOutlined, RobotOutlined, UserOutlined } from '@ant-design/icons';
import ReactMarkdown from 'react-markdown';
import { GPTVis } from '@antv/gpt-vis';
import { IChatDialogueMessageSchema } from '@/types/chat';
import rehypeRaw from 'rehype-raw';
import classNames from 'classnames';
Expand All @@ -22,7 +22,7 @@ interface Props {
onLinkClick?: () => void;
}

type MarkdownComponent = Parameters<typeof ReactMarkdown>['0']['components'];
type MarkdownComponent = Parameters<typeof GPTVis>['0']['components'];

type DBGPTView = {
name: string;
Expand Down Expand Up @@ -134,6 +134,7 @@ function ChatContent({ children, content, isChartChat, onLinkClick }: PropsWithC

if (!isRobot && !context) return <div className="h-12"></div>;

console.log(22222, 'render');
return (
<div
className={classNames('relative flex flex-wrap w-full p-2 md:p-4 rounded-xl break-words', {
Expand All @@ -159,9 +160,7 @@ function ChatContent({ children, content, isChartChat, onLinkClick }: PropsWithC
)}
{/* Markdown */}
{isRobot && typeof context === 'string' && (
<ReactMarkdown components={{ ...markdownComponents, ...extraMarkdownComponents }} rehypePlugins={[rehypeRaw]}>
{formatMarkdownVal(value)}
</ReactMarkdown>
<GPTVis components={{ ...markdownComponents, ...extraMarkdownComponents }}>{formatMarkdownVal(value)}</GPTVis>
)}
{!!relations?.length && (
<div className="flex flex-wrap mt-2">
Expand Down
6 changes: 3 additions & 3 deletions web/components/chat/chat-content/vis-code.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ReactMarkdown from 'react-markdown';
import { GPTVis } from '@antv/gpt-vis';
import remarkGfm from 'remark-gfm';
import markdownComponents from './config';
import { CodePreview } from './code-preview';
Expand Down Expand Up @@ -57,9 +57,9 @@ function VisCode({ data }: Props) {
</div>
</div>
<div className="p-4 max-h-72 overflow-y-auto whitespace-normal bg-white dark:dark:bg-theme-dark">
<ReactMarkdown components={markdownComponents} remarkPlugins={[remarkGfm]}>
<GPTVis components={markdownComponents} remarkPlugins={[remarkGfm]}>
{data.log}
</ReactMarkdown>
</GPTVis>
</div>
</div>
</div>
Expand Down
6 changes: 3 additions & 3 deletions web/components/chat/chat-content/vis-plugin.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { CheckOutlined, ClockCircleOutlined, CloseOutlined, LoadingOutlined } from '@ant-design/icons';
import classNames from 'classnames';
import { ReactNode } from 'react';
import ReactMarkdown from 'react-markdown';
import { GPTVis } from '@antv/gpt-vis';
import markdownComponents from './config';
import rehypeRaw from 'rehype-raw';

Expand Down Expand Up @@ -50,9 +50,9 @@ function VisPlugin({ data }: Props) {
</div>
{data.result ? (
<div className="px-4 md:px-6 py-4 text-sm whitespace-normal">
<ReactMarkdown components={markdownComponents} rehypePlugins={[rehypeRaw]}>
<GPTVis components={markdownComponents} rehypePlugins={[rehypeRaw]}>
{data.result ?? ''}
</ReactMarkdown>
</GPTVis>
</div>
) : (
<div className="px-4 md:px-6 py-4 text-sm">{data.err_msg}</div>
Expand Down
2 changes: 1 addition & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@ant-design/icons": "^5.2.5",
"@antv/ava": "3.5.0-alpha.4",
"@antv/g2": "^5.1.8",
"@antv/gpt-vis": "^0.x",
"@antv/s2": "^1.51.2",
"@berryv/g2-react": "^0.1.0",
"@emotion/react": "^11.11.4",
Expand Down Expand Up @@ -42,7 +43,6 @@
"react": "18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^13.2.0",
"react-markdown": "^8.0.7",
"react-syntax-highlighter": "^15.5.0",
"reactflow": "^11.10.2",
"rehype-raw": "6.1.1",
Expand Down
Loading