diff --git a/web/components/chat/agent-content.tsx b/web/components/chat/agent-content.tsx index 041d0e5ec..3c10f2c3f 100644 --- a/web/components/chat/agent-content.tsx +++ b/web/components/chat/agent-content.tsx @@ -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'; @@ -27,9 +27,9 @@ function AgentContent({ content }: Props) { })} > {isView ? ( - + {formatMarkdownVal(content.context)} - + ) : (
{content.context}
)} diff --git a/web/components/chat/chat-content/agent-messages.tsx b/web/components/chat/chat-content/agent-messages.tsx index 4940a8e39..74d4bb7e0 100644 --- a/web/components/chat/chat-content/agent-messages.tsx +++ b/web/components/chat/chat-content/agent-messages.tsx @@ -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'; @@ -32,9 +31,7 @@ function AgentMessages({ data }: Props) {
- - {item.markdown} - + {item.markdown}
{item.resource && item.resource !== 'null' && } diff --git a/web/components/chat/chat-content/agent-plans.tsx b/web/components/chat/chat-content/agent-plans.tsx index 73f9850bd..852ce03c4 100644 --- a/web/components/chat/chat-content/agent-plans.tsx +++ b/web/components/chat/chat-content/agent-plans.tsx @@ -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'; @@ -39,11 +39,7 @@ function AgentPlans({ data }: Props) { )} ), - children: ( - - {item.markdown} - - ), + children: {item.markdown}, }; })} /> diff --git a/web/components/chat/chat-content/config.tsx b/web/components/chat/chat-content/config.tsx index 43898c0ff..7911b9829 100644 --- a/web/components/chat/chat-content/config.tsx +++ b/web/components/chat/chat-content/config.tsx @@ -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'; @@ -20,7 +19,7 @@ import VisChatLink from './VisChatLink'; import VisResponse from './VisResponse'; import { formatSql } from '@/utils'; -type MarkdownComponent = Parameters['0']['components']; +type MarkdownComponent = Parameters['0']['components']; const customeTags: (keyof JSX.IntrinsicElements)[] = ['custom-view', 'chart-view', 'references', 'summary']; @@ -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[0]['data']; - return ; - } catch (e) { - return ; - } - } - - if (lang === 'agent-messages') { - try { - const data = JSON.parse(content) as Parameters[0]['data']; - return ; - } catch (e) { - return ; - } - } - - if (lang === 'vis-convert-error') { - try { - const data = JSON.parse(content) as Parameters[0]['data']; - return ; - } catch (e) { - return ; - } - } - - if (lang === 'vis-dashboard') { - try { - const data = JSON.parse(content) as Parameters[0]['data']; - return ; - } catch (e) { - return ; - } - } - - if (lang === 'vis-chart') { - try { - const data = JSON.parse(content) as Parameters[0]['data']; - return ; - } catch (e) { - return ; - } - } - - if (lang === 'vis-plugin') { - try { - const data = JSON.parse(content) as Parameters[0]['data']; - return ; - } catch (e) { - return ; - } - } +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[0]['data']; + return ; + } catch (e) { + return ; + } + }, + '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[0]['data']; + return ; + } catch (e) { + return ; + } + }, + '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[0]['data']; + return ; + } catch (e) { + return ; + } + }, + '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[0]['data']; + return ; + } catch (e) { + return ; + } + }, + '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[0]['data']; + return ; + } catch (e) { + return ; + } + }, + '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[0]['data']; + return ; + } catch (e) { + return ; + } + }, + '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[0]['data']; - return ; - } catch (e) { - return ; - } - } + try { + const data = JSON.parse(content) as Parameters[0]['data']; + return ; + } catch (e) { + return ; + } + }, + '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[0]['data']; + return ; + } catch (e) { + return ; + } + }, + '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[0]['data']; + return ; + } catch (e) { + return ; + } + }, + }, + defaultRenderer({ inline, node, className, children, style, ...props }) { + const content = String(children); + const lang = className?.replace('language-', '') || 'javascript'; + const { context, matchValues } = matchCustomeTagValues(content); + return ( + <> + {!inline ? ( + + ) : ( + + {children} + + )} + + {matchValues.join('\n')} + + + ); + }, + }), +}; - if (lang === 'vis-app-link') { - try { - const data = JSON.parse(content) as Parameters[0]['data']; - return ; - } catch (e) { - return ; - } - } - if (lang === 'vis-api-response') { - try { - const data = JSON.parse(content) as Parameters[0]['data']; - return ; - } catch (e) { - return ; - } - } - return ( - <> - {!inline ? ( - - ) : ( - - {children} - - )} - - {matchValues.join('\n')} - - - ); - }, +const basicComponents: MarkdownComponent = { + ...codeComponents, ul({ children }) { return
    {children}
; }, diff --git a/web/components/chat/chat-content/index.tsx b/web/components/chat/chat-content/index.tsx index b6db80cc5..0dec7ba99 100644 --- a/web/components/chat/chat-content/index.tsx +++ b/web/components/chat/chat-content/index.tsx @@ -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'; @@ -22,7 +22,7 @@ interface Props { onLinkClick?: () => void; } -type MarkdownComponent = Parameters['0']['components']; +type MarkdownComponent = Parameters['0']['components']; type DBGPTView = { name: string; @@ -159,9 +159,7 @@ function ChatContent({ children, content, isChartChat, onLinkClick }: PropsWithC )} {/* Markdown */} {isRobot && typeof context === 'string' && ( - - {formatMarkdownVal(value)} - + {formatMarkdownVal(value)} )} {!!relations?.length && (
diff --git a/web/components/chat/chat-content/vis-code.tsx b/web/components/chat/chat-content/vis-code.tsx index bd4db9089..f218c5e71 100644 --- a/web/components/chat/chat-content/vis-code.tsx +++ b/web/components/chat/chat-content/vis-code.tsx @@ -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'; @@ -57,9 +57,9 @@ function VisCode({ data }: Props) {
- + {data.log} - +
diff --git a/web/components/chat/chat-content/vis-plugin.tsx b/web/components/chat/chat-content/vis-plugin.tsx index 17d34c166..e6b51b4ba 100644 --- a/web/components/chat/chat-content/vis-plugin.tsx +++ b/web/components/chat/chat-content/vis-plugin.tsx @@ -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'; @@ -53,9 +53,9 @@ function VisPlugin({ data }: Props) { {data.result ? (
- + {data.result ?? ''} - +
) : (
{data.err_msg}
diff --git a/web/package.json b/web/package.json index 5df606e88..bb91a3154 100644 --- a/web/package.json +++ b/web/package.json @@ -16,6 +16,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", @@ -55,7 +56,6 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-i18next": "^13.2.0", - "react-markdown": "^8.0.7", "react-markdown-editor-lite": "^1.3.4", "react-syntax-highlighter": "^15.5.0", "react-virtualized": "^9.22.5",