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 all 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
6 changes: 3 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,9 +27,9 @@ function AgentContent({ content }: Props) {
})}
>
{isView ? (
<ReactMarkdown components={markdownComponents} rehypePlugins={[rehypeRaw]}>
<GPTVis components={markdownComponents} rehypePlugins={[rehypeRaw]}>
{formatMarkdownVal(content.context)}
</ReactMarkdown>
</GPTVis>
) : (
<div className="">{content.context}</div>
)}
Expand Down
9 changes: 3 additions & 6 deletions web/components/chat/chat-content/agent-messages.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { GPTVis } from '@antv/gpt-vis';
import ModelIcon from '@/new-components/chat/content/ModelIcon';
import { LinkOutlined, SwapRightOutlined } from '@ant-design/icons';
import { Popover, Space } from 'antd';
import ReactMarkdown from 'react-markdown';
import { SwapRightOutlined } from '@ant-design/icons';
import rehypeRaw from 'rehype-raw';
import remarkGfm from 'remark-gfm';
import markdownComponents from './config';
Expand Down Expand Up @@ -32,9 +31,7 @@ function AgentMessages({ data }: Props) {
</div>
</div>
<div className="whitespace-normal text-sm mb-3">
<ReactMarkdown components={markdownComponents} remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]}>
{item.markdown}
</ReactMarkdown>
<GPTVis components={markdownComponents} remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]}>{item.markdown}</GPTVis>
</div>
{item.resource && item.resource !== 'null' && <ReferencesContent references={item.resource} />}
</div>
Expand Down
8 changes: 2 additions & 6 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 rehypeRaw from 'rehype-raw';
import remarkGfm from 'remark-gfm';

Expand Down Expand Up @@ -39,11 +39,7 @@ function AgentPlans({ data }: Props) {
)}
</div>
),
children: (
<ReactMarkdown components={markdownComponents} rehypePlugins={[rehypeRaw]} remarkPlugins={[remarkGfm]}>
{item.markdown}
</ReactMarkdown>
),
children: <GPTVis components={markdownComponents} rehypePlugins={[rehypeRaw]} remarkPlugins={[remarkGfm]}>{item.markdown}</GPTVis>,
};
})}
/>
Expand Down
239 changes: 131 additions & 108 deletions web/components/chat/chat-content/config.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { AutoChart, BackEndChartType, getChartType } from '@/components/chart';
import { LinkOutlined, ReadOutlined, SyncOutlined } from '@ant-design/icons';
import { GPTVis, withDefaultChartCode } from '@antv/gpt-vis';
import { Table, Image, Tag, Tabs, TabsProps } from 'antd';
import { AutoChart, BackEndChartType, getChartType } from '@/components/chart';
import { Datum } from '@antv/ava';
import { Image, Table, Tabs, TabsProps, Tag } from 'antd';
import ReactMarkdown from 'react-markdown';
import rehypeRaw from 'rehype-raw';
import remarkGfm from 'remark-gfm';

import AgentMessages from './agent-messages';
import AgentPlans from './agent-plans';
import { CodePreview } from './code-preview';
Expand All @@ -20,7 +19,7 @@ import VisChatLink from './VisChatLink';
import VisResponse from './VisResponse';
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 @@ -36,111 +35,135 @@ 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';

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} />;
}
}
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 === '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} />;
}
},
'vis-app-link': ({ 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 VisAppLink>[0]['data'];
return <VisAppLink data={data} />;
} catch (e) {
return <CodePreview language={lang} code={content} />;
}
},
'vis-api-response': ({ 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 VisResponse>[0]['data'];
return <VisResponse 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]} remarkPlugins={[remarkGfm]}>
{matchValues.join('\n')}
</GPTVis>
</>
);
},
}),
};

if (lang === 'vis-app-link') {
try {
const data = JSON.parse(content) as Parameters<typeof VisAppLink>[0]['data'];
return <VisAppLink data={data} />;
} catch (e) {
return <CodePreview language={lang} code={content} />;
}
}
if (lang === 'vis-api-response') {
try {
const data = JSON.parse(content) as Parameters<typeof VisResponse>[0]['data'];
return <VisResponse data={data} />;
} catch (e) {
return <CodePreview language={lang} code={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>
)}
<ReactMarkdown components={markdownComponents} rehypePlugins={[rehypeRaw]} remarkPlugins={[remarkGfm]}>
{matchValues.join('\n')}
</ReactMarkdown>
</>
);
},
const basicComponents: MarkdownComponent = {
...codeComponents,
ul({ children }) {
return <ul className="py-1">{children}</ul>;
},
Expand Down
8 changes: 3 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 @@ -159,9 +159,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 rehypeRaw from 'rehype-raw';
import remarkGfm from 'remark-gfm';

Expand Down Expand Up @@ -53,9 +53,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]} remarkPlugins={[remarkGfm]}>
<GPTVis components={markdownComponents} rehypePlugins={[rehypeRaw]} remarkPlugins={[remarkGfm]}>
{data.result ?? ''}
</ReactMarkdown>
</GPTVis>
</div>
) : (
<div className="px-4 md:px-6 py-4 text-sm">{data.err_msg}</div>
Expand Down
Loading
Loading