diff --git a/docSite/content/docs/development/upgrading/464.md b/docSite/content/docs/development/upgrading/464.md index e3bd47568..404e5c458 100644 --- a/docSite/content/docs/development/upgrading/464.md +++ b/docSite/content/docs/development/upgrading/464.md @@ -28,14 +28,16 @@ curl --location --request POST 'https://{{host}}/api/admin/initv464' \ 1. 重写 - 分享链接身份逻辑,采用 localID 记录用户的ID。 2. 商业版新增 - 分享链接 SSO 方案,通过`身份鉴权`地址,仅需`3个接口`即可完全接入已有用户系统。具体参考[分享链接身份鉴权](/docs/development/openapi/share/) -3. 调整 - 知识库搜索模块 topk 逻辑,采用 MaxToken 计算,兼容不同长度的文本块 -4. 调整鉴权顺序,提高 apikey 的优先级,避免cookie抢占 apikey 的鉴权。 -5. 链接读取支持多选择器。参考[Web 站点同步用法](/docs/course/webSync) -6. 修复 - 分享链接图片上传鉴权问题 -7. 修复 - Mongo 连接池未释放问题。 -8. 修复 - Dataset Intro 无法更新 -9. 修复 - md 代码块问题 -10. 修复 - root 权限问题 -11. 优化 docker file +3. 新增 - 分享链接更多嵌入方式提示,更多DIY方式。 +4. 优化 - 历史记录模块。弃用旧的历史记录模块,直接在对应地方填写数值即可。 +5. 调整 - 知识库搜索模块 topk 逻辑,采用 MaxToken 计算,兼容不同长度的文本块 +6. 调整鉴权顺序,提高 apikey 的优先级,避免cookie抢占 apikey 的鉴权。 +7. 链接读取支持多选择器。参考[Web 站点同步用法](/docs/course/webSync) +8. 修复 - 分享链接图片上传鉴权问题 +9. 修复 - Mongo 连接池未释放问题。 +10. 修复 - Dataset Intro 无法更新 +11. 修复 - md 代码块问题 +12. 修复 - root 权限问题 +13. 优化 docker file diff --git a/packages/global/core/chat/api.d.ts b/packages/global/core/chat/api.d.ts index fcbcd7e4d..453303f43 100644 --- a/packages/global/core/chat/api.d.ts +++ b/packages/global/core/chat/api.d.ts @@ -1,4 +1,5 @@ export type UpdateChatFeedbackProps = { + appId: string; chatId: string; chatItemId: string; shareId?: string; diff --git a/packages/global/core/module/node/constant.ts b/packages/global/core/module/node/constant.ts index ea2c0c8c1..4459486bc 100644 --- a/packages/global/core/module/node/constant.ts +++ b/packages/global/core/module/node/constant.ts @@ -12,8 +12,11 @@ export enum FlowNodeInputTypeEnum { selectApp = 'selectApp', // chat special input aiSettings = 'aiSettings', - // maxToken = 'maxToken', + + // model select selectChatModel = 'selectChatModel', + selectCQModel = 'selectCQModel', + // dataset special input selectDataset = 'selectDataset', selectDatasetParamsModal = 'selectDatasetParamsModal', diff --git a/packages/global/core/module/template/input.ts b/packages/global/core/module/template/input.ts index 37f6a8b34..7c28962e3 100644 --- a/packages/global/core/module/template/input.ts +++ b/packages/global/core/module/template/input.ts @@ -14,9 +14,13 @@ export const Input_Template_TFSwitch: FlowNodeInputItemType = { export const Input_Template_History: FlowNodeInputItemType = { key: ModuleInputKeyEnum.history, - type: FlowNodeInputTypeEnum.target, + type: FlowNodeInputTypeEnum.numberInput, label: 'core.module.input.label.chat history', + required: true, + min: 0, + max: 30, valueType: ModuleDataTypeEnum.chatHistory, + value: 6, showTargetInApp: true, showTargetInPlugin: true }; diff --git a/packages/global/core/module/template/system/aiChat.ts b/packages/global/core/module/template/system/aiChat.ts index 4867287af..aba990f0b 100644 --- a/packages/global/core/module/template/system/aiChat.ts +++ b/packages/global/core/module/template/system/aiChat.ts @@ -87,7 +87,6 @@ export const AiChatModule: FlowModuleTemplateType = { type: FlowNodeInputTypeEnum.hidden, label: '引用内容模板', valueType: ModuleDataTypeEnum.string, - value: '', showTargetInApp: false, showTargetInPlugin: false }, @@ -96,7 +95,6 @@ export const AiChatModule: FlowModuleTemplateType = { type: FlowNodeInputTypeEnum.hidden, label: '引用内容提示词', valueType: ModuleDataTypeEnum.string, - value: '', showTargetInApp: false, showTargetInPlugin: false }, @@ -104,7 +102,6 @@ export const AiChatModule: FlowModuleTemplateType = { key: ModuleInputKeyEnum.aiChatSettingModal, type: FlowNodeInputTypeEnum.aiSettings, label: '', - connected: false, valueType: ModuleDataTypeEnum.any, showTargetInApp: false, showTargetInPlugin: false @@ -118,21 +115,19 @@ export const AiChatModule: FlowModuleTemplateType = { valueType: ModuleDataTypeEnum.string, description: chatNodeSystemPromptTip, placeholder: chatNodeSystemPromptTip, - value: '', showTargetInApp: true, showTargetInPlugin: true }, + Input_Template_History, { key: ModuleInputKeyEnum.aiChatDatasetQuote, type: FlowNodeInputTypeEnum.target, label: '引用内容', description: "对象数组格式,结构:\n [{q:'问题',a:'回答'}]", valueType: ModuleDataTypeEnum.datasetQuote, - connected: false, showTargetInApp: true, showTargetInPlugin: true }, - Input_Template_History, Input_Template_UserChatInput ], outputs: [ diff --git a/packages/global/core/module/template/system/assignedAnswer.ts b/packages/global/core/module/template/system/assignedAnswer.ts index 23c0e39cf..bb35a47a1 100644 --- a/packages/global/core/module/template/system/assignedAnswer.ts +++ b/packages/global/core/module/template/system/assignedAnswer.ts @@ -17,7 +17,6 @@ export const AssignedAnswerModule: FlowModuleTemplateType = { key: ModuleInputKeyEnum.answerText, type: FlowNodeInputTypeEnum.textarea, valueType: ModuleDataTypeEnum.any, - value: '', label: '回复的内容', description: '可以使用 \\n 来实现连续换行。\n\n可以通过外部模块输入实现回复,外部模块输入时会覆盖当前填写的内容。\n\n如传入非字符串类型数据将会自动转成字符串', diff --git a/packages/global/core/module/template/system/classifyQuestion.ts b/packages/global/core/module/template/system/classifyQuestion.ts index c86cad937..75ac31885 100644 --- a/packages/global/core/module/template/system/classifyQuestion.ts +++ b/packages/global/core/module/template/system/classifyQuestion.ts @@ -27,7 +27,7 @@ export const ClassifyQuestionModule: FlowModuleTemplateType = { Input_Template_TFSwitch, { key: ModuleInputKeyEnum.aiModel, - type: FlowNodeInputTypeEnum.selectChatModel, + type: FlowNodeInputTypeEnum.selectCQModel, valueType: ModuleDataTypeEnum.string, label: '分类模型', required: true, @@ -38,7 +38,6 @@ export const ClassifyQuestionModule: FlowModuleTemplateType = { key: ModuleInputKeyEnum.aiSystemPrompt, type: FlowNodeInputTypeEnum.textarea, valueType: ModuleDataTypeEnum.string, - value: '', label: '背景知识', description: '你可以添加一些特定内容的介绍,从而更好的识别用户的问题类型。这个内容通常是给模型介绍一个它不知道的内容。', @@ -57,15 +56,15 @@ export const ClassifyQuestionModule: FlowModuleTemplateType = { value: [ { value: '打招呼', - key: 'fasw' + key: 'wqre' }, { value: '关于 xxx 的问题', - key: 'fqsw' + key: 'sdfa' }, { value: '其他问题', - key: 'fesw' + key: 'agex' } ], showTargetInApp: false, @@ -75,19 +74,19 @@ export const ClassifyQuestionModule: FlowModuleTemplateType = { outputs: [ // custom output { - key: 'fasw', + key: 'wqre', label: '', type: FlowNodeOutputTypeEnum.hidden, targets: [] }, { - key: 'fqsw', + key: 'sdfa', label: '', type: FlowNodeOutputTypeEnum.hidden, targets: [] }, { - key: 'fesw', + key: 'agex', label: '', type: FlowNodeOutputTypeEnum.hidden, targets: [] diff --git a/packages/global/core/module/template/system/contextExtract.ts b/packages/global/core/module/template/system/contextExtract.ts index 24e7b4e50..25d8982a0 100644 --- a/packages/global/core/module/template/system/contextExtract.ts +++ b/packages/global/core/module/template/system/contextExtract.ts @@ -26,12 +26,11 @@ export const ContextExtractModule: FlowModuleTemplateType = { key: ModuleInputKeyEnum.description, type: FlowNodeInputTypeEnum.textarea, valueType: ModuleDataTypeEnum.string, - value: '', label: '提取要求描述', - description: '写一段提取要求,告诉 AI 需要提取哪些内容', + description: '给AI一些对应的背景知识或要求描述,引导AI更好的完成任务', required: true, placeholder: - '例如: \n1. 你是一个实验室预约助手。根据用户问题,提取出姓名、实验室号和预约时间', + '例如: \n1. 你是一个实验室预约助手,你的任务是帮助用户预约实验室。\n2. 你是谷歌搜索助手,需要从文本中提取出合适的搜索词。', showTargetInApp: true, showTargetInPlugin: true }, diff --git a/packages/global/core/module/template/system/datasetSearch.ts b/packages/global/core/module/template/system/datasetSearch.ts index b72b33093..08825ddde 100644 --- a/packages/global/core/module/template/system/datasetSearch.ts +++ b/packages/global/core/module/template/system/datasetSearch.ts @@ -74,7 +74,6 @@ export const DatasetSearchModule: FlowModuleTemplateType = { key: ModuleInputKeyEnum.datasetParamsModal, type: FlowNodeInputTypeEnum.selectDatasetParamsModal, label: '', - connected: false, valueType: ModuleDataTypeEnum.any, showTargetInApp: false, showTargetInPlugin: false diff --git a/packages/global/core/module/template/system/history.ts b/packages/global/core/module/template/system/history.ts index 9774de471..62aa8d161 100644 --- a/packages/global/core/module/template/system/history.ts +++ b/packages/global/core/module/template/system/history.ts @@ -11,7 +11,7 @@ export const HistoryModule: FlowModuleTemplateType = { templateType: ModuleTemplateTypeEnum.systemInput, flowType: FlowNodeTypeEnum.historyNode, avatar: '/imgs/module/history.png', - name: '聊天记录', + name: '聊天记录(弃用)', intro: '用户输入的内容。该模块通常作为应用的入口,用户在发送消息后会首先执行该模块。', inputs: [ { diff --git a/packages/global/core/module/template/system/http.ts b/packages/global/core/module/template/system/http.ts index 399095302..dbaeca824 100644 --- a/packages/global/core/module/template/system/http.ts +++ b/packages/global/core/module/template/system/http.ts @@ -16,7 +16,6 @@ export const HttpModule: FlowModuleTemplateType = { Input_Template_TFSwitch, { key: ModuleInputKeyEnum.httpUrl, - value: '', type: FlowNodeInputTypeEnum.input, valueType: ModuleDataTypeEnum.string, label: '请求地址', diff --git a/packages/global/package.json b/packages/global/package.json index a8b6dbbe8..fb1a29a59 100644 --- a/packages/global/package.json +++ b/packages/global/package.json @@ -8,7 +8,7 @@ "encoding": "^0.1.13", "js-tiktoken": "^1.0.7", "node-html-markdown": "^1.3.0", - "openai": "^4.16.1", + "openai": "^4.20.1", "timezones-list": "^3.0.2" }, "devDependencies": { diff --git a/packages/service/common/api/plusRequest.ts b/packages/service/common/api/plusRequest.ts index 6eed83333..b9390a097 100644 --- a/packages/service/common/api/plusRequest.ts +++ b/packages/service/common/api/plusRequest.ts @@ -70,8 +70,9 @@ instance.interceptors.request.use(requestStart, (err) => Promise.reject(err)); instance.interceptors.response.use(responseSuccess, (err) => Promise.reject(err)); export function request(url: string, data: any, config: ConfigType, method: Method): any { - if (global.systemEnv && !global.systemEnv?.pluginBaseUrl) { - return Promise.reject('该功能为商业版特有...'); + if (!global.systemEnv || !global.systemEnv?.pluginBaseUrl) { + console.log('未部署商业版接口'); + return Promise.reject('The The request was denied...'); } /* 去空 */ diff --git a/packages/service/core/chat/controller.ts b/packages/service/core/chat/controller.ts index 5063ec2fa..94241289b 100644 --- a/packages/service/core/chat/controller.ts +++ b/packages/service/core/chat/controller.ts @@ -14,7 +14,7 @@ export async function getChatItems({ return { history: [] }; } - const history = await MongoChatItem.find({ chatId }, field).sort({ _id: -1 }).limit(limit); + const history = await MongoChatItem.find({ chatId }, field).sort({ _id: -1 }).limit(limit).lean(); history.reverse(); diff --git a/packages/service/support/outLink/tools.ts b/packages/service/support/outLink/tools.ts index 24ef6e5cc..b44fbd816 100644 --- a/packages/service/support/outLink/tools.ts +++ b/packages/service/support/outLink/tools.ts @@ -30,7 +30,7 @@ export const pushResult2Remote = async ({ shareId?: string; responseData?: any[]; }) => { - if (!shareId || !outLinkUid || !global.systemEnv.pluginBaseUrl) return; + if (!shareId || !outLinkUid || !global.systemEnv?.pluginBaseUrl) return; try { const outLink = await MongoOutLink.findOne({ shareId diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b1023bc4d..93372c046 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,7 +13,7 @@ importers: version: registry.npmmirror.com/multer@1.4.5-lts.1 openai: specifier: 4.16.1 - version: registry.npmmirror.com/openai@4.16.1(encoding@0.1.13) + version: registry.npmmirror.com/openai@4.16.1 devDependencies: '@types/multer': specifier: ^1.4.10 @@ -61,8 +61,8 @@ importers: specifier: ^1.3.0 version: registry.npmmirror.com/node-html-markdown@1.3.0 openai: - specifier: ^4.16.1 - version: registry.npmmirror.com/openai@4.16.1(encoding@0.1.13) + specifier: ^4.20.1 + version: registry.npmmirror.com/openai@4.20.1(encoding@0.1.13) timezones-list: specifier: ^3.0.2 version: registry.npmmirror.com/timezones-list@3.0.2 @@ -10320,9 +10320,8 @@ packages: mimic-fn: registry.npmmirror.com/mimic-fn@4.0.0 dev: true - registry.npmmirror.com/openai@4.16.1(encoding@0.1.13): + registry.npmmirror.com/openai@4.16.1: resolution: {integrity: sha512-Gr+uqUN1ICSk6VhrX64E+zL7skjI1TgPr/XUN+ZQuNLLOvx15+XZulx/lSW4wFEAQzgjBDlMBbBeikguGIjiMg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/openai/-/openai-4.16.1.tgz} - id: registry.npmmirror.com/openai/4.16.1 name: openai version: 4.16.1 hasBin: true @@ -10340,6 +10339,26 @@ packages: - encoding dev: false + registry.npmmirror.com/openai@4.20.1(encoding@0.1.13): + resolution: {integrity: sha512-Dd3q8EvINfganZFtg6V36HjrMaihqRgIcKiHua4Nq9aw/PxOP48dhbsk8x5klrxajt5Lpnc1KTOG5i1S6BKAJA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/openai/-/openai-4.20.1.tgz} + id: registry.npmmirror.com/openai/4.20.1 + name: openai + version: 4.20.1 + hasBin: true + dependencies: + '@types/node': registry.npmmirror.com/@types/node@18.18.6 + '@types/node-fetch': registry.npmmirror.com/@types/node-fetch@2.6.7 + abort-controller: registry.npmmirror.com/abort-controller@3.0.0 + agentkeepalive: registry.npmmirror.com/agentkeepalive@4.5.0 + digest-fetch: registry.npmmirror.com/digest-fetch@1.3.0 + form-data-encoder: registry.npmmirror.com/form-data-encoder@1.7.2 + formdata-node: registry.npmmirror.com/formdata-node@4.4.1 + node-fetch: registry.npmmirror.com/node-fetch@2.7.0(encoding@0.1.13) + web-streams-polyfill: registry.npmmirror.com/web-streams-polyfill@3.2.1 + transitivePeerDependencies: + - encoding + dev: false + registry.npmmirror.com/option@0.2.4: resolution: {integrity: sha512-pkEqbDyl8ou5cpq+VsnQbe/WlEy5qS7xPzMS1U55OCG9KPvwFD46zDbxQIj3egJSFc3D+XhYOPUzz49zQAVy7A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/option/-/option-0.2.4.tgz} name: option diff --git a/projects/app/data/config.json b/projects/app/data/config.json index 62c639095..0162a314b 100644 --- a/projects/app/data/config.json +++ b/projects/app/data/config.json @@ -66,9 +66,9 @@ ], "CQModels": [ { - "model": "gpt-3.5-turbo-1106", - "name": "GPT35-1106", - "maxContext": 16000, + "model": "gpt-3.5-turbo", + "name": "GPT35", + "maxContext": 4000, "maxResponse": 4000, "price": 0, "functionCall": true, diff --git a/projects/app/package.json b/projects/app/package.json index fbf5627ee..9c3840781 100644 --- a/projects/app/package.json +++ b/projects/app/package.json @@ -1,6 +1,6 @@ { "name": "app", - "version": "4.6.3", + "version": "4.6.4", "private": false, "scripts": { "dev": "next dev", diff --git a/projects/app/public/docs/versionIntro.md b/projects/app/public/docs/versionIntro.md index ea0fd4760..c179a6d78 100644 --- a/projects/app/public/docs/versionIntro.md +++ b/projects/app/public/docs/versionIntro.md @@ -2,17 +2,12 @@ 1. 重写 - 分享链接身份逻辑,采用 localID 记录用户的ID。 2. 商业版新增 - 分享链接 SSO 方案,通过`身份鉴权`地址,仅需`3个接口`即可完全接入已有用户系统。具体参考[分享链接身份鉴权](https://doc.fastgpt.in/docs/development/openapi/share/) -3. 调整 - 知识库搜索模块 topk 逻辑,采用 MaxToken 计算,兼容不同长度的文本块 -4. 调整鉴权顺序,提高 apikey 的优先级,避免cookie抢占 apikey 的鉴权。 -5. 链接读取支持多选择器。参考[Web 站点同步用法](https://doc.fastgpt.in/docs/course/webSync) -6. 修复 - 分享链接图片上传鉴权问题 -7. 修复 - Mongo 连接池未释放问题。 -8. 修复 - Dataset Intro 无法更新 -9. 修复 - md 代码块问题 -10. 修复 - root 权限问题 -11. 优化 docker file -12. [知识库结构详解](https://doc.fastgpt.in/docs/use-cases/datasetengine/) -13. [知识库提示词详解](https://doc.fastgpt.in/docs/use-cases/ai_settings/#引用模板--引用提示词) -14. [使用文档](https://doc.fastgpt.in/docs/intro/) -15. [点击查看高级编排介绍文档](https://doc.fastgpt.in/docs/workflow) -16. [点击查看商业版](https://doc.fastgpt.in/docs/commercial/) +3. 新增 - 分享链接更多嵌入方式提示,更多DIY方式。 +4. 优化 - 历史记录模块。弃用旧的历史记录模块,直接在对应地方填写数值即可。 +5. 调整 - 知识库搜索模块 topk 逻辑,采用 MaxToken 计算,兼容不同长度的文本块 +6. 链接读取支持多选择器。参考[Web 站点同步用法](https://doc.fastgpt.in/docs/course/webSync) +7. [知识库结构详解](https://doc.fastgpt.in/docs/use-cases/datasetengine/) +8. [知识库提示词详解](https://doc.fastgpt.in/docs/use-cases/ai_settings/#引用模板--引用提示词) +9. [使用文档](https://doc.fastgpt.in/docs/intro/) +10. [点击查看高级编排介绍文档](https://doc.fastgpt.in/docs/workflow) +11. [点击查看商业版](https://doc.fastgpt.in/docs/commercial/) diff --git a/projects/app/public/imgs/modal/usingWay.svg b/projects/app/public/imgs/modal/usingWay.svg new file mode 100644 index 000000000..e61d2c6c7 --- /dev/null +++ b/projects/app/public/imgs/modal/usingWay.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/projects/app/public/imgs/outlink/iframe.svg b/projects/app/public/imgs/outlink/iframe.svg new file mode 100644 index 000000000..dec2c0a1c --- /dev/null +++ b/projects/app/public/imgs/outlink/iframe.svg @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/projects/app/public/imgs/outlink/link.svg b/projects/app/public/imgs/outlink/link.svg new file mode 100644 index 000000000..6c5048227 --- /dev/null +++ b/projects/app/public/imgs/outlink/link.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/projects/app/public/imgs/outlink/script.svg b/projects/app/public/imgs/outlink/script.svg new file mode 100644 index 000000000..69333fae9 --- /dev/null +++ b/projects/app/public/imgs/outlink/script.svg @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/projects/app/public/js/iframe.js b/projects/app/public/js/iframe.js index 08f1f6df6..0c645b60d 100644 --- a/projects/app/public/js/iframe.js +++ b/projects/app/public/js/iframe.js @@ -1,11 +1,17 @@ -async function embedChatbot() { +function embedChatbot() { const chatBtnId = 'fastgpt-chatbot-button'; const chatWindowId = 'fastgpt-chatbot-window'; - const script = document.getElementById('fastgpt-iframe'); - const botSrc = script?.getAttribute('data-src'); - const primaryColor = script?.getAttribute('data-color') || '#4e83fd'; + const script = document.getElementById('chatbot-iframe'); + const botSrc = script?.getAttribute('data-bot-src'); const defaultOpen = script?.getAttribute('data-default-open') === 'true'; - + const canDrag = script?.getAttribute('data-drag') === 'true'; + const MessageIcon = + script?.getAttribute('data-open-icon') || + `data:image/svg+xml;base64,PHN2ZyB0PSIxNjkwNTMyNzg1NjY0IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjQxMzIiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48cGF0aCBkPSJNNTEyIDMyQzI0Ny4wNCAzMiAzMiAyMjQgMzIgNDY0QTQxMC4yNCA0MTAuMjQgMCAwIDAgMTcyLjQ4IDc2OEwxNjAgOTY1LjEyYTI1LjI4IDI1LjI4IDAgMCAwIDM5LjA0IDIyLjRsMTY4LTExMkE1MjguNjQgNTI4LjY0IDAgMCAwIDUxMiA4OTZjMjY0Ljk2IDAgNDgwLTE5MiA0ODAtNDMyUzc3Ni45NiAzMiA1MTIgMzJ6IG0yNDQuOCA0MTZsLTM2MS42IDMwMS43NmExMi40OCAxMi40OCAwIDAgMS0xOS44NC0xMi40OGw1OS4yLTIzMy45MmgtMTYwYTEyLjQ4IDEyLjQ4IDAgMCAxLTcuMzYtMjMuMzZsMzYxLjYtMzAxLjc2YTEyLjQ4IDEyLjQ4IDAgMCAxIDE5Ljg0IDEyLjQ4bC01OS4yIDIzMy45MmgxNjBhMTIuNDggMTIuNDggMCAwIDEgOCAyMi4wOHoiIGZpbGw9IiM0ZTgzZmQiIHAtaWQ9IjQxMzMiPjwvcGF0aD48L3N2Zz4=`; + const CloseIcon = + script?.getAttribute('data-close-icon') || + 'data:image/svg+xml;base64,PHN2ZyB0PSIxNjkwNTM1NDQxNTI2IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjYzNjciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48cGF0aCBkPSJNNTEyIDEwMjRBNTEyIDUxMiAwIDEgMSA1MTIgMGE1MTIgNTEyIDAgMCAxIDAgMTAyNHpNMzA1Ljk1NjU3MSAzNzAuMzk1NDI5TDQ0Ny40ODggNTEyIDMwNS45NTY1NzEgNjUzLjYwNDU3MWE0NS41NjggNDUuNTY4IDAgMSAwIDY0LjQzODg1OCA2NC40Mzg4NThMNTEyIDU3Ni41MTJsMTQxLjYwNDU3MSAxNDEuNTMxNDI5YTQ1LjU2OCA0NS41NjggMCAwIDAgNjQuNDM4ODU4LTY0LjQzODg1OEw1NzYuNTEyIDUxMmwxNDEuNTMxNDI5LTE0MS42MDQ1NzFhNDUuNTY4IDQ1LjU2OCAwIDEgMC02NC40Mzg4NTgtNjQuNDM4ODU4TDUxMiA0NDcuNDg4IDM3MC4zOTU0MjkgMzA1Ljk1NjU3MWE0NS41NjggNDUuNTY4IDAgMCAwLTY0LjQzODg1OCA2NC40Mzg4NTh6IiBmaWxsPSIjNGU4M2ZkIiBwLWlkPSI2MzY4Ij48L3BhdGg+PC9zdmc+'; + if (!botSrc) { console.error(`Can't find appid`); return; @@ -14,17 +20,17 @@ async function embedChatbot() { return; } - const MessageIcon = ``; - - const CloseIcon = ``; - const ChatBtn = document.createElement('div'); ChatBtn.id = chatBtnId; ChatBtn.style.cssText = 'position: fixed; bottom: 1rem; right: 1rem; width: 40px; height: 40px; cursor: pointer; z-index: 2147483647; transition: 0;'; - const ChatBtnDiv = document.createElement('div'); - ChatBtnDiv.innerHTML = MessageIcon; + // btn icon + const ChatBtnDiv = document.createElement('img'); + ChatBtnDiv.src = defaultOpen ? CloseIcon : MessageIcon; + ChatBtnDiv.setAttribute('width', '100%'); + ChatBtnDiv.setAttribute('height', '100%'); + ChatBtnDiv.draggable = false; const iframe = document.createElement('iframe'); iframe.allow = 'fullscreen;microphone'; @@ -33,8 +39,8 @@ async function embedChatbot() { iframe.src = botSrc; iframe.style.cssText = 'border: none; position: fixed; flex-direction: column; justify-content: space-between; box-shadow: rgba(150, 150, 150, 0.2) 0px 10px 30px 0px, rgba(150, 150, 150, 0.2) 0px 0px 0px 1px; bottom: 4rem; right: 1rem; width: 24rem; height: 40rem; max-width: 90vw; max-height: 85vh; border-radius: 0.75rem; display: flex; z-index: 2147483647; overflow: hidden; left: unset; background-color: #F3F4F6;'; - iframe.style.visibility = defaultOpen ? 'unset' : 'hidden'; - + iframe.style.visibility = defaultOpen ? 'unset' : 'hidden'; + document.body.appendChild(iframe); let chatBtnDragged = false; @@ -52,14 +58,16 @@ async function embedChatbot() { const visibilityVal = chatWindow.style.visibility; if (visibilityVal === 'hidden') { chatWindow.style.visibility = 'unset'; - ChatBtnDiv.innerHTML = CloseIcon; + ChatBtnDiv.src = CloseIcon; } else { chatWindow.style.visibility = 'hidden'; - ChatBtnDiv.innerHTML = MessageIcon; + ChatBtnDiv.src = MessageIcon; } }); ChatBtn.addEventListener('mousedown', (e) => { + e.stopPropagation(); + if (!chatBtnMouseX && !chatBtnMouseY) { chatBtnMouseX = e.clientX; chatBtnMouseY = e.clientY; @@ -68,19 +76,21 @@ async function embedChatbot() { chatBtnDown = true; }); ChatBtn.addEventListener('mousemove', (e) => { - if (!chatBtnDown) return; + e.stopPropagation(); + if (!canDrag || !chatBtnDown) return; + chatBtnDragged = true; const transformX = e.clientX - chatBtnMouseX; const transformY = e.clientY - chatBtnMouseY; ChatBtn.style.transform = `translate3d(${transformX}px, ${transformY}px, 0)`; - - e.stopPropagation(); }); ChatBtn.addEventListener('mouseup', (e) => { + chatBtnDragged = false; chatBtnDown = false; }); - ChatBtn.addEventListener('mouseleave', (e) => { + window.addEventListener('mouseup', (e) => { + chatBtnDragged = false; chatBtnDown = false; }); diff --git a/projects/app/public/locales/en/common.json b/projects/app/public/locales/en/common.json index f9696fabc..36881897f 100644 --- a/projects/app/public/locales/en/common.json +++ b/projects/app/public/locales/en/common.json @@ -265,6 +265,20 @@ "logs": { "Source And Time": "Source & Time" }, + "outLink": { + "Can Drag": "Icon Drag", + "Default open": "Default Open", + "Iframe block title": "Copy the Iframe below and add it to your web page", + "Link block title": "Copy the link below to your browser to open", + "Script Close Icon": "Close Icon", + "Script Icon": "Icon", + "Script Open Icon": "Open Script", + "Script block title": "Add the following code to your website", + "Select Mode": "Select Mode", + "Select Using Way": "Select use mode", + "Show History": "Show History", + "Web Link": "Web Link" + }, "setting": "App Setting", "simple": { "mode template select": "Template" @@ -297,9 +311,9 @@ "feedback": { "Close User Good Feedback": "", "Close User Like": "The user like\nClick to close the tag", + "Feedback Close": "Close Feedback", "No Content": "The user did not fill in the specific feedback content", - "Read User dislike": "User dislike\nClick to view content", - "Feedback Close": "Close Feedback" + "Read User dislike": "User dislike\nClick to view content" }, "markdown": { "Edit Question": "Edit Question", diff --git a/projects/app/public/locales/zh/common.json b/projects/app/public/locales/zh/common.json index 9475030b3..21a61a267 100644 --- a/projects/app/public/locales/zh/common.json +++ b/projects/app/public/locales/zh/common.json @@ -265,6 +265,20 @@ "logs": { "Source And Time": "来源 & 时间" }, + "outLink": { + "Can Drag": "图标可拖拽", + "Default open": "默认打开", + "Iframe block title": "复制下面 Iframe 加入到你的网站中", + "Link block title": "将下面链接复制到浏览器打开", + "Script Close Icon": "关闭图标", + "Script Icon": "图标", + "Script Open Icon": "打开图标", + "Script block title": "将下面代码加入到你的网站中", + "Select Mode": "开始使用", + "Select Using Way": "选择使用方式", + "Show History": "展示历史对话", + "Web Link": "网络链接" + }, "setting": "应用信息设置", "simple": { "mode template select": "简易模板" @@ -297,9 +311,9 @@ "feedback": { "Close User Good Feedback": "", "Close User Like": "用户表示赞同\n点击关闭该标记", + "Feedback Close": "关闭反馈", "No Content": "用户没有填写具体反馈内容", - "Read User dislike": "用户表示反对\n点击查看内容", - "Feedback Close": "关闭反馈" + "Read User dislike": "用户表示反对\n点击查看内容" }, "markdown": { "Edit Question": "编辑问题", diff --git a/projects/app/src/components/ChatBox/FeedbackModal.tsx b/projects/app/src/components/ChatBox/FeedbackModal.tsx index e7f307402..87825b91a 100644 --- a/projects/app/src/components/ChatBox/FeedbackModal.tsx +++ b/projects/app/src/components/ChatBox/FeedbackModal.tsx @@ -6,11 +6,13 @@ import { useTranslation } from 'next-i18next'; import { updateChatUserFeedback } from '@/web/core/chat/api'; const FeedbackModal = ({ + appId, chatId, chatItemId, onSuccess, onClose }: { + appId: string; chatId: string; chatItemId: string; onSuccess: (e: string) => void; @@ -23,6 +25,7 @@ const FeedbackModal = ({ mutationFn: async () => { const val = ref.current?.value || t('core.chat.feedback.No Content'); return updateChatUserFeedback({ + appId, chatId, chatItemId, userBadFeedback: val diff --git a/projects/app/src/components/ChatBox/MessageInput.tsx b/projects/app/src/components/ChatBox/MessageInput.tsx index 8555b4216..439dbfb7a 100644 --- a/projects/app/src/components/ChatBox/MessageInput.tsx +++ b/projects/app/src/components/ChatBox/MessageInput.tsx @@ -429,7 +429,7 @@ ${images.map((img) => JSON.stringify({ src: img.src })).join('\n')} > {isChatting ? ( ) => void; onStartChat?: (e: StartChatFnProps) => Promise<{ responseText: string; @@ -125,6 +129,7 @@ const ChatBox = ( userGuideModule, showFileSelector, active = true, + appId, chatId, shareId, outLinkUid, @@ -711,7 +716,7 @@ const ChatBox = ( return; } return () => { - if (!item.dataId || !chatId) return; + if (!item.dataId || !chatId || !appId) return; const isGoodFeedback = !!item.userGoodFeedback; setChatHistory((state) => @@ -726,6 +731,7 @@ const ChatBox = ( ); try { updateChatUserFeedback({ + appId, chatId, chatItemId: item.dataId, shareId, @@ -738,7 +744,7 @@ const ChatBox = ( onCloseUserLike={ feedbackType === FeedbackTypeEnum.admin ? () => { - if (!item.dataId || !chatId) return; + if (!item.dataId || !chatId || !appId) return; setChatHistory((state) => state.map((chatItem) => chatItem.dataId === item.dataId @@ -747,6 +753,7 @@ const ChatBox = ( ) ); updateChatUserFeedback({ + appId, chatId, chatItemId: item.dataId, userGoodFeedback: undefined @@ -760,7 +767,7 @@ const ChatBox = ( } if (item.userBadFeedback) { return () => { - if (!item.dataId || !chatId) return; + if (!item.dataId || !chatId || !appId) return; setChatHistory((state) => state.map((chatItem) => chatItem.dataId === item.dataId @@ -770,6 +777,7 @@ const ChatBox = ( ); try { updateChatUserFeedback({ + appId, chatId, chatItemId: item.dataId, shareId, @@ -886,8 +894,9 @@ const ChatBox = ( /> ) : null} {/* user feedback modal */} - {!!feedbackId && chatId && ( + {!!feedbackId && chatId && appId && ( setFeedbackId(undefined)} @@ -915,8 +924,9 @@ const ChatBox = ( ) ); try { - if (!chatId) return; + if (!chatId || !appId) return; updateChatUserFeedback({ + appId, chatId, chatItemId: readFeedbackData.chatItemId }); @@ -948,8 +958,9 @@ const ChatBox = ( ) ); - if (readFeedbackData && chatId) { + if (readFeedbackData && chatId && appId) { updateChatUserFeedback({ + appId, chatId, chatItemId: readFeedbackData.chatItemId, userBadFeedback: undefined diff --git a/projects/app/src/components/MyModal/index.tsx b/projects/app/src/components/MyModal/index.tsx index fd0766e9b..044e79b2a 100644 --- a/projects/app/src/components/MyModal/index.tsx +++ b/projects/app/src/components/MyModal/index.tsx @@ -10,6 +10,7 @@ import { Image } from '@chakra-ui/react'; import MyIcon from '../Icon'; +import { useSystemStore } from '@/web/common/system/useSystemStore'; export interface MyModalProps extends ModalContentProps { iconSrc?: string; @@ -30,12 +31,13 @@ const MyModal = ({ maxW = ['90vw', '600px'], ...props }: MyModalProps) => { + const { isPc } = useSystemStore(); return ( onClose && onClose()} autoFocus={false} - isCentered={isCentered} + isCentered={isPc ? isCentered : true} > void; + value: any; + hiddenCircle?: boolean; + onChange: (e: any) => void; } const MyRadio = ({ @@ -17,6 +18,8 @@ const MyRadio = ({ value, align = 'center', iconSize = '18px', + hiddenCircle = false, + p, onChange, ...props }: Props) => { @@ -32,7 +35,8 @@ const MyRadio = ({ userSelect={'none'} py={3} pl={'14px'} - pr={'36px'} + pr={hiddenCircle ? '14px' : '36px'} + p={p !== undefined ? `${p} !important` : undefined} border={theme.borders.sm} borderWidth={'1.5px'} borderRadius={'md'} @@ -50,6 +54,7 @@ const MyRadio = ({ })} _after={{ content: '""', + display: hiddenCircle ? 'none' : 'block', position: 'absolute', right: '14px', w: '16px', @@ -79,8 +84,8 @@ const MyRadio = ({ )} )} - - {t(item.title)} + + {typeof item.title === 'string' ? t(item.title) : item.title} {!!item.desc && ( {t(item.desc)} diff --git a/projects/app/src/components/core/module/Flow/ChatTest.tsx b/projects/app/src/components/core/module/Flow/ChatTest.tsx index 426ceace6..eb2c5aafd 100644 --- a/projects/app/src/components/core/module/Flow/ChatTest.tsx +++ b/projects/app/src/components/core/module/Flow/ChatTest.tsx @@ -10,13 +10,13 @@ import React, { } from 'react'; import { Box, Flex, IconButton } from '@chakra-ui/react'; import MyIcon from '@/components/Icon'; -import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant'; import { streamFetch } from '@/web/common/api/fetch'; import MyTooltip from '@/components/MyTooltip'; import { useUserStore } from '@/web/support/user/useUserStore'; import ChatBox, { type ComponentRef, type StartChatFnProps } from '@/components/ChatBox'; import { getGuideModule } from '@fastgpt/global/core/module/utils'; import { checkChatSupportSelectFileByModules } from '@/web/core/chat/utils'; +import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants'; export type ChatTestComponentRef = { resetChatTest: () => void; @@ -40,10 +40,18 @@ const ChatTest = ( const startChat = useCallback( async ({ chatList, controller, generatingMessage, variables }: StartChatFnProps) => { - const historyMaxLen = - modules - ?.find((item) => item.flowType === FlowNodeTypeEnum.historyNode) - ?.inputs?.find((item) => item.key === 'maxContext')?.value || 0; + let historyMaxLen = 6; + modules.forEach((module) => { + module.inputs.forEach((input) => { + if ( + (input.key === ModuleInputKeyEnum.history || + input.key === ModuleInputKeyEnum.historyMaxAmount) && + typeof input.value === 'number' + ) { + historyMaxLen = Math.max(historyMaxLen, input.value); + } + }); + }); const history = chatList.slice(-historyMaxLen - 2, -2); // 流请求,获取数据 diff --git a/projects/app/src/components/core/module/Flow/FlowProvider.tsx b/projects/app/src/components/core/module/Flow/FlowProvider.tsx index 70a981c21..389d6f6f6 100644 --- a/projects/app/src/components/core/module/Flow/FlowProvider.tsx +++ b/projects/app/src/components/core/module/Flow/FlowProvider.tsx @@ -28,7 +28,7 @@ import React, { import { customAlphabet } from 'nanoid'; import { appModule2FlowEdge, appModule2FlowNode } from '@/utils/adapt'; import { useToast } from '@/web/common/hooks/useToast'; -import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant'; +import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant'; import { ModuleDataTypeEnum } from '@fastgpt/global/core/module/constants'; import { useTranslation } from 'next-i18next'; import { ModuleItemType } from '@fastgpt/global/core/module/type.d'; @@ -449,9 +449,9 @@ export function flowNode2Modules({ flowType: item.data.flowType, showStatus: item.data.showStatus, position: item.position, - inputs: item.data.inputs.map((item) => ({ - ...item, - connected: Boolean(item.value ?? item.connected ?? item.type !== FlowNodeInputTypeEnum.target) + inputs: item.data.inputs.map((input) => ({ + ...input, + connected: false })), outputs: item.data.outputs.map((item) => ({ ...item, @@ -462,10 +462,11 @@ export function flowNode2Modules({ // update inputs and outputs modules.forEach((module) => { module.inputs.forEach((input) => { - input.connected = - input.connected || - !!edges.find((edge) => edge.target === module.moduleId && edge.targetHandle === input.key); + input.connected = !!edges.find( + (edge) => edge.target === module.moduleId && edge.targetHandle === input.key + ); }); + module.outputs.forEach((output) => { output.targets = edges .filter( diff --git a/projects/app/src/components/core/module/Flow/components/modules/VariableEdit.tsx b/projects/app/src/components/core/module/Flow/components/modules/VariableEdit.tsx index ce0d925ac..e35ef351f 100644 --- a/projects/app/src/components/core/module/Flow/components/modules/VariableEdit.tsx +++ b/projects/app/src/components/core/module/Flow/components/modules/VariableEdit.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useMemo, useState } from 'react'; import { Box, Button, @@ -12,9 +12,7 @@ import { Flex, Switch, Input, - Grid, FormControl, - useTheme, Image, Table, Thead, @@ -39,6 +37,7 @@ import MyTooltip from '@/components/MyTooltip'; import { variableTip } from '@fastgpt/global/core/module/template/tip'; import { useTranslation } from 'next-i18next'; import { useToast } from '@/web/common/hooks/useToast'; +import MyRadio from '@/components/common/MyRadio'; const VariableEdit = ({ variables, @@ -49,26 +48,28 @@ const VariableEdit = ({ }) => { const { t } = useTranslation(); const { toast } = useToast(); - const theme = useTheme(); const [refresh, setRefresh] = useState(false); - const VariableTypeList = [ - { - label: t('core.module.variable.input type'), - icon: 'core/app/variable/input', - key: VariableInputEnum.input - }, - { - label: t('core.module.variable.textarea type'), - icon: 'core/app/variable/textarea', - key: VariableInputEnum.textarea - }, - { - label: t('core.module.variable.select type'), - icon: 'core/app/variable/select', - key: VariableInputEnum.select - } - ]; + const VariableTypeList = useMemo( + () => [ + { + title: t('core.module.variable.input type'), + icon: 'core/app/variable/input', + value: VariableInputEnum.input + }, + { + title: t('core.module.variable.textarea type'), + icon: 'core/app/variable/textarea', + value: VariableInputEnum.textarea + }, + { + title: t('core.module.variable.select type'), + icon: 'core/app/variable/select', + value: VariableInputEnum.select + } + ], + [t] + ); const { isOpen: isOpenEdit, onOpen: onOpenEdit, onClose: onCloseEdit } = useDisclosure(); const { @@ -102,9 +103,9 @@ const VariableEdit = ({ const formatVariables = useMemo(() => { return variables.map((item) => ({ ...item, - icon: VariableTypeList.find((type) => type.key === item.type)?.icon + icon: VariableTypeList.find((type) => type.value === item.type)?.icon })); - }, [variables]); + }, [VariableTypeList, variables]); return ( @@ -206,38 +207,18 @@ const VariableEdit = ({ {t('core.module.Field Type')} - - {VariableTypeList.map((item) => ( - { - setValuesEdit('variable.type', item.key); - setRefresh(!refresh); - } - })} - > - - {item.label} - - ))} - + { + setValuesEdit('variable.type', e as any); + setRefresh(!refresh); + }} + /> {getValuesEdit('variable.type') === VariableInputEnum.input && ( <> diff --git a/projects/app/src/components/core/module/Flow/components/nodes/NodeCQNode.tsx b/projects/app/src/components/core/module/Flow/components/nodes/NodeCQNode.tsx index fc9aaef17..251bbff53 100644 --- a/projects/app/src/components/core/module/Flow/components/nodes/NodeCQNode.tsx +++ b/projects/app/src/components/core/module/Flow/components/nodes/NodeCQNode.tsx @@ -97,7 +97,7 @@ const NodeCQNode = ({ data }: NodeProps) => { }); }} /> - + ))} diff --git a/projects/app/src/components/core/module/Flow/components/render/RenderInput.tsx b/projects/app/src/components/core/module/Flow/components/render/RenderInput.tsx index aaf1d6f40..6f51145a6 100644 --- a/projects/app/src/components/core/module/Flow/components/render/RenderInput.tsx +++ b/projects/app/src/components/core/module/Flow/components/render/RenderInput.tsx @@ -29,7 +29,7 @@ import TargetHandle from './TargetHandle'; import MyIcon from '@/components/Icon'; import { useTranslation } from 'next-i18next'; import type { AIChatModuleProps } from '@fastgpt/global/core/module/node/type.d'; -import { chatModelList } from '@/web/common/system/staticData'; +import { chatModelList, cqModelList } from '@/web/common/system/staticData'; import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools'; import { useDatasetStore } from '@/web/core/dataset/store/dataset'; import type { SelectedDatasetType } from '@fastgpt/global/core/module/api.d'; @@ -229,8 +229,11 @@ const RenderInput = ({ {item.type === FlowNodeInputTypeEnum.aiSettings && ( )} - {item.type === FlowNodeInputTypeEnum.selectChatModel && ( - + {[ + FlowNodeInputTypeEnum.selectChatModel, + FlowNodeInputTypeEnum.selectCQModel + ].includes(item.type as any) && ( + )} {item.type === FlowNodeInputTypeEnum.selectDataset && ( @@ -446,12 +449,21 @@ const AISetting = React.memo(function AISetting({ inputs = [], moduleId }: Rende ); }); -const SelectChatModelRender = React.memo(function SelectChatModelRender({ +const SelectAIModelRender = React.memo(function SelectAIModelRender({ inputs = [], item, moduleId }: RenderProps) { - const modelList = chatModelList || []; + const modelList = (() => { + if (item.type === FlowNodeInputTypeEnum.selectChatModel) return chatModelList; + if (item.type === FlowNodeInputTypeEnum.selectCQModel) return cqModelList; + return []; + })().map((item) => ({ + model: item.model, + name: item.name, + maxResponse: item.maxResponse, + price: item.price + })); const onChangeModel = useCallback( (e: string) => { diff --git a/projects/app/src/global/core/chat/api.d.ts b/projects/app/src/global/core/chat/api.d.ts index 647dc22b1..fd3c3ab2f 100644 --- a/projects/app/src/global/core/chat/api.d.ts +++ b/projects/app/src/global/core/chat/api.d.ts @@ -44,6 +44,7 @@ export type getHistoriesProps = { }; export type UpdateHistoryProps = { + appId: string; chatId: string; customTitle?: string; top?: boolean; @@ -52,6 +53,7 @@ export type UpdateHistoryProps = { }; export type DelHistoryProps = { + appId: string; chatId: string; shareId?: string; outLinkUid?: string; @@ -64,6 +66,7 @@ export type ClearHistoriesProps = { /* -------- chat item ---------- */ export type DeleteChatItemProps = { + appId: string; chatId: string; contentId?: string; shareId?: string; diff --git a/projects/app/src/global/core/prompt/agent.ts b/projects/app/src/global/core/prompt/agent.ts index 7fc8c9efb..69b0b95c0 100644 --- a/projects/app/src/global/core/prompt/agent.ts +++ b/projects/app/src/global/core/prompt/agent.ts @@ -18,46 +18,40 @@ A2: ` }; -export const Prompt_ExtractJson = `你可以从 "对话记录" 中提取指定信息,并返回一个 JSON 对象,JSON 对象要求: -1. JSON 对象仅包含字段说明中的值。 -2. 字段说明中的 required 决定 JSON 对象是否必须存在该字段。 -3. 必须存在的字段,值可以为空字符串或根据提取要求来设置,不能随机生成值。 - -提取要求: -""" +export const Prompt_ExtractJson = `你可以从 <对话记录> 中提取指定 JSON 信息,你仅需返回 JSON 字符串,无需回答问题。 +<提取要求> {{description}} -""" + + +<字段说明> +1. 下面的 JSON 字符串均按照 JSON Schema 的规则描述。 +2. key 代表字段名,description 代表字段的描述,required 代表字段是否必须。 +3. 如果字段内容为空,你可以返回空字符串。 -字段说明: -""" {{json}} -""" + -对话记录: -""" +<对话记录> {{text}} -""" + `; export const Prompt_CQJson = `我会给你几个问题类型,请参考额外的背景知识(可能为空)和对话内容,判断我本次的问题类型,并返回对应类型的 ID,格式为 JSON 字符串: """ -'{"type":"问题类型的 ID"}' +'{"问题类型":"类型的 ID"}' """ -问题类型: -""" +<问题类型> {{typeList}} -""" + -额外背景知识: -""" +<背景知识> {{systemPrompt}} -""" + -对话内容: -""" +<对话内容> {{text}} -""" + `; export const Prompt_QuestionGuide = `我不太清楚问你什么问题,请帮我生成 3 个问题,引导我继续提问。问题的长度应小于20个字符,按 JSON 格式返回: ["问题1", "问题2", "问题3"]`; diff --git a/projects/app/src/pages/api/admin/init464.ts b/projects/app/src/pages/api/admin/initv464.ts similarity index 100% rename from projects/app/src/pages/api/admin/init464.ts rename to projects/app/src/pages/api/admin/initv464.ts diff --git a/projects/app/src/pages/api/core/app/form2Modules/fastgpt-simple.ts b/projects/app/src/pages/api/core/app/form2Modules/fastgpt-simple.ts index 4716f4525..e3a411a72 100644 --- a/projects/app/src/pages/api/core/app/form2Modules/fastgpt-simple.ts +++ b/projects/app/src/pages/api/core/app/form2Modules/fastgpt-simple.ts @@ -71,47 +71,6 @@ function simpleChatTemplate({ } ] }, - { - moduleId: 'history', - name: '聊天记录', - avatar: '/imgs/module/history.png', - flowType: 'historyNode', - position: { - x: 452.5466249541586, - y: 1276.3930310334215 - }, - inputs: [ - { - key: 'maxContext', - type: 'numberInput', - label: '最长记录数', - value: 10, - min: 0, - max: 50, - connected: true - }, - { - key: 'history', - type: 'hidden', - label: '聊天记录', - connected: true - } - ], - outputs: [ - { - key: 'history', - label: '聊天记录', - valueType: 'chatHistory', - type: 'source', - targets: [ - { - moduleId: 'chatModule', - key: 'history' - } - ] - } - ] - }, { moduleId: 'chatModule', name: 'AI 对话', @@ -191,7 +150,6 @@ function simpleChatTemplate({ type: 'hidden', label: '引用内容模板', valueType: 'string', - value: '', connected: true }, { @@ -199,7 +157,6 @@ function simpleChatTemplate({ type: 'hidden', label: '引用内容提示词', valueType: 'string', - value: '', connected: true }, { @@ -234,7 +191,8 @@ function simpleChatTemplate({ type: 'target', label: 'core.module.input.label.chat history', valueType: 'chatHistory', - connected: true + connected: true, + value: 8 }, { key: 'userChatInput', @@ -318,47 +276,6 @@ function datasetTemplate({ } ] }, - { - moduleId: 'history', - name: '聊天记录', - avatar: '/imgs/module/history.png', - flowType: 'historyNode', - position: { - x: 452.5466249541586, - y: 1276.3930310334215 - }, - inputs: [ - { - key: 'maxContext', - type: 'numberInput', - label: '最长记录数', - value: 6, - min: 0, - max: 50, - connected: true - }, - { - key: 'history', - type: 'hidden', - label: '聊天记录', - connected: true - } - ], - outputs: [ - { - key: 'history', - label: '聊天记录', - valueType: 'chatHistory', - type: 'source', - targets: [ - { - moduleId: 'chatModule', - key: 'history' - } - ] - } - ] - }, { moduleId: 'datasetSearch', name: '知识库搜索', @@ -541,7 +458,6 @@ function datasetTemplate({ type: 'hidden', label: '引用内容模板', valueType: 'string', - value: '', connected: true }, { @@ -549,7 +465,6 @@ function datasetTemplate({ type: 'hidden', label: '引用内容提示词', valueType: 'string', - value: '', connected: true }, { @@ -584,7 +499,8 @@ function datasetTemplate({ type: 'target', label: 'core.module.input.label.chat history', valueType: 'chatHistory', - connected: true + connected: true, + value: 8 }, { key: 'userChatInput', diff --git a/projects/app/src/pages/api/core/app/form2Modules/fastgpt-universal.ts b/projects/app/src/pages/api/core/app/form2Modules/fastgpt-universal.ts index 1c7b2d6d3..9600b05e7 100644 --- a/projects/app/src/pages/api/core/app/form2Modules/fastgpt-universal.ts +++ b/projects/app/src/pages/api/core/app/form2Modules/fastgpt-universal.ts @@ -89,18 +89,19 @@ function chatModelInput(formData: AppSimpleEditFormType): FlowNodeInputItemType[ label: '触发器', connected: formData.dataset.datasets.length > 0 && !!formData.dataset.searchEmptyText }, + { + key: 'history', + type: 'target', + label: 'core.module.input.label.chat history', + connected: true, + value: 6 + }, { key: 'quoteQA', type: 'target', label: '引用内容', connected: formData.dataset.datasets.length > 0 }, - { - key: 'history', - type: 'target', - label: '聊天记录', - connected: true - }, { key: 'userChatInput', type: 'target', @@ -139,41 +140,6 @@ function simpleChatTemplate(formData: AppSimpleEditFormType): ModuleItemType[] { }, moduleId: 'userChatInput' }, - { - name: '聊天记录', - flowType: FlowNodeTypeEnum.historyNode, - inputs: [ - { - key: 'maxContext', - value: 6, - connected: true, - type: 'numberInput', - label: '最长记录数' - }, - { - key: 'history', - type: 'hidden', - label: '聊天记录', - connected: true - } - ], - outputs: [ - { - key: 'history', - targets: [ - { - moduleId: 'chatModule', - key: 'history' - } - ] - } - ], - position: { - x: 452.5466249541586, - y: 1276.3930310334215 - }, - moduleId: 'history' - }, { name: 'AI 对话', flowType: FlowNodeTypeEnum.chatNode, @@ -238,41 +204,6 @@ function datasetTemplate(formData: AppSimpleEditFormType): ModuleItemType[] { }, moduleId: 'userChatInput' }, - { - name: '聊天记录', - flowType: FlowNodeTypeEnum.historyNode, - inputs: [ - { - key: 'maxContext', - value: 6, - connected: true, - type: 'numberInput', - label: '最长记录数' - }, - { - key: 'history', - type: 'hidden', - label: '聊天记录', - connected: true - } - ], - outputs: [ - { - key: 'history', - targets: [ - { - moduleId: 'chatModule', - key: 'history' - } - ] - } - ], - position: { - x: 452.5466249541586, - y: 1276.3930310334215 - }, - moduleId: 'history' - }, { name: '知识库搜索', flowType: FlowNodeTypeEnum.datasetSearchNode, diff --git a/projects/app/src/pages/api/core/chat/chatTest.ts b/projects/app/src/pages/api/core/chat/chatTest.ts index 9d0898e88..7693dc8a2 100644 --- a/projects/app/src/pages/api/core/chat/chatTest.ts +++ b/projects/app/src/pages/api/core/chat/chatTest.ts @@ -64,8 +64,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) appId, modules, variables, - params: { - history, + histories: history, + startParams: { userChatInput: prompt }, stream: true, diff --git a/projects/app/src/pages/api/core/chat/delHistory.ts b/projects/app/src/pages/api/core/chat/delHistory.ts index 1b67c4287..39baca624 100644 --- a/projects/app/src/pages/api/core/chat/delHistory.ts +++ b/projects/app/src/pages/api/core/chat/delHistory.ts @@ -10,11 +10,12 @@ import { autChatCrud } from '@/service/support/permission/auth/chat'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { await connectToDatabase(); - const { chatId, shareId, outLinkUid } = req.query as DelHistoryProps; + const { appId, chatId, shareId, outLinkUid } = req.query as DelHistoryProps; await autChatCrud({ req, authToken: true, + appId, chatId, shareId, outLinkUid, diff --git a/projects/app/src/pages/api/core/chat/feedback/updateUserFeedback.ts b/projects/app/src/pages/api/core/chat/feedback/updateUserFeedback.ts index 6f85c2830..6d7c0749b 100644 --- a/projects/app/src/pages/api/core/chat/feedback/updateUserFeedback.ts +++ b/projects/app/src/pages/api/core/chat/feedback/updateUserFeedback.ts @@ -7,7 +7,7 @@ import { autChatCrud } from '@/service/support/permission/auth/chat'; /* 初始化我的聊天框,需要身份验证 */ export default async function handler(req: NextApiRequest, res: NextApiResponse) { - const { chatId, chatItemId, shareId, outLinkUid, userBadFeedback, userGoodFeedback } = + const { appId, chatId, chatItemId, shareId, outLinkUid, userBadFeedback, userGoodFeedback } = req.body as UpdateChatFeedbackProps; try { @@ -16,6 +16,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) await autChatCrud({ req, authToken: true, + appId, chatId, shareId, outLinkUid, diff --git a/projects/app/src/pages/api/core/chat/item/delete.ts b/projects/app/src/pages/api/core/chat/item/delete.ts index 41c3a5fc5..7a1b8c043 100644 --- a/projects/app/src/pages/api/core/chat/item/delete.ts +++ b/projects/app/src/pages/api/core/chat/item/delete.ts @@ -8,7 +8,7 @@ import type { DeleteChatItemProps } from '@/global/core/chat/api.d'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { await connectToDatabase(); - const { chatId, contentId, shareId, outLinkUid } = req.query as DeleteChatItemProps; + const { appId, chatId, contentId, shareId, outLinkUid } = req.query as DeleteChatItemProps; if (!contentId || !chatId) { return jsonRes(res); @@ -17,6 +17,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) await autChatCrud({ req, authToken: true, + appId, chatId, shareId, outLinkUid, diff --git a/projects/app/src/pages/api/core/chat/updateHistory.ts b/projects/app/src/pages/api/core/chat/updateHistory.ts index f3b647436..8e983fd7d 100644 --- a/projects/app/src/pages/api/core/chat/updateHistory.ts +++ b/projects/app/src/pages/api/core/chat/updateHistory.ts @@ -9,11 +9,12 @@ import { autChatCrud } from '@/service/support/permission/auth/chat'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { await connectToDatabase(); - const { chatId, shareId, outLinkUid, customTitle, top } = req.body as UpdateHistoryProps; + const { appId, chatId, shareId, outLinkUid, customTitle, top } = req.body as UpdateHistoryProps; await autChatCrud({ req, authToken: true, + appId, chatId, shareId, outLinkUid, diff --git a/projects/app/src/pages/api/core/plugin/templates.ts b/projects/app/src/pages/api/core/plugin/templates.ts index e32b8cd4a..e6fc8129b 100644 --- a/projects/app/src/pages/api/core/plugin/templates.ts +++ b/projects/app/src/pages/api/core/plugin/templates.ts @@ -16,7 +16,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< const [userPlugins, plusPlugins] = await Promise.all([ MongoPlugin.find({ teamId }).lean(), - global.systemEnv.pluginBaseUrl ? GET('/core/plugin/getTemplates') : [] + global.systemEnv?.pluginBaseUrl ? GET('/core/plugin/getTemplates') : [] ]); const data: FlowModuleTemplateType[] = [ diff --git a/projects/app/src/pages/api/system/getInitData.ts b/projects/app/src/pages/api/system/getInitData.ts index 966820965..cc7cf47fa 100644 --- a/projects/app/src/pages/api/system/getInitData.ts +++ b/projects/app/src/pages/api/system/getInitData.ts @@ -21,6 +21,7 @@ import { SimpleModeTemplate_FastGPT_Universal } from '@/global/core/app/constant import { getSimpleTemplatesFromPlus } from '@/service/core/app/utils'; import { PluginTypeEnum } from '@fastgpt/global/core/plugin/constants'; import { getFastGPTFeConfig } from '@fastgpt/service/common/system/config/controller'; +import { connectToDatabase } from '@/service/mongo'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { await getInitConfig(); @@ -68,6 +69,7 @@ const defaultFeConfigs: FeConfigsType = { export async function getInitConfig() { try { if (global.feConfigs) return; + await connectToDatabase(); initGlobal(); const filename = diff --git a/projects/app/src/pages/api/v1/chat/completions.ts b/projects/app/src/pages/api/v1/chat/completions.ts index 899bbd684..4719bd450 100644 --- a/projects/app/src/pages/api/v1/chat/completions.ts +++ b/projects/app/src/pages/api/v1/chat/completions.ts @@ -180,6 +180,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex req, authToken: true, authApiKey: true, + appId: app._id, chatId, shareId, outLinkUid, @@ -188,7 +189,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex // get and concat history const { history } = await getChatItems({ chatId, limit: 30, field: `dataId obj value` }); - const concatHistory = history.concat(chatMessages); + const concatHistories = history.concat(chatMessages); /* start flow controller */ const { responseData, answerText } = await dispatchModules({ @@ -200,8 +201,8 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex teamId: user.team.teamId, tmbId: user.team.tmbId, variables, - params: { - history: concatHistory, + histories: concatHistories, + startParams: { userChatInput: question.value }, stream, diff --git a/projects/app/src/pages/app/detail/components/AdEdit/Header.tsx b/projects/app/src/pages/app/detail/components/AdEdit/Header.tsx index fcde80b39..7dfb8d71a 100644 --- a/projects/app/src/pages/app/detail/components/AdEdit/Header.tsx +++ b/projects/app/src/pages/app/detail/components/AdEdit/Header.tsx @@ -1,4 +1,4 @@ -import React, { useRef, useState } from 'react'; +import React, { useCallback, useRef, useState } from 'react'; import { Box, Flex, IconButton, useTheme, useDisclosure } from '@chakra-ui/react'; import { SmallCloseIcon } from '@chakra-ui/icons'; import { ModuleItemType } from '@fastgpt/global/core/module/type'; @@ -14,6 +14,7 @@ import MyTooltip from '@/components/MyTooltip'; import ChatTest, { type ChatTestComponentRef } from '@/components/core/module/Flow/ChatTest'; import { flowNode2Modules, useFlowProviderStore } from '@/components/core/module/Flow/FlowProvider'; import { useAppStore } from '@/web/core/app/store/useAppStore'; +import { useToast } from '@/web/common/hooks/useToast'; const ImportSettings = dynamic(() => import('@/components/core/module/Flow/ImportSettings')); @@ -31,6 +32,7 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({ setTestModules: React.Dispatch; }) { const theme = useTheme(); + const { toast } = useToast(); const { t } = useTranslation(); const { copyData } = useCopyData(); const { isOpen: isOpenImport, onOpen: onOpenImport, onClose: onCloseImport } = useDisclosure(); @@ -38,8 +40,8 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({ const { nodes, edges, onFixView } = useFlowProviderStore(); - const { mutate: onclickSave, isLoading } = useRequest({ - mutationFn: () => { + const flow2ModulesAndCheck = useCallback( + (tip = false) => { const modules = flowNode2Modules({ nodes, edges }); // check required connect for (let i = 0; i < modules.length; i++) { @@ -51,12 +53,24 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({ return false; }) ) { - return Promise.reject(`【${item.name}】存在未填或未连接参数`); + const msg = `【${item.name}】存在未填或未连接参数`; + tip && + toast({ + status: 'warning', + title: msg + }); + return Promise.reject(msg); } } + return modules; + }, + [edges, nodes, toast] + ); + const { mutate: onclickSave, isLoading } = useRequest({ + mutationFn: async () => { return updateAppDetail(app._id, { - modules, + modules: await flow2ModulesAndCheck(), type: AppTypeEnum.advanced, permission: undefined }); @@ -139,8 +153,8 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({ borderRadius={'lg'} aria-label={'save'} variant={'base'} - onClick={() => { - setTestModules(flowNode2Modules({ nodes, edges })); + onClick={async () => { + setTestModules(await flow2ModulesAndCheck(true)); }} /> diff --git a/projects/app/src/pages/app/detail/components/Logs.tsx b/projects/app/src/pages/app/detail/components/Logs.tsx index f98bb3704..c6230779d 100644 --- a/projects/app/src/pages/app/detail/components/Logs.tsx +++ b/projects/app/src/pages/app/detail/components/Logs.tsx @@ -321,6 +321,7 @@ function DetailLogsModal({ showMarkIcon showVoiceIcon={false} userGuideModule={chat?.app?.userGuideModule} + appId={appId} chatId={chatId} /> diff --git a/projects/app/src/pages/app/detail/components/OutLink/EmbModal.tsx b/projects/app/src/pages/app/detail/components/OutLink/EmbModal.tsx deleted file mode 100644 index 950da7948..000000000 --- a/projects/app/src/pages/app/detail/components/OutLink/EmbModal.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { OutLinkSchema } from '@fastgpt/global/support/outLink/type'; -import React from 'react'; -import MyModal from '@/components/MyModal'; - -const EmbModal = ({ share }: { share: OutLinkSchema }) => { - return EmbModal; -}; - -export default EmbModal; diff --git a/projects/app/src/pages/app/detail/components/OutLink/SelectUsingWayModal.tsx b/projects/app/src/pages/app/detail/components/OutLink/SelectUsingWayModal.tsx new file mode 100644 index 000000000..1140e6993 --- /dev/null +++ b/projects/app/src/pages/app/detail/components/OutLink/SelectUsingWayModal.tsx @@ -0,0 +1,209 @@ +import { OutLinkSchema } from '@fastgpt/global/support/outLink/type'; +import React, { useCallback, useState } from 'react'; +import MyModal from '@/components/MyModal'; +import { useTranslation } from 'next-i18next'; +import { Box, Flex, FlexProps, Grid, Image, ModalBody, Switch, useTheme } from '@chakra-ui/react'; +import MyRadio from '@/components/common/MyRadio'; +import { useForm } from 'react-hook-form'; +import MyIcon from '@/components/Icon'; +import { useCopyData } from '@/web/common/hooks/useCopyData'; +import { useSelectFile } from '@/web/common/file/hooks/useSelectFile'; +import { fileToBase64 } from '@/web/common/file/utils'; + +enum UsingWayEnum { + link = 'link', + iframe = 'iframe', + script = 'script' +} + +const SelectUsingWayModal = ({ share, onClose }: { share: OutLinkSchema; onClose: () => void }) => { + const { t } = useTranslation(); + const theme = useTheme(); + const { copyData } = useCopyData(); + const { File, onOpen } = useSelectFile({ + multiple: false, + fileType: 'image/*' + }); + + const VariableTypeList = [ + { + title: {''}, + value: UsingWayEnum.link + }, + { + title: {''}, + value: UsingWayEnum.iframe + }, + { + title: {''}, + value: UsingWayEnum.script + } + ]; + + const [refresh, setRefresh] = useState(false); + + const { getValues, setValue, register, watch } = useForm({ + defaultValues: { + usingWay: UsingWayEnum.link, + showHistory: true, + scriptIconCanDrag: true, + scriptDefaultOpen: true, + scriptOpenIcon: + 'data:image/svg+xml;base64,PHN2ZyB0PSIxNjkwNTMyNzg1NjY0IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjQxMzIiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48cGF0aCBkPSJNNTEyIDMyQzI0Ny4wNCAzMiAzMiAyMjQgMzIgNDY0QTQxMC4yNCA0MTAuMjQgMCAwIDAgMTcyLjQ4IDc2OEwxNjAgOTY1LjEyYTI1LjI4IDI1LjI4IDAgMCAwIDM5LjA0IDIyLjRsMTY4LTExMkE1MjguNjQgNTI4LjY0IDAgMCAwIDUxMiA4OTZjMjY0Ljk2IDAgNDgwLTE5MiA0ODAtNDMyUzc3Ni45NiAzMiA1MTIgMzJ6IG0yNDQuOCA0MTZsLTM2MS42IDMwMS43NmExMi40OCAxMi40OCAwIDAgMS0xOS44NC0xMi40OGw1OS4yLTIzMy45MmgtMTYwYTEyLjQ4IDEyLjQ4IDAgMCAxLTcuMzYtMjMuMzZsMzYxLjYtMzAxLjc2YTEyLjQ4IDEyLjQ4IDAgMCAxIDE5Ljg0IDEyLjQ4bC01OS4yIDIzMy45MmgxNjBhMTIuNDggMTIuNDggMCAwIDEgOCAyMi4wOHoiIGZpbGw9IiM0ZTgzZmQiIHAtaWQ9IjQxMzMiPjwvcGF0aD48L3N2Zz4=', + scriptCloseIcon: + 'data:image/svg+xml;base64,PHN2ZyB0PSIxNjkwNTM1NDQxNTI2IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjYzNjciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48cGF0aCBkPSJNNTEyIDEwMjRBNTEyIDUxMiAwIDEgMSA1MTIgMGE1MTIgNTEyIDAgMCAxIDAgMTAyNHpNMzA1Ljk1NjU3MSAzNzAuMzk1NDI5TDQ0Ny40ODggNTEyIDMwNS45NTY1NzEgNjUzLjYwNDU3MWE0NS41NjggNDUuNTY4IDAgMSAwIDY0LjQzODg1OCA2NC40Mzg4NThMNTEyIDU3Ni41MTJsMTQxLjYwNDU3MSAxNDEuNTMxNDI5YTQ1LjU2OCA0NS41NjggMCAwIDAgNjQuNDM4ODU4LTY0LjQzODg1OEw1NzYuNTEyIDUxMmwxNDEuNTMxNDI5LTE0MS42MDQ1NzFhNDUuNTY4IDQ1LjU2OCAwIDEgMC02NC40Mzg4NTgtNjQuNDM4ODU4TDUxMiA0NDcuNDg4IDM3MC4zOTU0MjkgMzA1Ljk1NjU3MWE0NS41NjggNDUuNTY4IDAgMCAwLTY0LjQzODg1OCA2NC40Mzg4NTh6IiBmaWxsPSIjNGU4M2ZkIiBwLWlkPSI2MzY4Ij48L3BhdGg+PC9zdmc+' + } + }); + + const selectFile = useCallback( + async (files: File[], key: 'scriptOpenIcon' | 'scriptCloseIcon') => { + const file = files[0]; + if (!file) return; + // image to base64 + const base64 = await fileToBase64(file); + setValue(key, base64); + }, + [setValue] + ); + + watch(() => { + setRefresh(!refresh); + }); + + const linkUrl = `${location?.origin}/chat/share?shareId=${share?.shareId}${ + getValues('showHistory') ? '' : '&showHistory=0' + }`; + + const wayMap = { + [UsingWayEnum.link]: { + blockTitle: t('core.app.outLink.Link block title'), + code: linkUrl + }, + [UsingWayEnum.iframe]: { + blockTitle: t('core.app.outLink.Iframe block title'), + code: `