diff --git a/docSite/content/zh-cn/docs/course/fileInput.md b/docSite/content/zh-cn/docs/course/fileInput.md index 609fb65b1..d9e9c91bf 100644 --- a/docSite/content/zh-cn/docs/course/fileInput.md +++ b/docSite/content/zh-cn/docs/course/fileInput.md @@ -114,7 +114,7 @@ ${content} 它接收一个`string`类型的输入,除了可以引用文档解析结果外,还可以实现自定义内容引用,最终会进行提示词拼接,放置在 role=system 的消息中。提示词模板如下: ``` -将 中的内容作为本次对话的参考内容: +将 中的内容作为本次对话的参考: {{quote}} diff --git a/docSite/content/zh-cn/docs/development/openapi/share.md b/docSite/content/zh-cn/docs/development/openapi/share.md index 31ad99685..8bd784e59 100644 --- a/docSite/content/zh-cn/docs/development/openapi/share.md +++ b/docSite/content/zh-cn/docs/development/openapi/share.md @@ -227,7 +227,7 @@ curl --location --request POST '{{host}}/shareAuth/finish' \ "historyPreview": [ { "obj": "Human", - "value": "使用 标记中的内容作为本次对话的参考内容:\n\n\n导演是谁?\n电影《铃芽之旅》的导演是新海诚。\n------\n电影《铃芽之旅》的编剧是谁?22\n新海诚是本片的编剧。\n------\n电影《铃芽之旅》的女主角是谁?\n电影的女主角是铃芽。\n------\n电影《铃芽之旅》的制作团队中有哪位著名人士?2\n川村元气是本片的制作团队成员之一。\n------\n你是谁?\n我是电影《铃芽之旅》助手\n------\n电影《铃芽之旅》男主角是谁?\n电影《铃芽之旅》男主角是宗像草太,由松村北斗配音。\n------\n电影《铃芽之旅》的作者新海诚写了一本小说,叫什么名字?\n小说名字叫《铃芽之旅》。\n------\n电影《铃芽之旅》的女主角是谁?\n电影《铃芽之旅》的女主角是岩户铃芽,由原菜乃华配音。\n------\n电影《铃芽之旅》的故事背景是什么?\n日本\n------\n谁担任电影《铃芽之旅》中岩户环的配音?\n深津绘里担任电影《铃芽之旅》中岩户环的配音。\n\n\n回答要求:\n- 如果你不清楚答案,你需要澄清。\n- 避免提及你是从 获取的知识。\n- 保持答案与 中描述的一致。\n- 使用 Markdown 语法优化回答格式。\n- 使用与问题相同的语言回答。\n\n问题:\"\"\"导演是谁\"\"\"" + "value": "使用 标记中的内容作为本次对话的参考:\n\n\n导演是谁?\n电影《铃芽之旅》的导演是新海诚。\n------\n电影《铃芽之旅》的编剧是谁?22\n新海诚是本片的编剧。\n------\n电影《铃芽之旅》的女主角是谁?\n电影的女主角是铃芽。\n------\n电影《铃芽之旅》的制作团队中有哪位著名人士?2\n川村元气是本片的制作团队成员之一。\n------\n你是谁?\n我是电影《铃芽之旅》助手\n------\n电影《铃芽之旅》男主角是谁?\n电影《铃芽之旅》男主角是宗像草太,由松村北斗配音。\n------\n电影《铃芽之旅》的作者新海诚写了一本小说,叫什么名字?\n小说名字叫《铃芽之旅》。\n------\n电影《铃芽之旅》的女主角是谁?\n电影《铃芽之旅》的女主角是岩户铃芽,由原菜乃华配音。\n------\n电影《铃芽之旅》的故事背景是什么?\n日本\n------\n谁担任电影《铃芽之旅》中岩户环的配音?\n深津绘里担任电影《铃芽之旅》中岩户环的配音。\n\n\n回答要求:\n- 如果你不清楚答案,你需要澄清。\n- 避免提及你是从 获取的知识。\n- 保持答案与 中描述的一致。\n- 使用 Markdown 语法优化回答格式。\n- 使用与问题相同的语言回答。\n\n问题:\"\"\"导演是谁\"\"\"" }, { "obj": "AI", diff --git a/docSite/content/zh-cn/docs/workflow/examples/google_search.md b/docSite/content/zh-cn/docs/workflow/examples/google_search.md index d74c8f84f..9f01f4fd4 100644 --- a/docSite/content/zh-cn/docs/workflow/examples/google_search.md +++ b/docSite/content/zh-cn/docs/workflow/examples/google_search.md @@ -965,7 +965,7 @@ export default async function (ctx: FunctionContext) { "required": true, "description": "", "canEdit": false, - "value": "请使用下面 中的数据作为本次对话的参考内容。请直接输出答案,不要提及你是从 中获取的知识。\n\n当前时间:{{cTime}}\n\n\n{{response}}\n\n\n我的问题:\"{{q}}\"", + "value": "请使用下面 中的数据作为本次对话的参考。请直接输出答案,不要提及你是从 中获取的知识。\n\n当前时间:{{cTime}}\n\n\n{{response}}\n\n\n我的问题:\"{{q}}\"", "editField": { "key": true }, diff --git a/packages/global/core/ai/prompt/AIChat.ts b/packages/global/core/ai/prompt/AIChat.ts index 6a9d7b075..b0c47cfe9 100644 --- a/packages/global/core/ai/prompt/AIChat.ts +++ b/packages/global/core/ai/prompt/AIChat.ts @@ -48,7 +48,7 @@ export const Prompt_userQuotePromptList: PromptTemplateItem[] = [ { title: i18nT('app:template.standard_template'), desc: '', - value: `使用 标记中的内容作为本次对话的参考内容: + value: `使用 标记中的内容作为本次对话的参考: {{quote}} @@ -83,7 +83,7 @@ export const Prompt_userQuotePromptList: PromptTemplateItem[] = [ { title: i18nT('app:template.standard_strict'), desc: '', - value: `忘记你已有的知识,仅使用 标记中的内容作为本次对话的参考内容: + value: `忘记你已有的知识,仅使用 标记中的内容作为本次对话的参考: {{quote}} @@ -133,7 +133,7 @@ export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [ { title: i18nT('app:template.standard_template'), desc: '', - value: `使用 标记中的内容作为本次对话的参考内容: + value: `使用 标记中的内容作为本次对话的参考: {{quote}} @@ -164,7 +164,7 @@ export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [ { title: i18nT('app:template.standard_strict'), desc: '', - value: `忘记你已有的知识,仅使用 标记中的内容作为本次对话的参考内容: + value: `忘记你已有的知识,仅使用 标记中的内容作为本次对话的参考: {{quote}} @@ -207,7 +207,7 @@ export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [ ]; // Document quote prompt -export const Prompt_DocumentQuote = `将 中的内容作为本次对话的参考内容: +export const Prompt_DocumentQuote = `将 中的内容作为本次对话的参考: {{quote}} diff --git a/packages/service/core/chat/utils.ts b/packages/service/core/chat/utils.ts index 1212f3ec7..e6492bcb0 100644 --- a/packages/service/core/chat/utils.ts +++ b/packages/service/core/chat/utils.ts @@ -8,6 +8,8 @@ import axios from 'axios'; import { ChatCompletionRequestMessageRoleEnum } from '@fastgpt/global/core/ai/constants'; import { getFileContentTypeFromHeader, guessBase64ImageType } from '../../common/file/utils'; import { serverRequestBaseUrl } from '../../common/api/serverRequest'; +import { i18nT } from '../../../web/i18n/utils'; +import { addLog } from '../../common/system/log'; /* slice chat context by tokens */ const filterEmptyMessages = (messages: ChatCompletionMessageParam[]) => { @@ -111,20 +113,62 @@ export const loadRequestMessages = async ({ useVision?: boolean; origin?: string; }) => { + // Load image to base64 + const loadImageToBase64 = async (messages: ChatCompletionContentPart[]) => { + return Promise.all( + messages.map(async (item) => { + if (item.type === 'image_url') { + // Remove url origin + const imgUrl = (() => { + if (origin && item.image_url.url.startsWith(origin)) { + return item.image_url.url.replace(origin, ''); + } + return item.image_url.url; + })(); + + // If imgUrl is a local path, load image from local, and set url to base64 + if (imgUrl.startsWith('/') || process.env.VISION_FOCUS_BASE64 === 'true') { + addLog.debug('Load image from local server', { + baseUrl: serverRequestBaseUrl, + requestUrl: imgUrl + }); + const response = await axios.get(imgUrl, { + baseURL: serverRequestBaseUrl, + responseType: 'arraybuffer', + proxy: false + }); + const base64 = Buffer.from(response.data, 'binary').toString('base64'); + const imageType = + getFileContentTypeFromHeader(response.headers['content-type']) || + guessBase64ImageType(base64); + + return { + ...item, + image_url: { + ...item.image_url, + url: `data:${imageType};base64,${base64}` + } + }; + } + } + return item; + }) + ); + }; // Split question text and image - function parseStringWithImages(input: string): ChatCompletionContentPart[] { + const parseStringWithImages = (input: string): ChatCompletionContentPart[] => { if (!useVision) { return [{ type: 'text', text: input || '' }]; } // 正则表达式匹配图片URL const imageRegex = - /(https?:\/\/[^\s/$.?#].[^\s]*\.(?:png|jpe?g|gif|webp|bmp|tiff?|svg|ico|heic|avif))/i; + /(https?:\/\/[^\s/$.?#].[^\s]*\.(?:png|jpe?g|gif|webp|bmp|tiff?|svg|ico|heic|avif))/gi; const result: ChatCompletionContentPart[] = []; // 提取所有HTTPS图片URL并添加到result开头 - const httpsImages = input.match(imageRegex) || []; + const httpsImages = [...new Set(Array.from(input.matchAll(imageRegex), (m) => m[0]))]; httpsImages.forEach((url) => { result.push({ type: 'image_url', @@ -137,54 +181,27 @@ export const loadRequestMessages = async ({ // 添加原始input作为文本 result.push({ type: 'text', text: input }); return result; - } - // Load image + }; + // Parse user content(text and img) const parseUserContent = async (content: string | ChatCompletionContentPart[]) => { if (typeof content === 'string') { - return parseStringWithImages(content); + return loadImageToBase64(parseStringWithImages(content)); } const result = await Promise.all( content.map(async (item) => { if (item.type === 'text') return parseStringWithImages(item.text); - if (item.type === 'file_url') return; + if (item.type === 'file_url') return; // LLM not support file_url if (!item.image_url.url) return item; - // Remove url origin - const imgUrl = (() => { - if (origin && item.image_url.url.startsWith(origin)) { - return item.image_url.url.replace(origin, ''); - } - return item.image_url.url; - })(); - - /* Load local image */ - if (imgUrl.startsWith('/')) { - const response = await axios.get(imgUrl, { - baseURL: serverRequestBaseUrl, - responseType: 'arraybuffer' - }); - const base64 = Buffer.from(response.data, 'binary').toString('base64'); - const imageType = - getFileContentTypeFromHeader(response.headers['content-type']) || - guessBase64ImageType(base64); - - return { - ...item, - image_url: { - ...item.image_url, - url: `data:${imageType};base64,${base64}` - } - }; - } - return item; }) ); - return result.flat().filter(Boolean); + return loadImageToBase64(result.flat().filter(Boolean) as ChatCompletionContentPart[]); }; + // format GPT messages, concat text messages const clearInvalidMessages = (messages: ChatCompletionMessageParam[]) => { return messages @@ -247,7 +264,7 @@ export const loadRequestMessages = async ({ }; if (messages.length === 0) { - return Promise.reject('core.chat.error.Messages empty'); + return Promise.reject(i18nT('common:core.chat.error.Messages empty')); } // filter messages file @@ -275,6 +292,7 @@ export const loadRequestMessages = async ({ content: await parseUserContent(item.content) }; } else if (item.role === ChatCompletionRequestMessageRoleEnum.Assistant) { + // remove invalid field return { role: item.role, content: item.content, diff --git a/packages/web/i18n/en/chat.json b/packages/web/i18n/en/chat.json index 9e902ff5b..1c3ddf848 100644 --- a/packages/web/i18n/en/chat.json +++ b/packages/web/i18n/en/chat.json @@ -19,6 +19,7 @@ "input_guide": "Input Guide", "input_guide_lexicon": "Lexicon", "input_guide_tip": "You can set up some preset questions. When the user inputs a question, related questions from these presets will be suggested.", + "input_placeholder_phone": "Please enter your question", "insert_input_guide,_some_data_already_exists": "Duplicate data detected, automatically filtered, {{len}} items inserted", "is_chatting": "Chatting in progress... please wait until it finishes", "items": "Items", @@ -36,4 +37,4 @@ "stream_output": "Stream Output", "view_citations": "View References", "web_site_sync": "Web Site Sync" -} \ No newline at end of file +} diff --git a/packages/web/i18n/zh/chat.json b/packages/web/i18n/zh/chat.json index 84a7a96f6..add428052 100644 --- a/packages/web/i18n/zh/chat.json +++ b/packages/web/i18n/zh/chat.json @@ -19,6 +19,7 @@ "input_guide": "输入引导", "input_guide_lexicon": "词库", "input_guide_tip": "可以配置一些预设的问题。在用户输入问题时,会从这些预设问题中获取相关问题进行提示。", + "input_placeholder_phone": "输入问题", "insert_input_guide,_some_data_already_exists": "有重复数据,已自动过滤,共插入 {{len}} 条数据", "is_chatting": "正在聊天中...请等待结束", "items": "条", @@ -36,4 +37,4 @@ "stream_output": "流输出", "view_citations": "查看引用", "web_site_sync": "Web站点同步" -} \ No newline at end of file +} diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/Input/ChatInput.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/Input/ChatInput.tsx index 00a859b59..be7053cfc 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/Input/ChatInput.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/Input/ChatInput.tsx @@ -449,7 +449,11 @@ const ChatInput = ({ border: 'none' }} placeholder={ - isSpeaking ? t('common:core.chat.Speaking') : t('common:core.chat.Type a message') + isSpeaking + ? t('common:core.chat.Speaking') + : isPc + ? t('common:core.chat.Type a message') + : t('chat:input_placeholder_phone') } resize={'none'} rows={1} diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ChatItem.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ChatItem.tsx index e245a6eec..be1af1b85 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ChatItem.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ChatItem.tsx @@ -174,7 +174,7 @@ const ChatItem = (props: Props) => { // Check last group is interactive, Auto add a empty text node(animation) const lastGroup = groupedValues[groupedValues.length - 1]; - if (isChatting) { + if (isChatting || groupedValues.length === 0) { if ( (lastGroup && lastGroup[lastGroup.length - 1] && diff --git a/projects/app/src/pages/api/core/dataset/update.ts b/projects/app/src/pages/api/core/dataset/update.ts index c548c8b47..bcc197d0b 100644 --- a/projects/app/src/pages/api/core/dataset/update.ts +++ b/projects/app/src/pages/api/core/dataset/update.ts @@ -72,7 +72,7 @@ async function handler( ...(websiteConfig && { websiteConfig }), ...(status && { status }), ...(intro !== undefined && { intro }), - ...(externalReadUrl && { externalReadUrl }), + ...(externalReadUrl !== undefined && { externalReadUrl }), // move ...(updatedDefaultPermission !== undefined && { defaultPermission: updatedDefaultPermission diff --git a/projects/app/src/pages/api/v1/chat/completions.ts b/projects/app/src/pages/api/v1/chat/completions.ts index 1a0550d59..6688781fa 100644 --- a/projects/app/src/pages/api/v1/chat/completions.ts +++ b/projects/app/src/pages/api/v1/chat/completions.ts @@ -266,7 +266,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { workflowStreamResponse: workflowResponseWrite }); } - return Promise.reject('请升级工作流'); + return Promise.reject('您的工作流版本过低,请重新发布一次'); })(); // save chat diff --git a/projects/app/src/pages/app/detail/components/Plugin/Header.tsx b/projects/app/src/pages/app/detail/components/Plugin/Header.tsx index 816b4df04..2247d42a3 100644 --- a/projects/app/src/pages/app/detail/components/Plugin/Header.tsx +++ b/projects/app/src/pages/app/detail/components/Plugin/Header.tsx @@ -67,7 +67,7 @@ const Header = () => { future, setPast } = useContextSelector(WorkflowContext, (v) => v); - const { appType } = useSystemStore(); + const { lastAppListRouteType } = useSystemStore(); const [isPublished, setIsPublished] = useState(false); useDebounceEffect( @@ -138,11 +138,11 @@ const Header = () => { pathname: '/app/list', query: { parentId: appDetail.parentId, - type: appType + type: lastAppListRouteType } }); } catch (error) {} - }, [appDetail._id, appDetail.parentId, router]); + }, [appDetail._id, appDetail.parentId, lastAppListRouteType, router]); const Render = useMemo(() => { return ( diff --git a/projects/app/src/pages/app/detail/components/SimpleApp/Header.tsx b/projects/app/src/pages/app/detail/components/SimpleApp/Header.tsx index 17f893262..312322ca5 100644 --- a/projects/app/src/pages/app/detail/components/SimpleApp/Header.tsx +++ b/projects/app/src/pages/app/detail/components/SimpleApp/Header.tsx @@ -37,7 +37,7 @@ const Header = ({ const router = useRouter(); const { toast } = useToast(); const { appId, appDetail, onSaveApp, currentTab } = useContextSelector(AppContext, (v) => v); - const { appType } = useSystemStore(); + const { lastAppListRouteType } = useSystemStore(); const { data: paths = [] } = useRequest2(() => getAppFolderPath(appId), { manual: false, @@ -49,11 +49,11 @@ const Header = ({ pathname: '/app/list', query: { parentId, - type: appType + type: lastAppListRouteType } }); }, - [router, appType] + [router, lastAppListRouteType] ); const isPublished = useMemo(() => { diff --git a/projects/app/src/pages/app/detail/components/Workflow/Header.tsx b/projects/app/src/pages/app/detail/components/Workflow/Header.tsx index fc6d2cf2b..9019f70b3 100644 --- a/projects/app/src/pages/app/detail/components/Workflow/Header.tsx +++ b/projects/app/src/pages/app/detail/components/Workflow/Header.tsx @@ -67,7 +67,8 @@ const Header = () => { future, setPast } = useContextSelector(WorkflowContext, (v) => v); - const { appType } = useSystemStore(); + + const { lastAppListRouteType } = useSystemStore(); // Check if the workflow is published const [isPublished, setIsPublished] = useState(false); @@ -139,11 +140,11 @@ const Header = () => { pathname: '/app/list', query: { parentId: appDetail.parentId, - type: appType + type: lastAppListRouteType } }); } catch (error) {} - }, [appDetail._id, appDetail.parentId, router]); + }, [appDetail._id, appDetail.parentId, lastAppListRouteType, router]); const Render = useMemo(() => { return ( diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeVariableUpdate.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeVariableUpdate.tsx index f99f08d78..af889da30 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeVariableUpdate.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeVariableUpdate.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import NodeCard from './render/NodeCard'; import { NodeProps } from 'reactflow'; import { FlowNodeItemType } from '@fastgpt/global/core/workflow/type/node'; @@ -12,7 +12,8 @@ import { NumberInput, NumberInputField, NumberInputStepper, - Switch + Switch, + Textarea } from '@chakra-ui/react'; import { TUpdateListItem } from '@fastgpt/global/core/workflow/template/system/variableUpdate/type'; import { NodeInputKeyEnum, WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants'; @@ -33,7 +34,7 @@ import { getRefData } from '@/web/core/workflow/utils'; import { isReferenceValue } from '@fastgpt/global/core/workflow/utils'; import { AppContext } from '@/pages/app/detail/components/context'; import PromptEditor from '@fastgpt/web/components/common/Textarea/PromptEditor'; -import { useCreation } from 'ahooks'; +import { useCreation, useMemoizedFn } from 'ahooks'; import { getEditorVariables } from '../../utils'; const NodeVariableUpdate = ({ data, selected }: NodeProps) => { @@ -45,6 +46,19 @@ const NodeVariableUpdate = ({ data, selected }: NodeProps) => const appDetail = useContextSelector(AppContext, (v) => v.appDetail); const edges = useContextSelector(WorkflowContext, (v) => v.edges); + const menuList = useRef([ + { + renderType: FlowNodeInputTypeEnum.input, + icon: FlowNodeInputMap[FlowNodeInputTypeEnum.input].icon, + label: t('common:core.workflow.inputType.Manual input') + }, + { + renderType: FlowNodeInputTypeEnum.reference, + icon: FlowNodeInputMap[FlowNodeInputTypeEnum.reference].icon, + label: t('common:core.workflow.inputType.Reference') + } + ]); + const variables = useCreation(() => { return getEditorVariables({ nodeId, @@ -80,195 +94,182 @@ const NodeVariableUpdate = ({ data, selected }: NodeProps) => [inputs, nodeId, onChangeNode] ); - const Render = useMemo(() => { - const menuList = [ - { - renderType: FlowNodeInputTypeEnum.input, - icon: FlowNodeInputMap[FlowNodeInputTypeEnum.input].icon, - label: t('common:core.workflow.inputType.Manual input') - }, - { - renderType: FlowNodeInputTypeEnum.reference, - icon: FlowNodeInputMap[FlowNodeInputTypeEnum.reference].icon, - label: t('common:core.workflow.inputType.Reference') - } - ]; + const ValueRender = useMemoizedFn( + ({ updateItem, index }: { updateItem: TUpdateListItem; index: number }) => { + const { valueType } = getRefData({ + variable: updateItem.variable, + nodeList, + chatConfig: appDetail.chatConfig + }); + const renderTypeData = menuList.current.find( + (item) => item.renderType === updateItem.renderType + ); - return ( - <> - {updateList.map((updateItem, index) => { - const { valueType } = getRefData({ - variable: updateItem.variable, - nodeList, - chatConfig: appDetail.chatConfig - }); - const renderTypeData = menuList.find((item) => item.renderType === updateItem.renderType); - const handleUpdate = (newValue: ReferenceValueProps | string) => { - if (isReferenceValue(newValue)) { - onUpdateList( - updateList.map((update, i) => - i === index ? { ...update, value: newValue as ReferenceValueProps } : update - ) - ); - } else { - onUpdateList( - updateList.map((update, i) => - i === index ? { ...update, value: ['', newValue as string] } : update - ) - ); - } - }; + const handleUpdate = (newValue: ReferenceValueProps | string) => { + if (isReferenceValue(newValue)) { + onUpdateList( + updateList.map((update, i) => + i === index ? { ...update, value: newValue as ReferenceValueProps } : update + ) + ); + } else { + onUpdateList( + updateList.map((update, i) => + i === index ? { ...update, value: ['', newValue as string] } : update + ) + ); + } + }; - return ( - - - {t('common:core.workflow.variable')} - { + return ( + + + {t('common:core.workflow.variable')} + { + onUpdateList( + updateList.map((update, i) => { + if (i === index) { + return { + ...update, + value: ['', ''], + valueType, + variable: value + }; + } + return update; + }) + ); + }} + /> + + {updateList.length > 1 && ( + { + onUpdateList(updateList.filter((_, i) => i !== index)); + }} + /> + )} + + + + {t('common:core.workflow.value')} + item.renderType === updateItem.renderType)?.label + } + > + + + + + {/* Render input components */} + {(() => { + if (updateItem.renderType === FlowNodeInputTypeEnum.reference) { + return ( + - )} - - - - {t('common:core.workflow.value')} - item.renderType === updateItem.renderType)?.label - } - > - - - - - {/* Render input components */} - {(() => { - if (updateItem.renderType === FlowNodeInputTypeEnum.reference) { - return ( - - ); - } - if (valueType === WorkflowIOValueTypeEnum.string) { - return ( - - - - ); - } - if (valueType === WorkflowIOValueTypeEnum.number) { - return ( - - handleUpdate(e.target.value)} - /> - - - - - - ); - } - if (valueType === WorkflowIOValueTypeEnum.boolean) { - return ( - handleUpdate(String(e.target.checked))} - /> - ); - } - - return ( - { - handleUpdate(e); - }} + ); + } + if (valueType === WorkflowIOValueTypeEnum.string) { + return ( + + - ); - })()} - - - ); - })} - - ); - }, [appDetail.chatConfig, nodeId, nodeList, onUpdateList, t, updateList, variables]); + + ); + } + if (valueType === WorkflowIOValueTypeEnum.number) { + return ( + + handleUpdate(e.target.value)} /> + + + + + + ); + } + if (valueType === WorkflowIOValueTypeEnum.boolean) { + return ( + handleUpdate(String(e.target.checked))} + /> + ); + } + + return ( + + + + ); + })()} + + + ); + } + ); return ( - {Render} + <> + {updateList.map((updateItem, index) => ( + + ))} +