From 4da089b101105a584d1e97f7fc7ed4ee55703b14 Mon Sep 17 00:00:00 2001 From: archer <545436317@qq.com> Date: Wed, 20 Mar 2024 16:30:35 +0800 Subject: [PATCH 1/7] perf: prompt tool call --- packages/global/core/chat/adapt.ts | 3 +- .../dispatch/agent/runTool/constants.ts | 30 +++++++++++-------- .../workflow/dispatch/agent/runTool/index.ts | 1 + .../dispatch/agent/runTool/promptCall.ts | 29 +++++++----------- projects/app/public/imgs/model/ernie.svg | 11 +++++++ .../ChatBox/components/ChatItem.tsx | 11 ++++--- 6 files changed, 48 insertions(+), 37 deletions(-) create mode 100644 projects/app/public/imgs/model/ernie.svg diff --git a/packages/global/core/chat/adapt.ts b/packages/global/core/chat/adapt.ts index 31320e9d498..e9c40ef4c01 100644 --- a/packages/global/core/chat/adapt.ts +++ b/packages/global/core/chat/adapt.ts @@ -83,6 +83,7 @@ export const chats2GPTMessages = ({ }); } } else { + //AI item.value.forEach((value) => { if (value.type === ChatItemValueTypeEnum.tool && value.tools && reserveTool) { const tool_calls: ChatCompletionMessageToolCall[] = []; @@ -110,7 +111,7 @@ export const chats2GPTMessages = ({ tool_calls }) .concat(toolResponse); - } else if (value.text) { + } else if (value.text?.content) { results.push({ dataId, role: ChatCompletionRequestMessageRoleEnum.Assistant, diff --git a/packages/service/core/workflow/dispatch/agent/runTool/constants.ts b/packages/service/core/workflow/dispatch/agent/runTool/constants.ts index 1a5223f03c5..1a91b5f8439 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/constants.ts +++ b/packages/service/core/workflow/dispatch/agent/runTool/constants.ts @@ -1,30 +1,36 @@ -export const Prompt_Tool_Call = `你是一个智能机器人,除了可以回答用户问题外,你还掌握工具的使用能力。有时候,你可以依赖工具的运行结果,来更准确的回答用户。 +export const Prompt_Tool_Call = ` +你是一个智能机器人,除了可以回答用户问题外,你还掌握工具的使用能力。有时候,你可以依赖工具的运行结果,来更准确的回答用户。 下面是你可以使用的工具,使用 JSON Schema 的格式声明,其中 toolId 是工具的 description 是工具的描述,parameters 是工具的参数,包括参数的类型和描述,required 是必填参数的列表。 """ {{toolsPrompt}} """ -接下来,请你根据工具描述,决定回答问题或是使用工具。在完成任务过程中,USER代表用户的输入,TOOL_RESPONSE代表工具运行结果。你的任务是输出下面2种结果: -1. TOOL_CALL: 使用工具。 -2. ANSWER: 回答问题。 +接下来,请你根据工具描述,决定回答问题或是使用工具。在完成任务过程中,USER代表用户的输入,TOOL_RESPONSE代表工具运行结果。ASSISTANT 代表你的输出。 +你的每次输出都必须以0,1开头,代表是否需要调用工具: +0: 不使用工具,直接回答内容。 +1: 使用工具,返回工具调用的参数。 例如: -""" USER: 你好呀 -ANSWER: 你好,有什么可以帮助你的么? +ANSWER: 0: 你好,有什么可以帮助你的么? USER: 今天杭州的天气如何 -TOOL_CALL: {"toolId":"w2121",arguments:{"city": "杭州"}} -TOOL_RESPONSE: 晴天...... -ANSWER: 今天杭州是晴天。 +ANSWER: 1: {"toolId":"w2121",arguments:{"city": "杭州"}} +TOOL_RESPONSE: """ +晴天...... +""" +ANSWER: 0: 今天杭州是晴天。 USER: 今天杭州的天气适合去哪里玩? -TOOL_CALL: {"toolId":"as21da",arguments:{"query": "杭州 天气 去哪里玩"}} -TOOL_RESPONSE: 晴天. 西湖、灵隐寺、千岛湖…… -ANSWER: 今天杭州是晴天,适合去西湖、灵隐寺、千岛湖等地玩。 +ANSWER: 1: {"toolId":"as21da",arguments:{"query": "杭州 天气 去哪里玩"}} +TOOL_RESPONSE: """ +晴天. 西湖、灵隐寺、千岛湖…… """ +ANSWER: 0: 今天杭州是晴天,适合去西湖、灵隐寺、千岛湖等地玩。 + 现在,我们开始吧! USER: {{question}} +ANSWER: `; diff --git a/packages/service/core/workflow/dispatch/agent/runTool/index.ts b/packages/service/core/workflow/dispatch/agent/runTool/index.ts index 112dc5095ea..18862e5dcf7 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/index.ts +++ b/packages/service/core/workflow/dispatch/agent/runTool/index.ts @@ -81,6 +81,7 @@ export const dispatchRunTools = async (props: DispatchToolModuleProps): Promise< assistantResponses = [] // FastGPT system store assistant.value response } = await (async () => { const adaptMessages = chats2GPTMessages({ messages, reserveId: false }); + if (toolModel.toolChoice) { return runToolWithToolChoice({ ...props, diff --git a/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts b/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts index 5bd7956752d..9c9f5942a2d 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts +++ b/packages/service/core/workflow/dispatch/agent/runTool/promptCall.ts @@ -131,7 +131,7 @@ export const runToolWithPromptCall = async ( })(); const parseAnswerResult = parseAnswer(answer); - + // console.log(answer, '==11=='); // No tools if (typeof parseAnswerResult === 'string') { // No tool is invoked, indicating that the process is over @@ -271,7 +271,7 @@ export const runToolWithPromptCall = async ( // get the next user prompt lastMessage.content += `${answer} TOOL_RESPONSE: ${toolsRunResponse.toolResponsePrompt} -`; +ANSWER: `; /* check stop signal */ const hasStopSignal = toolsRunResponse.moduleRunResponse.flowResponses.some( @@ -336,21 +336,13 @@ async function streamResponse({ text: content }) }); - } else if (textAnswer.length >= 10) { - if (!textAnswer.startsWith('TOOL_CALL:')) { - startResponseWrite = true; - responseWrite({ - write, - event: detail ? SseResponseEventEnum.answer : undefined, - data: textAdaptGptResponse({ - text: textAnswer - }) - }); - } - } else if (textAnswer.length >= 7) { - if (textAnswer.startsWith('ANSWER:')) { + } else if (textAnswer.length >= 3) { + textAnswer = textAnswer.trim(); + if (textAnswer.startsWith('0')) { startResponseWrite = true; - textAnswer = textAnswer.substring(7).trim(); + // find first : index + const firstIndex = textAnswer.indexOf(':'); + textAnswer = textAnswer.substring(firstIndex + 1).trim(); responseWrite({ write, event: detail ? SseResponseEventEnum.answer : undefined, @@ -372,12 +364,13 @@ async function streamResponse({ const parseAnswer = (str: string): FunctionCallCompletion | string => { // 首先,使用正则表达式提取TOOL_ID和TOOL_ARGUMENTS - const prefix = 'TOOL_CALL:'; + const prefix = '1:'; + str = str.trim(); if (str.startsWith(prefix)) { const toolString = str.substring(prefix.length).trim(); try { - const toolCall = JSON.parse(toolString); + const toolCall = json5.parse(toolString); return { id: getNanoid(), name: toolCall.toolId, diff --git a/projects/app/public/imgs/model/ernie.svg b/projects/app/public/imgs/model/ernie.svg new file mode 100644 index 00000000000..ca91863f644 --- /dev/null +++ b/projects/app/public/imgs/model/ernie.svg @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/projects/app/src/components/ChatBox/components/ChatItem.tsx b/projects/app/src/components/ChatBox/components/ChatItem.tsx index 47396ba6c50..024f2714a8b 100644 --- a/projects/app/src/components/ChatBox/components/ChatItem.tsx +++ b/projects/app/src/components/ChatBox/components/ChatItem.tsx @@ -112,12 +112,11 @@ ${JSON.stringify(questionGuides)}`; } return ( - - - + ); } if (value.type === ChatItemValueTypeEnum.tool && value.tools) { From 69faeec2b04e3047995a041dc8d777a3d2e1b382 Mon Sep 17 00:00:00 2001 From: archer <545436317@qq.com> Date: Wed, 20 Mar 2024 17:06:06 +0800 Subject: [PATCH 2/7] perf: chat box ux --- projects/app/public/locales/zh/common.json | 3 +- projects/app/src/components/ChatBox/index.tsx | 24 +- .../detail/components/SimpleEdit/AppCard.tsx | 3 +- .../components/SimpleEdit/ToolSelectModal.tsx | 17 +- projects/app/src/web/core/app/templates.ts | 640 +++++++++--------- 5 files changed, 343 insertions(+), 344 deletions(-) diff --git a/projects/app/public/locales/zh/common.json b/projects/app/public/locales/zh/common.json index 101a205a8fc..daf29128aca 100644 --- a/projects/app/public/locales/zh/common.json +++ b/projects/app/public/locales/zh/common.json @@ -579,8 +579,7 @@ "success": "开始同步" } }, - "training": { - } + "training": {} }, "data": { "Auxiliary Data": "辅助数据", diff --git a/projects/app/src/components/ChatBox/index.tsx b/projects/app/src/components/ChatBox/index.tsx index 8bc05e1f7b2..281c95c5197 100644 --- a/projects/app/src/components/ChatBox/index.tsx +++ b/projects/app/src/components/ChatBox/index.tsx @@ -560,14 +560,29 @@ const ChatBox = ( }, [chatHistories, onDelMessage, sendPrompt, setLoading, toast] ); - // delete one message + // delete one message(One human and the ai response) const delOneMessage = useCallback( (dataId?: string) => { if (!dataId || !onDelMessage) return; return () => { - setChatHistories((state) => state.filter((chat) => chat.dataId !== dataId)); - onDelMessage({ - contentId: dataId + setChatHistories((state) => { + let aiIndex = -1; + + return state.filter((chat, i) => { + if (chat.dataId === dataId) { + aiIndex = i + 1; + onDelMessage({ + contentId: dataId + }); + return false; + } else if (aiIndex === i && chat.obj === ChatRoleEnum.AI && chat.dataId) { + onDelMessage({ + contentId: chat.dataId + }); + return false; + } + return true; + }); }); }; }, @@ -872,7 +887,6 @@ const ChatBox = ( avatar={appAvatar} chat={item} isChatting={isChatting} - onDelete={delOneMessage(item.dataId)} {...(item.obj === 'AI' && { setChatHistories, showVoiceIcon, diff --git a/projects/app/src/pages/app/detail/components/SimpleEdit/AppCard.tsx b/projects/app/src/pages/app/detail/components/SimpleEdit/AppCard.tsx index fa5e43740bb..e4ec517015c 100644 --- a/projects/app/src/pages/app/detail/components/SimpleEdit/AppCard.tsx +++ b/projects/app/src/pages/app/detail/components/SimpleEdit/AppCard.tsx @@ -27,7 +27,8 @@ const AppCard = ({ appId }: { appId: string }) => { const [TeamTagsSet, setTeamTagsSet] = useState(); const { openConfirm: openConfirmDel, ConfirmModal: ConfirmDelModal } = useConfirm({ - content: t('app.Confirm Del App Tip') + content: t('app.Confirm Del App Tip'), + type: 'delete' }); /* 点击删除 */ diff --git a/projects/app/src/pages/app/detail/components/SimpleEdit/ToolSelectModal.tsx b/projects/app/src/pages/app/detail/components/SimpleEdit/ToolSelectModal.tsx index e66195252f1..65c2447e14f 100644 --- a/projects/app/src/pages/app/detail/components/SimpleEdit/ToolSelectModal.tsx +++ b/projects/app/src/pages/app/detail/components/SimpleEdit/ToolSelectModal.tsx @@ -81,7 +81,7 @@ const ToolSelectModal = ({ onClose, ...props }: Props & { onClose: () => void }) errorToast: t('core.module.templates.Load plugin error') }); - useQuery(['teamNodeTemplate', currentParent.parentId, searchKey], () => + const { isLoading } = useQuery(['teamNodeTemplate', currentParent.parentId, searchKey], () => loadTeamPluginNodeTemplates(currentParent.parentId, searchKey, true) ); @@ -127,7 +127,7 @@ const ToolSelectModal = ({ onClose, ...props }: Props & { onClose: () => void }) /> - + {templateType === TemplateTypeEnum.teamPlugin && !searchKey && ( void }) /> )} - - + + ); }; @@ -153,11 +158,13 @@ export default React.memo(ToolSelectModal); const RenderList = React.memo(function RenderList({ templates, selectedTools, + isLoadingData, onAddTool, onRemoveTool, setCurrentParent }: Props & { templates: FlowNodeTemplateType[]; + isLoadingData: boolean; setCurrentParent: (e: { parentId: string | null; parentName: string }) => void; }) { const { t } = useTranslation(); @@ -185,7 +192,7 @@ const RenderList = React.memo(function RenderList({ errorToast: t('core.module.templates.Load plugin error') }); - return templates.length === 0 ? ( + return templates.length === 0 && !isLoadingData ? ( ) : ( diff --git a/projects/app/src/web/core/app/templates.ts b/projects/app/src/web/core/app/templates.ts index 98b73bb2000..fe4319a765a 100644 --- a/projects/app/src/web/core/app/templates.ts +++ b/projects/app/src/web/core/app/templates.ts @@ -10,8 +10,8 @@ export const appTemplates: (AppItemType & { { id: 'simpleChat', avatar: '/imgs/module/AI.png', - name: 'core.app.template.Simple chat', - intro: 'core.app.template.Simple chat desc', + name: '简易模板', + intro: '一个极其简单的 AI 应用,你可以绑定知识库或工具。', type: AppTypeEnum.simple, modules: [ { @@ -291,15 +291,16 @@ export const appTemplates: (AppItemType & { ] }, { - id: 'simpleDatasetChat', - avatar: '/imgs/module/db.png', - name: 'core.app.template.Dataset and guide', - intro: 'core.app.template.Dataset and guide desc', + id: 'chatGuide', + avatar: '/imgs/module/userGuide.png', + name: '对话引导 + 变量', + intro: '可以在对话开始发送一段提示,或者让用户填写一些内容,作为本次对话的变量', type: AppTypeEnum.simple, modules: [ { moduleId: 'userGuide', name: 'core.module.template.User guide', + avatar: '/imgs/module/userGuide.png', flowType: 'userGuide', position: { x: 447.98520778293346, @@ -310,18 +311,48 @@ export const appTemplates: (AppItemType & { key: 'welcomeText', type: 'hidden', valueType: 'string', - label: 'core.app.Welcome Text', + label: '', showTargetInApp: false, showTargetInPlugin: false, - value: '你好,我是知识库助手,请不要忘记选择知识库噢~\n[你是谁]\n[如何使用]', + value: '你好,我可以为你翻译各种语言,请告诉我你需要翻译成什么语言?', connected: false }, { key: 'variables', type: 'hidden', valueType: 'any', - label: 'core.module.Variable', - value: [], + label: '', + value: [ + { + id: '35c640eb-cf22-431f-bb57-3fc21643880e', + key: 'language', + label: '目标语言', + type: 'input', + required: true, + maxLen: 50, + enums: [ + { + value: '' + } + ] + }, + { + id: '2011ff08-91aa-4f60-ae69-f311ab4797b3', + key: 'language2', + label: '下拉框测试', + type: 'select', + required: false, + maxLen: 50, + enums: [ + { + value: '英语' + }, + { + value: '法语' + } + ] + } + ], showTargetInApp: false, showTargetInPlugin: false, connected: false @@ -343,9 +374,6 @@ export const appTemplates: (AppItemType & { label: '', showTargetInApp: false, showTargetInPlugin: false, - value: { - type: 'web' - }, connected: false } ], @@ -354,10 +382,11 @@ export const appTemplates: (AppItemType & { { moduleId: 'userChatInput', name: 'core.module.template.Chat entrance', + avatar: '/imgs/module/userChatInput.png', flowType: 'questionInput', position: { - x: 324.81436595478294, - y: 1527.0012457753612 + x: 464.32198615344566, + y: 1602.2698463081606 }, inputs: [ { @@ -376,168 +405,6 @@ export const appTemplates: (AppItemType & { label: 'core.module.input.label.user question', type: 'source', valueType: 'string', - targets: [ - { - moduleId: 'datasetSearch', - key: 'userChatInput' - } - ] - } - ] - }, - { - moduleId: 'datasetSearch', - name: 'core.module.template.Dataset search', - flowType: 'datasetSearchNode', - showStatus: true, - position: { - x: 1351.5043753345153, - y: 947.0780385418003 - }, - inputs: [ - { - key: 'switch', - type: 'target', - label: 'core.module.input.label.switch', - description: 'core.module.input.description.Trigger', - valueType: 'any', - showTargetInApp: true, - showTargetInPlugin: true, - connected: false - }, - { - key: 'datasets', - type: 'selectDataset', - label: 'core.module.input.label.Select dataset', - value: [], - valueType: 'selectDataset', - list: [], - required: true, - showTargetInApp: false, - showTargetInPlugin: true, - connected: false - }, - { - key: 'similarity', - type: 'selectDatasetParamsModal', - label: '', - value: 0.4, - valueType: 'number', - showTargetInApp: false, - showTargetInPlugin: false, - connected: false - }, - { - key: 'limit', - type: 'hidden', - label: '', - value: 1500, - valueType: 'number', - showTargetInApp: false, - showTargetInPlugin: false, - connected: false - }, - { - key: 'searchMode', - type: 'hidden', - label: '', - valueType: 'string', - showTargetInApp: false, - showTargetInPlugin: false, - value: 'embedding', - connected: false - }, - { - key: 'usingReRank', - type: 'hidden', - label: '', - valueType: 'boolean', - showTargetInApp: false, - showTargetInPlugin: false, - value: false, - connected: false - }, - { - key: 'datasetSearchUsingExtensionQuery', - type: 'hidden', - label: '', - valueType: 'boolean', - showTargetInApp: false, - showTargetInPlugin: false, - value: true, - connected: false - }, - { - key: 'datasetSearchExtensionModel', - type: 'hidden', - label: '', - valueType: 'string', - showTargetInApp: false, - showTargetInPlugin: false, - value: 'gpt-3.5-turbo', - connected: false - }, - { - key: 'datasetSearchExtensionBg', - type: 'hidden', - label: '', - valueType: 'string', - showTargetInApp: false, - showTargetInPlugin: false, - value: '', - connected: false - }, - { - key: 'userChatInput', - type: 'custom', - label: '', - required: true, - valueType: 'string', - showTargetInApp: true, - showTargetInPlugin: true, - connected: true - } - ], - outputs: [ - { - key: 'isEmpty', - label: 'core.module.output.label.Search result empty', - type: 'source', - valueType: 'boolean', - targets: [] - }, - { - key: 'unEmpty', - label: 'core.module.output.label.Search result not empty', - type: 'source', - valueType: 'boolean', - targets: [] - }, - { - key: 'quoteQA', - label: 'core.module.Dataset quote.label', - type: 'source', - valueType: 'datasetQuote', - targets: [ - { - moduleId: 'chatModule', - key: 'quoteQA' - } - ] - }, - { - key: 'finish', - label: 'core.module.output.label.running done', - description: 'core.module.output.description.running done', - valueType: 'boolean', - type: 'source', - targets: [] - }, - { - key: 'userChatInput', - label: 'core.module.input.label.user question', - type: 'hidden', - valueType: 'string', targets: [ { moduleId: 'chatModule', @@ -550,18 +417,18 @@ export const appTemplates: (AppItemType & { { moduleId: 'chatModule', name: 'AI 对话', + avatar: '/imgs/module/AI.png', flowType: 'chatNode', showStatus: true, position: { - x: 2022.7264786978908, - y: 1006.3102431257475 + x: 981.9682828103937, + y: 890.014595014464 }, inputs: [ { key: 'switch', type: 'target', label: 'core.module.input.label.switch', - description: 'core.module.input.description.Trigger', valueType: 'any', showTargetInApp: true, showTargetInPlugin: true, @@ -581,12 +448,22 @@ export const appTemplates: (AppItemType & { { key: 'temperature', type: 'hidden', - label: '', + label: '温度', value: 0, valueType: 'number', min: 0, max: 10, step: 1, + markList: [ + { + label: '严谨', + value: 0 + }, + { + label: '发散', + value: 10 + } + ], showTargetInApp: false, showTargetInPlugin: false, connected: false @@ -594,14 +471,12 @@ export const appTemplates: (AppItemType & { { key: 'maxToken', type: 'hidden', - label: '', - value: 2000, + label: '回复上限', + value: 8000, valueType: 'number', min: 100, max: 4000, step: 50, - showTargetInApp: false, - showTargetInPlugin: false, markList: [ { label: '100', @@ -612,12 +487,14 @@ export const appTemplates: (AppItemType & { value: 4000 } ], + showTargetInApp: false, + showTargetInPlugin: false, connected: false }, { key: 'isResponseAnswerText', type: 'hidden', - label: '', + label: '返回AI内容', value: true, valueType: 'boolean', showTargetInApp: false, @@ -627,21 +504,19 @@ export const appTemplates: (AppItemType & { { key: 'quoteTemplate', type: 'hidden', - label: '', + label: '引用内容模板', valueType: 'string', showTargetInApp: false, showTargetInPlugin: false, - value: '', connected: false }, { key: 'quotePrompt', type: 'hidden', - label: '', + label: '引用内容提示词', valueType: 'string', showTargetInApp: false, showTargetInPlugin: false, - value: '', connected: false }, { @@ -659,11 +534,13 @@ export const appTemplates: (AppItemType & { label: 'core.ai.Prompt', max: 300, valueType: 'string', - description: 'core.app.tip.chatNodeSystemPromptTip', - placeholder: 'core.app.tip.chatNodeSystemPromptTip', + description: + '模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}', + placeholder: + '模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}', showTargetInApp: true, showTargetInPlugin: true, - value: '', + value: '请直接将我的问题翻译成{{language}},不需要回答问题。', connected: false }, { @@ -680,21 +557,21 @@ export const appTemplates: (AppItemType & { connected: false }, { - key: 'userChatInput', - type: 'custom', - label: '', - required: true, - valueType: 'string', + key: 'quoteQA', + type: 'target', + label: '引用内容', + description: "对象数组格式,结构:\n [{q:'问题',a:'回答'}]", + valueType: 'datasetQuote', showTargetInApp: true, showTargetInPlugin: true, - connected: true + connected: false }, { - key: 'quoteQA', + key: 'userChatInput', type: 'target', - label: '知识库引用', - description: 'core.module.Dataset quote.Input description', - valueType: 'datasetQuote', + label: 'core.module.input.label.user question', + required: true, + valueType: 'string', showTargetInApp: true, showTargetInPlugin: true, connected: true @@ -703,8 +580,8 @@ export const appTemplates: (AppItemType & { outputs: [ { key: 'answerText', - label: 'core.module.output.label.Ai response content', - description: 'core.module.output.description.Ai response content', + label: 'AI回复', + description: '将在 stream 回复完毕后触发', valueType: 'string', type: 'source', targets: [] @@ -719,33 +596,27 @@ export const appTemplates: (AppItemType & { }, { key: 'history', - label: 'core.module.output.label.New context', - description: 'core.module.output.description.New context', + label: '新的上下文', + description: '将本次回复内容拼接上历史记录,作为新的上下文返回', valueType: 'chatHistory', type: 'source', targets: [] - }, - { - key: 'userChatInput', - label: 'core.module.input.label.user question', - type: 'hidden', - valueType: 'string', - targets: [] } ] } ] }, { - id: 'chatGuide', - avatar: '/imgs/module/userGuide.png', - name: 'core.app.template.Guide and variables', - intro: 'core.app.template.Guide and variables desc', - type: AppTypeEnum.simple, + id: 'simpleDatasetChat', + avatar: '/imgs/module/db.png', + name: '知识库+对话引导', + intro: '每次提问时进行一次知识库搜索,将搜索结果注入 LLM 模型进行参考回答', + type: AppTypeEnum.advanced, modules: [ { moduleId: 'userGuide', name: 'core.module.template.User guide', + intro: 'core.app.tip.userGuideTip', avatar: '/imgs/module/userGuide.png', flowType: 'userGuide', position: { @@ -757,48 +628,18 @@ export const appTemplates: (AppItemType & { key: 'welcomeText', type: 'hidden', valueType: 'string', - label: '', + label: 'core.app.Welcome Text', showTargetInApp: false, showTargetInPlugin: false, - value: '你好,我可以为你翻译各种语言,请告诉我你需要翻译成什么语言?', + value: '你好,我是知识库助手,请不要忘记选择知识库噢~\n[你是谁]\n[如何使用]', connected: false }, { key: 'variables', type: 'hidden', valueType: 'any', - label: '', - value: [ - { - id: '35c640eb-cf22-431f-bb57-3fc21643880e', - key: 'language', - label: '目标语言', - type: 'input', - required: true, - maxLen: 50, - enums: [ - { - value: '' - } - ] - }, - { - id: '2011ff08-91aa-4f60-ae69-f311ab4797b3', - key: 'language2', - label: '下拉框测试', - type: 'select', - required: false, - maxLen: 50, - enums: [ - { - value: '英语' - }, - { - value: '法语' - } - ] - } - ], + label: 'core.module.Variable', + value: [], showTargetInApp: false, showTargetInPlugin: false, connected: false @@ -820,6 +661,9 @@ export const appTemplates: (AppItemType & { label: '', showTargetInApp: false, showTargetInPlugin: false, + value: { + type: 'web' + }, connected: false } ], @@ -828,11 +672,12 @@ export const appTemplates: (AppItemType & { { moduleId: 'userChatInput', name: 'core.module.template.Chat entrance', - avatar: '/imgs/module/userChatInput.png', + intro: '当用户发送一个内容后,流程将会从这个模块开始执行。', + avatar: '/imgs/module/userChatInput.svg', flowType: 'questionInput', position: { - x: 464.32198615344566, - y: 1602.2698463081606 + x: 324.81436595478294, + y: 1527.0012457753612 }, inputs: [ { @@ -853,7 +698,7 @@ export const appTemplates: (AppItemType & { valueType: 'string', targets: [ { - moduleId: 'chatModule', + moduleId: '0voh5n', key: 'userChatInput' } ] @@ -861,20 +706,22 @@ export const appTemplates: (AppItemType & { ] }, { - moduleId: 'chatModule', + moduleId: '63toub', name: 'AI 对话', + intro: 'AI 大模型对话', avatar: '/imgs/module/AI.png', flowType: 'chatNode', showStatus: true, - position: { - x: 981.9682828103937, - y: 890.014595014464 + position: { + x: 1962.4010270586014, + y: 1026.9105717680477 }, inputs: [ { key: 'switch', type: 'target', label: 'core.module.input.label.switch', + description: 'core.module.input.description.Trigger', valueType: 'any', showTargetInApp: true, showTargetInPlugin: true, @@ -882,7 +729,7 @@ export const appTemplates: (AppItemType & { }, { key: 'model', - type: 'selectLLMModel', + type: 'settingLLMModel', label: 'core.module.input.label.aiModel', required: true, valueType: 'string', @@ -894,22 +741,12 @@ export const appTemplates: (AppItemType & { { key: 'temperature', type: 'hidden', - label: '温度', + label: '', value: 0, valueType: 'number', min: 0, max: 10, step: 1, - markList: [ - { - label: '严谨', - value: 0 - }, - { - label: '发散', - value: 10 - } - ], showTargetInApp: false, showTargetInPlugin: false, connected: false @@ -917,22 +754,12 @@ export const appTemplates: (AppItemType & { { key: 'maxToken', type: 'hidden', - label: '回复上限', - value: 8000, + label: '', + value: 2000, valueType: 'number', min: 100, max: 4000, step: 50, - markList: [ - { - label: '100', - value: 100 - }, - { - label: '4000', - value: 4000 - } - ], showTargetInApp: false, showTargetInPlugin: false, connected: false @@ -940,7 +767,7 @@ export const appTemplates: (AppItemType & { { key: 'isResponseAnswerText', type: 'hidden', - label: '返回AI内容', + label: '', value: true, valueType: 'boolean', showTargetInApp: false, @@ -950,7 +777,7 @@ export const appTemplates: (AppItemType & { { key: 'quoteTemplate', type: 'hidden', - label: '引用内容模板', + label: '', valueType: 'string', showTargetInApp: false, showTargetInPlugin: false, @@ -959,17 +786,8 @@ export const appTemplates: (AppItemType & { { key: 'quotePrompt', type: 'hidden', - label: '引用内容提示词', - valueType: 'string', - showTargetInApp: false, - showTargetInPlugin: false, - connected: false - }, - { - key: 'aiSettings', - type: 'aiSettings', label: '', - valueType: 'any', + valueType: 'string', showTargetInApp: false, showTargetInPlugin: false, connected: false @@ -977,16 +795,13 @@ export const appTemplates: (AppItemType & { { key: 'systemPrompt', type: 'textarea', - label: 'core.ai.Prompt', - max: 300, + max: 3000, valueType: 'string', - description: - '模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}', - placeholder: - '模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}', + label: 'core.ai.Prompt', + description: 'core.app.tip.chatNodeSystemPromptTip', + placeholder: 'core.app.tip.chatNodeSystemPromptTip', showTargetInApp: true, showTargetInPlugin: true, - value: '请直接将我的问题翻译成{{language}},不需要回答问题。', connected: false }, { @@ -1002,49 +817,221 @@ export const appTemplates: (AppItemType & { showTargetInPlugin: true, connected: false }, + { + key: 'userChatInput', + type: 'custom', + label: '', + required: true, + valueType: 'string', + showTargetInApp: true, + showTargetInPlugin: true, + toolDescription: '用户问题', + connected: true + }, { key: 'quoteQA', - type: 'target', - label: '引用内容', - description: "对象数组格式,结构:\n [{q:'问题',a:'回答'}]", + type: 'settingDatasetQuotePrompt', + label: '知识库引用', + description: 'core.module.Dataset quote.Input description', valueType: 'datasetQuote', showTargetInApp: true, showTargetInPlugin: true, + connected: true + } + ], + outputs: [ + { + key: 'userChatInput', + label: 'core.module.input.label.user question', + type: 'hidden', + valueType: 'string', + targets: [] + }, + { + key: 'history', + label: 'core.module.output.label.New context', + description: 'core.module.output.description.New context', + valueType: 'chatHistory', + type: 'source', + targets: [] + }, + { + key: 'answerText', + label: 'core.module.output.label.Ai response content', + description: 'core.module.output.description.Ai response content', + valueType: 'string', + type: 'source', + targets: [] + }, + { + key: 'finish', + label: 'core.module.output.label.running done', + description: 'core.module.output.description.running done', + valueType: 'boolean', + type: 'source', + targets: [] + } + ] + }, + { + moduleId: '0voh5n', + name: '知识库搜索', + intro: '调用知识库搜索能力,查找“有可能”与问题相关的内容', + avatar: '/imgs/module/db.png', + flowType: 'datasetSearchNode', + showStatus: true, + position: { + x: 1098.245668870126, + y: 1166.7285333032098 + }, + inputs: [ + { + key: 'switch', + type: 'target', + label: 'core.module.input.label.switch', + description: 'core.module.input.description.Trigger', + valueType: 'any', + showTargetInApp: true, + showTargetInPlugin: true, + connected: false + }, + { + key: 'datasets', + type: 'selectDataset', + label: 'core.module.input.label.Select dataset', + value: [], + valueType: 'selectDataset', + list: [], + required: true, + showTargetInApp: false, + showTargetInPlugin: true, + connected: false + }, + { + key: 'similarity', + type: 'selectDatasetParamsModal', + label: '', + value: 0.4, + valueType: 'number', + showTargetInApp: false, + showTargetInPlugin: false, + connected: false + }, + { + key: 'limit', + type: 'hidden', + label: '', + value: 1500, + valueType: 'number', + showTargetInApp: false, + showTargetInPlugin: false, + connected: false + }, + { + key: 'searchMode', + type: 'hidden', + label: '', + valueType: 'string', + showTargetInApp: false, + showTargetInPlugin: false, + value: 'embedding', + connected: false + }, + { + key: 'usingReRank', + type: 'hidden', + label: '', + valueType: 'boolean', + showTargetInApp: false, + showTargetInPlugin: false, + value: false, + connected: false + }, + { + key: 'datasetSearchUsingExtensionQuery', + type: 'hidden', + label: '', + valueType: 'boolean', + showTargetInApp: false, + showTargetInPlugin: false, + value: true, + connected: false + }, + { + key: 'datasetSearchExtensionModel', + type: 'hidden', + label: '', + valueType: 'string', + showTargetInApp: false, + showTargetInPlugin: false, + connected: false + }, + { + key: 'datasetSearchExtensionBg', + type: 'hidden', + label: '', + valueType: 'string', + showTargetInApp: false, + showTargetInPlugin: false, + value: '', connected: false }, { key: 'userChatInput', - type: 'target', - label: 'core.module.input.label.user question', + type: 'custom', + label: '', required: true, valueType: 'string', showTargetInApp: true, showTargetInPlugin: true, + toolDescription: '需要检索的内容', connected: true } ], outputs: [ { - key: 'answerText', - label: 'AI回复', - description: '将在 stream 回复完毕后触发', + key: 'userChatInput', + label: 'core.module.input.label.user question', + type: 'hidden', valueType: 'string', + targets: [ + { + moduleId: '63toub', + key: 'userChatInput' + } + ] + }, + { + key: 'isEmpty', + label: 'core.module.output.label.Search result empty', type: 'source', + valueType: 'boolean', targets: [] }, { - key: 'finish', - label: 'core.module.output.label.running done', - description: 'core.module.output.description.running done', - valueType: 'boolean', + key: 'unEmpty', + label: 'core.module.output.label.Search result not empty', type: 'source', + valueType: 'boolean', targets: [] }, { - key: 'history', - label: '新的上下文', - description: '将本次回复内容拼接上历史记录,作为新的上下文返回', - valueType: 'chatHistory', + key: 'quoteQA', + label: 'core.module.Dataset quote.label', + type: 'source', + valueType: 'datasetQuote', + targets: [ + { + moduleId: '63toub', + key: 'quoteQA' + } + ] + }, + { + key: 'finish', + label: 'core.module.output.label.running done', + description: 'core.module.output.description.running done', + valueType: 'boolean', type: 'source', targets: [] } @@ -1055,8 +1042,8 @@ export const appTemplates: (AppItemType & { { id: 'CQ', avatar: '/imgs/module/cq.png', - name: 'core.app.template.Classify and dataset', - intro: 'core.app.template.Classify and dataset desc', + name: '问题分类 + 知识库', + intro: '先对用户的问题进行分类,再根据不同类型问题,执行不同的操作', type: AppTypeEnum.advanced, modules: [ { @@ -1408,15 +1395,6 @@ export const appTemplates: (AppItemType & { showTargetInPlugin: false, connected: false }, - { - key: 'aiSettings', - type: 'aiSettings', - label: '', - valueType: 'any', - showTargetInApp: false, - showTargetInPlugin: false, - connected: false - }, { key: 'systemPrompt', type: 'textarea', From 1fa0a33b69b5cce22d8a832137473bdf28cf2bb1 Mon Sep 17 00:00:00 2001 From: archer <545436317@qq.com> Date: Wed, 20 Mar 2024 17:35:42 +0800 Subject: [PATCH 3/7] doc --- .../content/docs/development/configuration.md | 44 +++++++++---------- docSite/content/docs/development/faq.md | 32 +++++--------- docSite/content/docs/development/intro.md | 19 +++++++- docSite/content/docs/development/one-api.md | 10 ++++- .../content/docs/development/upgrading/47.md | 11 ++++- packages/service/core/dataset/schema.ts | 2 +- projects/app/data/config.json | 28 +++--------- projects/app/src/service/mongo.ts | 7 ++- 8 files changed, 76 insertions(+), 77 deletions(-) diff --git a/docSite/content/docs/development/configuration.md b/docSite/content/docs/development/configuration.md index 62088eb5f18..847261d9f50 100644 --- a/docSite/content/docs/development/configuration.md +++ b/docSite/content/docs/development/configuration.md @@ -11,7 +11,7 @@ weight: 708 **开发环境下**,你需要将示例配置文件 `config.json` 复制成 `config.local.json` 文件才会生效。 -这个配置文件中包含了系统参数和各个模型配置,使用时务必去掉注释。 +这个配置文件中包含了系统参数和各个模型配置,`使用时务必去掉注释!!!!!!!!!!!!!!` ## 4.6.8+ 版本新配置文件 @@ -28,6 +28,7 @@ llm模型全部合并 { "model": "gpt-3.5-turbo", // 模型名 "name": "gpt-3.5-turbo", // 别名 + "avatar": "/imgs/model/openai.svg", // 模型的logo "maxContext": 16000, // 最大上下文 "maxResponse": 4000, // 最大回复 "quoteMaxToken": 13000, // 最大引用内容 @@ -35,7 +36,7 @@ llm模型全部合并 "charsPointsPrice": 0, "censor": false, "vision": false, // 是否支持图片输入 - "datasetProcess": false, // 是否设置为知识库处理模型(QA),务必保证至少有一个为true,否则知识库会报错 + "datasetProcess": true, // 是否设置为知识库处理模型(QA),务必保证至少有一个为true,否则知识库会报错 "usedInClassify": true, // 是否用于问题分类(务必保证至少有一个为true) "usedInExtractFields": true, // 是否用于内容提取(务必保证至少有一个为true) "usedInToolCall": true, // 是否用于工具调用(务必保证至少有一个为true) @@ -47,31 +48,10 @@ llm模型全部合并 "defaultSystemChatPrompt": "", // 对话默认携带的系统提示词 "defaultConfig":{} // LLM默认配置,可以针对不同模型设置特殊值(比如 GLM4 的 top_p }, - { - "model": "gpt-3.5-turbo-16k", - "name": "gpt-3.5-turbo-16k", - "maxContext": 16000, - "maxResponse": 16000, - "quoteMaxToken": 13000, - "maxTemperature": 1.2, - "charsPointsPrice": 0, - "censor": false, - "vision": false, - "datasetProcess": true, - "usedInClassify": true, - "usedInExtractFields": true, - "usedInToolCall": true, - "usedInQueryExtension": true, - "toolChoice": true, - "functionCall": false, - "customCQPrompt": "", - "customExtractPrompt": "", - "defaultSystemChatPrompt": "", - "defaultConfig":{} - }, { "model": "gpt-4-0125-preview", "name": "gpt-4-turbo", + "avatar": "/imgs/model/openai.svg", "maxContext": 125000, "maxResponse": 4000, "quoteMaxToken": 100000, @@ -94,6 +74,7 @@ llm模型全部合并 { "model": "gpt-4-vision-preview", "name": "gpt-4-vision", + "avatar": "/imgs/model/openai.svg", "maxContext": 128000, "maxResponse": 4000, "quoteMaxToken": 100000, @@ -118,6 +99,7 @@ llm模型全部合并 { "model": "text-embedding-ada-002", "name": "Embedding-2", + "avatar": "/imgs/model/openai.svg", "charsPointsPrice": 0, "defaultToken": 700, "maxToken": 3000, @@ -149,6 +131,20 @@ llm模型全部合并 } ``` +## 关于模型 logo + +统一放置在项目的`public/imgs/model/xxx`目录中,目前内置了以下几种,如果有需要,可以PR增加。 + +- /imgs/model/baichuan.svg - 百川 +- /imgs/model/chatglm.svg - 智谱 +- /imgs/model/calude.svg - calude +- /imgs/model/ernie.svg - 文心一言 +- /imgs/model/moonshot.svg - 月之暗面 +- /imgs/model/openai.svg - OpenAI GPT +- /imgs/model/qwen.svg - 通义千问 +- /imgs/model/yi.svg - 零一万物 +- + ## 特殊模型 ### ReRank 接入 diff --git a/docSite/content/docs/development/faq.md b/docSite/content/docs/development/faq.md index f1c6be3ed67..954900efe67 100644 --- a/docSite/content/docs/development/faq.md +++ b/docSite/content/docs/development/faq.md @@ -1,13 +1,13 @@ --- weight: 749 -title: "常见开发 & 部署问题" -description: "FastGPT 常见开发 & 部署问题" +title: "私有部署常见问题" +description: "FastGPT 私有部署常见问题" icon: upgrade draft: false images: [] --- -## 错误排查方式 +## 一、错误排查方式 遇到问题先按下面方式排查。 @@ -17,7 +17,7 @@ images: [] 4. 无法解决时,可以找找[Issue](https://github.com/labring/FastGPT/issues),或新提 Issue,私有部署错误,务必提供详细的日志,否则很难排查。 -## 通用问题 +## 二、通用问题 ### 能否纯本地运行 @@ -54,7 +54,11 @@ OneAPI 的 API Key 配置错误,需要修改`OPENAI_API_KEY`环境变量,并 1. 问题补全需要经过一轮AI生成。 2. 会进行3~5轮的查询,如果数据库性能不足,会有明显影响。 -## 私有部署问题 +### 模型响应为空 + +1. 检查 key 问题。 +2. 如果是国内模型,可能是命中风控了。 +3. 查看模型请求日志,检查出入参数是否异常。 ### 知识库索引没有进度 @@ -64,11 +68,7 @@ OneAPI 的 API Key 配置错误,需要修改`OPENAI_API_KEY`环境变量,并 2. 不能对话,也不能索引:API调用失败。可能是没连上OneAPI或OpenAI 3. 有进度,但是非常慢:api key不行,OpenAI的免费号,一分钟只有3次还是60次。一天上限200次。 -## Docker 部署常见问题 - -### 首次部署,root用户提示未注册 - -没有启动 Mongo 副本集模式。 +## 三、Docker 部署常见问题 ### 如何更新? @@ -133,14 +133,6 @@ mongo连接失败,检查 2. 环境变量(账号密码,注意host和port) 3. 副本集启动失败,一直在重启:没挂载mongo key;key没有权限; -## 本地开发问题 - -### TypeError: Cannot read properties of null (reading 'useMemo' ) - -删除所有的`node_modules`,用 Node18 重新 install 试试,可能最新的 Node 有问题。 本地开发流程: +### 首次部署,root用户提示未注册 -1. 根目录: `pnpm i` -2. 复制 `config.json` -> `config.local.json` -3. 复制 `.env.template` -> `.env.local` -4. `cd projects/app` -5. `pnpm dev` +没有启动 Mongo 副本集模式。 diff --git a/docSite/content/docs/development/intro.md b/docSite/content/docs/development/intro.md index 1fafe864f4e..635181c8d28 100644 --- a/docSite/content/docs/development/intro.md +++ b/docSite/content/docs/development/intro.md @@ -48,7 +48,7 @@ git clone git@github.com:/FastGPT.git 第一次开发,需要先部署数据库,建议本地开发可以随便找一台 2C2G 的轻量小数据库实践。数据库部署教程:[Docker 快速部署](/docs/development/docker/)。部署完了,可以本地访问其数据库。 -Mongo 数据库需要修改副本集的`host`,从原来的`mongo:27017`修改为`ip:27017`。 +Mongo 数据库需要修改副本集的`host`,从原来的`mongo:27017`修改为`ip:27017`(ip为对应的公网IP)。 ### 4. 初始配置 @@ -113,7 +113,22 @@ docker build -t dockername/fastgpt:tag --build-arg name=app --build-arg proxy=ta FastGPT 在`pnpm i`后会执行`postinstall`脚本,用于自动生成`ChakraUI`的`Type`。如果没有权限,可以先执行`chmod -R +x ./scripts/`,再执行`pnpm i`。 -### 加入社区 +### 长时间运行后崩溃 + +似乎是由于 tiktoken 库的开发环境问题,生产环境中未遇到,暂时可忽略。 + +### TypeError: Cannot read properties of null (reading 'useMemo' ) + +删除所有的`node_modules`,用 Node18 重新 install 试试,可能最新的 Node 有问题。 本地开发流程: + +1. 根目录: `pnpm i` +2. 复制 `config.json` -> `config.local.json` +3. 复制 `.env.template` -> `.env.local` +4. `cd projects/app` +5. `pnpm dev` + + +## 加入社区 遇到困难了吗?有任何问题吗? 加入微信群与开发者和用户保持沟通。 diff --git a/docSite/content/docs/development/one-api.md b/docSite/content/docs/development/one-api.md index 4b1a14218d0..30e15d967b6 100644 --- a/docSite/content/docs/development/one-api.md +++ b/docSite/content/docs/development/one-api.md @@ -112,6 +112,7 @@ CHAT_API_KEY=sk-xxxxxx { "model": "ERNIE-Bot", // 这里的模型需要对应 One API 的模型 "name": "文心一言", // 对外展示的名称 + "avatar": "/imgs/model/openai.svg", // 模型的logo "maxContext": 16000, // 最大上下文 "maxResponse": 4000, // 最大回复 "quoteMaxToken": 13000, // 最大引用内容 @@ -135,4 +136,11 @@ CHAT_API_KEY=sk-xxxxxx ], ``` -添加完后,重启 FastGPT 即可在选择文心一言模型进行对话。**添加向量模型也是类似操作,增加到 `vectorModels`里。** +### 3. 重启 FastGPT + +```bash +docker-compose down +docker-compose up -d +``` + +重启 FastGPT 即可在选择文心一言模型进行对话。**添加向量模型也是类似操作,增加到 `vectorModels`里。** diff --git a/docSite/content/docs/development/upgrading/47.md b/docSite/content/docs/development/upgrading/47.md index 512b669d8e7..034b3514ca8 100644 --- a/docSite/content/docs/development/upgrading/47.md +++ b/docSite/content/docs/development/upgrading/47.md @@ -9,11 +9,18 @@ weight: 826 ## 修改配置文件 -增加一些 Boolean 值,用于决定不同功能块可以使用哪些模型:[点击查看最新的配置文件](/docs/development/configuration/) +增加一些 Boolean 值,用于决定不同功能块可以使用哪些模型,同时增加了模型的 logo:[点击查看最新的配置文件](/docs/development/configuration/) ## V4.7 更新说明 1. 新增 - 工具调用模块,可以让LLM模型根据用户意图,动态的选择其他模型或插件执行。 2. 新增 - 分类和内容提取支持 functionCall 模式。部分模型支持 functionCall 不支持 ToolCall,也可以使用了。需要把 LLM 模型配置文件里的 `functionCall` 设置为 `true`, `toolChoice`设置为 `false`。如果 `toolChoice` 为 true,会走 tool 模式。 -3. 优化 - 高级编排性能 +3. 新增 - HTTP插件,可实现OpenAPI快速生成插件。 +4. 优化 - 高级编排性能。 +5. 优化 - 抽离 Flow controller 到 packages。 +6. 优化 - AI模型选择。 +7. 修复 - 开源版重排选不上。 +8. 修复 - http 请求 body,不使用时,传入undefined。(会造成部分GET请求失败) +9. 新增 - 支持 http url 使用变量。 +10. 修复 - 469 的提取的提示词容易造成幻觉。 diff --git a/packages/service/core/dataset/schema.ts b/packages/service/core/dataset/schema.ts index 52badd16a6a..1c7c55eee2b 100644 --- a/packages/service/core/dataset/schema.ts +++ b/packages/service/core/dataset/schema.ts @@ -67,7 +67,7 @@ const DatasetSchema = new Schema({ agentModel: { type: String, required: true, - default: 'gpt-3.5-turbo-16k' + default: 'gpt-3.5-turbo' }, intro: { type: String, diff --git a/projects/app/data/config.json b/projects/app/data/config.json index e8003eaddfc..a91fdb55c20 100644 --- a/projects/app/data/config.json +++ b/projects/app/data/config.json @@ -10,41 +10,20 @@ "model": "gpt-3.5-turbo", "name": "gpt-3.5-turbo", "maxContext": 16000, + "avatar": "/imgs/model/openai.svg", "maxResponse": 4000, "quoteMaxToken": 13000, "maxTemperature": 1.2, "charsPointsPrice": 0, "censor": false, "vision": false, - "datasetProcess": false, - "usedInClassify": true, - "usedInExtractFields": true, - "usedInToolCall": true, - "usedInQueryExtension": true, - "toolChoice": true, - "functionCall": false, - "customCQPrompt": "", - "customExtractPrompt": "", - "defaultSystemChatPrompt": "", - "defaultConfig": {} - }, - { - "model": "gpt-3.5-turbo-16k", - "name": "gpt-3.5-turbo-16k", - "maxContext": 16000, - "maxResponse": 16000, - "quoteMaxToken": 13000, - "maxTemperature": 1.2, - "charsPointsPrice": 0, - "censor": false, - "vision": false, "datasetProcess": true, "usedInClassify": true, "usedInExtractFields": true, "usedInToolCall": true, "usedInQueryExtension": true, "toolChoice": true, - "functionCall": false, + "functionCall": true, "customCQPrompt": "", "customExtractPrompt": "", "defaultSystemChatPrompt": "", @@ -53,6 +32,7 @@ { "model": "gpt-4-0125-preview", "name": "gpt-4-turbo", + "avatar": "/imgs/model/openai.svg", "maxContext": 125000, "maxResponse": 4000, "quoteMaxToken": 100000, @@ -75,6 +55,7 @@ { "model": "gpt-4-vision-preview", "name": "gpt-4-vision", + "avatar": "/imgs/model/openai.svg", "maxContext": 128000, "maxResponse": 4000, "quoteMaxToken": 100000, @@ -99,6 +80,7 @@ { "model": "text-embedding-ada-002", "name": "Embedding-2", + "avatar": "/imgs/model/openai.svg", "charsPointsPrice": 0, "defaultToken": 700, "maxToken": 3000, diff --git a/projects/app/src/service/mongo.ts b/projects/app/src/service/mongo.ts index 89c79e01b9b..954757d9917 100644 --- a/projects/app/src/service/mongo.ts +++ b/projects/app/src/service/mongo.ts @@ -27,12 +27,11 @@ export function connectToDatabase(): Promise { // init system config getInitConfig(); - // init vector database - await initVectorStore(); + // init vector database, init root user + await Promise.all([initVectorStore(), initRootUser()]); + // start queue startTrainingQueue(true); - - initRootUser(); } }); } From 32244a01b92b57f61d73a2722d34dc69529b3e3b Mon Sep 17 00:00:00 2001 From: archer <545436317@qq.com> Date: Wed, 20 Mar 2024 18:05:54 +0800 Subject: [PATCH 4/7] doc --- docSite/content/docs/development/faq.md | 2 +- docSite/content/docs/use-cases/feishu.md | 4 ++-- docSite/content/docs/use-cases/wechat.md | 2 +- .../global/core/module/template/system/contextExtract.ts | 1 - packages/service/core/workflow/dispatch/agent/extract.ts | 6 +++--- pnpm-lock.yaml | 4 ++-- projects/app/package.json | 4 ++-- projects/app/public/locales/zh/common.json | 5 +++-- projects/app/src/pages/api/core/plugin/create.ts | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docSite/content/docs/development/faq.md b/docSite/content/docs/development/faq.md index 954900efe67..12b22c2ba56 100644 --- a/docSite/content/docs/development/faq.md +++ b/docSite/content/docs/development/faq.md @@ -46,7 +46,7 @@ OneAPI 的 API Key 配置错误,需要修改`OPENAI_API_KEY`环境变量,并 ### 页面崩溃 1. 关闭翻译 -2. 检查配置文件是否正常加载,如果没有正常加载会导致缺失系统信息,在某些操作下会导致空指针。(95%情况,可以F12打开控制台,看具体的空指针情况) +2. 检查配置文件是否正常加载,如果没有正常加载会导致缺失系统信息,在某些操作下会导致空指针。(95%情况是配置文件不对,可以F12打开控制台,看具体的空指针情况) 3. 某些api不兼容问题(较少) ### 开启内容补全后,响应速度变慢 diff --git a/docSite/content/docs/use-cases/feishu.md b/docSite/content/docs/use-cases/feishu.md index dc494d84dca..d98acfeee22 100644 --- a/docSite/content/docs/use-cases/feishu.md +++ b/docSite/content/docs/use-cases/feishu.md @@ -1,6 +1,6 @@ --- -title: " 接入飞书 " -description: "FastGPT 接入飞书机器人 " +title: " 接入飞书(社区文章)" +description: "FastGPT 接入飞书机器人" icon: "chat" draft: false toc: true diff --git a/docSite/content/docs/use-cases/wechat.md b/docSite/content/docs/use-cases/wechat.md index a79c32bd7d8..165421f2e2e 100644 --- a/docSite/content/docs/use-cases/wechat.md +++ b/docSite/content/docs/use-cases/wechat.md @@ -1,5 +1,5 @@ --- -title: " 接入微信和企业微信 " +title: "接入微信和企业微信 " description: "FastGPT 接入微信和企业微信 " icon: "chat" draft: false diff --git a/packages/global/core/module/template/system/contextExtract.ts b/packages/global/core/module/template/system/contextExtract.ts index 9f6455f5476..fa444ad7a56 100644 --- a/packages/global/core/module/template/system/contextExtract.ts +++ b/packages/global/core/module/template/system/contextExtract.ts @@ -39,7 +39,6 @@ export const ContextExtractModule: FlowNodeTemplateType = { label: '提取要求描述', description: '给AI一些对应的背景知识或要求描述,引导AI更好的完成任务。\n该输入框可使用全局变量。', - required: true, placeholder: '例如: \n1. 当前时间为: {{cTime}}。你是一个实验室预约助手,你的任务是帮助用户预约实验室,从文本中获取对应的预约信息。\n2. 你是谷歌搜索助手,需要从文本中提取出合适的搜索词。', showTargetInApp: true, diff --git a/packages/service/core/workflow/dispatch/agent/extract.ts b/packages/service/core/workflow/dispatch/agent/extract.ts index 0e9099d19cf..83685802fc3 100644 --- a/packages/service/core/workflow/dispatch/agent/extract.ts +++ b/packages/service/core/workflow/dispatch/agent/extract.ts @@ -158,8 +158,8 @@ const getFunctionCallSchema = ({ text: { content: `我正在执行一个函数,需要你提供一些参数,请以 JSON 字符串格式返回这些参数,要求: """ -- ${description} -- 不是每个参数都是必须生成的,如果没有合适的参数值,不要生成该参数。 +${description ? `- ${description}` : ''} +- 不是每个参数都是必须生成的,如果没有合适的参数值,不要生成该参数,或返回空字符串。 - 需要结合前面的对话内容,一起生成合适的参数。 """ @@ -222,7 +222,7 @@ const toolChoice = async (props: ActionProps) => { userKey: user.openaiAccount, timeout: 480000 }); - + console.log(JSON.stringify({ messages: filterMessages, tools }, null, 2)); const response = await ai.chat.completions.create({ model: extractModel.model, temperature: 0, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5bb3552fcef..71623b46901 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -330,10 +330,10 @@ importers: specifier: ^1.11.7 version: 1.11.7 echarts: - specifier: ^5.4.1 + specifier: 5.4.1 version: 5.4.1 echarts-gl: - specifier: ^2.0.9 + specifier: 2.0.9 version: 2.0.9(echarts@5.4.1) formidable: specifier: ^2.1.1 diff --git a/projects/app/package.json b/projects/app/package.json index 3653c2fa192..1be8f9f5cf0 100644 --- a/projects/app/package.json +++ b/projects/app/package.json @@ -28,8 +28,8 @@ "axios": "^1.5.1", "date-fns": "2.30.0", "dayjs": "^1.11.7", - "echarts": "^5.4.1", - "echarts-gl": "^2.0.9", + "echarts": "5.4.1", + "echarts-gl": "2.0.9", "formidable": "^2.1.1", "framer-motion": "^9.0.6", "hyperdown": "^2.4.29", diff --git a/projects/app/public/locales/zh/common.json b/projects/app/public/locales/zh/common.json index daf29128aca..9bd3afac196 100644 --- a/projects/app/public/locales/zh/common.json +++ b/projects/app/public/locales/zh/common.json @@ -579,7 +579,8 @@ "success": "开始同步" } }, - "training": {} + "training": { + } }, "data": { "Auxiliary Data": "辅助数据", @@ -1389,7 +1390,7 @@ "Upgrade plan": "升级套餐", "function": { "History store": "{{amount}} 天对话记录保留", - "Max app": "{{amount}} 个应用与插件", + "Max app": "{{amount}} 个应用", "Max dataset": "{{amount}} 个知识库", "Max dataset size": "{{amount}} 组知识库索引", "Max members": "{{amount}} 个团队成员", diff --git a/projects/app/src/pages/api/core/plugin/create.ts b/projects/app/src/pages/api/core/plugin/create.ts index 205500d3235..7b58b789a0a 100644 --- a/projects/app/src/pages/api/core/plugin/create.ts +++ b/projects/app/src/pages/api/core/plugin/create.ts @@ -14,7 +14,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< const { teamId, tmbId } = await authUserNotVisitor({ req, authToken: true }); const body = req.body as CreateOnePluginParams; - await checkTeamPluginLimit(teamId); + // await checkTeamPluginLimit(teamId); // create parent plugin and child plugin if (body.metadata?.apiSchemaStr) { From b4ca8a2d92aae96bb33565f7101b38502605c287 Mon Sep 17 00:00:00 2001 From: archer <545436317@qq.com> Date: Wed, 20 Mar 2024 18:25:09 +0800 Subject: [PATCH 5/7] price tip --- .../web/components/common/Icon/constants.ts | 1 + .../common/Icon/icons/modal/concat.svg | 12 +++++++++++ projects/app/public/imgs/modal/concat.svg | 1 - projects/app/public/locales/en/common.json | 4 ++++ projects/app/public/locales/zh/common.json | 4 ++++ .../src/components/CommunityModal/index.tsx | 7 +------ .../wallet/StandardPlanContentList.tsx | 13 ++++++++++++ .../app/src/pages/account/components/Info.tsx | 21 ++++++++++++++++++- .../app/src/pages/price/components/FAQ.tsx | 2 +- .../app/src/pages/price/components/Points.tsx | 7 +++++-- 10 files changed, 61 insertions(+), 11 deletions(-) create mode 100644 packages/web/components/common/Icon/icons/modal/concat.svg delete mode 100644 projects/app/public/imgs/modal/concat.svg diff --git a/packages/web/components/common/Icon/constants.ts b/packages/web/components/common/Icon/constants.ts index 7ffd51f122d..87732f1b34d 100644 --- a/packages/web/components/common/Icon/constants.ts +++ b/packages/web/components/common/Icon/constants.ts @@ -135,6 +135,7 @@ export const iconPaths = { kbTest: () => import('./icons/kbTest.svg'), menu: () => import('./icons/menu.svg'), minus: () => import('./icons/minus.svg'), + 'modal/concat': () => import('./icons/modal/concat.svg'), 'modal/confirmPay': () => import('./icons/modal/confirmPay.svg'), 'modal/edit': () => import('./icons/modal/edit.svg'), 'modal/manualDataset': () => import('./icons/modal/manualDataset.svg'), diff --git a/packages/web/components/common/Icon/icons/modal/concat.svg b/packages/web/components/common/Icon/icons/modal/concat.svg new file mode 100644 index 00000000000..3023552ada1 --- /dev/null +++ b/packages/web/components/common/Icon/icons/modal/concat.svg @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/projects/app/public/imgs/modal/concat.svg b/projects/app/public/imgs/modal/concat.svg deleted file mode 100644 index f721d5fdbce..00000000000 --- a/projects/app/public/imgs/modal/concat.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/projects/app/public/locales/en/common.json b/projects/app/public/locales/en/common.json index c6a1e031936..df8fcc97218 100644 --- a/projects/app/public/locales/en/common.json +++ b/projects/app/public/locales/en/common.json @@ -1355,6 +1355,10 @@ "noBill": "Not Bills", "subscription": { "AI points": "AI points", + "AI points click to read tip": "Each time an AI model is invoked, a certain amount of AI credits (similar to Tokens) are consumed. Click to view the detailed calculation rules.", + "AI points tip": "", + "AI points usage": "AI point usage", + "AI points usage tip": "Each time the AI model is invoked, a certain amount of AI credits are consumed. Please refer to the \"Charging Standard\" above for specific calculation standards.", "Ai points": "AI Points Standard", "Buy now": "Buy now", "Change will take effect after the current subscription expires": "Change will take effect after the current subscription expires", diff --git a/projects/app/public/locales/zh/common.json b/projects/app/public/locales/zh/common.json index 9bd3afac196..949606f801a 100644 --- a/projects/app/public/locales/zh/common.json +++ b/projects/app/public/locales/zh/common.json @@ -1357,6 +1357,10 @@ "noBill": "无账单记录~", "subscription": { "AI points": "AI积分", + "AI points click to read tip": "每次调用AI模型时,都会消耗一定的AI积分(类似于 Tokens)。点击可查看详细计算规则。", + "AI points tip": "每次调用AI模型时,都会消耗一定的AI积分。具体的计算标准可参考下方的“计费标准”", + "AI points usage": "AI积分使用量", + "AI points usage tip": "每次调用AI模型时,都会消耗一定的AI积分。具体的计算标准可参考上方的“计费标准”", "Ai points": "AI 积分计算标准", "Buy now": "切换套餐", "Change will take effect after the current subscription expires": "更新成功。将会再下个订阅周期生效。", diff --git a/projects/app/src/components/CommunityModal/index.tsx b/projects/app/src/components/CommunityModal/index.tsx index 496277793b3..4195d23294d 100644 --- a/projects/app/src/components/CommunityModal/index.tsx +++ b/projects/app/src/components/CommunityModal/index.tsx @@ -10,12 +10,7 @@ const CommunityModal = ({ onClose }: { onClose: () => void }) => { const { feConfigs } = useSystemStore(); return ( - + diff --git a/projects/app/src/components/support/wallet/StandardPlanContentList.tsx b/projects/app/src/components/support/wallet/StandardPlanContentList.tsx index 6a5eda48769..1614dd9ac33 100644 --- a/projects/app/src/components/support/wallet/StandardPlanContentList.tsx +++ b/projects/app/src/components/support/wallet/StandardPlanContentList.tsx @@ -5,6 +5,10 @@ import { standardSubLevelMap } from '@fastgpt/global/support/wallet/sub/constant import { Box, Flex, Grid } from '@chakra-ui/react'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { useTranslation } from 'next-i18next'; +import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; +import { QuestionOutlineIcon } from '@chakra-ui/icons'; +import { useRouter } from 'next/router'; +import { AI_POINT_USAGE_CARD_ROUTE } from '@/web/support/wallet/sub/constants'; const StandardPlanContentList = ({ level, @@ -15,6 +19,7 @@ const StandardPlanContentList = ({ }) => { const { t } = useTranslation(); const { subPlans } = useSystemStore(); + const router = useRouter(); const planContent = useMemo(() => { const plan = subPlans?.standard?.[level]; @@ -87,6 +92,14 @@ const StandardPlanContentList = ({ amount: planContent.totalPoints })} + + { + router.push(AI_POINT_USAGE_CARD_ROUTE); + }} + /> + diff --git a/projects/app/src/pages/account/components/Info.tsx b/projects/app/src/pages/account/components/Info.tsx index f47b0aeff30..659b9e50d04 100644 --- a/projects/app/src/pages/account/components/Info.tsx +++ b/projects/app/src/pages/account/components/Info.tsx @@ -16,6 +16,7 @@ import { useToast } from '@fastgpt/web/hooks/useToast'; import { useUserStore } from '@/web/support/user/useUserStore'; import type { UserType } from '@fastgpt/global/support/user/type.d'; import { useQuery } from '@tanstack/react-query'; +import { QuestionOutlineIcon } from '@chakra-ui/icons'; import dynamic from 'next/dynamic'; import { useSelectFile } from '@/web/common/file/hooks/useSelectFile'; import { compressImgFileAndUpload } from '@/web/common/file/controller'; @@ -40,11 +41,13 @@ import { } from '@/web/support/wallet/sub/constants'; import StandardPlanContentList from '@/components/support/wallet/StandardPlanContentList'; + const StandDetailModal = dynamic(() => import('./standardDetailModal')); const TeamMenu = dynamic(() => import('@/components/support/user/team/TeamMenu')); const PayModal = dynamic(() => import('./PayModal')); const UpdatePswModal = dynamic(() => import('./UpdatePswModal')); const OpenAIAccountModal = dynamic(() => import('./OpenAIAccountModal')); +const CommunityModal = dynamic(() => import('@/components/CommunityModal')); const Account = () => { const { isPc } = useSystemStore(); @@ -471,7 +474,10 @@ const PlanUsage = () => { - {t('support.wallet.subscription.AI points')} + {t('support.wallet.subscription.AI points usage')} + + + {aiPointsUsageMap.used}/{aiPointsUsageMap.max} @@ -506,6 +512,7 @@ const Other = () => { }); const { isOpen: isOpenOpenai, onClose: onCloseOpenai, onOpen: onOpenOpenai } = useDisclosure(); + const { isOpen: isOpenConcat, onClose: onCloseConcat, onOpen: onOpenConcat } = useDisclosure(); const onclickSave = useCallback( async (data: UserType) => { @@ -596,6 +603,17 @@ const Other = () => { /> )} + {feConfigs?.concatMd && ( + + )} {isOpenOpenai && userInfo && ( @@ -610,6 +628,7 @@ const Other = () => { onClose={onCloseOpenai} /> )} + {isOpenConcat && } ); }; diff --git a/projects/app/src/pages/price/components/FAQ.tsx b/projects/app/src/pages/price/components/FAQ.tsx index fd1c262b4ff..afec6fead76 100644 --- a/projects/app/src/pages/price/components/FAQ.tsx +++ b/projects/app/src/pages/price/components/FAQ.tsx @@ -23,7 +23,7 @@ const FAQ = () => { }, { title: '知识库存储怎么计算?', - desc: '1条知识库存储等于1条知识库索引。一条知识库数据可以包含1条或多条知识库索引。' + desc: '1条知识库存储等于1条知识库索引。一条知识库数据可以包含1条或多条知识库索引。增强训练中,1条数据会生成5条索引。' }, { title: '知识库索引超出会删除么?', diff --git a/projects/app/src/pages/price/components/Points.tsx b/projects/app/src/pages/price/components/Points.tsx index e079da7f0dd..110e5ace7ab 100644 --- a/projects/app/src/pages/price/components/Points.tsx +++ b/projects/app/src/pages/price/components/Points.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Box, Flex, Grid } from '@chakra-ui/react'; +import { Box, Flex, Grid, Link } from '@chakra-ui/react'; import { useTranslation } from 'next-i18next'; import { useSystemStore } from '@/web/common/system/useSystemStore'; @@ -18,7 +18,10 @@ const Points = () => { {t('support.wallet.subscription.Ai points')} - + + 点击查看在线 Tokens 计算器 + + Date: Wed, 20 Mar 2024 18:48:30 +0800 Subject: [PATCH 6/7] perf: tool selector --- .../core/module/Flow/ModuleTemplateList.tsx | 32 ++++++------ .../api/core/plugin/getTeamPluginTemplates.ts | 12 ++++- .../components/SimpleEdit/ToolSelectModal.tsx | 52 +++++++++++-------- .../src/web/core/workflow/store/workflow.ts | 16 +++--- 4 files changed, 64 insertions(+), 48 deletions(-) diff --git a/projects/app/src/components/core/module/Flow/ModuleTemplateList.tsx b/projects/app/src/components/core/module/Flow/ModuleTemplateList.tsx index a7d235d5809..d8ca1549a72 100644 --- a/projects/app/src/components/core/module/Flow/ModuleTemplateList.tsx +++ b/projects/app/src/components/core/module/Flow/ModuleTemplateList.tsx @@ -35,8 +35,8 @@ type ModuleTemplateListProps = { type RenderListProps = { templates: FlowNodeTemplateType[]; onClose: () => void; - currentParent: { parentId: string | null; parentName: string }; - setCurrentParent: (e: { parentId: string | null; parentName: string }) => void; + currentParent?: { parentId: string; parentName: string }; + setCurrentParent: (e: { parentId: string; parentName: string }) => void; }; enum TemplateTypeEnum { @@ -50,10 +50,7 @@ const sliderWidth = 380; const ModuleTemplateList = ({ isOpen, onClose }: ModuleTemplateListProps) => { const { t } = useTranslation(); const router = useRouter(); - const [currentParent, setCurrentParent] = useState<{ - parentId: string | null; - parentName: string; - }>({ parentId: null, parentName: '' }); + const [currentParent, setCurrentParent] = useState(); const [searchKey, setSearchKey] = useState(''); const { @@ -74,7 +71,7 @@ const ModuleTemplateList = ({ isOpen, onClose }: ModuleTemplateListProps) => { ) }; return map[templateType]; - }, [basicNodeTemplates, systemNodeTemplates, teamPluginNodeTemplates, templateType]); + }, [basicNodeTemplates, searchKey, systemNodeTemplates, teamPluginNodeTemplates, templateType]); const { mutate: onChangeTab } = useRequest({ mutationFn: async (e: any) => { @@ -82,15 +79,21 @@ const ModuleTemplateList = ({ isOpen, onClose }: ModuleTemplateListProps) => { if (val === TemplateTypeEnum.systemPlugin) { await loadSystemNodeTemplates(); } else if (val === TemplateTypeEnum.teamPlugin) { - await loadTeamPluginNodeTemplates(currentParent.parentId); + await loadTeamPluginNodeTemplates({ + parentId: currentParent?.parentId + }); } setTemplateType(val); }, errorToast: t('core.module.templates.Load plugin error') }); - useQuery(['teamNodeTemplate', currentParent.parentId, searchKey], () => - loadTeamPluginNodeTemplates(currentParent.parentId, searchKey, true) + useQuery(['teamNodeTemplate', currentParent?.parentId, searchKey], () => + loadTeamPluginNodeTemplates({ + parentId: currentParent?.parentId, + searchKey, + init: true + }) ); return ( @@ -169,7 +172,6 @@ const ModuleTemplateList = ({ isOpen, onClose }: ModuleTemplateListProps) => { bg={'myGray.50'} placeholder={t('plugin.Search plugin')} onChange={debounce((e) => setSearchKey(e.target.value), 200)} - fontSize={'lg'} /> @@ -186,15 +188,13 @@ const ModuleTemplateList = ({ isOpen, onClose }: ModuleTemplateListProps) => { )} - {templateType === TemplateTypeEnum.teamPlugin && !searchKey && ( + {templateType === TemplateTypeEnum.teamPlugin && !searchKey && currentParent && ( { - setCurrentParent({ parentId: null, parentName: '' }); + setCurrentParent(undefined); }} fontSize="md" /> diff --git a/projects/app/src/pages/api/core/plugin/getTeamPluginTemplates.ts b/projects/app/src/pages/api/core/plugin/getTeamPluginTemplates.ts index 9e9be7e93ce..16361ccd59c 100644 --- a/projects/app/src/pages/api/core/plugin/getTeamPluginTemplates.ts +++ b/projects/app/src/pages/api/core/plugin/getTeamPluginTemplates.ts @@ -18,9 +18,17 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< userPlugins = await MongoPlugin.find({ teamId, name: { $regex: searchKey, $options: 'i' } - }).lean(); + }) + .sort({ + updateTime: -1 + }) + .lean(); } else { - userPlugins = await MongoPlugin.find({ teamId, parentId }).lean(); + userPlugins = await MongoPlugin.find({ teamId, parentId }) + .sort({ + updateTime: -1 + }) + .lean(); } const data: FlowNodeTemplateType[] = userPlugins.map((plugin) => ({ diff --git a/projects/app/src/pages/app/detail/components/SimpleEdit/ToolSelectModal.tsx b/projects/app/src/pages/app/detail/components/SimpleEdit/ToolSelectModal.tsx index 65c2447e14f..429bbd4f290 100644 --- a/projects/app/src/pages/app/detail/components/SimpleEdit/ToolSelectModal.tsx +++ b/projects/app/src/pages/app/detail/components/SimpleEdit/ToolSelectModal.tsx @@ -51,9 +51,9 @@ const ToolSelectModal = ({ onClose, ...props }: Props & { onClose: () => void }) const [templateType, setTemplateType] = useState(TemplateTypeEnum.teamPlugin); const [currentParent, setCurrentParent] = useState<{ - parentId: string | null; + parentId: string; parentName: string; - }>({ parentId: null, parentName: '' }); + }>(); const [searchKey, setSearchKey] = useState(''); const templates = useMemo(() => { @@ -66,7 +66,7 @@ const ToolSelectModal = ({ onClose, ...props }: Props & { onClose: () => void }) ) }; return map[templateType]; - }, [systemNodeTemplates, teamPluginNodeTemplates, templateType]); + }, [searchKey, systemNodeTemplates, teamPluginNodeTemplates, templateType]); const { mutate: onChangeTab } = useRequest({ mutationFn: async (e: any) => { @@ -74,15 +74,21 @@ const ToolSelectModal = ({ onClose, ...props }: Props & { onClose: () => void }) if (val === TemplateTypeEnum.systemPlugin) { await loadSystemNodeTemplates(); } else if (val === TemplateTypeEnum.teamPlugin) { - await loadTeamPluginNodeTemplates(currentParent.parentId); + await loadTeamPluginNodeTemplates({ + parentId: currentParent?.parentId + }); } setTemplateType(val); }, errorToast: t('core.module.templates.Load plugin error') }); - const { isLoading } = useQuery(['teamNodeTemplate', currentParent.parentId, searchKey], () => - loadTeamPluginNodeTemplates(currentParent.parentId, searchKey, true) + const { isLoading } = useQuery(['teamNodeTemplate', currentParent?.parentId, searchKey], () => + loadTeamPluginNodeTemplates({ + parentId: currentParent?.parentId, + searchKey, + init: true + }) ); return ( @@ -123,30 +129,27 @@ const ToolSelectModal = ({ onClose, ...props }: Props & { onClose: () => void }) bg={'myGray.50'} placeholder={t('plugin.Search plugin')} onChange={debounce((e) => setSearchKey(e.target.value), 200)} - fontSize={'lg'} /> + {templateType === TemplateTypeEnum.teamPlugin && !searchKey && currentParent && ( + + { + setCurrentParent(undefined); + }} + fontSize="md" + /> + + )} - {templateType === TemplateTypeEnum.teamPlugin && !searchKey && ( - - { - setCurrentParent({ parentId: null, parentName: '' }); - }} - fontSize="md" - /> - - )} @@ -165,7 +168,7 @@ const RenderList = React.memo(function RenderList({ }: Props & { templates: FlowNodeTemplateType[]; isLoadingData: boolean; - setCurrentParent: (e: { parentId: string | null; parentName: string }) => void; + setCurrentParent: (e: { parentId: string; parentName: string }) => void; }) { const { t } = useTranslation(); const { toast } = useToast(); @@ -207,6 +210,9 @@ const RenderList = React.memo(function RenderList({ borderBottomWidth: '1px', borderBottomColor: 'myGray.150' }} + _hover={{ + bg: 'myGray.50' + }} > Promise; teamPluginNodeTemplates: FlowNodeTemplateType[]; - loadTeamPluginNodeTemplates: ( - parentId: string | null, - searchKey?: string, - init?: boolean - ) => Promise; + loadTeamPluginNodeTemplates: (e?: { + parentId?: string | null; + searchKey?: string; + init?: boolean; + }) => Promise; }; export const useWorkflowStore = create()( @@ -39,12 +39,14 @@ export const useWorkflowStore = create()( return templates; }, teamPluginNodeTemplates: [], - async loadTeamPluginNodeTemplates(parentId, searchKey, init) { + async loadTeamPluginNodeTemplates(e) { + const { parentId = null, searchKey, init } = e || {}; + if (!init && get().teamPluginNodeTemplates.length > 0) { return get().teamPluginNodeTemplates; } const templates = await getTeamPlugTemplates({ - parentId: parentId, + parentId: parentId || null, searchKey: searchKey }); set((state) => { From c60ff645830069d46812c72db179836f4a2403a8 Mon Sep 17 00:00:00 2001 From: archer <545436317@qq.com> Date: Wed, 20 Mar 2024 18:49:37 +0800 Subject: [PATCH 7/7] ui' --- .../app/src/components/core/module/Flow/ModuleTemplateList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/app/src/components/core/module/Flow/ModuleTemplateList.tsx b/projects/app/src/components/core/module/Flow/ModuleTemplateList.tsx index d8ca1549a72..540acf2cd35 100644 --- a/projects/app/src/components/core/module/Flow/ModuleTemplateList.tsx +++ b/projects/app/src/components/core/module/Flow/ModuleTemplateList.tsx @@ -125,7 +125,7 @@ const ModuleTemplateList = ({ isOpen, onClose }: ModuleTemplateListProps) => { userSelect={'none'} overflow={isOpen ? 'none' : 'hidden'} > - +