From 3f9b0fa1d425dc95e21ae6f0299aaa2d92ee73cb Mon Sep 17 00:00:00 2001 From: Archer <545436317@qq.com> Date: Sun, 7 Sep 2025 14:41:48 +0800 Subject: [PATCH] V4.12.3 features (#5595) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: remove ModelProviderIdType and update related types (#5549) * perf: model provider * fix eval create split (#5570) * git rebase --continuedoc * add more variable types (#5540) * variable types * password * time picker * internal var * file * fix-test * time select default value & range * password & type render * fix * fix build * fix * move method * split date select * icon * perf: variable code * prompt editor add markdown plugin (#5556) * editor markdown * fix build * pnpm lock * add props * update code * fix list * editor ui * fix variable reset (#5586) * perf: variables type code * customize lexical indent (#5588) * perf: multiple selector * perf: tab plugin * doc * refactor: update workflow constants to use ToolTypeEnum (#5491) * refactor: replace FlowNodeTemplateTypeEnum with string literals in workflow templates * perf: tool type --------- Co-authored-by: archer <545436317@qq.com> * update doc * fix: make table's row more natural while dragging it (#5596) * feat: add APIGetTemplate function and refactor template fetching logic (#5498) * feat: add APIGetTemplate function and refactor template fetching logic * chore: adjust the code * chore: update sdk --------- Co-authored-by: FinleyGe * perf init system * doc * remove log * remove i18n * perf: variables render --------- Co-authored-by: Ctrlz <143257420+ctrlz526@users.noreply.github.com> Co-authored-by: heheer Co-authored-by: 伍闲犬 Co-authored-by: FinleyGe --- document/content/docs/upgrading/4-12/4120.mdx | 2 +- document/content/docs/upgrading/4-12/4121.mdx | 2 +- document/content/docs/upgrading/4-12/4122.mdx | 2 +- document/content/docs/upgrading/4-12/4123.mdx | 12 +- document/data/doc-last-modified.json | 8 +- document/source.config.ts | 2 +- packages/global/common/i18n/utils.ts | 4 +- packages/global/common/secret/utils.ts | 3 + packages/global/core/ai/model.d.ts | 3 +- packages/global/core/ai/model.ts | 24 - packages/global/core/ai/provider.ts | 119 +- packages/global/core/app/type.d.ts | 12 + packages/global/core/app/utils.ts | 2 +- packages/global/core/workflow/constants.ts | 176 +- .../global/core/workflow/node/constant.ts | 14 +- .../global/core/workflow/runtime/utils.ts | 40 +- .../template/system/customFeedback.ts | 4 +- .../core/workflow/template/system/http468.ts | 4 +- .../workflow/template/system/textEditor.ts | 4 +- packages/global/core/workflow/utils.ts | 21 +- packages/global/package.json | 2 +- packages/service/common/secret/utils.ts | 7 + .../service/common/vectorDB/milvus/index.ts | 2 +- packages/service/core/ai/config/utils.ts | 12 +- packages/service/core/ai/type.d.ts | 11 + packages/service/core/app/evaluation/utils.ts | 147 ++ .../service/core/app/plugin/controller.ts | 26 +- .../core/app/plugin/pluginGroupSchema.ts | 4 +- packages/service/core/app/plugin/type.d.ts | 5 +- .../service/core/app/provider/controller.ts | 29 + .../core/app}/templates/register.ts | 37 +- packages/service/core/app/tool/api.ts | 24 + .../service/core/workflow/dispatch/index.ts | 36 +- .../workflow/dispatch/tools/runUpdateVar.ts | 7 +- .../service/core/workflow/dispatch/utils.ts | 23 +- packages/service/core/workflow/utils.ts | 1 - .../thirdProvider/fastgptPlugin/model.ts | 11 + packages/service/worker/preload.ts | 45 +- packages/templates/README.md | 3 - packages/templates/package.json | 10 - packages/templates/src/CQ/template.json | 411 ---- packages/templates/src/Chinese/template.json | 507 ---- .../src/TranslateRobot/template.json | 581 ----- .../templates/src/animalLife/template.json | 503 ---- .../templates/src/chatGuide/template.json | 196 -- .../templates/src/divination/template.json | 518 ---- packages/templates/src/flux/template.json | 330 --- .../templates/src/githubIssue/template.json | 926 ------- packages/templates/src/google/template.json | 443 ---- .../templates/src/longTranslate/template.json | 2161 ----------------- .../templates/src/plugin-dalle/template.json | 330 --- .../templates/src/plugin-feishu/template.json | 355 --- .../src/simpleDatasetChat/template.json | 288 --- .../templates/src/srt-translate/template.json | 1934 --------------- packages/templates/src/stock/template.json | 503 ---- packages/templates/src/timeBot/template.json | 186 -- packages/templates/tsconfig.json | 21 - packages/templates/type.d.ts | 5 - .../common/DateTimePicker/index.tsx | 106 + .../web/components/common/Icon/constants.ts | 12 + .../icons/core/workflow/inputType/dataset.svg | 5 + .../core/workflow/inputType/external.svg | 3 + .../icons/core/workflow/inputType/input.svg | 6 +- .../core/workflow/inputType/internal.svg | 5 + .../icons/core/workflow/inputType/model.svg | 3 + .../workflow/inputType/multipleSelect.svg | 3 + .../icons/core/workflow/inputType/option.svg | 4 +- .../core/workflow/inputType/password.svg | 3 + .../workflow/inputType/timePointSelect.svg | 3 + .../workflow/inputType/timeRangeSelect.svg | 3 + .../common/Icon/icons/model/huggingface.svg | 15 + .../common/Input/HttpInput/Editor.tsx | 1 - .../common/Input/HttpInput/index.tsx | 2 +- .../common/Input/NumberInput/index.tsx | 30 +- .../common/MySelect/MultipleSelect.tsx | 162 +- .../common/Textarea/PromptEditor/Editor.tsx | 180 +- .../Textarea/PromptEditor/index.module.scss | 11 + .../common/Textarea/PromptEditor/index.tsx | 22 +- .../modules/DropDownMenu/index.tsx | 93 - .../plugins/ListDisplayFixPlugin/index.tsx | 66 + .../plugins/ListExitPlugin/index.tsx | 135 + .../plugins/MarkdownPlugin/index.tsx | 8 + .../plugins/MarkdownTransformers/index.ts | 12 + .../plugins/TabToSpacesPlugin/index.tsx | 216 ++ .../common/Textarea/PromptEditor/utils.ts | 49 +- packages/web/core/workflow/constants.ts | 74 +- packages/web/i18n/en/app.json | 22 +- packages/web/i18n/en/chat.json | 3 +- packages/web/i18n/en/common.json | 21 +- packages/web/i18n/en/workflow.json | 2 + packages/web/i18n/zh-CN/app.json | 24 +- packages/web/i18n/zh-CN/chat.json | 19 +- packages/web/i18n/zh-CN/common.json | 22 +- packages/web/i18n/zh-CN/workflow.json | 2 + packages/web/i18n/zh-Hant/app.json | 21 +- packages/web/i18n/zh-Hant/chat.json | 3 +- packages/web/i18n/zh-Hant/common.json | 21 +- packages/web/i18n/zh-Hant/workflow.json | 2 + packages/web/package.json | 6 +- pnpm-lock.yaml | 62 +- projects/app/.env.template | 9 +- projects/app/package.json | 1 - .../src/components/Select/AIModelSelector.tsx | 63 +- .../PromptEditor/OptimizerPopover/index.tsx | 1 - .../components/core/ai/ModelTable/index.tsx | 24 +- .../app/src/components/core/app/TTSSelect.tsx | 6 +- .../src/components/core/app/VariableEdit.tsx | 233 +- .../core/app/formRender/LabelAndForm.tsx | 28 +- .../core/app/formRender/TimeInput.tsx | 178 ++ .../core/app/formRender/constant.ts | 5 +- .../components/core/app/formRender/index.tsx | 161 +- .../components/core/app/formRender/type.d.ts | 20 +- .../components/core/app/formRender/utils.ts | 9 +- .../chat/ChatContainer/ChatBox/Provider.tsx | 4 +- .../ChatBox/components/VariableInputForm.tsx | 153 +- .../ChatBox/components/VariablePopover.tsx | 108 - .../components/home/ChatHomeVariablesForm.tsx | 8 +- .../chat/ChatContainer/ChatBox/constants.ts | 1 + .../core/chat/ChatContainer/ChatBox/index.tsx | 46 +- .../ChatContainer/PluginRunBox/context.tsx | 6 +- .../components/VariablePopover.tsx | 172 ++ projects/app/src/global/aiproxy/constants.ts | 8 +- .../app/src/global/common/api/systemRes.d.ts | 22 - projects/app/src/instrumentation.ts | 21 +- .../account/model/AddModelBox.tsx | 12 +- .../model/Channel/EditChannelModal.tsx | 23 +- .../account/model/Channel/ModelTest.tsx | 6 +- .../account/model/Channel/index.tsx | 12 +- .../account/model/Log/index.tsx | 12 +- .../account/model/ModelConfigTable.tsx | 27 +- .../account/model/ModelDashboard/index.tsx | 6 +- .../app/detail/MCPTools/ChatTest.tsx | 4 +- .../app/detail/SimpleApp/ChatTest.tsx | 5 +- .../app/detail/SimpleApp/EditForm.tsx | 1 + .../SimpleApp/components/ToolSelectModal.tsx | 47 +- .../WorkflowComponents/Flow/ChatTest.tsx | 7 +- .../Flow/components/NodeTemplates/list.tsx | 139 +- .../Flow/hooks/useDebug.tsx | 32 +- .../nodes/NodePluginIO/InputTypeConfig.tsx | 123 +- .../Flow/nodes/NodeVariableUpdate.tsx | 75 +- .../Flow/nodes/render/RenderInput/index.tsx | 9 + .../pageComponents/app/detail/useChatTest.tsx | 23 +- .../app/evaluation/DetailModal.tsx | 10 +- .../src/pageComponents/chat/ChatHeader.tsx | 7 +- .../FavouriteAppSetting/TagManageModal.tsx | 2 +- .../ChatSetting/FavouriteAppSetting/index.tsx | 270 +- .../chat/ChatSetting/ToolSelectModal.tsx | 53 +- .../pageComponents/dashboard/Container.tsx | 15 +- .../dashboard/SystemPlugin/ToolCard.tsx | 9 +- .../src/pageComponents/dataset/list/List.tsx | 3 +- .../app/src/pageComponents/login/index.tsx | 6 +- .../pages/api/common/system/getInitData.ts | 35 +- .../app/src/pages/api/core/ai/model/list.ts | 3 +- .../app/plugin/getSystemPluginTemplates.ts | 2 +- .../api/core/app/plugin/getToolGroups.ts | 29 + .../src/pages/api/core/app/template/detail.ts | 2 +- .../src/pages/api/core/app/template/list.ts | 2 +- .../app/src/pages/api/v2/chat/completions.ts | 1 + .../app/src/service/common/system/index.ts | 37 +- .../service/common/system/volumnMongoWatch.ts | 2 +- projects/app/src/web/common/system/api.ts | 2 +- .../src/web/common/system/useSystemStore.ts | 55 +- projects/app/src/web/core/app/api/plugin.ts | 9 +- .../web/core/chat/context/chatItemContext.tsx | 39 +- projects/app/src/web/styles/reset.scss | 3 + test/setupModels.ts | 5 +- 166 files changed, 3407 insertions(+), 11604 deletions(-) create mode 100644 packages/global/common/secret/utils.ts create mode 100644 packages/service/core/app/evaluation/utils.ts create mode 100644 packages/service/core/app/provider/controller.ts rename packages/{ => service/core/app}/templates/register.ts (66%) create mode 100644 packages/service/thirdProvider/fastgptPlugin/model.ts delete mode 100644 packages/templates/README.md delete mode 100644 packages/templates/package.json delete mode 100644 packages/templates/src/CQ/template.json delete mode 100644 packages/templates/src/Chinese/template.json delete mode 100644 packages/templates/src/TranslateRobot/template.json delete mode 100644 packages/templates/src/animalLife/template.json delete mode 100644 packages/templates/src/chatGuide/template.json delete mode 100644 packages/templates/src/divination/template.json delete mode 100644 packages/templates/src/flux/template.json delete mode 100644 packages/templates/src/githubIssue/template.json delete mode 100644 packages/templates/src/google/template.json delete mode 100644 packages/templates/src/longTranslate/template.json delete mode 100644 packages/templates/src/plugin-dalle/template.json delete mode 100644 packages/templates/src/plugin-feishu/template.json delete mode 100644 packages/templates/src/simpleDatasetChat/template.json delete mode 100644 packages/templates/src/srt-translate/template.json delete mode 100644 packages/templates/src/stock/template.json delete mode 100644 packages/templates/src/timeBot/template.json delete mode 100644 packages/templates/tsconfig.json delete mode 100644 packages/templates/type.d.ts create mode 100644 packages/web/components/common/DateTimePicker/index.tsx create mode 100644 packages/web/components/common/Icon/icons/core/workflow/inputType/dataset.svg create mode 100644 packages/web/components/common/Icon/icons/core/workflow/inputType/external.svg create mode 100644 packages/web/components/common/Icon/icons/core/workflow/inputType/internal.svg create mode 100644 packages/web/components/common/Icon/icons/core/workflow/inputType/model.svg create mode 100644 packages/web/components/common/Icon/icons/core/workflow/inputType/multipleSelect.svg create mode 100644 packages/web/components/common/Icon/icons/core/workflow/inputType/password.svg create mode 100644 packages/web/components/common/Icon/icons/core/workflow/inputType/timePointSelect.svg create mode 100644 packages/web/components/common/Icon/icons/core/workflow/inputType/timeRangeSelect.svg create mode 100644 packages/web/components/common/Icon/icons/model/huggingface.svg delete mode 100644 packages/web/components/common/Textarea/PromptEditor/modules/DropDownMenu/index.tsx create mode 100644 packages/web/components/common/Textarea/PromptEditor/plugins/ListDisplayFixPlugin/index.tsx create mode 100644 packages/web/components/common/Textarea/PromptEditor/plugins/ListExitPlugin/index.tsx create mode 100644 packages/web/components/common/Textarea/PromptEditor/plugins/MarkdownPlugin/index.tsx create mode 100644 packages/web/components/common/Textarea/PromptEditor/plugins/MarkdownTransformers/index.ts create mode 100644 packages/web/components/common/Textarea/PromptEditor/plugins/TabToSpacesPlugin/index.tsx create mode 100644 projects/app/src/components/core/app/formRender/TimeInput.tsx delete mode 100644 projects/app/src/components/core/chat/ChatContainer/ChatBox/components/VariablePopover.tsx create mode 100644 projects/app/src/components/core/chat/ChatContainer/components/VariablePopover.tsx delete mode 100644 projects/app/src/global/common/api/systemRes.d.ts create mode 100644 projects/app/src/pages/api/core/app/plugin/getToolGroups.ts diff --git a/document/content/docs/upgrading/4-12/4120.mdx b/document/content/docs/upgrading/4-12/4120.mdx index 49ee58de3..a65b55e33 100644 --- a/document/content/docs/upgrading/4-12/4120.mdx +++ b/document/content/docs/upgrading/4-12/4120.mdx @@ -1,6 +1,6 @@ --- title: 'V4.12.0(包含升级脚本)' -description: 'FastGPT V4.12.0 更新说明, 发布于 2025-8-11。' +description: 'FastGPT V4.12.0 更新说明, 发布于 2025-8-11' --- ## 更新指南 diff --git a/document/content/docs/upgrading/4-12/4121.mdx b/document/content/docs/upgrading/4-12/4121.mdx index 0560cf6d8..48a6e69ed 100644 --- a/document/content/docs/upgrading/4-12/4121.mdx +++ b/document/content/docs/upgrading/4-12/4121.mdx @@ -1,6 +1,6 @@ --- title: 'V4.12.1(包含升级脚本)' -description: 'FastGPT V4.12.1 更新说明, 发布于 2025-8-18。' +description: 'FastGPT V4.12.1 更新说明, 发布于 2025-8-18' --- ## 更新指南 diff --git a/document/content/docs/upgrading/4-12/4122.mdx b/document/content/docs/upgrading/4-12/4122.mdx index b93f4eddf..49cf24885 100644 --- a/document/content/docs/upgrading/4-12/4122.mdx +++ b/document/content/docs/upgrading/4-12/4122.mdx @@ -1,6 +1,6 @@ --- title: 'V4.12.2' -description: 'FastGPT V4.12.2 更新说明, 发布于 2025-8-26。' +description: 'FastGPT V4.12.2 更新说明, 发布于 2025-8-26' --- ## 更新指南 diff --git a/document/content/docs/upgrading/4-12/4123.mdx b/document/content/docs/upgrading/4-12/4123.mdx index fa9ed83af..3cb45ca0d 100644 --- a/document/content/docs/upgrading/4-12/4123.mdx +++ b/document/content/docs/upgrading/4-12/4123.mdx @@ -3,13 +3,16 @@ title: 'V4.12.3(进行中)' description: 'FastGPT V4.12.3 更新说明' --- - ## 🚀 新增内容 +1. 提示词编辑器支持列表、tab 渲染等部分富文本交互。 +2. 应用增加更多全局变量:密码、多选、内部变量(在站内对话不会显示)。 ## ⚙️ 优化 1. 纠正 RRF 权重合并算法,使用标准 RRF 权重公式。 +2. 多选组件支持动态宽度计算,适配可见 tag。 +3. 变量更新组件渲染优化,与全局变量渲染保持一致性。 ## 🐛 修复 @@ -17,5 +20,10 @@ description: 'FastGPT V4.12.3 更新说明' 2. 工作流文件上传默认打开,但输入侧未添加文件输出。 3. 连续用户选择,分支无法正常运行。 4. 工作流,变量更新,数组选择器异常。 +5. 应用评测,评测内容仅获取了首个输出文本,未获取所有输出文本。 -## 🔨 工具更新 +## 🔨 插件更新 + +1. 系统工具类型迁移至 plugin。 +2. 将模型提供商配置移动到 plugin,实现热更新。 +3. 将应用模板移动至 plugin。 \ No newline at end of file diff --git a/document/data/doc-last-modified.json b/document/data/doc-last-modified.json index 4dac3ea2c..0707b7ef3 100644 --- a/document/data/doc-last-modified.json +++ b/document/data/doc-last-modified.json @@ -102,10 +102,10 @@ "document/content/docs/upgrading/4-10/4101.mdx": "2025-08-02T19:38:37+08:00", "document/content/docs/upgrading/4-11/4110.mdx": "2025-08-05T23:20:39+08:00", "document/content/docs/upgrading/4-11/4111.mdx": "2025-08-07T22:49:09+08:00", - "document/content/docs/upgrading/4-12/4120.mdx": "2025-08-12T22:45:19+08:00", - "document/content/docs/upgrading/4-12/4121.mdx": "2025-08-15T22:53:06+08:00", - "document/content/docs/upgrading/4-12/4122.mdx": "2025-09-04T21:37:57+08:00", - "document/content/docs/upgrading/4-12/4123.mdx": "2025-09-04T21:37:57+08:00", + "document/content/docs/upgrading/4-12/4120.mdx": "2025-09-04T22:59:41+08:00", + "document/content/docs/upgrading/4-12/4121.mdx": "2025-09-04T22:59:41+08:00", + "document/content/docs/upgrading/4-12/4122.mdx": "2025-09-04T22:59:41+08:00", + "document/content/docs/upgrading/4-12/4123.mdx": "2025-09-05T17:31:22+08:00", "document/content/docs/upgrading/4-8/40.mdx": "2025-08-02T19:38:37+08:00", "document/content/docs/upgrading/4-8/41.mdx": "2025-08-02T19:38:37+08:00", "document/content/docs/upgrading/4-8/42.mdx": "2025-08-02T19:38:37+08:00", diff --git a/document/source.config.ts b/document/source.config.ts index 886d4bac0..153c59297 100644 --- a/document/source.config.ts +++ b/document/source.config.ts @@ -19,4 +19,4 @@ export default defineConfig({ mdxOptions: { // MDX options } -}); \ No newline at end of file +}); diff --git a/packages/global/common/i18n/utils.ts b/packages/global/common/i18n/utils.ts index 8e3f5082b..ac271bcab 100644 --- a/packages/global/common/i18n/utils.ts +++ b/packages/global/common/i18n/utils.ts @@ -1,6 +1,6 @@ import type { I18nStringType, localeType } from './type'; -export const parseI18nString = (str: I18nStringType | string = '', lang: localeType = 'en') => { +export const parseI18nString = (str: I18nStringType | string = '', lang = 'en') => { if (!str || typeof str === 'string') return str; - return str[lang] ?? str['en']; + return str[lang as localeType] ?? str['en']; }; diff --git a/packages/global/common/secret/utils.ts b/packages/global/common/secret/utils.ts new file mode 100644 index 000000000..cf8ec472c --- /dev/null +++ b/packages/global/common/secret/utils.ts @@ -0,0 +1,3 @@ +export const isSecretValue = (val: any) => { + return typeof val === 'object' && val !== null && !!val.secret; +}; diff --git a/packages/global/core/ai/model.d.ts b/packages/global/core/ai/model.d.ts index 694c63b48..fe9a81f6b 100644 --- a/packages/global/core/ai/model.d.ts +++ b/packages/global/core/ai/model.d.ts @@ -1,5 +1,4 @@ import type { ModelTypeEnum } from './model'; -import type { ModelProviderIdType } from './provider'; type PriceType = { charsPointsPrice?: number; // 1k chars=n points; 60s=n points; @@ -9,7 +8,7 @@ type PriceType = { outputPrice?: number; // 1k tokens=n points }; type BaseModelItemType = { - provider: ModelProviderIdType; + provider: string; model: string; name: string; avatar?: string; // model icon, from provider diff --git a/packages/global/core/ai/model.ts b/packages/global/core/ai/model.ts index ca5aacde1..766026cf2 100644 --- a/packages/global/core/ai/model.ts +++ b/packages/global/core/ai/model.ts @@ -1,6 +1,5 @@ import { i18nT } from '../../../web/i18n/utils'; import type { LLMModelItemType, STTModelType, EmbeddingModelItemType } from './model.d'; -import { getModelProvider, type ModelProviderIdType } from './provider'; export enum ModelTypeEnum { llm = 'llm', @@ -54,29 +53,6 @@ export const defaultSTTModels: STTModelType[] = [ } ]; -export const getModelFromList = ( - modelList: { provider: ModelProviderIdType; name: string; model: string }[], - model: string, - language: string -): - | { - avatar: string; - provider: ModelProviderIdType; - name: string; - model: string; - } - | undefined => { - const modelData = modelList.find((item) => item.model === model) ?? modelList[0]; - if (!modelData) { - return; - } - const provider = getModelProvider(modelData.provider, language); - return { - ...modelData, - avatar: provider.avatar - }; -}; - export const modelTypeList = [ { label: i18nT('common:model.type.chat'), value: ModelTypeEnum.llm }, { label: i18nT('common:model.type.embedding'), value: ModelTypeEnum.embedding }, diff --git a/packages/global/core/ai/provider.ts b/packages/global/core/ai/provider.ts index 9c8a7216a..96047dca8 100644 --- a/packages/global/core/ai/provider.ts +++ b/packages/global/core/ai/provider.ts @@ -1,77 +1,70 @@ -import { ModelProviders } from '../../sdk/fastgpt-plugin'; +import type { I18nStringStrictType } from '@fastgpt-sdk/plugin'; -export type ModelProviderIdType = keyof typeof ModelProviders; -type ProviderValueTypes = (typeof ModelProviders)[ModelProviderIdType]; -type langType = 'en' | 'zh-CN' | 'zh-Hant'; - -export type ModelProviderType = { - id: ModelProviderIdType; - name: any; +export type ModelProviderItemType = { + id: string; + name: string; avatar: string; order: number; }; -const getLocalizedName = (translations: ProviderValueTypes, language = 'en'): string => { - return translations[language as langType]; +export type ModelProviderListType = { + id: string; + name: I18nStringStrictType | string; + avatar: string; + provider: string; }; -export const formatModelProviderList = (language?: string) => { - return Object.entries(ModelProviders).map(([id, translations], index) => ({ - id: id as ModelProviderIdType, - name: getLocalizedName(translations, language), - avatar: `/api/system/plugin/models/${id}.svg`, - order: index - })); -}; -export const formatModelProviderMap = (language?: string) => { - const provider = {} as Record< - ModelProviderIdType, - { - id: string; - name: string; - avatar: string; - order: number; - } - >; +export type langType = keyof I18nStringStrictType; - Object.entries(ModelProviders).forEach(([id, translations], index) => { - provider[id as ModelProviderIdType] = { - id: id as ModelProviderIdType, - name: getLocalizedName(translations, language), - avatar: `/api/system/plugin/models/${id}.svg`, - order: index - }; - }); - - return provider; -}; - -const ModelProviderListCache = { - en: formatModelProviderList('en'), - 'zh-CN': formatModelProviderList('zh-CN'), - 'zh-Hant': formatModelProviderList('zh-Hant') -}; -const ModelProviderMapCache = { - en: formatModelProviderMap('en'), - 'zh-CN': formatModelProviderMap('zh-CN'), - 'zh-Hant': formatModelProviderMap('zh-Hant') -}; - -const defaultProvider = { - id: 'Other' as ModelProviderIdType, +export const defaultProvider: ModelProviderItemType = { + id: 'Other', name: 'Other', - avatar: 'model/other', - order: 0 + avatar: 'model/huggingface', + order: 999 }; -export const getModelProviders = (language = 'en') => { - return ModelProviderListCache[language as langType]; -}; +export const formatModelProviders = (data: { provider: string; value: I18nStringStrictType }[]) => { + const getLocalizedName = (translations: I18nStringStrictType, language = 'en'): string => { + return translations[language as langType] || translations.en; + }; -export const getModelProvider = (provider?: ModelProviderIdType, language = 'en') => { - if (!provider) { - return defaultProvider; - } + const formatModelProviderList = (language?: string): ModelProviderItemType[] => { + return data.map(({ provider, value }, index) => ({ + id: provider, + name: getLocalizedName(value, language), + avatar: `/api/system/plugin/models/${provider}.svg`, + order: index + })); + }; - return ModelProviderMapCache[language as langType][provider] ?? defaultProvider; + const formatModelProviderMap = (language?: string) => { + const provider = {} as Record; + + data.forEach(({ provider: id, value }, index) => { + provider[id] = { + id, + name: getLocalizedName(value, language), + avatar: `/api/system/plugin/models/${id}.svg`, + order: index + }; + }); + + return provider; + }; + + const ModelProviderListCache = { + en: formatModelProviderList('en'), + 'zh-CN': formatModelProviderList('zh-CN'), + 'zh-Hant': formatModelProviderList('zh-Hant') + }; + const ModelProviderMapCache = { + en: formatModelProviderMap('en'), + 'zh-CN': formatModelProviderMap('zh-CN'), + 'zh-Hant': formatModelProviderMap('zh-Hant') + }; + + return { + ModelProviderListCache, + ModelProviderMapCache + }; }; diff --git a/packages/global/core/app/type.d.ts b/packages/global/core/app/type.d.ts index 624533289..f0fb3666a 100644 --- a/packages/global/core/app/type.d.ts +++ b/packages/global/core/app/type.d.ts @@ -162,11 +162,23 @@ export type VariableItemType = { // input maxLength?: number; + // password + minLength?: number; // numberInput max?: number; min?: number; // select list?: { label: string; value: string }[]; + // file + canSelectFile?: boolean; + canSelectImg?: boolean; + maxFiles?: number; + // timeSelect + timeGranularity?: 'second' | 'minute' | 'hour' | 'day'; + timeType?: 'point' | 'range'; + timeRangeStart?: string; + timeRangeEnd?: string; + // @deprecated enums?: { value: string; label: string }[]; }; diff --git a/packages/global/core/app/utils.ts b/packages/global/core/app/utils.ts index e967f7584..0f8cc4222 100644 --- a/packages/global/core/app/utils.ts +++ b/packages/global/core/app/utils.ts @@ -1,6 +1,6 @@ import type { AppChatConfigType, AppSimpleEditFormType } from '../app/type'; import { FlowNodeTypeEnum } from '../workflow/node/constant'; -import { NodeInputKeyEnum, FlowNodeTemplateTypeEnum } from '../workflow/constants'; +import { FlowNodeTemplateTypeEnum, NodeInputKeyEnum } from '../workflow/constants'; import type { FlowNodeInputItemType } from '../workflow/type/io.d'; import { getAppChatConfig } from '../workflow/utils'; import { type StoreNodeItemType } from '../workflow/type/node'; diff --git a/packages/global/core/workflow/constants.ts b/packages/global/core/workflow/constants.ts index 1cb29ffb6..a8eccad71 100644 --- a/packages/global/core/workflow/constants.ts +++ b/packages/global/core/workflow/constants.ts @@ -4,21 +4,8 @@ import type { JsonSchemaPropertiesItemType } from '../app/jsonschema'; export enum FlowNodeTemplateTypeEnum { systemInput = 'systemInput', ai = 'ai', - function = 'function', interactive = 'interactive', - - // System tool type tools = 'tools', - search = 'search', - multimodal = 'multimodal', - communication = 'communication', - finance = 'finance', - design = 'design', - productivity = 'productivity', - news = 'news', - entertainment = 'entertainment', - social = 'social', - scientific = 'scientific', other = 'other', // Team app type @@ -332,53 +319,144 @@ export enum VariableInputEnum { input = 'input', textarea = 'textarea', numberInput = 'numberInput', + JSONEditor = 'JSONEditor', select = 'select', - custom = 'custom' + multipleSelect = 'multipleSelect', + timePointSelect = 'timePointSelect', + timeRangeSelect = 'timeRangeSelect', + switch = 'switch', + password = 'password', + file = 'file', + + modelSelect = 'modelSelect', + datasetSelect = 'datasetSelect', + + custom = 'custom', + internal = 'internal' } -export const variableMap: Record< - VariableInputEnum, - { - icon: string; - label: string; - value: VariableInputEnum; - defaultValueType: WorkflowIOValueTypeEnum; - description?: string; - } -> = { - [VariableInputEnum.input]: { - icon: 'core/workflow/inputType/input', - label: i18nT('common:core.workflow.inputType.textInput'), - value: VariableInputEnum.input, - defaultValueType: WorkflowIOValueTypeEnum.string - }, + +type VariableConfigType = { + icon: string; + label: string; + value: VariableInputEnum; + defaultValueType: WorkflowIOValueTypeEnum; + description?: string; +}; + +export const variableConfigs: VariableConfigType[][] = [ + [ + { + icon: 'core/workflow/inputType/input', + label: i18nT('common:core.workflow.inputType.textInput'), + value: VariableInputEnum.input, + defaultValueType: WorkflowIOValueTypeEnum.string + }, + { + icon: 'core/workflow/inputType/password', + label: i18nT('common:core.workflow.inputType.password'), + value: VariableInputEnum.password, + defaultValueType: WorkflowIOValueTypeEnum.string + }, + { + icon: 'core/workflow/inputType/numberInput', + label: i18nT('common:core.workflow.inputType.number input'), + value: VariableInputEnum.numberInput, + defaultValueType: WorkflowIOValueTypeEnum.number + }, + // { + // icon: 'core/workflow/inputType/jsonEditor', + // label: i18nT('common:core.workflow.inputType.jsonEditor'), + // value: VariableInputEnum.JSONEditor, + // defaultValueType: WorkflowIOValueTypeEnum.object + // }, + { + icon: 'core/workflow/inputType/option', + label: i18nT('common:core.workflow.inputType.select'), + value: VariableInputEnum.select, + defaultValueType: WorkflowIOValueTypeEnum.string + }, + { + icon: 'core/workflow/inputType/multipleSelect', + label: i18nT('common:core.workflow.inputType.multipleSelect'), + value: VariableInputEnum.multipleSelect, + defaultValueType: WorkflowIOValueTypeEnum.arrayString + }, + { + icon: 'core/workflow/inputType/switch', + label: i18nT('common:core.workflow.inputType.switch'), + value: VariableInputEnum.switch, + defaultValueType: WorkflowIOValueTypeEnum.boolean + } + // { + // icon: 'core/workflow/inputType/timePointSelect', + // label: i18nT('common:core.workflow.inputType.timePointSelect'), + // value: VariableInputEnum.timePointSelect, + // defaultValueType: WorkflowIOValueTypeEnum.string + // }, + // { + // icon: 'core/workflow/inputType/timeRangeSelect', + // label: i18nT('common:core.workflow.inputType.timeRangeSelect'), + // value: VariableInputEnum.timeRangeSelect, + // defaultValueType: WorkflowIOValueTypeEnum.arrayString + // } + // { + // icon: 'core/workflow/inputType/file', + // label: i18nT('common:core.workflow.inputType.file'), + // value: VariableInputEnum.file, + // defaultValueType: WorkflowIOValueTypeEnum.arrayString + // } + ], + // [ + // { + // icon: 'core/workflow/inputType/model', + // label: i18nT('common:core.workflow.inputType.modelSelect'), + // value: VariableInputEnum.modelSelect, + // defaultValueType: WorkflowIOValueTypeEnum.string + // }, + // { + // icon: 'core/workflow/inputType/dataset', + // label: i18nT('common:core.workflow.inputType.datasetSelect'), + // value: VariableInputEnum.datasetSelect, + // defaultValueType: WorkflowIOValueTypeEnum.arrayString + // } + // ], + [ + { + icon: 'core/workflow/inputType/external', + label: i18nT('common:core.workflow.inputType.custom'), + value: VariableInputEnum.custom, + defaultValueType: WorkflowIOValueTypeEnum.string, + description: i18nT('app:variable.select type_desc') + }, + { + icon: 'core/workflow/inputType/internal', + label: i18nT('common:core.workflow.inputType.internal'), + value: VariableInputEnum.internal, + defaultValueType: WorkflowIOValueTypeEnum.string, + description: i18nT('app:variable.internal_type_desc') + } + ] +]; + +export const variableMap: Record = { + ...variableConfigs + .flat() + .reduce( + (acc, config) => ({ ...acc, [config.value]: config }), + {} as Record + ), [VariableInputEnum.textarea]: { icon: 'core/workflow/inputType/textarea', label: i18nT('common:core.workflow.inputType.textarea'), value: VariableInputEnum.textarea, defaultValueType: WorkflowIOValueTypeEnum.string, description: i18nT('app:variable.textarea_type_desc') - }, - [VariableInputEnum.numberInput]: { - icon: 'core/workflow/inputType/numberInput', - label: i18nT('common:core.workflow.inputType.number input'), - value: VariableInputEnum.numberInput, - defaultValueType: WorkflowIOValueTypeEnum.number - }, - [VariableInputEnum.select]: { - icon: 'core/workflow/inputType/option', - label: i18nT('common:core.workflow.inputType.select'), - value: VariableInputEnum.select, - defaultValueType: WorkflowIOValueTypeEnum.string - }, - [VariableInputEnum.custom]: { - icon: 'core/workflow/inputType/customVariable', - label: i18nT('common:core.workflow.inputType.custom'), - value: VariableInputEnum.custom, - defaultValueType: WorkflowIOValueTypeEnum.string, - description: i18nT('app:variable.select type_desc') } }; +// Keep backward compatibility +export const variableMapGroups = variableConfigs; + /* run time */ export enum RuntimeEdgeStatusEnum { 'waiting' = 'waiting', diff --git a/packages/global/core/workflow/node/constant.ts b/packages/global/core/workflow/node/constant.ts index eec34dc3a..c04aeda37 100644 --- a/packages/global/core/workflow/node/constant.ts +++ b/packages/global/core/workflow/node/constant.ts @@ -30,7 +30,10 @@ export enum FlowNodeInputTypeEnum { // render ui hidden = 'hidden', custom = 'custom', - fileSelect = 'fileSelect' + fileSelect = 'fileSelect', + timePointSelect = 'timePointSelect', + timeRangeSelect = 'timeRangeSelect', + password = 'password' } export const FlowNodeInputMap: Record< FlowNodeInputTypeEnum, @@ -94,6 +97,15 @@ export const FlowNodeInputMap: Record< }, [FlowNodeInputTypeEnum.fileSelect]: { icon: 'core/workflow/inputType/file' + }, + [FlowNodeInputTypeEnum.timePointSelect]: { + icon: 'core/workflow/inputType/timePointSelect' + }, + [FlowNodeInputTypeEnum.timeRangeSelect]: { + icon: 'core/workflow/inputType/timeRangeSelect' + }, + [FlowNodeInputTypeEnum.password]: { + icon: 'core/workflow/inputType/password' } }; diff --git a/packages/global/core/workflow/runtime/utils.ts b/packages/global/core/workflow/runtime/utils.ts index 2b9865bc5..575d9fc47 100644 --- a/packages/global/core/workflow/runtime/utils.ts +++ b/packages/global/core/workflow/runtime/utils.ts @@ -19,6 +19,7 @@ import type { FlowNodeOutputItemType, ReferenceValueType } from '../type/io'; import type { StoreNodeItemType } from '../type/node'; import { isValidReferenceValueFormat } from '../utils'; import type { RuntimeEdgeItemType, RuntimeNodeItemType } from './type'; +import { isSecretValue } from '../../../common/secret/utils'; export const checkIsBranchNode = (node: RuntimeNodeItemType) => { if (node.catchError) return true; @@ -67,7 +68,7 @@ export const getMaxHistoryLimitFromNodes = (nodes: StoreNodeItemType[]): number }; /* value type format */ -export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => { +export const valueTypeFormat = (value: any, valueType?: WorkflowIOValueTypeEnum) => { const isObjectString = (value: any) => { if (typeof value === 'string' && value !== 'false' && value !== 'true') { const trimmedValue = value.trim(); @@ -81,34 +82,37 @@ export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => { // 1. any值,忽略格式化 if (value === undefined || value === null) return value; - if (!type || type === WorkflowIOValueTypeEnum.any) return value; + if (!valueType || valueType === WorkflowIOValueTypeEnum.any) return value; + + // Password check + if (valueType === WorkflowIOValueTypeEnum.string && isSecretValue(value)) return value; // 2. 如果值已经符合目标类型,直接返回 if ( - (type === WorkflowIOValueTypeEnum.string && typeof value === 'string') || - (type === WorkflowIOValueTypeEnum.number && typeof value === 'number') || - (type === WorkflowIOValueTypeEnum.boolean && typeof value === 'boolean') || - (type.startsWith('array') && Array.isArray(value)) || - (type === WorkflowIOValueTypeEnum.object && typeof value === 'object') || - (type === WorkflowIOValueTypeEnum.chatHistory && + (valueType === WorkflowIOValueTypeEnum.string && typeof value === 'string') || + (valueType === WorkflowIOValueTypeEnum.number && typeof value === 'number') || + (valueType === WorkflowIOValueTypeEnum.boolean && typeof value === 'boolean') || + (valueType.startsWith('array') && Array.isArray(value)) || + (valueType === WorkflowIOValueTypeEnum.object && typeof value === 'object') || + (valueType === WorkflowIOValueTypeEnum.chatHistory && (Array.isArray(value) || typeof value === 'number')) || - (type === WorkflowIOValueTypeEnum.datasetQuote && Array.isArray(value)) || - (type === WorkflowIOValueTypeEnum.selectDataset && Array.isArray(value)) || - (type === WorkflowIOValueTypeEnum.selectApp && typeof value === 'object') + (valueType === WorkflowIOValueTypeEnum.datasetQuote && Array.isArray(value)) || + (valueType === WorkflowIOValueTypeEnum.selectDataset && Array.isArray(value)) || + (valueType === WorkflowIOValueTypeEnum.selectApp && typeof value === 'object') ) { return value; } // 4. 按目标类型,进行格式转化 // 4.1 基本类型转换 - if (type === WorkflowIOValueTypeEnum.string) { + if (valueType === WorkflowIOValueTypeEnum.string) { return typeof value === 'object' ? JSON.stringify(value) : String(value); } - if (type === WorkflowIOValueTypeEnum.number) { + if (valueType === WorkflowIOValueTypeEnum.number) { if (value === '') return undefined; return Number(value); } - if (type === WorkflowIOValueTypeEnum.boolean) { + if (valueType === WorkflowIOValueTypeEnum.boolean) { if (typeof value === 'string') { return value.toLowerCase() === 'true'; } @@ -116,7 +120,7 @@ export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => { } // 4.3 字符串转对象 - if (type === WorkflowIOValueTypeEnum.object) { + if (valueType === WorkflowIOValueTypeEnum.object) { if (isObjectString(value)) { const trimmedValue = value.trim(); try { @@ -127,7 +131,7 @@ export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => { } // 4.4 数组类型(这里 value 不是数组类型)(TODO: 嵌套数据类型转化) - if (type.startsWith('array')) { + if (valueType.startsWith('array')) { if (isObjectString(value)) { try { return json5.parse(value); @@ -142,7 +146,7 @@ export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => { WorkflowIOValueTypeEnum.datasetQuote, WorkflowIOValueTypeEnum.selectDataset, WorkflowIOValueTypeEnum.selectApp - ].includes(type) + ].includes(valueType) ) { if (isObjectString(value)) { try { @@ -153,7 +157,7 @@ export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => { } // Invalid history type - if (type === WorkflowIOValueTypeEnum.chatHistory) { + if (valueType === WorkflowIOValueTypeEnum.chatHistory) { if (isObjectString(value)) { try { return json5.parse(value); diff --git a/packages/global/core/workflow/template/system/customFeedback.ts b/packages/global/core/workflow/template/system/customFeedback.ts index 5ee9f482d..88926a6e2 100644 --- a/packages/global/core/workflow/template/system/customFeedback.ts +++ b/packages/global/core/workflow/template/system/customFeedback.ts @@ -2,8 +2,8 @@ import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../../node/constant'; import { type FlowNodeTemplateType } from '../../type/node.d'; import { WorkflowIOValueTypeEnum, - FlowNodeTemplateTypeEnum, - NodeInputKeyEnum + NodeInputKeyEnum, + FlowNodeTemplateTypeEnum } from '../../constants'; import { i18nT } from '../../../../../web/i18n/utils'; diff --git a/packages/global/core/workflow/template/system/http468.ts b/packages/global/core/workflow/template/system/http468.ts index ddd2f83dd..5c1412fdb 100644 --- a/packages/global/core/workflow/template/system/http468.ts +++ b/packages/global/core/workflow/template/system/http468.ts @@ -8,8 +8,8 @@ import { WorkflowIOValueTypeEnum, NodeInputKeyEnum, NodeOutputKeyEnum, - FlowNodeTemplateTypeEnum, - ContentTypes + ContentTypes, + FlowNodeTemplateTypeEnum } from '../../constants'; import { Input_Template_DynamicInput } from '../input'; import { Output_Template_AddOutput } from '../output'; diff --git a/packages/global/core/workflow/template/system/textEditor.ts b/packages/global/core/workflow/template/system/textEditor.ts index 84b797fef..bbc0451f0 100644 --- a/packages/global/core/workflow/template/system/textEditor.ts +++ b/packages/global/core/workflow/template/system/textEditor.ts @@ -7,8 +7,8 @@ import { type FlowNodeTemplateType } from '../../type/node.d'; import { WorkflowIOValueTypeEnum, NodeOutputKeyEnum, - FlowNodeTemplateTypeEnum, - NodeInputKeyEnum + NodeInputKeyEnum, + FlowNodeTemplateTypeEnum } from '../../constants'; import { i18nT } from '../../../../../web/i18n/utils'; diff --git a/packages/global/core/workflow/utils.ts b/packages/global/core/workflow/utils.ts index 070f29ea7..c5bd93296 100644 --- a/packages/global/core/workflow/utils.ts +++ b/packages/global/core/workflow/utils.ts @@ -18,7 +18,6 @@ import { type ReferenceArrayValueType, type ReferenceItemValueType } from './type/io.d'; -import type { NodeToolConfigType } from './type/node'; import { type StoreNodeItemType } from './type/node'; import type { VariableItemType, @@ -247,7 +246,7 @@ export const appData2FlowNodeIO = ({ const variableInput = !chatConfig?.variables ? [] : chatConfig.variables.map((item) => { - const renderTypeMap = { + const renderTypeMap: Record = { [VariableInputEnum.input]: [FlowNodeInputTypeEnum.input, FlowNodeInputTypeEnum.reference], [VariableInputEnum.textarea]: [ FlowNodeInputTypeEnum.textarea, @@ -255,16 +254,22 @@ export const appData2FlowNodeIO = ({ ], [VariableInputEnum.numberInput]: [FlowNodeInputTypeEnum.numberInput], [VariableInputEnum.select]: [FlowNodeInputTypeEnum.select], - [VariableInputEnum.custom]: [ - FlowNodeInputTypeEnum.input, - FlowNodeInputTypeEnum.reference - ], - default: [FlowNodeInputTypeEnum.reference] + [VariableInputEnum.multipleSelect]: [FlowNodeInputTypeEnum.multipleSelect], + [VariableInputEnum.JSONEditor]: [FlowNodeInputTypeEnum.JSONEditor], + [VariableInputEnum.timePointSelect]: [FlowNodeInputTypeEnum.timePointSelect], + [VariableInputEnum.timeRangeSelect]: [FlowNodeInputTypeEnum.timeRangeSelect], + [VariableInputEnum.switch]: [FlowNodeInputTypeEnum.switch], + [VariableInputEnum.password]: [FlowNodeInputTypeEnum.password], + [VariableInputEnum.file]: [FlowNodeInputTypeEnum.fileSelect], + [VariableInputEnum.modelSelect]: [FlowNodeInputTypeEnum.selectLLMModel], + [VariableInputEnum.datasetSelect]: [FlowNodeInputTypeEnum.selectDataset], + [VariableInputEnum.internal]: [FlowNodeInputTypeEnum.hidden], + [VariableInputEnum.custom]: [FlowNodeInputTypeEnum.input, FlowNodeInputTypeEnum.reference] }; return { key: item.key, - renderTypeList: renderTypeMap[item.type] || renderTypeMap.default, + renderTypeList: renderTypeMap[item.type] || [FlowNodeInputTypeEnum.reference], label: item.label, debugLabel: item.label, description: '', diff --git a/packages/global/package.json b/packages/global/package.json index d70405d5f..98261ede6 100644 --- a/packages/global/package.json +++ b/packages/global/package.json @@ -2,7 +2,7 @@ "name": "@fastgpt/global", "version": "1.0.0", "dependencies": { - "@fastgpt-sdk/plugin": "^0.1.12", + "@fastgpt-sdk/plugin": "^0.1.16", "@apidevtools/swagger-parser": "^10.1.0", "@bany/curl-to-json": "^1.2.8", "axios": "^1.8.2", diff --git a/packages/service/common/secret/utils.ts b/packages/service/common/secret/utils.ts index 8faca6ada..8e65ff713 100644 --- a/packages/service/common/secret/utils.ts +++ b/packages/service/common/secret/utils.ts @@ -2,6 +2,7 @@ import { decryptSecret, encryptSecret } from './aes256gcm'; import type { SecretValueType } from '@fastgpt/global/common/secret/type'; import { type StoreSecretValueType } from '@fastgpt/global/common/secret/type'; import { HeaderSecretTypeEnum } from '@fastgpt/global/common/secret/constants'; +import { isSecretValue } from '../../../global/common/secret/utils'; export const encryptSecretValue = (value: SecretValueType): SecretValueType => { if (!value.value) { @@ -48,3 +49,9 @@ export const getSecretValue = ({ return acc; }, {}); }; + +export const anyValueDecrypt = (value: any) => { + if (!isSecretValue(value)) return value; + + return decryptSecret(value.secret); +}; diff --git a/packages/service/common/vectorDB/milvus/index.ts b/packages/service/common/vectorDB/milvus/index.ts index a6db2b173..6da807b56 100644 --- a/packages/service/common/vectorDB/milvus/index.ts +++ b/packages/service/common/vectorDB/milvus/index.ts @@ -11,7 +11,7 @@ import type { EmbeddingRecallResponse, InsertVectorControllerProps } from '../controller.d'; -import { delay, retryFn } from '@fastgpt/global/common/system/utils'; +import { retryFn } from '@fastgpt/global/common/system/utils'; import { addLog } from '../../system/log'; import { customNanoid } from '@fastgpt/global/common/string/tools'; diff --git a/packages/service/core/ai/config/utils.ts b/packages/service/core/ai/config/utils.ts index e50bb4958..743b1a521 100644 --- a/packages/service/core/ai/config/utils.ts +++ b/packages/service/core/ai/config/utils.ts @@ -9,7 +9,7 @@ import { type RerankModelItemType } from '@fastgpt/global/core/ai/model.d'; import { debounce } from 'lodash'; -import { getModelProvider } from '@fastgpt/global/core/ai/provider'; +import { getModelProvider } from '../../../core/app/provider/controller'; import { findModelFromAlldata } from '../model'; import { reloadFastGPTConfigBuffer, @@ -18,6 +18,7 @@ import { import { delay } from '@fastgpt/global/common/system/utils'; import { pluginClient } from '../../../thirdProvider/fastgptPlugin'; import { setCron } from '../../../common/system/cron'; +import { preloadModelProviders } from '../../../core/app/provider/controller'; export const loadSystemModels = async (init = false, language = 'en') => { const pushModel = (model: SystemModelItemType) => { @@ -77,6 +78,8 @@ export const loadSystemModels = async (init = false, language = 'en') => { if (!init && global.systemModelList) return; + await preloadModelProviders(); + global.systemModelList = []; global.systemActiveModelList = []; global.llmModelMap = new Map(); @@ -109,14 +112,13 @@ export const loadSystemModels = async (init = false, language = 'en') => { }; const dbModel = dbModels.find((item) => item.model === model.model); + const provider = getModelProvider(dbModel?.metadata?.provider || model.provider, language); const modelData: any = { ...model, ...dbModel?.metadata, - provider: getModelProvider( - dbModel?.metadata?.provider || (model.provider as any), - language - ).id, + provider: provider.id, + avatar: provider.avatar, type: dbModel?.metadata?.type || model.type, isCustom: false, diff --git a/packages/service/core/ai/type.d.ts b/packages/service/core/ai/type.d.ts index 395bddc04..58760ad08 100644 --- a/packages/service/core/ai/type.d.ts +++ b/packages/service/core/ai/type.d.ts @@ -6,6 +6,12 @@ import type { EmbeddingModelItemType, LLMModelItemType } from '@fastgpt/global/core/ai/model.d'; +import type { ModelProviderListType } from '@fastgpt/global/core/app/model/type'; +import type { + AiproxyMapProviderType, + I18nStringStrictType +} from '@fastgpt/global/sdk/fastgpt-plugin'; +import type { langType, ModelProviderItemType } from '@fastgpt/global/core/ai/provider'; export type SystemModelSchemaType = { _id: string; @@ -32,6 +38,11 @@ export type SystemDefaultModelType = { }; declare global { + var ModelProviderRawCache: { provider: string; value: I18nStringStrictType }[]; + var ModelProviderListCache: Record; + var ModelProviderMapCache: Record>; + var aiproxyIdMapCache: AiproxyMapProviderType; + var systemModelList: SystemModelItemType[]; // var systemModelMap: Map; var llmModelMap: Map; diff --git a/packages/service/core/app/evaluation/utils.ts b/packages/service/core/app/evaluation/utils.ts new file mode 100644 index 000000000..57dc28008 --- /dev/null +++ b/packages/service/core/app/evaluation/utils.ts @@ -0,0 +1,147 @@ +import { evaluationFileErrors } from '@fastgpt/global/core/app/evaluation/constants'; +import { getEvaluationFileHeader } from '@fastgpt/global/core/app/evaluation/utils'; +import type { VariableItemType } from '@fastgpt/global/core/app/type'; +import { addLog } from '../../../common/system/log'; +import { VariableInputEnum } from '@fastgpt/global/core/workflow/constants'; +import Papa from 'papaparse'; + +export const parseEvaluationCSV = (rawText: string) => { + const parseResult = Papa.parse(rawText.trim(), { + skipEmptyLines: true, + header: false, + transformHeader: (header: string) => header.trim() + }); + + if (parseResult.errors.length > 0) { + addLog.error('CSV parsing failed', parseResult.errors); + throw new Error('CSV parsing failed'); + } + + return parseResult.data as string[][]; +}; + +export const validateEvaluationFile = async ( + rawText: string, + appVariables?: VariableItemType[] +) => { + // Parse CSV using Papa Parse + const csvData = parseEvaluationCSV(rawText); + const dataLength = csvData.length; + + // Validate file header + const expectedHeader = getEvaluationFileHeader(appVariables); + const actualHeader = csvData[0]?.join(',') || ''; + if (actualHeader !== expectedHeader) { + addLog.error(`Header mismatch. Expected: ${expectedHeader}, Got: ${actualHeader}`); + return Promise.reject(evaluationFileErrors); + } + + // Validate data rows count + if (dataLength <= 1) { + addLog.error('No data rows found'); + return Promise.reject(evaluationFileErrors); + } + + const maxRows = 1000; + if (dataLength - 1 > maxRows) { + addLog.error(`Too many rows. Max: ${maxRows}, Got: ${dataLength - 1}`); + return Promise.reject(evaluationFileErrors); + } + + const headers = csvData[0]; + + // Get required field indices + const requiredFields = headers + .map((header, index) => ({ header: header.trim(), index })) + .filter(({ header }) => header.startsWith('*')); + + const errors: string[] = []; + + // Validate each data row + for (let i = 1; i < csvData.length; i++) { + const values = csvData[i]; + + // Check required fields + requiredFields.forEach(({ header, index }) => { + if (!values[index]?.trim()) { + errors.push(`Row ${i + 1}: required field "${header}" is empty`); + } + }); + + // Validate app variables + if (appVariables) { + validateRowVariables({ + values, + variables: appVariables, + rowNum: i + 1, + errors + }); + } + } + + if (errors.length > 0) { + addLog.error(`Validation failed: ${errors.join('; ')}`); + return Promise.reject(evaluationFileErrors); + } + + return { csvData, dataLength }; +}; + +const validateRowVariables = ({ + values, + variables, + rowNum, + errors +}: { + values: string[]; + variables: VariableItemType[]; + rowNum: number; + errors: string[]; +}) => { + variables.forEach((variable, index) => { + const value = values[index]?.trim(); + + // Skip validation if value is empty and not required + if (!value && !variable.required) return; + + switch (variable.type) { + case VariableInputEnum.input: + // Validate string length + if (variable.maxLength && value && value.length > variable.maxLength) { + errors.push( + `Row ${rowNum}: "${variable.label}" exceeds max length (${variable.maxLength})` + ); + } + break; + + case VariableInputEnum.numberInput: + // Validate number type and range + if (value) { + const numValue = Number(value); + if (isNaN(numValue)) { + errors.push(`Row ${rowNum}: "${variable.label}" must be a number`); + } else { + if (variable.min !== undefined && numValue < variable.min) { + errors.push(`Row ${rowNum}: "${variable.label}" below minimum (${variable.min})`); + } + if (variable.max !== undefined && numValue > variable.max) { + errors.push(`Row ${rowNum}: "${variable.label}" exceeds maximum (${variable.max})`); + } + } + } + break; + + case VariableInputEnum.select: + // Validate select options + if (value && variable.enums?.length) { + const validOptions = variable.enums.map((item) => item.value); + if (!validOptions.includes(value)) { + errors.push( + `Row ${rowNum}: "${variable.label}" invalid option. Valid: [${validOptions.join(', ')}]` + ); + } + } + break; + } + }); +}; diff --git a/packages/service/core/app/plugin/controller.ts b/packages/service/core/app/plugin/controller.ts index 7f2fe4d4c..387985927 100644 --- a/packages/service/core/app/plugin/controller.ts +++ b/packages/service/core/app/plugin/controller.ts @@ -504,17 +504,17 @@ const dbPluginFormat = (item: SystemPluginConfigSchemaType): SystemPluginTemplat /* FastsGPT-Pluign api: */ function getCachedSystemPlugins() { - if (!global.systemPlugins_cache) { - global.systemPlugins_cache = { + if (!global.systemToolsCache) { + global.systemToolsCache = { expires: 0, data: [] as SystemPluginTemplateItemType[] }; } - return global.systemPlugins_cache; + return global.systemToolsCache; } const cleanSystemPluginCache = () => { - global.systemPlugins_cache = undefined; + global.systemToolsCache = undefined; }; export const refetchSystemPlugins = () => { @@ -579,15 +579,20 @@ export const getSystemTools = async (): Promise .filter((item) => item.customConfig?.associatedPluginId) .map((item) => dbPluginFormat(item)); - const plugins = [...formatTools, ...dbPlugins]; - plugins.sort((a, b) => (a.pluginOrder ?? 0) - (b.pluginOrder ?? 0)); + const concatTools = [...formatTools, ...dbPlugins]; + concatTools.sort((a, b) => (a.pluginOrder ?? 0) - (b.pluginOrder ?? 0)); - global.systemPlugins_cache = { + global.systemToolsCache = { expires: Date.now() + 30 * 60 * 1000, // 30 minutes - data: plugins + data: concatTools }; - return plugins; + global.systemToolsTypeCache = {}; + concatTools.forEach((item) => { + global.systemToolsTypeCache[item.templateType] = 1; + }); + + return concatTools; } }; @@ -608,10 +613,11 @@ export const getSystemToolById = async (id: string): Promise; } diff --git a/packages/service/core/app/plugin/pluginGroupSchema.ts b/packages/service/core/app/plugin/pluginGroupSchema.ts index b359c1d60..eaf149888 100644 --- a/packages/service/core/app/plugin/pluginGroupSchema.ts +++ b/packages/service/core/app/plugin/pluginGroupSchema.ts @@ -1,5 +1,5 @@ import { connectionMongo, getMongoModel } from '../../../common/mongo/index'; -import { type PluginGroupSchemaType, type TGroupType } from './type'; +import { type SystemToolGroupSchemaType, type TGroupType } from './type'; const { Schema } = connectionMongo; export const collectionName = 'app_plugin_groups'; @@ -29,7 +29,7 @@ const PluginGroupSchema = new Schema({ PluginGroupSchema.index({ groupId: 1 }, { unique: true }); -export const MongoPluginGroups = getMongoModel( +export const MongoToolGroups = getMongoModel( collectionName, PluginGroupSchema ); diff --git a/packages/service/core/app/plugin/type.d.ts b/packages/service/core/app/plugin/type.d.ts index f9de55522..5d117fc38 100644 --- a/packages/service/core/app/plugin/type.d.ts +++ b/packages/service/core/app/plugin/type.d.ts @@ -2,6 +2,7 @@ import { SystemPluginListItemType } from '@fastgpt/global/core/app/type'; import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants'; import type { WorkflowTemplateBasicType } from '@fastgpt/global/core/workflow/type'; import type { InputConfigType } from '@fastgpt/global/core/workflow/type/io'; +import type { I18nStringStrictType } from '@fastgpt/global/sdk/fastgpt-plugin'; export type SystemPluginConfigSchemaType = { pluginId: string; @@ -38,11 +39,11 @@ export type SystemPluginConfigSchemaType = { }; export type TGroupType = { - typeName: string; + typeName: I18nStringStrictType | string; typeId: string; }; -export type PluginGroupSchemaType = { +export type SystemToolGroupSchemaType = { groupId: string; groupAvatar: string; groupName: string; diff --git a/packages/service/core/app/provider/controller.ts b/packages/service/core/app/provider/controller.ts new file mode 100644 index 000000000..452c6bbfa --- /dev/null +++ b/packages/service/core/app/provider/controller.ts @@ -0,0 +1,29 @@ +import { loadModelProviders } from '../../../thirdProvider/fastgptPlugin/model'; +import { + type langType, + defaultProvider, + formatModelProviders +} from '@fastgpt/global/core/ai/provider'; + +// Preload model providers +export async function preloadModelProviders(): Promise { + const { modelProviders, aiproxyIdMap } = await loadModelProviders(); + + const { ModelProviderListCache, ModelProviderMapCache } = formatModelProviders(modelProviders); + global.ModelProviderRawCache = modelProviders; + global.ModelProviderListCache = ModelProviderListCache; + global.ModelProviderMapCache = ModelProviderMapCache; + + global.aiproxyIdMapCache = aiproxyIdMap; +} + +export const getModelProviders = (language = 'en') => { + return global.ModelProviderListCache[language as langType] || []; +}; +export const getModelProvider = (provider?: string, language = 'en') => { + if (!provider) { + return defaultProvider; + } + + return ModelProviderMapCache[language as langType][provider] ?? defaultProvider; +}; diff --git a/packages/templates/register.ts b/packages/service/core/app/templates/register.ts similarity index 66% rename from packages/templates/register.ts rename to packages/service/core/app/templates/register.ts index 0c6b22310..3b3df55b7 100644 --- a/packages/templates/register.ts +++ b/packages/service/core/app/templates/register.ts @@ -1,36 +1,13 @@ -import fs from 'fs'; -import path from 'path'; import { isProduction } from '@fastgpt/global/common/system/constants'; import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants'; -import { MongoAppTemplate } from '@fastgpt/service/core/app/templates/templateSchema'; import { type AppTemplateSchemaType } from '@fastgpt/global/core/app/type'; - -const getTemplateNameList = () => { - const currentFileUrl = new URL(import.meta.url); - const filePath = decodeURIComponent( - process.platform === 'win32' - ? currentFileUrl.pathname.substring(1) // Remove leading slash on Windows - : currentFileUrl.pathname - ); - const templatesPath = path.join(path.dirname(filePath), 'src'); - - return fs.promises.readdir(templatesPath); -}; +import { MongoAppTemplate } from './templateSchema'; +import { pluginClient } from '../../../thirdProvider/fastgptPlugin'; const getFileTemplates = async (): Promise => { - const templateNames = await getTemplateNameList(); - - return Promise.all( - templateNames.map>(async (name) => { - const fileContent = (await import(`./src/${name}/template.json`))?.default; - - return { - ...fileContent, - templateId: `${PluginSourceEnum.community}-${name}`, - isActive: true - }; - }) - ); + const res = await pluginClient.workflow.getTemplateList(); + if (res.status === 200) return res.body as AppTemplateSchemaType[]; + else return Promise.reject(res.body); }; const getAppTemplates = async () => { @@ -86,3 +63,7 @@ export const getAppTemplatesAndLoadThem = async (refresh = false) => { export const isCommunityTemplate = (templateId: string) => { return templateId.startsWith(PluginSourceEnum.community); }; + +declare global { + var appTemplates: AppTemplateSchemaType[]; +} diff --git a/packages/service/core/app/tool/api.ts b/packages/service/core/app/tool/api.ts index 31c69b182..db76aa5f8 100644 --- a/packages/service/core/app/tool/api.ts +++ b/packages/service/core/app/tool/api.ts @@ -1,6 +1,9 @@ +import type { I18nStringStrictType, ToolTypeEnum } from '@fastgpt/global/sdk/fastgpt-plugin'; import { RunToolWithStream } from '@fastgpt/global/sdk/fastgpt-plugin'; import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants'; import { pluginClient, BASE_URL, TOKEN } from '../../../thirdProvider/fastgptPlugin'; +import { addLog } from '../../../common/system/log'; +import { retryFn } from '@fastgpt/global/common/system/utils'; export async function APIGetSystemToolList() { const res = await pluginClient.tool.list(); @@ -27,3 +30,24 @@ const runToolInstance = new RunToolWithStream({ token: TOKEN }); export const APIRunSystemTool = runToolInstance.run.bind(runToolInstance); + +// Tool Types Cache +type SystemToolTypeItem = { + type: ToolTypeEnum; + name: I18nStringStrictType; +}; + +export const getSystemToolTypes = (): Promise => { + return retryFn(async () => { + const res = await pluginClient.tool.getType(); + + if (res.status === 200) { + const toolTypes = res.body || []; + + return toolTypes; + } + + addLog.error('Get system tool type error', res.body); + return []; + }); +}; diff --git a/packages/service/core/workflow/dispatch/index.ts b/packages/service/core/workflow/dispatch/index.ts index 6c9acf8f3..e2c92ef69 100644 --- a/packages/service/core/workflow/dispatch/index.ts +++ b/packages/service/core/workflow/dispatch/index.ts @@ -7,7 +7,7 @@ import type { ToolRunResponseItemType } from '@fastgpt/global/core/chat/type.d'; import type { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants'; -import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; +import { NodeInputKeyEnum, VariableInputEnum } from '@fastgpt/global/core/workflow/constants'; import { FlowNodeInputTypeEnum, FlowNodeTypeEnum @@ -43,9 +43,10 @@ import type { ChatNodeUsageType } from '@fastgpt/global/support/wallet/bill/type import { addLog } from '../../../common/system/log'; import { surrenderProcess } from '../../../common/system/tools'; import type { DispatchFlowResponse, WorkflowDebugResponse } from './type'; -import { removeSystemVariable, rewriteRuntimeWorkFlow } from './utils'; +import { rewriteRuntimeWorkFlow, removeSystemVariable } from './utils'; import { getHandleId } from '@fastgpt/global/core/workflow/utils'; import { callbackMap } from './constants'; +import { anyValueDecrypt } from '../../../common/secret/utils'; type Props = Omit & { runtimeNodes: RuntimeNodeItemType[]; @@ -147,7 +148,11 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise 0 ? workflowQueue.system_memories @@ -937,10 +945,18 @@ const getSystemVariables = ({ variables }: Props): SystemVariablesType => { // Get global variables(Label -> key; Key -> key) - const globalVariables = chatConfig?.variables || []; - const variablesMap = globalVariables.reduce>((acc, item) => { + const variablesConfig = chatConfig?.variables || []; + + const variablesMap = variablesConfig.reduce>((acc, item) => { + // For internal variables, ignore external input and use default value + if (item.type === VariableInputEnum.password) { + const val = variables[item.label] || variables[item.key] || item.defaultValue; + const actualValue = anyValueDecrypt(val); + acc[item.key] = valueTypeFormat(actualValue, item.valueType); + } + // API - if (variables[item.label] !== undefined) { + else if (variables[item.label] !== undefined) { acc[item.key] = valueTypeFormat(variables[item.label], item.valueType); } // Web diff --git a/packages/service/core/workflow/dispatch/tools/runUpdateVar.ts b/packages/service/core/workflow/dispatch/tools/runUpdateVar.ts index a29319992..15df8efd9 100644 --- a/packages/service/core/workflow/dispatch/tools/runUpdateVar.ts +++ b/packages/service/core/workflow/dispatch/tools/runUpdateVar.ts @@ -22,6 +22,7 @@ type Response = DispatchNodeResultType<{}>; export const dispatchUpdateVariable = async (props: Props): Promise => { const { + chatConfig, params, variables, runtimeNodes, @@ -91,7 +92,11 @@ export const dispatchUpdateVariable = async (props: Props): Promise => if (!runningAppInfo.isChildApp) { workflowStreamResponse?.({ event: SseResponseEventEnum.updateVariables, - data: removeSystemVariable(variables, externalProvider.externalWorkflowVariables) + data: removeSystemVariable( + variables, + externalProvider.externalWorkflowVariables, + chatConfig?.variables + ) }); } diff --git a/packages/service/core/workflow/dispatch/utils.ts b/packages/service/core/workflow/dispatch/utils.ts index e17282594..70fdcf7a6 100644 --- a/packages/service/core/workflow/dispatch/utils.ts +++ b/packages/service/core/workflow/dispatch/utils.ts @@ -1,7 +1,9 @@ import { getErrText } from '@fastgpt/global/common/error/utils'; import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants'; import type { ChatItemType } from '@fastgpt/global/core/chat/type.d'; -import { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants'; +import { NodeOutputKeyEnum, VariableInputEnum } from '@fastgpt/global/core/workflow/constants'; +import type { VariableItemType } from '@fastgpt/global/core/app/type'; +import { encryptSecret } from '../../../common/secret/aes256gcm'; import { type RuntimeEdgeItemType, type RuntimeNodeItemType, @@ -115,9 +117,12 @@ export const checkQuoteQAValue = (quoteQA?: SearchDataResponseItemType[]) => { /* remove system variable */ export const removeSystemVariable = ( variables: Record, - removeObj: Record = {} + removeObj: Record = {}, + userVariablesConfigs: VariableItemType[] = [] ) => { const copyVariables = { ...variables }; + + // Delete system variables delete copyVariables.userId; delete copyVariables.appId; delete copyVariables.chatId; @@ -125,13 +130,25 @@ export const removeSystemVariable = ( delete copyVariables.histories; delete copyVariables.cTime; - // delete external provider workflow variables + // Delete special variables Object.keys(removeObj).forEach((key) => { delete copyVariables[key]; }); + // Encrypt password variables + userVariablesConfigs.forEach((item) => { + const val = copyVariables[item.key]; + if (item.type === VariableInputEnum.password && typeof val === 'string') { + copyVariables[item.key] = { + value: '', + secret: encryptSecret(val) + }; + } + }); + return copyVariables; }; + export const filterSystemVariables = (variables: Record): SystemVariablesType => { return { userId: variables.userId, diff --git a/packages/service/core/workflow/utils.ts b/packages/service/core/workflow/utils.ts index 7c65df375..11e70791a 100644 --- a/packages/service/core/workflow/utils.ts +++ b/packages/service/core/workflow/utils.ts @@ -3,7 +3,6 @@ import { countPromptTokens } from '../../common/string/tiktoken/index'; import type { RuntimeNodeItemType } from '@fastgpt/global/core/workflow/runtime/type'; import { getSystemPluginByIdAndVersionId, getSystemTools } from '../app/plugin/controller'; import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; -import { getNanoid } from '@fastgpt/global/common/string/tools'; import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; import { parseI18nString } from '@fastgpt/global/common/i18n/utils'; import type { localeType } from '@fastgpt/global/common/i18n/type'; diff --git a/packages/service/thirdProvider/fastgptPlugin/model.ts b/packages/service/thirdProvider/fastgptPlugin/model.ts new file mode 100644 index 000000000..33d1c954f --- /dev/null +++ b/packages/service/thirdProvider/fastgptPlugin/model.ts @@ -0,0 +1,11 @@ +import { pluginClient } from '.'; + +export const loadModelProviders = async () => { + const res = await pluginClient.model.getProviders(); + + if (res.status === 200) { + return res.body; + } + + return Promise.reject(res.body); +}; diff --git a/packages/service/worker/preload.ts b/packages/service/worker/preload.ts index f1d58ba30..b15897a2f 100644 --- a/packages/service/worker/preload.ts +++ b/packages/service/worker/preload.ts @@ -1,24 +1,41 @@ import { getWorkerController, WorkerNameEnum } from './utils'; export const preLoadWorker = async () => { - const max = Math.min(Number(global.systemEnv?.tokenWorkers || 30), 100); + const start = Date.now(); + const max = Math.min(Number(global.systemEnv?.tokenWorkers || 30), 500); const workerController = getWorkerController({ name: WorkerNameEnum.countGptMessagesTokens, maxReservedThreads: max }); - for await (const item of new Array(max).fill(0)) { - const worker = workerController.createWorker(); - await workerController.run({ - workerId: worker.id, - messages: [ - { - role: 'user', - content: '1' - } - ] - }); - console.log(`Preload worker ${workerController.workerQueue.length}`); + // Batch size for concurrent loading + const batchSize = 5; + + for (let i = 0; i < max; i += batchSize) { + const currentBatchSize = Math.min(batchSize, max - i); + const promises = []; + + // Create batch of promises for concurrent loading + for (let j = 0; j < currentBatchSize; j++) { + const promise = (async () => { + const worker = workerController.createWorker(); + await workerController.run({ + workerId: worker.id, + messages: [ + { + role: 'user', + content: '1' + } + ] + }); + })(); + promises.push(promise); + } + + // Wait for current batch to complete + await Promise.all(promises); + console.log('Preload worker', workerController.workerQueue.length); } - console.log('Preload worker success'); + + console.log('Preload worker success', workerController.workerQueue.length, Date.now() - start); }; diff --git a/packages/templates/README.md b/packages/templates/README.md deleted file mode 100644 index 0ebd531dd..000000000 --- a/packages/templates/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Package 说明 - -该 package 存放应用模板。 \ No newline at end of file diff --git a/packages/templates/package.json b/packages/templates/package.json deleted file mode 100644 index 447c38042..000000000 --- a/packages/templates/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "@fastgpt/templates", - "version": "1.0.0", - "type": "module", - "dependencies": {}, - "devDependencies": { - "@fastgpt/global": "workspace:*", - "@fastgpt/service": "workspace:*" - } -} diff --git a/packages/templates/src/CQ/template.json b/packages/templates/src/CQ/template.json deleted file mode 100644 index d8094e175..000000000 --- a/packages/templates/src/CQ/template.json +++ /dev/null @@ -1,411 +0,0 @@ -{ - "name": "问题分类 + 知识库", - "intro": "先对用户的问题进行分类,再根据不同类型问题,执行不同的操作", - "author": "", - "avatar": "core/workflow/template/questionClassify", - "tags": ["office-services"], - "type": "advanced", - "workflow": { - "nodes": [ - { - "nodeId": "userGuide", - "name": "系统配置", - "intro": "可以配置应用的系统参数", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "userGuide", - "position": { - "x": 531.2422736065552, - "y": -486.7611729549753 - }, - "version": "481", - "inputs": [], - "outputs": [] - }, - { - "nodeId": "workflowStartNodeId", - "name": "流程开始", - "intro": "", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "workflowStart", - "position": { - "x": 558.4082376415505, - "y": 123.72387429194112 - }, - "version": "481", - "inputs": [ - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题" - } - ], - "outputs": [ - { - "id": "userChatInput", - "key": "userChatInput", - "label": "core.module.input.label.user question", - "valueType": "string", - "type": "FlowNodeOutputTypeEnum.static" - } - ] - }, - { - "nodeId": "7BdojPlukIQw", - "name": "AI 对话", - "intro": "AI 大模型对话", - "avatar": "core/workflow/template/aiChat", - "flowNodeType": "chatNode", - "showStatus": true, - "position": { - "x": 2701.1267277679685, - "y": -767.8956312653042 - }, - "version": "481", - "inputs": [ - { - "key": "model", - "renderTypeList": ["settingLLMModel", "reference"], - "label": "core.module.input.label.aiModel", - "valueType": "string", - "value": "gpt-5" - }, - { - "key": "temperature", - "renderTypeList": ["hidden"], - "label": "", - "value": 3, - "valueType": "number", - "min": 0, - "max": 10, - "step": 1 - }, - { - "key": "maxToken", - "renderTypeList": ["hidden"], - "label": "", - "value": 1950, - "valueType": "number", - "min": 100, - "max": 4000, - "step": 50 - }, - { - "key": "isResponseAnswerText", - "renderTypeList": ["hidden"], - "label": "", - "value": true, - "valueType": "boolean" - }, - { - "key": "quoteTemplate", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string" - }, - { - "key": "quotePrompt", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string" - }, - { - "key": "systemPrompt", - "renderTypeList": ["textarea", "reference"], - "max": 3000, - "valueType": "string", - "label": "core.ai.Prompt", - "description": "core.app.tip.systemPromptTip", - "placeholder": "core.app.tip.chatNodeSystemPromptTip", - "value": "" - }, - { - "key": "history", - "renderTypeList": ["numberInput", "reference"], - "valueType": "chatHistory", - "label": "core.module.input.label.chat history", - "required": true, - "min": 0, - "max": 30, - "value": 6 - }, - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题", - "value": ["workflowStartNodeId", "userChatInput"] - }, - { - "key": "quoteQA", - "renderTypeList": ["settingDatasetQuotePrompt"], - "label": "", - "debugLabel": "知识库引用", - "description": "", - "valueType": "datasetQuote", - "value": ["MNMMMIjjWyMU", "quoteQA"] - } - ], - "outputs": [ - { - "id": "history", - "key": "history", - "label": "core.module.output.label.New context", - "description": "core.module.output.description.New context", - "valueType": "chatHistory", - "type": "FlowNodeOutputTypeEnum.static" - }, - { - "id": "answerText", - "key": "answerText", - "label": "core.module.output.label.Ai response content", - "description": "core.module.output.description.Ai response content", - "valueType": "string", - "type": "FlowNodeOutputTypeEnum.static" - } - ] - }, - { - "nodeId": "rvbo634w3AYj", - "name": "问题分类", - "intro": "根据用户的历史记录和当前问题判断该次提问的类型。可以添加多组问题类型,下面是一个模板例子:\n类型1: 打招呼\n类型2: 关于商品\"使用\"问题\n类型3: 关于商品\"购买\"问题\n类型4: 其他问题", - "avatar": "core/workflow/template/questionClassify", - "flowNodeType": "classifyQuestion", - "showStatus": true, - "position": { - "x": 1020.9667229609946, - "y": -385.0060974413916 - }, - "version": "481", - "inputs": [ - { - "key": "model", - "renderTypeList": ["selectLLMModel", "reference"], - "label": "core.module.input.label.aiModel", - "required": true, - "valueType": "string", - "llmModelType": "classify", - "value": "gpt-5" - }, - { - "key": "systemPrompt", - "renderTypeList": ["textarea", "reference"], - "max": 3000, - "valueType": "string", - "label": "core.module.input.label.Background", - "description": "core.module.input.description.Background", - "placeholder": "core.module.input.placeholder.Classify background", - "value": "" - }, - { - "key": "history", - "renderTypeList": ["numberInput", "reference"], - "valueType": "chatHistory", - "label": "core.module.input.label.chat history", - "required": true, - "min": 0, - "max": 30, - "value": 6 - }, - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "value": ["workflowStartNodeId", "userChatInput"] - }, - { - "key": "agents", - "renderTypeList": ["custom"], - "valueType": "any", - "label": "", - "value": [ - { - "value": "关于电影《星际穿越》的问题", - "key": "wqre" - }, - { - "value": "打招呼、问候等问题", - "key": "sdfa" - }, - { - "value": "其他问题", - "key": "agex" - } - ] - } - ], - "outputs": [ - { - "id": "cqResult", - "key": "cqResult", - "label": "分类结果", - "valueType": "string", - "type": "FlowNodeOutputTypeEnum.static" - } - ] - }, - { - "nodeId": "7kwgL1dVlwG6", - "name": "指定回复", - "intro": "该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。", - "avatar": "core/workflow/template/reply", - "flowNodeType": "answerNode", - "position": { - "x": 1874.9167551056487, - "y": 434.98431875888207 - }, - "version": "481", - "inputs": [ - { - "key": "text", - "renderTypeList": ["textarea", "reference"], - "valueType": "string", - "label": "core.module.input.label.Response content", - "description": "core.module.input.description.Response content", - "placeholder": "core.module.input.description.Response content", - "selectedTypeIndex": 1, - "value": ["rvbo634w3AYj", "cqResult"] - } - ], - "outputs": [] - }, - { - "nodeId": "MNMMMIjjWyMU", - "name": "知识库搜索", - "intro": "调用\"语义检索\"和\"全文检索\"能力,从\"知识库\"中查找可能与问题相关的参考内容", - "avatar": "core/workflow/template/datasetSearch", - "flowNodeType": "datasetSearchNode", - "showStatus": true, - "position": { - "x": 1851.010152279949, - "y": -613.3555232387284 - }, - "version": "481", - "inputs": [ - { - "key": "datasets", - "renderTypeList": ["selectDataset", "reference"], - "label": "core.module.input.label.Select dataset", - "value": [], - "valueType": "selectDataset", - "list": [], - "required": true - }, - { - "key": "similarity", - "renderTypeList": ["selectDatasetParamsModal"], - "label": "", - "value": 0.4, - "valueType": "number" - }, - { - "key": "limit", - "renderTypeList": ["hidden"], - "label": "", - "value": 5000, - "valueType": "number" - }, - { - "key": "searchMode", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "value": "embedding" - }, - { - "key": "usingReRank", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "boolean", - "value": false - }, - { - "key": "datasetSearchUsingExtensionQuery", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "boolean", - "value": true - }, - { - "key": "datasetSearchExtensionModel", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string" - }, - { - "key": "datasetSearchExtensionBg", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "value": "" - }, - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "需要检索的内容", - "value": ["workflowStartNodeId", "userChatInput"] - } - ], - "outputs": [ - { - "id": "quoteQA", - "key": "quoteQA", - "label": "core.module.Dataset quote.label", - "description": "特殊数组格式,搜索结果为空时,返回空数组。", - "type": "FlowNodeOutputTypeEnum.static", - "valueType": "datasetQuote" - } - ] - } - ], - "edges": [ - { - "source": "workflowStartNodeId", - "target": "rvbo634w3AYj", - "sourceHandle": "workflowStartNodeId-source-right", - "targetHandle": "rvbo634w3AYj-target-left" - }, - { - "source": "rvbo634w3AYj", - "target": "7kwgL1dVlwG6", - "sourceHandle": "rvbo634w3AYj-source-agex", - "targetHandle": "7kwgL1dVlwG6-target-left" - }, - { - "source": "rvbo634w3AYj", - "target": "MNMMMIjjWyMU", - "sourceHandle": "rvbo634w3AYj-source-wqre", - "targetHandle": "MNMMMIjjWyMU-target-left" - }, - { - "source": "MNMMMIjjWyMU", - "target": "7BdojPlukIQw", - "sourceHandle": "MNMMMIjjWyMU-source-right", - "targetHandle": "7BdojPlukIQw-target-left" - }, - { - "source": "rvbo634w3AYj", - "target": "7kwgL1dVlwG6", - "sourceHandle": "rvbo634w3AYj-source-sdfa", - "targetHandle": "7kwgL1dVlwG6-target-left" - } - ], - "chatConfig": { - "scheduledTriggerConfig": { - "cronString": "", - "timezone": "Asia/Shanghai", - "defaultPrompt": "" - }, - "welcomeText": "你好,我是知识库助手,请不要忘记选择知识库噢~\n[你是谁]\n[如何使用]" - } - } -} diff --git a/packages/templates/src/Chinese/template.json b/packages/templates/src/Chinese/template.json deleted file mode 100644 index 7930229bb..000000000 --- a/packages/templates/src/Chinese/template.json +++ /dev/null @@ -1,507 +0,0 @@ -{ - "name": "汉语新解", - "intro": "生成汉语释义图", - "author": "", - "avatar": "core/app/templates/chinese", - "tags": ["roleplay"], - "type": "advanced", - "userGuide": { - "type": "link", - "content": "https://mp.weixin.qq.com/s/T90-uZqGovYR90fST0o80Q" - }, - "workflow": { - "nodes": [ - { - "nodeId": "userGuide", - "name": "common:core.module.template.system_config", - "intro": "common:core.module.template.system_config_info", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "userGuide", - "position": { - "x": 262.2732338817093, - "y": -476.00241136598146 - }, - "version": "481", - "inputs": [ - { - "key": "welcomeText", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "core.app.Welcome Text", - "value": "" - }, - { - "key": "variables", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "core.app.Chat Variable", - "value": [] - }, - { - "key": "questionGuide", - "valueType": "any", - "renderTypeList": ["hidden"], - "label": "core.app.Question Guide", - "value": { - "open": false - } - }, - { - "key": "tts", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "type": "web" - } - }, - { - "key": "whisper", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - } - }, - { - "key": "scheduleTrigger", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": null - } - ], - "outputs": [] - }, - { - "nodeId": "448745", - "name": "common:core.module.template.work_start", - "intro": "", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "workflowStart", - "position": { - "x": 632.368838596004, - "y": -347.7446492944009 - }, - "version": "481", - "inputs": [ - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "common:core.module.input.label.user question", - "required": true, - "toolDescription": "用户问题", - "debugLabel": "" - } - ], - "outputs": [ - { - "id": "userChatInput", - "key": "userChatInput", - "label": "common:core.module.input.label.user question", - "type": "static", - "valueType": "string", - "description": "" - } - ] - }, - { - "nodeId": "bg853CwHAw4a", - "name": "AI 对话", - "intro": "AI 大模型对话", - "avatar": "core/workflow/template/aiChat", - "flowNodeType": "chatNode", - "showStatus": true, - "position": { - "x": 1318.728987052518, - "y": -612.0024113659815 - }, - "version": "481", - "inputs": [ - { - "key": "model", - "renderTypeList": ["settingLLMModel", "reference"], - "label": "AI 模型", - "valueType": "string", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "", - "value": "claude-3-5-sonnet-20240620" - }, - { - "key": "temperature", - "renderTypeList": ["hidden"], - "label": "", - "value": 0, - "valueType": "number", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "maxToken", - "renderTypeList": ["hidden"], - "label": "", - "value": 2000, - "valueType": "number", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "isResponseAnswerText", - "renderTypeList": ["hidden"], - "label": "", - "value": false, - "valueType": "boolean", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "aiChatQuoteRole", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "value": "system", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quoteTemplate", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quotePrompt", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "aiChatVision", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "boolean", - "value": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "systemPrompt", - "renderTypeList": ["textarea", "reference"], - "max": 3000, - "valueType": "string", - "label": "提示词", - "description": "core.app.tip.chatNodeSystemPromptTip", - "placeholder": "core.app.tip.chatNodeSystemPromptTip", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "", - "value": "{提示词 START:\n;; 作者: 李继刚\n;; 版本: 0.3\n;; 模型: Claude Sonnet\n;; 用途: 将一个汉语词汇进行全新角度的解释\n\n;; 设定如下内容为你的 *System Prompt*\n(defun 新汉语老师 ()\n \"你是年轻人,批判现实,思考深刻,语言风趣\"\n (风格 . (\"Oscar Wilde\" \"鲁迅\" \"罗永浩\"))\n (擅长 . 一针见血)\n (表达 . 隐喻)\n (批判 . 讽刺幽默))\n\n(defun 汉语新解 (用户输入)\n \"你会用一个特殊视角来解释一个词汇\"\n (let (解释 (精练表达\n (隐喻 (一针见血 (辛辣讽刺 (抓住本质 用户输入))))))\n (few-shots (委婉 . \"刺向他人时, 决定在剑刃上撒上止痛药。\"))\n (SVG-Card 解释)))\n\n(defun SVG-Card (解释)\n \"输出SVG 卡片\"\n (setq design-rule \"合理使用负空间,整体排版要有呼吸感\"\n design-principles '(干净 简洁 典雅))\n\n (设置画布 '(宽度 400 高度 600 边距 20))\n (标题字体 '毛笔楷体)\n (自动缩放 '(最小字号 16))\n\n (配色风格 '((背景色 (蒙德里安风格 设计感)))\n (主要文字 (汇文明朝体 粉笔灰))\n (装饰图案 随机几何图))\n\n (卡片元素 ((居中标题 \"汉语新解\")\n 分隔线\n (排版输出 用户输入 英文 日语)\n 解释\n (线条图 (批判内核 解释))\n (极简总结 线条图))))\n\n(defun start ()\n \"启动时运行\"\n (let (system-role 新汉语老师)\n (print \"说吧, 他们又用哪个词来忽悠你了?\")))\n\n;; 运行规则\n;; 1. 启动时必须运行 (start) 函数\n;; 2. 之后调用主函数 (汉语新解 用户输入)\n提示词 END}\n\n(直接生成 svg 完整代码,我会复制,需要你用代码块)\n(除此之外不要有多余的解释,不要在开头加上任何说明)\n解释的内容自动加入换行标签,例如:\n文字1,\n 文字12," - }, - { - "key": "history", - "renderTypeList": ["numberInput", "reference"], - "valueType": "chatHistory", - "label": "聊天记录", - "description": "workflow:max_dialog_rounds", - "required": true, - "min": 0, - "max": 50, - "value": 0, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quoteQA", - "renderTypeList": ["settingDatasetQuotePrompt"], - "label": "", - "debugLabel": "知识库引用", - "description": "", - "valueType": "datasetQuote", - "valueDesc": "", - "toolDescription": "" - }, - { - "key": "stringQuoteText", - "renderTypeList": ["reference", "textarea"], - "label": "文档引用", - "debugLabel": "文档引用", - "description": "app:document_quote_tip", - "valueType": "string", - "valueDesc": "", - "toolDescription": "" - }, - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题", - "valueDesc": "", - "description": "", - "debugLabel": "", - "value": ["448745", "userChatInput"] - } - ], - "outputs": [ - { - "id": "history", - "key": "history", - "required": true, - "label": "common:core.module.output.label.New context", - "description": "将本次回复内容拼接上历史记录,作为新的上下文返回", - "valueType": "chatHistory", - "valueDesc": "{\n obj: System | Human | AI;\n value: string;\n}[]", - "type": "static" - }, - { - "id": "answerText", - "key": "answerText", - "required": true, - "label": "common:core.module.output.label.Ai response content", - "description": "将在 stream 回复完毕后触发", - "valueType": "string", - "type": "static" - } - ] - }, - { - "nodeId": "sbVUb0efY6Fm", - "name": "代码运行", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 2210.2574140398733, - "y": -621.0024113659815 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({svg_str}){\n\n // 使用正则表达式匹配代码块中的内容\n const match = svg_str.match(/```[\\w]*\\n([\\s\\S]*?)```/);\n\n if (!match) {\n // 如果没有匹配到代码块,返回一个错误信息或空结果\n return {\n result: null,\n error: \"未找到有效的代码块标记。\"\n };\n }\n\n // 提取代码块中的 SVG 内容\n const extractedSvg = match[1].trim();\n \n const base64 = strToBase64(extractedSvg,'data:image/svg+xml;base64,')\n\n return {\n result: base64\n }\n}", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "svg_str", - "label": "svg_str", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "", - "value": ["bg853CwHAw4a", "answerText"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key", - "valueDesc": "" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "result", - "valueType": "string", - "label": "result", - "valueDesc": "", - "description": "" - } - ] - }, - { - "nodeId": "cPh2VZnVxjQ8", - "name": "指定回复", - "intro": "该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。", - "avatar": "core/workflow/template/reply", - "flowNodeType": "answerNode", - "position": { - "x": 2911.2230784647795, - "y": -411.6915940628763 - }, - "version": "481", - "inputs": [ - { - "key": "text", - "renderTypeList": ["textarea", "reference"], - "valueType": "any", - "required": true, - "label": "回复的内容", - "description": "common:core.module.input.description.Response content", - "placeholder": "common:core.module.input.description.Response content", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "", - "value": "SVG:\n\n{{$bg853CwHAw4a.answerText$}}\n\n卡片:\n\n![]({{$sbVUb0efY6Fm.qLUQfhG0ILRX$}})" - } - ], - "outputs": [] - } - ], - "edges": [ - { - "source": "bg853CwHAw4a", - "target": "sbVUb0efY6Fm", - "sourceHandle": "bg853CwHAw4a-source-right", - "targetHandle": "sbVUb0efY6Fm-target-left" - }, - { - "source": "448745", - "target": "bg853CwHAw4a", - "sourceHandle": "448745-source-right", - "targetHandle": "bg853CwHAw4a-target-left" - }, - { - "source": "sbVUb0efY6Fm", - "target": "cPh2VZnVxjQ8", - "sourceHandle": "sbVUb0efY6Fm-source-right", - "targetHandle": "cPh2VZnVxjQ8-target-left" - } - ], - "chatConfig": { - "variables": [], - "scheduledTriggerConfig": { - "cronString": "", - "timezone": "Asia/Shanghai", - "defaultPrompt": "" - }, - "_id": "66f0f7540a40cd1f97da9dd6" - } - } -} diff --git a/packages/templates/src/TranslateRobot/template.json b/packages/templates/src/TranslateRobot/template.json deleted file mode 100644 index bd4eb1f3d..000000000 --- a/packages/templates/src/TranslateRobot/template.json +++ /dev/null @@ -1,581 +0,0 @@ -{ - "name": "多轮翻译机器人", - "intro": "通过 4 轮翻译,提高翻译英文的质量", - "author": "", - "avatar": "core/app/templates/TranslateRobot", - "tags": ["office-services"], - "type": "advanced", - "workflow": { - "nodes": [ - { - "nodeId": "userGuide", - "name": "系统配置", - "intro": "可以配置应用的系统参数", - "avatar": "/imgs/workflow/userGuide.png", - "flowNodeType": "userGuide", - "position": { - "x": 531.2422736065552, - "y": -486.7611729549753 - }, - "version": "481", - "inputs": [ - { - "key": "welcomeText", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "core.app.Welcome Text", - "value": "" - }, - { - "key": "variables", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "core.app.Chat Variable", - "value": [] - }, - { - "key": "questionGuide", - "valueType": "any", - "renderTypeList": ["hidden"], - "label": "core.app.Question Guide", - "value": { - "open": false - } - }, - { - "key": "tts", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "type": "web" - } - }, - { - "key": "whisper", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - } - }, - { - "key": "scheduleTrigger", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": null - } - ], - "outputs": [] - }, - { - "nodeId": "448745", - "name": "流程开始", - "intro": "", - "avatar": "/imgs/workflow/userChatInput.svg", - "flowNodeType": "workflowStart", - "position": { - "x": 558.4082376415505, - "y": 123.72387429194112 - }, - "version": "481", - "inputs": [ - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题" - } - ], - "outputs": [ - { - "id": "userChatInput", - "key": "userChatInput", - "label": "core.module.input.label.user question", - "type": "static", - "valueType": "string" - } - ] - }, - { - "nodeId": "loOvhld2ZTKa", - "name": "第一轮翻译", - "intro": "AI 大模型对话", - "avatar": "/imgs/workflow/AI.png", - "flowNodeType": "chatNode", - "showStatus": true, - "position": { - "x": 1748.8252410306534, - "y": -245.08260685989214 - }, - "version": "481", - "inputs": [ - { - "key": "model", - "renderTypeList": ["settingLLMModel", "reference"], - "label": "core.module.input.label.aiModel", - "valueType": "string", - "value": "claude-3-5-sonnet-20240620" - }, - { - "key": "temperature", - "renderTypeList": ["hidden"], - "label": "", - "value": 0, - "valueType": "number", - "min": 0, - "max": 10, - "step": 1 - }, - { - "key": "maxToken", - "renderTypeList": ["hidden"], - "label": "", - "value": 2000, - "valueType": "number", - "min": 100, - "max": 4000, - "step": 50 - }, - { - "key": "isResponseAnswerText", - "renderTypeList": ["hidden"], - "label": "", - "value": true, - "valueType": "boolean" - }, - { - "key": "quoteTemplate", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string" - }, - { - "key": "quotePrompt", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string" - }, - { - "key": "systemPrompt", - "renderTypeList": ["textarea", "reference"], - "max": 3000, - "valueType": "string", - "label": "core.ai.Prompt", - "description": "core.app.tip.systemPromptTip", - "placeholder": "core.app.tip.chatNodeSystemPromptTip", - "value": "# Role: 资深英汉翻译专家\n\n## Background:\n你是一位经验丰富的英汉翻译专家,精通英汉互译,尤其擅长将英文文章译成流畅易懂的现代汉语。你曾多次带领团队完成大型翻译项目,译文广受好评。\n\n## Attention:\n- 翻译过程中要始终坚持\"信、达、雅\"的原则,但\"达\"尤为重要\n- 译文要符合现代汉语的表达习惯,通俗易懂,连贯流畅 \n- 避免使用过于文绉绉的表达和晦涩难懂的典故引用\n\n## Profile: \n- Author: 米开朗基杨 \n- Version: 0.2\n- Language: 中文\n- Description: 你是一位资深英汉翻译专家,精通英汉互译。你擅长将英文文章译成地道流畅的现代汉语,表达准确易懂,符合当代中文语言习惯。\n\n## Constraints:\n- 必须严格遵循四轮翻译流程:直译、意译、校审、定稿 \n- 译文要忠实原文,准确无误,不能遗漏或曲解原意\n- 译文应以现代白话文为主,避免过多使用文言文和古典诗词\n- 每一轮翻译前后必须添加【思考】和【翻译】标记\n- 最终译文使用Markdown的代码块呈现\n\n## Goals:\n- 通过四轮翻译流程,将英文原文译成高质量的现代汉语译文 \n- 译文要准确传达原文意思,语言表达力求浅显易懂,朗朗上口\n- 适度使用一些熟语俗语、流行网络用语等,增强译文的亲和力\n- 在直译的基础上,提供至少2个不同风格的意译版本供选择\n\n## Skills:\n- 精通英汉双语,具有扎实的语言功底和丰富的翻译经验\n- 擅长将英语表达习惯转换为地道自然的现代汉语\n- 对当代中文语言的发展变化有敏锐洞察,善于把握语言流行趋势\n\n## Workflow:\n1. 第一轮直译:逐字逐句忠实原文,不遗漏任何信息\n2. 第二轮意译:在直译的基础上用通俗流畅的现代汉语意译原文,至少提供2个不同风格的版本\n3. 第三轮校审:仔细审视译文,消除偏差和欠缺,使译文更加地道易懂 \n4. 第四轮定稿:择优选取,反复修改润色,最终定稿出一个简洁畅达、符合大众阅读习惯的译文\n\n## OutputFormat: \n- 每一轮翻译前用【思考】说明该轮要点\n- 每一轮翻译后用【翻译】呈现译文\n- 在\\`\\`\\`代码块中展示最终定稿译文\n\n## Suggestions:\n- 直译时力求忠实原文,但不要过于拘泥逐字逐句\n- 意译时在准确表达原意的基础上,用最朴实无华的现代汉语来表达 \n- 校审环节重点关注译文是否符合当代汉语表达习惯,是否通俗易懂\n- 定稿时适度采用一些熟语谚语、网络流行语等,使译文更接地气\n- 善于利用中文的灵活性,用不同的表述方式展现同一内容,提高译文的可读性\n\n## Initialization\n作为一名资深英汉翻译专家,你必须严格遵循翻译流程的各项要求。首先请向用户问好,介绍你将带领团队完成翻译任务,力求将英文原文译成通俗易懂的现代汉语。然后简要说明四轮翻译流程,请用户提供英文原文,开始进行翻译工作。" - }, - { - "key": "history", - "renderTypeList": ["numberInput", "reference"], - "valueType": "chatHistory", - "label": "core.module.input.label.chat history", - "description": "最多携带多少轮对话记录", - "required": true, - "min": 0, - "max": 50, - "value": 6 - }, - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题", - "value": ["gBDvemE4FBhp", "system_text"] - }, - { - "key": "quoteQA", - "renderTypeList": ["settingDatasetQuotePrompt"], - "label": "", - "debugLabel": "知识库引用", - "description": "", - "valueType": "datasetQuote" - } - ], - "outputs": [ - { - "id": "history", - "key": "history", - "required": true, - "label": "core.module.output.label.New context", - "description": "core.module.output.description.New context", - "valueType": "chatHistory", - "type": "static" - }, - { - "id": "answerText", - "key": "answerText", - "required": true, - "label": "core.module.output.label.Ai response content", - "description": "core.module.output.description.Ai response content", - "valueType": "string", - "type": "static" - } - ] - }, - { - "nodeId": "w0oBbQ3YJHye", - "name": "代码运行", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "/imgs/workflow/code.svg", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 2522.61682940854, - "y": -79.74569750380468 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "这些变量会作为代码的运行的输入参数", - "editField": { - "key": true, - "valueType": true - }, - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({data1}) {\n const codeBlocks = data1.match(/```[\\s\\S]*?```/g);\n\n if (codeBlocks && codeBlocks.length > 0) {\n const lastCodeBlock = codeBlocks[codeBlocks.length - 1];\n const cleanedCodeBlock = lastCodeBlock.replace(/```[a-zA-Z]*|```/g, '').trim();\n \n return {\n result: cleanedCodeBlock\n };\n }\n\n return {\n result: '未截取到代码块内容'\n };\n}\n" - }, - { - "key": "data1", - "valueType": "string", - "label": "data1", - "renderTypeList": ["reference"], - "description": "", - "canEdit": true, - "editField": { - "key": true, - "valueType": true - }, - "value": ["loOvhld2ZTKa", "answerText"] - } - ], - "outputs": [ - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "description": "将代码中 return 的对象作为输出,传递给后续的节点" - }, - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "完整响应数据", - "valueType": "object", - "type": "static" - }, - { - "id": "error", - "key": "error", - "label": "运行错误", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "result", - "valueType": "string", - "label": "result" - }, - { - "id": "gR0mkQpJ4Og8", - "type": "dynamic", - "key": "data2", - "valueType": "string", - "label": "data2" - } - ] - }, - { - "nodeId": "foO69L5FOmDQ", - "name": "指定回复", - "intro": "该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。", - "avatar": "/imgs/workflow/reply.png", - "flowNodeType": "answerNode", - "position": { - "x": 3798.4479531204515, - "y": 116.03040242110023 - }, - "version": "481", - "inputs": [ - { - "key": "text", - "renderTypeList": ["textarea", "reference"], - "valueType": "any", - "required": true, - "label": "core.module.input.label.Response content", - "description": "core.module.input.description.Response content", - "placeholder": "core.module.input.description.Response content", - "selectedTypeIndex": 1, - "value": ["bcqtxqxE2R6o", "system_text"] - } - ], - "outputs": [] - }, - { - "nodeId": "gBDvemE4FBhp", - "name": "文本拼接", - "intro": "可对固定或传入的文本进行加工后输出,非字符串类型数据最终会转成字符串类型。", - "avatar": "/imgs/workflow/textEditor.svg", - "flowNodeType": "textEditor", - "position": { - "x": 1031.371061396644, - "y": 38.65839420088383 - }, - "version": "486", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "可以引用其他节点的输出,作为文本拼接的变量,通过 {{字段名}} 来引用变量", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - } - }, - { - "key": "system_textareaInput", - "renderTypeList": ["textarea"], - "valueType": "string", - "required": true, - "label": "拼接文本", - "placeholder": "可通过 {{字段名}} 来引用变量", - "value": "原文:\n\"\"\"\n{{q}}\n\"\"\"" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "q", - "label": "q", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "required": true, - "value": ["448745", "userChatInput"] - } - ], - "outputs": [ - { - "id": "system_text", - "key": "system_text", - "label": "拼接结果", - "type": "static", - "valueType": "string" - } - ] - }, - { - "nodeId": "bcqtxqxE2R6o", - "name": "合并输出结果", - "intro": "可对固定或传入的文本进行加工后输出,非字符串类型数据最终会转成字符串类型。", - "avatar": "/imgs/workflow/textEditor.svg", - "flowNodeType": "textEditor", - "position": { - "x": 3113.6227559936665, - "y": 12.909197647746709 - }, - "version": "486", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "可以引用其他节点的输出,作为文本拼接的变量,通过 {{字段名}} 来引用变量", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - } - }, - { - "key": "system_textareaInput", - "renderTypeList": ["textarea"], - "valueType": "string", - "required": true, - "label": "拼接文本", - "placeholder": "可通过 {{字段名}} 来引用变量", - "value": "****** \n\n最终翻译结果如下: \n\n```\n{{result}}\n```" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "result", - "label": "result", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "required": true, - "value": ["w0oBbQ3YJHye", "qLUQfhG0ILRX"] - } - ], - "outputs": [ - { - "id": "system_text", - "key": "system_text", - "label": "拼接结果", - "type": "static", - "valueType": "string" - } - ] - } - ], - "edges": [ - { - "source": "loOvhld2ZTKa", - "target": "w0oBbQ3YJHye", - "sourceHandle": "loOvhld2ZTKa-source-right", - "targetHandle": "w0oBbQ3YJHye-target-left" - }, - { - "source": "448745", - "target": "gBDvemE4FBhp", - "sourceHandle": "448745-source-right", - "targetHandle": "gBDvemE4FBhp-target-left" - }, - { - "source": "gBDvemE4FBhp", - "target": "loOvhld2ZTKa", - "sourceHandle": "gBDvemE4FBhp-source-right", - "targetHandle": "loOvhld2ZTKa-target-left" - }, - { - "source": "w0oBbQ3YJHye", - "target": "bcqtxqxE2R6o", - "sourceHandle": "w0oBbQ3YJHye-source-right", - "targetHandle": "bcqtxqxE2R6o-target-left" - }, - { - "source": "bcqtxqxE2R6o", - "target": "foO69L5FOmDQ", - "sourceHandle": "bcqtxqxE2R6o-source-right", - "targetHandle": "foO69L5FOmDQ-target-left" - } - ], - "chatConfig": { - "scheduledTriggerConfig": { - "cronString": "", - "timezone": "Asia/Shanghai", - "defaultPrompt": "" - } - } - } -} diff --git a/packages/templates/src/animalLife/template.json b/packages/templates/src/animalLife/template.json deleted file mode 100644 index 4706c1dbf..000000000 --- a/packages/templates/src/animalLife/template.json +++ /dev/null @@ -1,503 +0,0 @@ -{ - "name": "动物的一生", - "intro": "使用AI生成任何事物的 “人生图”", - "author": "", - "avatar": "core/app/templates/animalLife", - "tags": ["roleplay"], - "type": "advanced", - "workflow": { - "nodes": [ - { - "nodeId": "userGuide", - "name": "common:core.module.template.system_config", - "intro": "common:core.module.template.system_config_info", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "userGuide", - "position": { - "x": 262.2732338817093, - "y": -476.00241136598146 - }, - "version": "481", - "inputs": [ - { - "key": "welcomeText", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "core.app.Welcome Text", - "value": "" - }, - { - "key": "variables", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "core.app.Chat Variable", - "value": [] - }, - { - "key": "questionGuide", - "valueType": "any", - "renderTypeList": ["hidden"], - "label": "core.app.Question Guide", - "value": { - "open": false - } - }, - { - "key": "tts", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "type": "web" - } - }, - { - "key": "whisper", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - } - }, - { - "key": "scheduleTrigger", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": null - } - ], - "outputs": [] - }, - { - "nodeId": "448745", - "name": "common:core.module.template.work_start", - "intro": "", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "workflowStart", - "position": { - "x": 632.368838596004, - "y": -347.7446492944009 - }, - "version": "481", - "inputs": [ - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "common:core.module.input.label.user question", - "required": true, - "toolDescription": "用户问题", - "debugLabel": "" - } - ], - "outputs": [ - { - "id": "userChatInput", - "key": "userChatInput", - "label": "common:core.module.input.label.user question", - "type": "static", - "valueType": "string", - "description": "" - } - ] - }, - { - "nodeId": "bg853CwHAw4a", - "name": "AI 对话", - "intro": "AI 大模型对话", - "avatar": "core/workflow/template/aiChat", - "flowNodeType": "chatNode", - "showStatus": true, - "position": { - "x": 1318.728987052518, - "y": -612.0024113659815 - }, - "version": "481", - "inputs": [ - { - "key": "model", - "renderTypeList": ["settingLLMModel", "reference"], - "label": "AI 模型", - "valueType": "string", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "", - "value": "claude-3-5-sonnet-20240620" - }, - { - "key": "temperature", - "renderTypeList": ["hidden"], - "label": "", - "value": 0, - "valueType": "number", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "maxToken", - "renderTypeList": ["hidden"], - "label": "", - "value": 4000, - "valueType": "number", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "isResponseAnswerText", - "renderTypeList": ["hidden"], - "label": "", - "value": false, - "valueType": "boolean", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "aiChatQuoteRole", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "value": "system", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quoteTemplate", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quotePrompt", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "aiChatVision", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "boolean", - "value": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "systemPrompt", - "renderTypeList": ["textarea", "reference"], - "max": 3000, - "valueType": "string", - "label": "提示词", - "description": "core.app.tip.systemPromptTip", - "placeholder": "core.app.tip.chatNodeSystemPromptTip", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "", - "value": "{提示词 START:\n;; 提示词:动物的一生\n;; 作者:空格 zephyr\n\n(defun 动物生命周期 ()\n \"生成动物的生命周期SVG图表和描述\"\n (lambda (主题)\n (let* ((生命阶段 (获取生命阶段 主题))\n (科普数据 (获取科普数据 主题))\n (背景样式 (设计背景 主题))\n (时间轴 (创建时间轴 主题))\n (阶段emoji (选择阶段emoji 主题))\n (装饰emoji (选择装饰emoji 主题))\n (副标题 (生成副标题 主题 科普数据)))\n (创建优化SVG图表 主题 生命阶段 科普数据 背景样式 时间轴 阶段emoji 装饰emoji 副标题))))\n\n(defun 获取生命阶段 (主题)\n \"获取主题的主要生命阶段\"\n (case 主题\n (蝉 '(\"卵\" \"若虫期(地下)\" \"成虫期\"))\n (鲸鱼 '(\"胎儿期\" \"幼年期\" \"青年期\" \"成年期\" \"老年期\"))\n (长颈鹿 '(\"新生期\" \"幼年期\" \"青年期\" \"成年期\" \"老年期\"))\n (t '(\"初期\" \"成长期\" \"成熟期\" \"衰老期\"))))\n\n(defun 获取科普数据 (主题)\n \"获取主题的科普数据列表\"\n (case 主题\n (蝉 '((\"卵在树枝中孵化6-10周,每窝可产200-600颗卵。\"\n \"若虫在地下生活多年,吸食树根汁液生存。\"\n \"若虫经历5次蜕皮,体型可增大20倍。\"\n \"最后一次蜕皮后钻出地面,变为成虫。\"\n \"成虫期仅4-6周,专注于繁衍后代和鸣叫。\")\n \"蝉的地下潜伏期长达17年,成虫仅存活4-6周,鸣叫声可达120分贝,相当于飞机起飞的噪音。\"))\n (鲸鱼 '((\"蓝鲸胎儿每天增重90公斤,出生时重达2.5吨,长7米。\"\n \"幼鲸每天喝380升奶,7个月增重30吨。\"\n \"青年蓝鲸可潜水200米深,屏息长达40分钟。\"\n \"成年蓝鲸长30米,重190吨,一天吃4吨磷虾。\"\n \"最长寿蓝鲸年龄可达110岁,终生可游13次地球赤道距离。\")\n \"蓝鲸是地球上最大的动物,心脏重达600公斤,舌头重如一头大象,叫声可传播1600公里。\"))\n (t '((\"阶段1的数据描述\"\n \"阶段2的数据描述\"\n \"阶段3的数据描述\"\n \"阶段4的数据描述\"\n \"阶段5的数据描述\")\n \"通用主题的有趣数据描述\"))))\n\n(defun 设计背景 (主题)\n \"根据主题设计适合的背景\"\n (case 主题\n (蝉 '(渐变 \"E6F3FF\" \"B3E5FC\" 土地))\n (鲸鱼 '(渐变 \"E3F2FD\" \"90CAF9\" 海洋))\n (长颈鹿 '(渐变 \"FFF8E1\" \"FFE0B2\" 草原))\n (t '(渐变 \"F5F5F5\" \"E0E0E0\" 通用))))\n\n(defun 创建时间轴 (主题)\n \"创建主题生命周期的时间轴\"\n (case 主题\n (蝉 '(\"0年\" \"4年\" \"8年\" \"12年\" \"16年\" \"17年\"))\n (鲸鱼 '(\"0年\" \"10年\" \"25年\" \"50年\" \"75年\" \"100年\"))\n (长颈鹿 '(\"0月\" \"6月\" \"2年\" \"4年\" \"15年\" \"25年\"))\n (t '(\"初期\" \"成长期\" \"成熟期\" \"后期\" \"衰老期\"))))\n\n(defun 选择阶段emoji (主题)\n \"选择与生命阶段相关的emoji\"\n (case 主题\n (蝉 '(\"🥚\" \"🐛\" \"🦟\" \"🎵\"))\n (鲸鱼 '(\"🤰\" \"🍼\" \"🏊\" \"🐋\" \"👵\"))\n (长颈鹿 '(\"👶\" \"🐕\" \"🏃\" \"🦒\" \"👵\"))\n (t '(\"🌱\" \"🌿\" \"🌳\" \"🍂\"))))\n\n(defun 选择装饰emoji (主题)\n \"选择与主题相关的装饰emoji\"\n (case 主题\n (蝉 '(\"🌳\" \"🍃\" \"🌿\" \"🍂\"))\n (鲸鱼 '(\"🌊\" \"🐠\" \"🦈\" \"🐙\"))\n (长颈鹿 '(\"🌴\" \"🌿\" \"🦓\" \"🦁\"))\n (t '(\"🌱\" \"🌳\" \"🍃\" \"🌞\"))))\n\n(defun 生成副标题 (主题 科普数据)\n \"根据科普数据生成副标题\"\n (format \"你知道吗?%s\" (第二个元素 科普数据)))\n\n(defun 创建优化SVG图表 (主题 生命阶段 科普数据 背景样式 时间轴 阶段emoji 装饰emoji 副标题)\n \"创建优化的生命周期SVG图表\"\n (let ((svg-template\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 \n \n \n \n 图例:\n \n 生命阶段\n \n 生命历程\n {图例emoji}\n \n {底部装饰Emoji}\n \"))\n (填充优化SVG模板 svg-template 主题 生命阶段 科普数据 背景样式 时间轴 阶段emoji 装饰emoji 副标题)))\n(defun start ()\n (print \"请输入您想了解的生命主题(如:蝉、鲸鱼、长颈鹿等):\")\n (let ((用户输入 (read)))\n (优化生命周期生成器 用户输入)))\n;; 运行规则\n;; 1. 启动时运行 (start) 函数\n;; 2. 根据用户输入的主题,生成对应的生命周期SVG图表和描述\n;; 3. 输出应包括优化后的SVG图表和相关的文字说明,重点突出科学数据和有趣事实\n提示词 END}\n\n(直接生成 svg 完整代码,我会复制,需要你用代码块)\n(除此之外不要有多余的解释,不要在开头加上任何说明)" - }, - { - "key": "history", - "renderTypeList": ["numberInput", "reference"], - "valueType": "chatHistory", - "label": "聊天记录", - "description": "workflow:max_dialog_rounds", - "required": true, - "min": 0, - "max": 50, - "value": 0, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quoteQA", - "renderTypeList": ["settingDatasetQuotePrompt"], - "label": "", - "debugLabel": "知识库引用", - "description": "", - "valueType": "datasetQuote", - "valueDesc": "", - "toolDescription": "" - }, - { - "key": "stringQuoteText", - "renderTypeList": ["reference", "textarea"], - "label": "文档引用", - "debugLabel": "文档引用", - "description": "app:document_quote_tip", - "valueType": "string", - "valueDesc": "", - "toolDescription": "" - }, - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题", - "valueDesc": "", - "description": "", - "debugLabel": "", - "value": ["448745", "userChatInput"] - } - ], - "outputs": [ - { - "id": "history", - "key": "history", - "required": true, - "label": "common:core.module.output.label.New context", - "description": "将本次回复内容拼接上历史记录,作为新的上下文返回", - "valueType": "chatHistory", - "valueDesc": "{\n obj: System | Human | AI;\n value: string;\n}[]", - "type": "static" - }, - { - "id": "answerText", - "key": "answerText", - "required": true, - "label": "common:core.module.output.label.Ai response content", - "description": "将在 stream 回复完毕后触发", - "valueType": "string", - "type": "static" - } - ] - }, - { - "nodeId": "sbVUb0efY6Fm", - "name": "代码运行", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 2210.2574140398733, - "y": -621.0024113659815 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({svg_str}){\n\n // 使用正则表达式匹配代码块中的内容\n const match = svg_str.match(/```[\\w]*\\n([\\s\\S]*?)```/);\n\n if (!match) {\n // 如果没有匹配到代码块,返回一个错误信息或空结果\n return {\n result: null,\n error: \"未找到有效的代码块标记。\"\n };\n }\n\n // 提取代码块中的 SVG 内容\n const extractedSvg = match[1].trim();\n \n const base64 = strToBase64(extractedSvg,'data:image/svg+xml;base64,')\n\n return {\n result: base64\n }\n}", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "svg_str", - "label": "svg_str", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "", - "value": ["bg853CwHAw4a", "answerText"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key", - "valueDesc": "" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "result", - "valueType": "string", - "label": "result", - "valueDesc": "", - "description": "" - } - ] - }, - { - "nodeId": "cPh2VZnVxjQ8", - "name": "指定回复", - "intro": "该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。", - "avatar": "core/workflow/template/reply", - "flowNodeType": "answerNode", - "position": { - "x": 2911.2230784647795, - "y": -411.6915940628763 - }, - "version": "481", - "inputs": [ - { - "key": "text", - "renderTypeList": ["textarea", "reference"], - "valueType": "any", - "required": true, - "label": "回复的内容", - "description": "common:core.module.input.description.Response content", - "placeholder": "common:core.module.input.description.Response content", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "", - "value": "SVG:\n\n{{$bg853CwHAw4a.answerText$}}\n\n卡片:\n\n![]({{$sbVUb0efY6Fm.qLUQfhG0ILRX$}})" - } - ], - "outputs": [] - } - ], - "edges": [ - { - "source": "bg853CwHAw4a", - "target": "sbVUb0efY6Fm", - "sourceHandle": "bg853CwHAw4a-source-right", - "targetHandle": "sbVUb0efY6Fm-target-left" - }, - { - "source": "448745", - "target": "bg853CwHAw4a", - "sourceHandle": "448745-source-right", - "targetHandle": "bg853CwHAw4a-target-left" - }, - { - "source": "sbVUb0efY6Fm", - "target": "cPh2VZnVxjQ8", - "sourceHandle": "sbVUb0efY6Fm-source-right", - "targetHandle": "cPh2VZnVxjQ8-target-left" - } - ], - "chatConfig": { - "variables": [], - "scheduledTriggerConfig": { - "cronString": "", - "timezone": "Asia/Shanghai", - "defaultPrompt": "" - }, - "_id": "66f0f7540a40cd1f97da9dd6" - } - } -} diff --git a/packages/templates/src/chatGuide/template.json b/packages/templates/src/chatGuide/template.json deleted file mode 100644 index 67dab9bcd..000000000 --- a/packages/templates/src/chatGuide/template.json +++ /dev/null @@ -1,196 +0,0 @@ -{ - "name": "对话引导 + 变量", - "intro": "可以在对话开始发送一段提示,或者让用户填写一些内容,作为本次对话的变量", - "author": "", - "avatar": "core/workflow/template/systemConfig", - "tags": ["office-services"], - "type": "simple", - "weight": 1, - "workflow": { - "nodes": [ - { - "nodeId": "userGuide", - "name": "系统配置", - "intro": "可以配置应用的系统参数", - "avatar": "/imgs/workflow/userGuide.png", - "flowNodeType": "userGuide", - "position": { - "x": 496.57560693988853, - "y": -490.7611729549753 - }, - "version": "481", - "inputs": [], - "outputs": [] - }, - { - "nodeId": "448745", - "name": "流程开始", - "intro": "", - "avatar": "/imgs/workflow/userChatInput.svg", - "flowNodeType": "workflowStart", - "position": { - "x": 558.4082376415505, - "y": 123.72387429194112 - }, - "version": "481", - "inputs": [ - { - "key": "userChatInput", - "renderTypeList": ["FlowNodeInputTypeEnum.reference", "FlowNodeInputTypeEnum.textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题" - } - ], - "outputs": [ - { - "id": "userChatInput", - "key": "userChatInput", - "label": "core.module.input.label.user question", - "valueType": "string", - "type": "FlowNodeOutputTypeEnum.static" - } - ] - }, - { - "nodeId": "loOvhld2ZTKa", - "name": "AI 对话", - "intro": "AI 大模型对话", - "avatar": "/imgs/workflow/AI.png", - "flowNodeType": "chatNode", - "showStatus": true, - "position": { - "x": 1097.7317280958762, - "y": -244.16014496351386 - }, - "version": "481", - "inputs": [ - { - "key": "model", - "renderTypeList": [ - "FlowNodeInputTypeEnum.settingLLMModel", - "FlowNodeInputTypeEnum.reference" - ], - "label": "core.module.input.label.aiModel", - "valueType": "string", - "value": "gpt-3.5-turbo" - }, - { - "key": "temperature", - "renderTypeList": ["FlowNodeInputTypeEnum.hidden"], - "label": "", - "value": 0, - "valueType": "number", - "min": 0, - "max": 10, - "step": 1 - }, - { - "key": "maxToken", - "renderTypeList": ["FlowNodeInputTypeEnum.hidden"], - "label": "", - "value": 2000, - "valueType": "number", - "min": 100, - "max": 4000, - "step": 50 - }, - { - "key": "isResponseAnswerText", - "renderTypeList": ["FlowNodeInputTypeEnum.hidden"], - "label": "", - "value": true, - "valueType": "boolean" - }, - { - "key": "quoteTemplate", - "renderTypeList": ["FlowNodeInputTypeEnum.hidden"], - "label": "", - "valueType": "string" - }, - { - "key": "quotePrompt", - "renderTypeList": ["FlowNodeInputTypeEnum.hidden"], - "label": "", - "valueType": "string" - }, - { - "key": "systemPrompt", - "renderTypeList": ["FlowNodeInputTypeEnum.textarea", "FlowNodeInputTypeEnum.reference"], - "max": 3000, - "valueType": "string", - "label": "core.ai.Prompt", - "description": "core.app.tip.systemPromptTip", - "placeholder": "core.app.tip.chatNodeSystemPromptTip", - "value": "请直接将我的问题翻译成{{language}},不需要回答问题。" - }, - { - "key": "history", - "renderTypeList": [ - "FlowNodeInputTypeEnum.numberInput", - "FlowNodeInputTypeEnum.reference" - ], - "valueType": "chatHistory", - "label": "core.module.input.label.chat history", - "required": true, - "min": 0, - "max": 30, - "value": 6 - }, - { - "key": "userChatInput", - "renderTypeList": ["FlowNodeInputTypeEnum.reference", "FlowNodeInputTypeEnum.textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题", - "value": ["448745", "userChatInput"] - }, - { - "key": "quoteQA", - "renderTypeList": ["FlowNodeInputTypeEnum.settingDatasetQuotePrompt"], - "label": "", - "debugLabel": "知识库引用", - "description": "", - "valueType": "datasetQuote" - } - ], - "outputs": [ - { - "id": "history", - "key": "history", - "label": "core.module.output.label.New context", - "description": "core.module.output.description.New context", - "valueType": "chatHistory", - "type": "FlowNodeOutputTypeEnum.static" - }, - { - "id": "answerText", - "key": "answerText", - "label": "core.module.output.label.Ai response content", - "description": "core.module.output.description.Ai response content", - "valueType": "string", - "type": "FlowNodeOutputTypeEnum.static" - } - ] - } - ], - "edges": [ - { - "source": "448745", - "target": "loOvhld2ZTKa", - "sourceHandle": "448745-source-right", - "targetHandle": "loOvhld2ZTKa-target-left" - } - ], - "chatConfig": { - "welcomeText": "你好,我可以为你翻译各种语言,请告诉我你需要翻译成什么语言?", - "scheduledTriggerConfig": { - "cronString": "", - "timezone": "Asia/Shanghai", - "defaultPrompt": "" - } - } - } -} diff --git a/packages/templates/src/divination/template.json b/packages/templates/src/divination/template.json deleted file mode 100644 index fcfdf647f..000000000 --- a/packages/templates/src/divination/template.json +++ /dev/null @@ -1,518 +0,0 @@ -{ - "name": "周易占卜", - "intro": "AI占卜,快来算算你的运势~", - "author": "", - "avatar": "core/app/templates/divination", - "tags": ["roleplay"], - "type": "advanced", - "workflow": { - "nodes": [ - { - "nodeId": "userGuide", - "name": "common:core.module.template.system_config", - "intro": "common:core.module.template.system_config_info", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "userGuide", - "position": { - "x": 262.2732338817093, - "y": -476.00241136598146 - }, - "version": "481", - "inputs": [ - { - "key": "welcomeText", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "core.app.Welcome Text", - "value": "" - }, - { - "key": "variables", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "core.app.Chat Variable", - "value": [] - }, - { - "key": "questionGuide", - "valueType": "any", - "renderTypeList": ["hidden"], - "label": "core.app.Question Guide", - "value": { - "open": false - } - }, - { - "key": "tts", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "type": "web" - } - }, - { - "key": "whisper", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - } - }, - { - "key": "scheduleTrigger", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": null - } - ], - "outputs": [] - }, - { - "nodeId": "448745", - "name": "common:core.module.template.work_start", - "intro": "", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "workflowStart", - "position": { - "x": 632.368838596004, - "y": -347.7446492944009 - }, - "version": "481", - "inputs": [ - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "common:core.module.input.label.user question", - "required": true, - "toolDescription": "用户问题", - "debugLabel": "" - } - ], - "outputs": [ - { - "id": "userChatInput", - "key": "userChatInput", - "label": "common:core.module.input.label.user question", - "type": "static", - "valueType": "string", - "description": "" - } - ] - }, - { - "nodeId": "bg853CwHAw4a", - "name": "AI 对话", - "intro": "AI 大模型对话", - "avatar": "core/workflow/template/aiChat", - "flowNodeType": "chatNode", - "showStatus": true, - "position": { - "x": 1318.728987052518, - "y": -612.0024113659815 - }, - "version": "481", - "inputs": [ - { - "key": "model", - "renderTypeList": ["settingLLMModel", "reference"], - "label": "AI 模型", - "valueType": "string", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "", - "value": "claude-3-5-sonnet-20240620" - }, - { - "key": "temperature", - "renderTypeList": ["hidden"], - "label": "", - "value": 0, - "valueType": "number", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "maxToken", - "renderTypeList": ["hidden"], - "label": "", - "value": 4000, - "valueType": "number", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "isResponseAnswerText", - "renderTypeList": ["hidden"], - "label": "", - "value": false, - "valueType": "boolean", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "aiChatQuoteRole", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "value": "system", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quoteTemplate", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quotePrompt", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "aiChatVision", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "boolean", - "value": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "systemPrompt", - "renderTypeList": ["textarea", "reference"], - "max": 3000, - "valueType": "string", - "label": "提示词", - "description": "core.app.tip.chatNodeSystemPromptTip", - "placeholder": "core.app.tip.chatNodeSystemPromptTip", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "", - "value": "你是精通中国传统周易八卦理论的卜算大师,能够对用户所求的问题进行占卜, 要列出正确的卦名,并用如下模版展示答案,注意模版中各部分内容字数,确保展示完全\n\n你应该先确认卦名,然后根据下表确认卦象对应的二进制,一步一步从上到下输出该二进制对应的阴阳爻,绝对不能出错, 在绘制svg的时候确保阴阳爻正确,最后根据阴阳爻得到svg卡片,最后输出对卦象的解读\n把思考过程输出到中\n把 svg 卡片的内容输出到 svg 代码块中\n\n二进制转阴阳爻的示例: \n小畜卦的二进制是110111,从上到下对应的阴阳爻依次为: 阳阳阴阳阳阳\n损卦的二进制是100011,从上到下对应的阴阳爻依次为: 阳阴阴阴阳阳\n需卦的二进制是010111,从上到下对应的阴阳爻依次为: 阴阳阴阳阳阳\n\n\nsvg中的阳爻示例:\n\n\nsvg中的阴爻示例:\n\nline x1=\"66\" y1=\"33\" x2=\"110\" y2=\"33\" stroke=\"#8A4419\" stroke-width=\"8\"/>\n\n\n64卦对应的二进制 (注意二进制中的1表示阳,0表示阴):\n`\n| 卦名 | 二进制值 |\n|------|----------|\n| 乾 | 111111 |\n| 坤 | 000000 |\n| 屯 | 010001 |\n| 蒙 | 100010 |\n| 需 | 010111 |\n| 讼 | 111010 |\n| 师 | 000010 |\n| 比 | 010000 |\n| 小畜 | 110111 |\n| 履 | 111011 |\n| 泰 | 000111 |\n| 否 | 111000 |\n| 同人 | 111101 |\n| 大有 | 101111 |\n| 谦 | 000100 |\n| 豫 | 001000 |\n| 随 | 011001 |\n| 蛊 | 100110 |\n| 临 | 000011 |\n| 观 | 110000 |\n| 噬嗑 | 101001 |\n| 贲 | 100101 |\n| 剥 | 100000 |\n| 复 | 000001 |\n| 无妄 | 111001 |\n| 大畜 | 100111 |\n| 颐 | 100001 |\n| 大过 | 011110 |\n| 坎 | 010010 |\n| 离 | 101101 |\n| 咸 | 011100 |\n| 恒 | 001110 |\n| 遁 | 111100 |\n| 大壮 | 001111 |\n| 晋 | 101000 |\n| 明夷 | 000101 |\n| 家人 | 110101 |\n| 睽 | 101011 |\n| 蹇 | 010100 |\n| 解 | 001010 |\n| 损 | 100011 |\n| 益 | 110001 |\n| 夬 | 011111 |\n| 姤 | 111110 |\n| 萃 | 011000 |\n| 升 | 000110 |\n| 困 | 011010 |\n| 井 | 010110 |\n| 革 | 011101 |\n| 鼎 | 101110 |\n| 震 | 001001 |\n| 艮 | 100100 |\n| 渐 | 110100 |\n| 归妹 | 001011 |\n| 丰 | 001101 |\n| 旅 | 101100 |\n| 巽 | 110110 |\n| 兑 | 011011 |\n| 涣 | 110010 |\n| 节 | 010011 |\n| 中孚 | 110011 |\n| 小过 | 001100 |\n| 既济 | 010101 |\n| 未济 | 101010 |\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 \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 \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 卦意:喜悦中有变,柔中寓刚。当今三十有四,\n 至三十六七载,当有睡后之财渐成气候。\n 切记:以柔克刚,顺势而为,终可成就大事。\n \n \n \n \n \n 妙算\n 子印\n \n \n \n 天机玄妙,此卦聊备参考,切勿执着\n \n \n 妙算子 Claude 敬上\n\n`" - }, - { - "key": "history", - "renderTypeList": ["numberInput", "reference"], - "valueType": "chatHistory", - "label": "聊天记录", - "description": "workflow:max_dialog_rounds", - "required": true, - "min": 0, - "max": 50, - "value": 6, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quoteQA", - "renderTypeList": ["settingDatasetQuotePrompt"], - "label": "", - "debugLabel": "知识库引用", - "description": "", - "valueType": "datasetQuote", - "valueDesc": "", - "toolDescription": "" - }, - { - "key": "stringQuoteText", - "renderTypeList": ["reference", "textarea"], - "label": "文档引用", - "debugLabel": "文档引用", - "description": "app:document_quote_tip", - "valueType": "string", - "valueDesc": "", - "toolDescription": "" - }, - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题", - "valueDesc": "", - "description": "", - "debugLabel": "", - "value": ["448745", "userChatInput"] - } - ], - "outputs": [ - { - "id": "history", - "key": "history", - "required": true, - "label": "common:core.module.output.label.New context", - "description": "将本次回复内容拼接上历史记录,作为新的上下文返回", - "valueType": "chatHistory", - "valueDesc": "{\n obj: System | Human | AI;\n value: string;\n}[]", - "type": "static" - }, - { - "id": "answerText", - "key": "answerText", - "required": true, - "label": "common:core.module.output.label.Ai response content", - "description": "将在 stream 回复完毕后触发", - "valueType": "string", - "type": "static" - } - ] - }, - { - "nodeId": "sbVUb0efY6Fm", - "name": "代码运行", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 2210.2574140398733, - "y": -621.0024113659815 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({svg_str}){\n\n // 正则表达式匹配代码块中的内容\n const codeBlockRegex = /```[\\w]*\\n([\\s\\S]*?)```/;\n const codeMatch = svg_str.match(codeBlockRegex);\n\n // 正则表达式匹配 标签中的内容\n const thinkingRegex = /([\\s\\S]*?)<\\/thinking>/;\n const thinkingMatch = svg_str.match(thinkingRegex);\n\n // 提取代码块之后的所有内容\n let contentAfterCodeBlock = null;\n if (codeMatch) {\n const endIndex = codeMatch.index + codeMatch[0].length;\n contentAfterCodeBlock = svg_str.slice(endIndex).trim();\n }\n\n // 处理代码块内容\n let base64 = null;\n if (codeMatch) {\n const extractedSvg = codeMatch[1].trim();\n base64 = strToBase64(extractedSvg, 'data:image/svg+xml;base64,');\n } else {\n // 如果没有找到代码块,返回错误信息\n return {\n result: null,\n thinking: null,\n error: \"未找到有效的代码块标记。\"\n };\n }\n\n // 处理 标签内容\n let thinkingContent = null;\n if (thinkingMatch) {\n thinkingContent = thinkingMatch[1].trim();\n }\n\n return {\n result: base64,\n thinking: thinkingContent,\n contentAfter: contentAfterCodeBlock\n }\n}", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "svg_str", - "label": "svg_str", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "", - "value": ["bg853CwHAw4a", "answerText"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key", - "valueDesc": "" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "result", - "valueType": "string", - "label": "result", - "valueDesc": "", - "description": "" - }, - { - "id": "faWiQXDtBUKj", - "valueType": "string", - "type": "dynamic", - "key": "thinking", - "label": "thinking" - }, - { - "id": "mS7yAR8REIhZ", - "valueType": "string", - "type": "dynamic", - "key": "contentAfter", - "label": "contentAfter" - } - ] - }, - { - "nodeId": "cPh2VZnVxjQ8", - "name": "指定回复", - "intro": "该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。", - "avatar": "core/workflow/template/reply", - "flowNodeType": "answerNode", - "position": { - "x": 2911.2230784647795, - "y": -411.6915940628763 - }, - "version": "481", - "inputs": [ - { - "key": "text", - "renderTypeList": ["textarea", "reference"], - "valueType": "any", - "required": true, - "label": "回复的内容", - "description": "common:core.module.input.description.Response content", - "placeholder": "common:core.module.input.description.Response content", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "", - "value": "{{$sbVUb0efY6Fm.faWiQXDtBUKj$}}\n\n![]({{$sbVUb0efY6Fm.qLUQfhG0ILRX$}})\n\n{{$sbVUb0efY6Fm.mS7yAR8REIhZ$}}" - } - ], - "outputs": [] - } - ], - "edges": [ - { - "source": "bg853CwHAw4a", - "target": "sbVUb0efY6Fm", - "sourceHandle": "bg853CwHAw4a-source-right", - "targetHandle": "sbVUb0efY6Fm-target-left" - }, - { - "source": "448745", - "target": "bg853CwHAw4a", - "sourceHandle": "448745-source-right", - "targetHandle": "bg853CwHAw4a-target-left" - }, - { - "source": "sbVUb0efY6Fm", - "target": "cPh2VZnVxjQ8", - "sourceHandle": "sbVUb0efY6Fm-source-right", - "targetHandle": "cPh2VZnVxjQ8-target-left" - } - ], - "chatConfig": { - "welcomeText": "请输入您的问题,老朽将为您算上一卦~", - "variables": [], - "scheduledTriggerConfig": { - "cronString": "", - "timezone": "Asia/Shanghai", - "defaultPrompt": "" - }, - "_id": "66f3c581e7fbb61a42775716" - } - } -} diff --git a/packages/templates/src/flux/template.json b/packages/templates/src/flux/template.json deleted file mode 100644 index d31e03e7c..000000000 --- a/packages/templates/src/flux/template.json +++ /dev/null @@ -1,330 +0,0 @@ -{ - "name": "Flux 绘图", - "intro": "通过请求 Flux 接口绘图,需要有 api key", - "author": "", - "avatar": "core/app/templates/flux", - "type": "plugin", - "tags": ["image-generation"], - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "插件开始", - "intro": "可以配置插件需要哪些输入,利用这些输入来运行插件", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 503.3030871469042, - "y": -91.64434154072819 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "绘图提示词", - "label": "绘图提示词", - "description": "绘图提示词", - "required": true, - "toolDescription": "绘图提示词" - } - ], - "outputs": [ - { - "id": "绘图提示词", - "valueType": "string", - "key": "绘图提示词", - "label": "绘图提示词", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "插件输出", - "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 1876.2082565873427, - "y": -110.14434154072819 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "图片访问链接", - "label": "图片访问链接", - "description": "", - "value": ["tMvel910bnrJ", "pJXgWoTpPoMy"] - }, - { - "renderTypeList": ["reference"], - "valueType": "object", - "canEdit": true, - "key": "error", - "label": "错误信息", - "description": "", - "value": ["tMvel910bnrJ", "error"] - } - ], - "outputs": [] - }, - { - "nodeId": "tMvel910bnrJ", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1138.1732435351091, - "y": -416.6443415407282 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "https://fal.run/fal-ai/flux-pro", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [ - { - "key": "Authorization", - "type": "string", - "value": "Key {{apikey}}" - } - ], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\n \"prompt\": \"{{prompt}}\",\n \"image_size\": \"landscape_4_3\",\n \"num_inference_steps\": 28,\n \"guidance_scale\": 3.5\n}", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "prompt", - "label": "prompt", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "绘图提示词"] - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - } - }, - { - "id": "pJXgWoTpPoMy", - "valueType": "string", - "type": "dynamic", - "key": "images[0].url", - "label": "images[0].url" - } - ] - }, - { - "nodeId": "lSYsc889IXDr", - "name": "系统配置", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": 45.52914573588026, - "y": -110.14434154072819 - }, - "version": "4811", - "inputs": [], - "outputs": [] - } - ], - "edges": [ - { - "source": "pluginInput", - "target": "tMvel910bnrJ", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "tMvel910bnrJ-target-left" - }, - { - "source": "tMvel910bnrJ", - "target": "pluginOutput", - "sourceHandle": "tMvel910bnrJ-source-right", - "targetHandle": "pluginOutput-target-left" - } - ] - } -} diff --git a/packages/templates/src/githubIssue/template.json b/packages/templates/src/githubIssue/template.json deleted file mode 100644 index e53aec743..000000000 --- a/packages/templates/src/githubIssue/template.json +++ /dev/null @@ -1,926 +0,0 @@ -{ - "name": "GitHub Issue 总结机器人", - "intro": "定时获取GitHub Issue信息,使用AI进行总结,并推送到飞书群中", - "author": "", - "avatar": "core/app/templates/githubIssue", - "tags": ["office-services"], - "type": "advanced", - "userGuide": { - "type": "link", - "content": "https://mp.weixin.qq.com/s/CBrwSn1jQZO7ybsMSx5GnQ" - }, - "workflow": { - "nodes": [ - { - "nodeId": "userGuide", - "name": "common:core.module.template.system_config", - "intro": "common:core.module.template.system_config_info", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "userGuide", - "position": { - "x": 262.2732338817093, - "y": -476.00241136598146 - }, - "version": "481", - "inputs": [ - { - "key": "welcomeText", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "core.app.Welcome Text", - "value": "" - }, - { - "key": "variables", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "core.app.Chat Variable", - "value": [] - }, - { - "key": "questionGuide", - "valueType": "hidden", - "renderTypeList": ["hidden"], - "label": "core.app.Question Guide", - "value": { - "open": false - } - }, - { - "key": "tts", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "type": "web" - } - }, - { - "key": "whisper", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - } - }, - { - "key": "scheduleTrigger", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": null - } - ], - "outputs": [] - }, - { - "nodeId": "448745", - "name": "common:core.module.template.work_start", - "intro": "", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "workflowStart", - "position": { - "x": 632.368838596004, - "y": -347.7446492944009 - }, - "version": "481", - "inputs": [ - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "common:core.module.input.label.user question", - "required": true, - "toolDescription": "用户问题", - "debugLabel": "" - } - ], - "outputs": [ - { - "id": "userChatInput", - "key": "userChatInput", - "label": "common:core.module.input.label.user question", - "type": "static", - "valueType": "string", - "description": "" - } - ] - }, - { - "nodeId": "jVGuKrDfFTU6", - "name": "获取 24 小时前的日期", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 1045.4174257570808, - "y": -94.5419824521446 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main() {\n const date = new Date();\n date.setDate(date.getDate() - 3);\n const day = date.getDate();\n const month = date.getMonth() + 1;\n const year = date.getFullYear();\n const hours = date.getHours();\n const minutes = date.getMinutes();\n\n return {\n date: `${year}-${month}-${day}T${hours}:${minutes}:000Z`,\n }\n }", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key", - "valueDesc": "" - }, - { - "id": "gR0mkQpJ4Og8", - "type": "dynamic", - "key": "date", - "valueType": "string", - "label": "date", - "valueDesc": "", - "description": "" - } - ] - }, - { - "nodeId": "jyftFRrd4RQf", - "name": "指定回复", - "intro": "该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。", - "avatar": "core/workflow/template/reply", - "flowNodeType": "answerNode", - "position": { - "x": 1758.8251385440858, - "y": 80.55020745654087 - }, - "version": "481", - "inputs": [ - { - "key": "text", - "renderTypeList": ["textarea", "reference"], - "valueType": "any", - "required": true, - "label": "回复的内容", - "description": "common:core.module.input.description.Response content", - "placeholder": "common:core.module.input.description.Response content", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "", - "value": "拉取从 {{$jVGuKrDfFTU6.gR0mkQpJ4Og8$}} 以来所有的 open issue \\n" - } - ], - "outputs": [] - }, - { - "nodeId": "mCaalLpFoZFk", - "name": "获取 Issues", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 2602.5615507147536, - "y": -67.18952984768578 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "GET", - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "https://api.github.com/repos/labring/FastGPT/issues", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [ - { - "key": "state", - "type": "string", - "value": "open" - }, - { - "key": "since", - "type": "string", - "value": "{{$jVGuKrDfFTU6.gR0mkQpJ4Og8$}}" - } - ], - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "", - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "valueDesc": "", - "description": "" - } - ] - }, - { - "nodeId": "gALvyJcXPoep", - "name": "处理 API 响应数据", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 3396.722564475613, - "y": -80.79235153344955 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({res}) {\n const issues = JSON.parse(res);\n const ret = [];\n for(const issue of issues) {\n if (issue.pull_request) continue;\n ret.push({\n title: issue.title,\n body: issue.body,\n url: issue.html_url\n })\n }\n\n return {\n ret: JSON.stringify(ret)\n }\n}", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "res", - "label": "res", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "", - "value": ["mCaalLpFoZFk", "httpRawResponse"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key", - "valueDesc": "" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "ret", - "valueType": "string", - "label": "ret", - "valueDesc": "", - "description": "" - } - ] - }, - { - "nodeId": "aLrp6IjV8zAf", - "name": "AI 对话", - "intro": "AI 大模型对话", - "avatar": "core/workflow/template/aiChat", - "flowNodeType": "chatNode", - "showStatus": true, - "position": { - "x": 3907.7186093895143, - "y": -148.24856757598377 - }, - "version": "481", - "inputs": [ - { - "key": "model", - "renderTypeList": ["settingLLMModel", "reference"], - "label": "AI 模型", - "valueType": "string", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "", - "value": "qwen-plus" - }, - { - "key": "temperature", - "renderTypeList": ["hidden"], - "label": "", - "value": 0, - "valueType": "number", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "maxToken", - "renderTypeList": ["hidden"], - "label": "", - "value": 8000, - "valueType": "number", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "isResponseAnswerText", - "renderTypeList": ["hidden"], - "label": "", - "value": true, - "valueType": "boolean", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "aiChatQuoteRole", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "value": "system", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quoteTemplate", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quotePrompt", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "aiChatVision", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "boolean", - "value": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "systemPrompt", - "renderTypeList": ["textarea", "reference"], - "max": 3000, - "valueType": "string", - "label": "提示词", - "description": "core.app.tip.systemPromptTip", - "placeholder": "core.app.tip.chatNodeSystemPromptTip", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "", - "value": "你是一个简洁高效的 GitHub Issue 概述助手,专长于提炼核心问题并以清晰简洁的方式呈现。\n\n## 任务\n分析输入的多条 issue 信息,为每个 issue 创建一个简明扼要的概述。使用中文输出。\n\n## 输入格式\nJSON 数组,每项包含 title(标题)、body(内容)和 url(链接)。\n\n## 输出格式\n对每个 issue 使用 Markdown 语法创建简洁的概述块。每个概述应包含:\n\n1. 使用加粗呈现 issue 的原标题\n2. 一段简短的问题概述(不超过 2-3 句话)\n3. 原 issue 的链接(使用 Markdown 链接语法)\n\n在概述中适当使用 emoji 来增加可读性,但不要过度使用。保持整体风格简洁明了。\n\n示例输出:\n\n---\n\n**🔍 数据可视化组件性能优化**\n\n这个 issue 反映了在处理大量数据时图表加载缓慢的问题。用户在数据点超过一定数量时experiencing明显的性能下降,影响了用户体验。\n\n📎 [查看原 issue](url1)\n\n---\n\n**🐞 移动端界面适配问题**\n\n该 issue 指出在某些特定型号的移动设备上出现了界面布局错乱的情况。这个问题影响了应用在不同尺寸屏幕上的一致性展现。\n\n📎 [查看原 issue](url2)\n\n---\n\n请确保每个 issue 概述都简洁明了,突出核心问题,避免过多细节。保持整体风格统一,让读者能快速理解每个 issue 的要点。" - }, - { - "key": "history", - "renderTypeList": ["numberInput", "reference"], - "valueType": "chatHistory", - "label": "聊天记录", - "description": "workflow:max_dialog_rounds", - "required": true, - "min": 0, - "max": 50, - "value": 0, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quoteQA", - "renderTypeList": ["settingDatasetQuotePrompt"], - "label": "", - "debugLabel": "知识库引用", - "description": "", - "valueType": "datasetQuote", - "valueDesc": "", - "toolDescription": "" - }, - { - "key": "stringQuoteText", - "renderTypeList": ["reference", "textarea"], - "label": "文档引用", - "debugLabel": "文档引用", - "description": "app:document_quote_tip", - "valueType": "string", - "valueDesc": "", - "toolDescription": "" - }, - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "toolDescription": "用户问题", - "required": true, - "value": ["gALvyJcXPoep", "qLUQfhG0ILRX"], - "valueDesc": "", - "description": "", - "debugLabel": "" - } - ], - "outputs": [ - { - "id": "history", - "key": "history", - "required": true, - "label": "common:core.module.output.label.New context", - "description": "将本次回复内容拼接上历史记录,作为新的上下文返回", - "valueType": "chatHistory", - "valueDesc": "{\n obj: System | Human | AI;\n value: string;\n}[]", - "type": "static" - }, - { - "id": "answerText", - "key": "answerText", - "required": true, - "label": "common:core.module.output.label.Ai response content", - "description": "将在 stream 回复完毕后触发", - "valueType": "string", - "type": "static" - } - ] - }, - { - "nodeId": "jmSiT6OXA3Fe", - "name": "飞书机器人 webhook", - "intro": "向飞书机器人发起 webhook 请求。", - "avatar": "/appMarketTemplates/plugin-feishu/avatar.svg", - "flowNodeType": "pluginModule", - "showStatus": false, - "position": { - "x": 4682.428295424065, - "y": 120.04658236877646 - }, - "version": "488", - "inputs": [ - { - "key": "system_forbid_stream", - "renderTypeList": ["switch"], - "valueType": "boolean", - "label": "禁用流输出", - "description": "强制设置嵌套运行的应用,均以非流模式运行", - "value": true, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": false, - "key": "content", - "label": "content", - "description": "需要发送的消息", - "required": true, - "toolDescription": "需要发送的消息", - "value": ["aLrp6IjV8zAf", "answerText"], - "valueDesc": "", - "debugLabel": "" - }, - { - "renderTypeList": ["input"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": false, - "key": "hook_url", - "label": "hook_url", - "description": "飞书机器人地址", - "required": true, - "defaultValue": "", - "value": "https://www.feishu.cn/flow/api/trigger-webhook/5a1657d6f024c639e1e9af4d9d611292", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - } - ], - "outputs": [ - { - "id": "result", - "type": "static", - "key": "result", - "valueType": "object", - "label": "result", - "description": "", - "valueDesc": "" - } - ], - "pluginId": "community-feishu" - } - ], - "edges": [ - { - "source": "448745", - "target": "jVGuKrDfFTU6", - "sourceHandle": "448745-source-right", - "targetHandle": "jVGuKrDfFTU6-target-left" - }, - { - "source": "jVGuKrDfFTU6", - "target": "jyftFRrd4RQf", - "sourceHandle": "jVGuKrDfFTU6-source-right", - "targetHandle": "jyftFRrd4RQf-target-left" - }, - { - "source": "jyftFRrd4RQf", - "target": "mCaalLpFoZFk", - "sourceHandle": "jyftFRrd4RQf-source-right", - "targetHandle": "mCaalLpFoZFk-target-left" - }, - { - "source": "mCaalLpFoZFk", - "target": "gALvyJcXPoep", - "sourceHandle": "mCaalLpFoZFk-source-right", - "targetHandle": "gALvyJcXPoep-target-left" - }, - { - "source": "gALvyJcXPoep", - "target": "aLrp6IjV8zAf", - "sourceHandle": "gALvyJcXPoep-source-right", - "targetHandle": "aLrp6IjV8zAf-target-left" - }, - { - "source": "aLrp6IjV8zAf", - "target": "jmSiT6OXA3Fe", - "sourceHandle": "aLrp6IjV8zAf-source-right", - "targetHandle": "jmSiT6OXA3Fe-target-left" - } - ], - "chatConfig": { - "variables": [], - "scheduledTriggerConfig": { - "cronString": "", - "timezone": "Asia/Shanghai", - "defaultPrompt": "" - }, - "_id": "67152011bb78889107c3a4ec" - } - } -} diff --git a/packages/templates/src/google/template.json b/packages/templates/src/google/template.json deleted file mode 100644 index 6097dee77..000000000 --- a/packages/templates/src/google/template.json +++ /dev/null @@ -1,443 +0,0 @@ -{ - "name": "谷歌搜索", - "intro": "通过请求谷歌搜索,查询相关内容作为模型的参考。", - "author": "", - "avatar": "core/app/templates/google", - "tags": ["recommendation", "web-search"], - "type": "advanced", - "workflow": { - "nodes": [ - { - "nodeId": "userGuide", - "name": "系统配置", - "intro": "可以配置应用的系统参数", - "avatar": "/imgs/workflow/userGuide.png", - "flowNodeType": "userGuide", - "position": { - "x": 262.2732338817093, - "y": -476.00241136598146 - }, - "version": "481", - "inputs": [ - { - "key": "welcomeText", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "core.app.Welcome Text", - "value": "" - }, - { - "key": "variables", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "core.app.Chat Variable", - "value": [] - }, - { - "key": "questionGuide", - "valueType": "any", - "renderTypeList": ["hidden"], - "label": "core.app.Question Guide", - "value": { - "open": false - } - }, - { - "key": "tts", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "type": "web" - } - }, - { - "key": "whisper", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - } - }, - { - "key": "scheduleTrigger", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": null - } - ], - "outputs": [] - }, - { - "nodeId": "448745", - "name": "流程开始", - "intro": "", - "avatar": "/imgs/workflow/userChatInput.svg", - "flowNodeType": "workflowStart", - "position": { - "x": 295.8944548701009, - "y": 110.81336038514848 - }, - "version": "481", - "inputs": [ - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题" - } - ], - "outputs": [ - { - "id": "userChatInput", - "key": "userChatInput", - "label": "core.module.input.label.user question", - "valueType": "string", - "type": "static" - } - ] - }, - { - "nodeId": "NOgbnBzUwDgT", - "name": "工具调用", - "intro": "通过AI模型自动选择一个或多个功能块进行调用,也可以对插件进行调用。", - "avatar": "/imgs/workflow/tool.svg", - "flowNodeType": "tools", - "showStatus": true, - "position": { - "x": 1028.8358722416106, - "y": -500.8755882990822 - }, - "version": "481", - "inputs": [ - { - "key": "model", - "renderTypeList": ["settingLLMModel", "reference"], - "label": "core.module.input.label.aiModel", - "valueType": "string", - "llmModelType": "all", - "value": "FastAI-plus" - }, - { - "key": "temperature", - "renderTypeList": ["hidden"], - "label": "", - "value": 0, - "valueType": "number", - "min": 0, - "max": 10, - "step": 1 - }, - { - "key": "maxToken", - "renderTypeList": ["hidden"], - "label": "", - "value": 2000, - "valueType": "number", - "min": 100, - "max": 4000, - "step": 50 - }, - { - "key": "systemPrompt", - "renderTypeList": ["textarea", "reference"], - "max": 3000, - "valueType": "string", - "label": "core.ai.Prompt", - "description": "core.app.tip.systemPromptTip", - "placeholder": "core.app.tip.chatNodeSystemPromptTip", - "value": "" - }, - { - "key": "history", - "renderTypeList": ["numberInput", "reference"], - "valueType": "chatHistory", - "label": "core.module.input.label.chat history", - "description": "最多携带多少轮对话记录", - "required": true, - "min": 0, - "max": 30, - "value": 6 - }, - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "value": ["448745", "userChatInput"] - } - ], - "outputs": [ - { - "id": "NodeOutputKeyEnum.answerText", - "key": "NodeOutputKeyEnum.answerText", - "label": "core.module.output.label.Ai response content", - "description": "core.module.output.description.Ai response content", - "valueType": "string", - "type": "FlowNodeOutputTypeEnum.static" - } - ] - }, - { - "nodeId": "GMELVPxHfpg5", - "name": "HTTP 请求", - "intro": "调用谷歌搜索,查询相关内容", - "avatar": "/imgs/workflow/http.png", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1005.4777753640342, - "y": 319.4905539380939 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "core.module.input.description.HTTP Dynamic Input" - }, - { - "valueType": "string", - "renderTypeList": ["reference"], - "key": "query", - "label": "query", - "toolDescription": "谷歌搜索检索词", - "required": true, - "canEdit": true, - "editField": { - "key": true, - "description": true - } - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "GET", - "required": true - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "https://www.googleapis.com/customsearch/v1" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "core.module.input.description.Http Request Header", - "placeholder": "core.module.input.description.Http Request Header", - "required": false - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [ - { - "key": "q", - "type": "string", - "value": "{{query}}" - }, - { - "key": "cx", - "type": "string", - "value": "谷歌搜索cxID" - }, - { - "key": "key", - "type": "string", - "value": "谷歌搜索key" - }, - { - "key": "c2coff", - "type": "string", - "value": "1" - }, - { - "key": "start", - "type": "string", - "value": "1" - }, - { - "key": "end", - "type": "string", - "value": "20" - }, - { - "key": "dateRestrict", - "type": "string", - "value": "m[1]" - } - ], - "label": "", - "required": false - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "", - "label": "", - "required": false - } - ], - "outputs": [ - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "editField": { - "key": true, - "valueType": true - } - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "label": "原始响应", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static", - "required": true - }, - { - "id": "M5YmxaYe8em1", - "type": "dynamic", - "key": "prompt", - "valueType": "string", - "label": "prompt" - } - ] - }, - { - "nodeId": "poIbrrA8aiR0", - "name": "代码运行", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "/imgs/workflow/code.svg", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 1711.805344753384, - "y": 650.1023414708576 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "这些变量会作为代码的运行的输入参数", - "editField": { - "key": true, - "valueType": true - } - }, - { - "key": "data", - "valueType": "object", - "label": "data", - "renderTypeList": ["reference"], - "description": "", - "canEdit": true, - "editField": { - "key": true, - "valueType": true - }, - "value": ["GMELVPxHfpg5", "httpRawResponse"] - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({data}){\n const result = data.items.map((item) => ({\n title: item.title,\n link: item.link,\n snippet: item.snippet\n }))\n return { prompt: JSON.stringify(result) }\n}" - } - ], - "outputs": [ - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "editField": { - "key": true, - "valueType": true - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点" - }, - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "完整响应数据", - "valueType": "object", - "type": "static" - }, - { - "id": "error", - "key": "error", - "label": "运行错误", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "prompt", - "valueType": "string", - "label": "prompt" - } - ] - } - ], - "edges": [ - { - "source": "448745", - "target": "NOgbnBzUwDgT", - "sourceHandle": "448745-source-right", - "targetHandle": "NOgbnBzUwDgT-target-left" - }, - { - "source": "NOgbnBzUwDgT", - "target": "GMELVPxHfpg5", - "sourceHandle": "selectedTools", - "targetHandle": "selectedTools" - }, - { - "source": "GMELVPxHfpg5", - "target": "poIbrrA8aiR0", - "sourceHandle": "GMELVPxHfpg5-source-right", - "targetHandle": "poIbrrA8aiR0-target-left" - } - ] - } -} diff --git a/packages/templates/src/longTranslate/template.json b/packages/templates/src/longTranslate/template.json deleted file mode 100644 index 11396b36c..000000000 --- a/packages/templates/src/longTranslate/template.json +++ /dev/null @@ -1,2161 +0,0 @@ -{ - "name": "长文翻译专家", - "intro": "使用专有名词知识库协助翻译,更适合长文本的翻译机器人", - "author": "", - "avatar": "core/app/templates/TranslateRobot", - "tags": ["office-services"], - "type": "advanced", - "userGuide": { - "type": "link", - "content": "https://mp.weixin.qq.com/s/2kXdaSLOImhH1DTaFU8qXA" - }, - "workflow": { - "nodes": [ - { - "nodeId": "userGuide", - "name": "系统配置", - "intro": "可以配置应用的系统参数", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "userGuide", - "position": { - "x": -3580.557768149762, - "y": -789.3781335716197 - }, - "version": "481", - "inputs": [ - { - "key": "welcomeText", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "core.app.Welcome Text", - "value": "" - }, - { - "key": "variables", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "core.app.Chat Variable", - "value": [] - }, - { - "key": "questionGuide", - "valueType": "any", - "renderTypeList": ["hidden"], - "label": "core.app.Question Guide", - "value": { - "open": false - } - }, - { - "key": "tts", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "type": "web" - } - }, - { - "key": "whisper", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - } - }, - { - "key": "scheduleTrigger", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": null - } - ], - "outputs": [] - }, - { - "nodeId": "448745", - "name": "流程开始", - "intro": "", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "workflowStart", - "position": { - "x": -4423.869761318094, - "y": 270.52507717746244 - }, - "version": "481", - "inputs": [ - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题", - "debugLabel": "" - } - ], - "outputs": [ - { - "id": "userChatInput", - "key": "userChatInput", - "label": "common:core.module.input.label.user question", - "type": "static", - "valueType": "string", - "description": "" - }, - { - "id": "userFiles", - "key": "userFiles", - "label": "app:workflow.user_file_input", - "description": "app:workflow.user_file_input_desc", - "type": "static", - "valueType": "arrayString" - } - ] - }, - { - "nodeId": "yjFO3YcM7KG2", - "name": "多文本块翻译", - "intro": "AI 大模型对话", - "avatar": "core/workflow/template/aiChat", - "flowNodeType": "chatNode", - "showStatus": true, - "position": { - "x": 889.049018199629, - "y": -146.47492282253756 - }, - "version": "481", - "inputs": [ - { - "key": "model", - "renderTypeList": ["settingLLMModel", "reference"], - "label": "core.module.input.label.aiModel", - "valueType": "string", - "selectedTypeIndex": 0, - "value": "claude-3-5-sonnet-20240620", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "temperature", - "renderTypeList": ["hidden"], - "label": "", - "value": 3, - "valueType": "number", - "min": 0, - "max": 10, - "step": 1, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "maxToken", - "renderTypeList": ["hidden"], - "label": "", - "value": 4000, - "valueType": "number", - "min": 100, - "max": 4000, - "step": 50, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "isResponseAnswerText", - "renderTypeList": ["hidden"], - "label": "", - "value": false, - "valueType": "boolean", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "aiChatQuoteRole", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "value": "system", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quoteTemplate", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "value": "{{q}}\n{{a}}", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quotePrompt", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "value": "使用 标记中的内容作为你的翻译词库:\n\n\n{{quote}}\n\n\n原文: \"\"\"{{question}}\"\"\"", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "aiChatVision", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "boolean", - "value": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "systemPrompt", - "renderTypeList": ["textarea", "reference"], - "max": 3000, - "valueType": "string", - "label": "core.ai.Prompt", - "description": "core.app.tip.systemPromptTip", - "placeholder": "core.app.tip.chatNodeSystemPromptTip", - "value": "# Role: 资深翻译专家\n\n## Background:\n你是一位经验丰富的翻译专家,精通{{source_lang}}和{{target_lang}}互译,尤其擅长将{{source_lang}}文章译成流畅易懂的{{target_lang}}。你曾多次带领团队完成大型翻译项目,译文广受好评。\n\n## Attention:\n- 翻译过程中要始终坚持\"信、达、雅\"的原则,但\"达\"尤为重要\n- 翻译的译文要符合{{target_lang}}的表达习惯,通俗易懂,连贯流畅\n- 避免使用过于文绉绉的表达和晦涩难懂的典故引用 \n- 诗词歌词等内容需按原文换行和节奏分行,不破坏原排列格式 \n- 对于专有的名词或术语,按照给出的术语表进行合理替换 \n- 在翻译过程中,注意保留文档原有的列表项和格式标识\n- 不要翻译代码块中的内容,保持原样输出\n\n## Constraints:\n- 必须严格遵循四轮翻译流程:直译、意译、反思、提升\n- 译文要忠实原文,准确无误,不能遗漏或曲解原意\n- 注意判断上下文,避免重复翻译\n- 最终译文使用Markdown的代码块呈现,但是不用输出markdown这个单词\n\n## Goals:\n- 通过四轮翻译流程,将{{source_lang}}原文译成高质量的{{target_lang}}译文 \n- 译文要准确传达原文意思,语言表达力求浅显易懂,朗朗上口\n- 适度使用一些熟语俗语、流行网络用语等,增强译文的亲和力\n\n## Skills:\n- 精通{{source_lang}} {{target_lang}}两种语言,具有扎实的语言功底和丰富的翻译经验\n- 擅长将{{source_lang}}表达习惯转换为地道自然的{{target_lang}}\n- 对当代{{target_lang}}语言的发展变化有敏锐洞察,善于把握语言流行趋势\n\n## Workflow:\n1. 第一轮直译:逐字逐句忠实原文,不遗漏任何信息(代码块内容除外)\n2. 第二轮意译:在直译的基础上用通俗流畅的{{target_lang}}意译原文(代码块内容除外)\n3. 第三轮反思:仔细审视译文,分点列出一份建设性的批评和有用的建议清单以改进翻译,逐句提出建议,从以下6个角度展开\n (i) 准确性(纠正冗余、误译、遗漏或未翻译的文本错误),\n (ii) 流畅性(应用{{target_lang}}的语法、拼写和标点规则,并确保没有不必要的重复),\n (iii) 风格(确保翻译反映源文本的风格并考虑其文化背景),\n (iv) 术语(严格参考给出的术语表,确保术语使用一致)\n (v) 语序(合理调整语序,不要生搬{{source_lang}}中的语序,注意调整为{{target_lang}}中的合理语序)\n (vi) 代码保护(确保所有代码块内容保持原样,不被翻译)\n4. 第四轮提升:严格遵循第三轮提出的建议对翻译修改,定稿出一个简洁畅达、符合大众阅读习惯的译文\n\n## OutputFormat:\n- 每一轮前用【思考】说明该轮要点\n- 第一轮和第二轮翻译后用【翻译】呈现译文\n- 第三轮用【建议】输出建议清单,分点列出,在每一点前用*xxx*标识这条建议对应的要点,如*风格*;建议前用【思考】说明该轮要点,建议后用【建议】呈现建议\n- 第四轮在\\`\\`\\`代码块中展示最终译文内容,如\\`\\`\\`xxx\\`\\`\\`,不用输出markdown这个单词\n\n## Suggestions:\n- 直译时力求忠实原文,但不要过于拘泥逐字逐句\n- 意译时在准确表达原意的基础上,用最朴实无华的{{target_lang}}来表达\n- 反思环节重点关注译文是否符合{{target_lang}}表达习惯,是否通俗易懂,是否准确流畅,是否术语一致\n- 提升环节采用反思环节的建议对意译环节的翻译进行修改,适度采用一些口语化的表达、网络流行语等,增强译文的亲和力\n- 所有包含在代码块(\\`\\`\\`)中的内容都应保持原样,不进行翻译", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "history", - "renderTypeList": ["numberInput", "reference"], - "valueType": "chatHistory", - "label": "core.module.input.label.chat history", - "description": "workflow:max_dialog_rounds", - "required": true, - "min": 0, - "max": 50, - "value": 6, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quoteQA", - "renderTypeList": ["settingDatasetQuotePrompt"], - "label": "", - "debugLabel": "知识库引用", - "description": "", - "valueType": "datasetQuote", - "value": ["nLBlOh6lWxkY", "quoteQA"], - "toolDescription": "" - }, - { - "key": "stringQuoteText", - "renderTypeList": ["reference", "textarea"], - "label": "app:document_quote", - "debugLabel": "文档引用", - "description": "app:document_quote_tip", - "valueType": "string", - "toolDescription": "" - }, - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题", - "selectedTypeIndex": 1, - "value": "Your task is provide a professional translation from {{$VARIABLE_NODE_ID.source_lang$}} to {{$VARIABLE_NODE_ID.target_lang$}} of PART of a text.\n\nThe source text is below, delimited by XML tags and . Translate only the part within the source text\ndelimited by and . You can use the rest of the source text as context, but do not translate any\nof the other text. Do not output anything other than the translation of the indicated part of the text.\n\n\n{{$quYZgsW32ApA.xhXu6sdEWBnF$}}\n\n\nTo reiterate, you should translate only this part of the text, shown here again between and :\n\n{{$quYZgsW32ApA.eCp73lztAEGK$}}\n\n\nOutput only the translation of the portion you are asked to translate, and nothing else", - "debugLabel": "" - } - ], - "outputs": [ - { - "id": "history", - "key": "history", - "required": true, - "label": "common:core.module.output.label.New context", - "description": "将本次回复内容拼接上历史记录,作为新的上下文返回", - "valueType": "chatHistory", - "valueDesc": "{\n obj: System | Human | AI;\n value: string;\n}[]", - "type": "static" - }, - { - "id": "answerText", - "key": "answerText", - "required": true, - "label": "common:core.module.output.label.Ai response content", - "description": "将在 stream 回复完毕后触发", - "valueType": "string", - "type": "static" - } - ] - }, - { - "nodeId": "w4heEpNflz59", - "name": "判断是否执行结束", - "intro": "根据一定的条件,执行不同的分支。", - "avatar": "core/workflow/template/ifelse", - "flowNodeType": "ifElseNode", - "showStatus": true, - "position": { - "x": 4127.598997947211, - "y": 266.8413637678663 - }, - "version": "481", - "inputs": [ - { - "key": "ifElseList", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": [ - { - "condition": "AND", - "list": [ - { - "variable": ["a2lqxASWi1vb", "nmBmGaARbKkl"], - "condition": "equalTo", - "value": "true" - } - ] - } - ], - "debugLabel": "", - "toolDescription": "" - } - ], - "outputs": [ - { - "id": "ifElseResult", - "key": "ifElseResult", - "label": "workflow:judgment_result", - "valueType": "string", - "type": "static", - "description": "" - } - ] - }, - { - "nodeId": "a2lqxASWi1vb", - "name": "判断是否执行结束", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 3477.215830836187, - "y": 191.17869154122482 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({chunks, doc_chunks, currentChunk}){\n let new_chunks = doc_chunks || chunks\n const findIndex = new_chunks.findIndex((item) => item ===currentChunk)\n \n return {\n isEnd: new_chunks.length-1 === findIndex,\n i: findIndex + 1,\n }\n}", - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "arrayString", - "canEdit": true, - "key": "chunks", - "label": "chunks", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["rDzA1VxdpPIz", "qLUQfhG0ILRX"] - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "currentChunk", - "label": "currentChunk", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["quYZgsW32ApA", "eCp73lztAEGK"] - }, - { - "renderTypeList": ["reference"], - "valueType": "arrayString", - "canEdit": true, - "key": "doc_chunks", - "label": "doc_chunks", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["rhyUytTUBm19", "qLUQfhG0ILRX"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key" - }, - { - "id": "nmBmGaARbKkl", - "valueType": "boolean", - "type": "dynamic", - "key": "isEnd", - "label": "isEnd" - }, - { - "id": "nqB98uKpq6Ig", - "valueType": "number", - "type": "dynamic", - "key": "i", - "label": "i" - } - ] - }, - { - "nodeId": "quYZgsW32ApA", - "name": "格式化源文本块", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": -453.20482176291137, - "y": 277.1422839492036 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({source_text_chunks, source_doc_text_chunks, i=0}){\n let chunks = source_doc_text_chunks || source_text_chunks;\n let before = chunks.slice(0, i).join(\"\");\n let current = \" \" + chunks[i] + \"\";\n let after = chunks.slice(i + 1).join(\"\");\n let tagged_text = before + current + after;\n\n return {\n tagged_text,\n chunk_to_translate: chunks[i],\n }\n}", - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "number", - "canEdit": true, - "key": "i", - "label": "i", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["a2lqxASWi1vb", "nqB98uKpq6Ig"] - }, - { - "renderTypeList": ["reference"], - "valueType": "arrayString", - "canEdit": true, - "key": "source_text_chunks", - "label": "source_text_chunks", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["rDzA1VxdpPIz", "qLUQfhG0ILRX"] - }, - { - "renderTypeList": ["reference"], - "valueType": "arrayString", - "canEdit": true, - "key": "source_doc_text_chunks", - "label": "source_doc_text_chunks", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["rhyUytTUBm19", "qLUQfhG0ILRX"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key" - }, - { - "id": "xhXu6sdEWBnF", - "valueType": "string", - "type": "dynamic", - "key": "tagged_text", - "label": "tagged_text" - }, - { - "id": "eCp73lztAEGK", - "valueType": "string", - "type": "dynamic", - "key": "chunk_to_translate", - "label": "chunk_to_translate" - } - ] - }, - { - "nodeId": "vlNHndpNuFXB", - "name": "取出翻译文本", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 1614.87521037251, - "y": 105.52507717746244 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "editField": { - "key": true, - "valueType": true - }, - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({data1}){\n const result = data1.split(\"```\").filter(item => !!item.trim())\n\n if(result[result.length-1]) {\n return {\n result: result[result.length-1]\n }\n }\n\n return {\n result: '未截取到翻译内容'\n }\n}", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "data1", - "valueType": "string", - "label": "data1", - "renderTypeList": ["reference"], - "description": "", - "canEdit": true, - "editField": { - "key": true, - "valueType": true - }, - "value": ["yjFO3YcM7KG2", "answerText"], - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "result", - "valueType": "string", - "label": "result" - } - ] - }, - { - "nodeId": "qlt9KJbbS9yJ", - "name": "判断源语言和目标语言是否相同", - "intro": "根据一定的条件,执行不同的分支。", - "avatar": "core/workflow/template/ifelse", - "flowNodeType": "ifElseNode", - "showStatus": true, - "position": { - "x": -3489.136669871181, - "y": 500.7167825391806 - }, - "version": "481", - "inputs": [ - { - "key": "ifElseList", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": [ - { - "condition": "AND", - "list": [ - { - "variable": ["frjbsrlnJJsR", "qLUQfhG0ILRX"], - "condition": "equalTo", - "value": "false" - } - ] - } - ], - "debugLabel": "", - "toolDescription": "" - } - ], - "outputs": [ - { - "id": "ifElseResult", - "key": "ifElseResult", - "label": "workflow:judgment_result", - "valueType": "string", - "type": "static", - "description": "" - } - ] - }, - { - "nodeId": "frjbsrlnJJsR", - "name": "判断源语言和目标语言是否相同", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": -4015.234465113403, - "y": 286.93335454913375 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({source_lang, target_lang}){\n \n return {\n result: source_lang === target_lang\n }\n}", - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "source_lang", - "label": "source_lang", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["VARIABLE_NODE_ID", "source_lang"] - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "target_lang", - "label": "target_lang", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["VARIABLE_NODE_ID", "target_lang"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "result", - "valueType": "string", - "label": "result" - } - ], - "isFolded": false - }, - { - "nodeId": "dFxrGZS3Wmnz", - "name": "提示源语言与目标语言相同", - "intro": "该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。", - "avatar": "core/workflow/template/reply", - "flowNodeType": "answerNode", - "position": { - "x": -2965.234667648691, - "y": 976.026813286592 - }, - "version": "481", - "inputs": [ - { - "key": "text", - "renderTypeList": ["textarea", "reference"], - "valueType": "any", - "required": true, - "label": "core.module.input.label.Response content", - "description": "common:core.module.input.description.Response content", - "placeholder": "common:core.module.input.description.Response content", - "selectedTypeIndex": 0, - "value": "{{source_lang}} 无需再次翻译为 {{target_lang}} ~", - "debugLabel": "", - "toolDescription": "" - } - ], - "outputs": [] - }, - { - "nodeId": "rDzA1VxdpPIz", - "name": "切分文本", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": -1023.4352731829587, - "y": 122.9539005059388 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "const MAX_HEADING_LENGTH = 7; // 最大标题长度\nconst MAX_HEADING_CONTENT_LENGTH = 200; // 最大标题内容长度\nconst MAX_HEADING_UNDERLINE_LENGTH = 200; // 最大标题下划线长度\nconst MAX_HTML_HEADING_ATTRIBUTES_LENGTH = 100; // 最大HTML标题属性长度\nconst MAX_LIST_ITEM_LENGTH = 200; // 最大列表项长度\nconst MAX_NESTED_LIST_ITEMS = 6; // 最大嵌套列表项数\nconst MAX_LIST_INDENT_SPACES = 7; // 最大列表缩进空格数\nconst MAX_BLOCKQUOTE_LINE_LENGTH = 200; // 最大块引用行长度\nconst MAX_BLOCKQUOTE_LINES = 15; // 最大块引用行数\nconst MAX_CODE_BLOCK_LENGTH = 1500; // 最大代码块长度\nconst MAX_CODE_LANGUAGE_LENGTH = 20; // 最大代码语言长度\nconst MAX_INDENTED_CODE_LINES = 20; // 最大缩进代码行数\nconst MAX_TABLE_CELL_LENGTH = 200; // 最大表格单元格长度\nconst MAX_TABLE_ROWS = 20; // 最大表格行数\nconst MAX_HTML_TABLE_LENGTH = 2000; // 最大HTML表格长度\nconst MIN_HORIZONTAL_RULE_LENGTH = 3; // 最小水平分隔线长度\nconst MAX_SENTENCE_LENGTH = 400; // 最大句子长度\nconst MAX_QUOTED_TEXT_LENGTH = 300; // 最大引用文本长度\nconst MAX_PARENTHETICAL_CONTENT_LENGTH = 200; // 最大括号内容长度\nconst MAX_NESTED_PARENTHESES = 5; // 最大嵌套括号数\nconst MAX_MATH_INLINE_LENGTH = 100; // 最大行内数学公式长度\nconst MAX_MATH_BLOCK_LENGTH = 500; // 最大数学公式块长度\nconst MAX_PARAGRAPH_LENGTH = 1000; // 最大段落长度\nconst MAX_STANDALONE_LINE_LENGTH = 800; // 最大独立行长度\nconst MAX_HTML_TAG_ATTRIBUTES_LENGTH = 100; // 最大HTML标签属性长度\nconst MAX_HTML_TAG_CONTENT_LENGTH = 1000; // 最大HTML标签内容长度\nconst LOOKAHEAD_RANGE = 100; // 向前查找句子边界的字符数\n\nconst AVOID_AT_START = `[\\\\s\\\\]})>,']`; // 避免在开头匹配的字符\nconst PUNCTUATION = `[.!?…]|\\\\.{3}|[\\\\u2026\\\\u2047-\\\\u2049]|[\\\\p{Emoji_Presentation}\\\\p{Extended_Pictographic}]`; // 标点符号\nconst QUOTE_END = `(?:'(?=\\`)|''(?=\\`\\`))`; // 引号结束\nconst SENTENCE_END = `(?:${PUNCTUATION}(?]{0,${MAX_HTML_HEADING_ATTRIBUTES_LENGTH}}>)[^\\\\r\\\\n]{1,${MAX_HEADING_CONTENT_LENGTH}}(?:)?(?:\\\\r?\\\\n|$))` +\n \"|\" +\n // New pattern for citations\n `(?:\\\\[[0-9]+\\\\][^\\\\r\\\\n]{1,${MAX_STANDALONE_LINE_LENGTH}})` +\n \"|\" +\n // 2. List items (bulleted, numbered, lettered, or task lists, including nested, up to three levels, with length constraints)\n `(?:(?:^|\\\\r?\\\\n)[ \\\\t]{0,3}(?:[-*+•]|\\\\d{1,3}\\\\.\\\\w\\\\.|\\\\[[ xX]\\\\])[ \\\\t]+${SENTENCE_PATTERN.replace(/{MAX_LENGTH}/g, String(MAX_LIST_ITEM_LENGTH))}` +\n `(?:(?:\\\\r?\\\\n[ \\\\t]{2,5}(?:[-*+•]|\\\\d{1,3}\\\\.\\\\w\\\\.|\\\\[[ xX]\\\\])[ \\\\t]+${SENTENCE_PATTERN.replace(/{MAX_LENGTH}/g, String(MAX_LIST_ITEM_LENGTH))}){0,${MAX_NESTED_LIST_ITEMS}}` +\n `(?:\\\\r?\\\\n[ \\\\t]{4,${MAX_LIST_INDENT_SPACES}}(?:[-*+•]|\\\\d{1,3}\\\\.\\\\w\\\\.|\\\\[[ xX]\\\\])[ \\\\t]+${SENTENCE_PATTERN.replace(/{MAX_LENGTH}/g, String(MAX_LIST_ITEM_LENGTH))}){0,${MAX_NESTED_LIST_ITEMS}})?)` +\n \"|\" +\n // 3. Block quotes (including nested quotes and citations, up to three levels, with length constraints)\n `(?:(?:^>(?:>|\\\\s{2,}){0,2}${SENTENCE_PATTERN.replace(/{MAX_LENGTH}/g, String(MAX_BLOCKQUOTE_LINE_LENGTH))}\\\\r?\\\\n?){1,${MAX_BLOCKQUOTE_LINES}})` +\n \"|\" +\n // 4. Code blocks (fenced, indented, or HTML pre/code tags, with length constraints)\n `(?:(?:^|\\\\r?\\\\n)(?:\\`\\`\\`|~~~)(?:\\\\w{0,${MAX_CODE_LANGUAGE_LENGTH}})?\\\\r?\\\\n[\\\\s\\\\S]{0,${MAX_CODE_BLOCK_LENGTH}}?(?:\\`\\`\\`|~~~)\\\\r?\\\\n?` +\n `|(?:(?:^|\\\\r?\\\\n)(?: {4}|\\\\t)[^\\\\r\\\\n]{0,${MAX_LIST_ITEM_LENGTH}}(?:\\\\r?\\\\n(?: {4}|\\\\t)[^\\\\r\\\\n]{0,${MAX_LIST_ITEM_LENGTH}}){0,${MAX_INDENTED_CODE_LINES}}\\\\r?\\\\n?)` +\n `|(?:
(?:)?[\\\\s\\\\S]{0,${MAX_CODE_BLOCK_LENGTH}}?(?:)?
))` +\n \"|\" +\n // 5. Tables (Markdown, grid tables, and HTML tables, with length constraints)\n `(?:(?:^|\\\\r?\\\\n)(?:\\\\|[^\\\\r\\\\n]{0,${MAX_TABLE_CELL_LENGTH}}\\\\|(?:\\\\r?\\\\n\\\\|[-:]{1,${MAX_TABLE_CELL_LENGTH}}\\\\|){0,1}(?:\\\\r?\\\\n\\\\|[^\\\\r\\\\n]{0,${MAX_TABLE_CELL_LENGTH}}\\\\|){0,${MAX_TABLE_ROWS}}` +\n `|[\\\\s\\\\S]{0,${MAX_HTML_TABLE_LENGTH}}?
))` +\n \"|\" +\n // 6. Horizontal rules (Markdown and HTML hr tag)\n `(?:^(?:[-*_]){${MIN_HORIZONTAL_RULE_LENGTH},}\\\\s*$|)` +\n \"|\" +\n // 10. Standalone lines or phrases (including single-line blocks and HTML elements, with length constraints)\n `(?!${AVOID_AT_START})(?:^(?:<[a-zA-Z][^>]{0,${MAX_HTML_TAG_ATTRIBUTES_LENGTH}}>)?${SENTENCE_PATTERN.replace(/{MAX_LENGTH}/g, String(MAX_STANDALONE_LINE_LENGTH))}(?:)?(?:\\\\r?\\\\n|$))` +\n \"|\" +\n // 7. Sentences or phrases ending with punctuation (including ellipsis and Unicode punctuation)\n `(?!${AVOID_AT_START})${SENTENCE_PATTERN.replace(/{MAX_LENGTH}/g, String(MAX_SENTENCE_LENGTH))}` +\n \"|\" +\n // 8. Quoted text, parenthetical phrases, or bracketed content (with length constraints)\n \"(?:\" +\n `(?)?${SENTENCE_PATTERN.replace(/{MAX_LENGTH}/g, String(MAX_PARAGRAPH_LENGTH))}(?:

)?(?=\\\\r?\\\\n\\\\r?\\\\n|$))` +\n \"|\" +\n // 11. HTML-like tags and their content (including self-closing tags and attributes, with length constraints)\n `(?:<[a-zA-Z][^>]{0,${MAX_HTML_TAG_ATTRIBUTES_LENGTH}}(?:>[\\\\s\\\\S]{0,${MAX_HTML_TAG_CONTENT_LENGTH}}?|\\\\s*/>))` +\n \"|\" +\n // 12. LaTeX-style math expressions (inline and block, with length constraints)\n `(?:(?:\\\\$\\\\$[\\\\s\\\\S]{0,${MAX_MATH_BLOCK_LENGTH}}?\\\\$\\\\$)|(?:\\\\$[^\\\\$\\\\r\\\\n]{0,${MAX_MATH_INLINE_LENGTH}}\\\\$))` +\n \"|\" +\n // 14. Fallback for any remaining content (with length constraints)\n `(?!${AVOID_AT_START})${SENTENCE_PATTERN.replace(/{MAX_LENGTH}/g, String(MAX_STANDALONE_LINE_LENGTH))}` +\n \")\",\n \"gmu\"\n);\n\nfunction main({text}){\n const chunks = [];\n let currentChunk = '';\n const tokens = countToken(text)\n\n const matches = text.match(regex);\n if (matches) {\n matches.forEach((match) => {\n if (currentChunk.length + match.length <= 1000) {\n currentChunk += match;\n } else {\n if (currentChunk) {\n chunks.push(currentChunk);\n }\n currentChunk = match;\n }\n });\n if (currentChunk) {\n chunks.push(currentChunk);\n }\n }\n\n return {chunks, tokens};\n}\n\n", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "text", - "label": "text", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["448745", "userChatInput"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key", - "valueDesc": "" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "chunks", - "valueType": "arrayString", - "label": "chunks", - "valueDesc": "", - "description": "" - } - ] - }, - { - "nodeId": "qwKPaLWbYTLa", - "name": "输出翻译结果", - "intro": "该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。", - "avatar": "core/workflow/template/reply", - "flowNodeType": "answerNode", - "position": { - "x": 2771.2891802720287, - "y": 320.5042731766072 - }, - "version": "481", - "inputs": [ - { - "key": "text", - "renderTypeList": ["textarea", "reference"], - "valueType": "any", - "required": true, - "label": "回复的内容", - "description": "common:core.module.input.description.Response content", - "placeholder": "common:core.module.input.description.Response content", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "", - "value": "{{$uow83rLCI2pI.qLUQfhG0ILRX$}}" - } - ], - "outputs": [] - }, - { - "nodeId": "nLBlOh6lWxkY", - "name": "搜索词库", - "intro": "调用“语义检索”和“全文检索”能力,从“知识库”中查找可能与问题相关的参考内容", - "avatar": "core/workflow/template/datasetSearch", - "flowNodeType": "datasetSearchNode", - "showStatus": true, - "position": { - "x": 164.44155974241983, - "y": 187.52507717746244 - }, - "version": "481", - "inputs": [ - { - "key": "datasets", - "renderTypeList": ["selectDataset", "reference"], - "label": "选择知识库", - "value": [], - "valueType": "selectDataset", - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "similarity", - "renderTypeList": ["selectDatasetParamsModal"], - "label": "", - "value": 0.2, - "valueType": "number", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "limit", - "renderTypeList": ["hidden"], - "label": "", - "value": 11000, - "valueType": "number", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "searchMode", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "value": "embedding", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "usingReRank", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "boolean", - "value": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "datasetSearchUsingExtensionQuery", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "boolean", - "value": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "datasetSearchExtensionModel", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "", - "value": "gpt-5" - }, - { - "key": "datasetSearchExtensionBg", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "value": "需要翻译一段特定的文本,其中会使用到大量专有词汇,需要从词库中进行查询", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "需要检索的内容", - "valueDesc": "", - "description": "", - "debugLabel": "", - "selectedTypeIndex": 1, - "value": "中是你要翻译的原文,其中包含特定术语,请查找词库中术语对应的翻译\n\n\n\n{{$quYZgsW32ApA.eCp73lztAEGK$}}\n\n" - }, - { - "key": "collectionFilterMatch", - "renderTypeList": ["JSONEditor", "reference"], - "label": "集合元数据过滤", - "valueType": "object", - "isPro": true, - "description": "workflow:filter_description", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - } - ], - "outputs": [ - { - "id": "quoteQA", - "key": "quoteQA", - "label": "common:core.module.Dataset quote.label", - "description": "特殊数组格式,搜索结果为空时,返回空数组。", - "type": "static", - "valueType": "datasetQuote", - "valueDesc": "{\n id: string;\n datasetId: string;\n collectionId: string;\n sourceName: string;\n sourceId?: string;\n q: string;\n a: string\n}[]" - } - ] - }, - { - "nodeId": "bdjAb5B2U1DQ", - "name": "指定回复#3", - "intro": "该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。", - "avatar": "core/workflow/template/reply", - "flowNodeType": "answerNode", - "position": { - "x": 5144.978517483216, - "y": 401.52507717746244 - }, - "version": "481", - "inputs": [ - { - "key": "text", - "renderTypeList": ["textarea", "reference"], - "valueType": "any", - "required": true, - "label": "回复的内容", - "description": "common:core.module.input.description.Response content", - "placeholder": "common:core.module.input.description.Response content", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "", - "value": "*** 文档翻译完成!***" - } - ], - "outputs": [] - }, - { - "nodeId": "mt7GlCIwbO9I", - "name": "判断是否上传了文件", - "intro": "根据一定的条件,执行不同的分支。", - "avatar": "core/workflow/template/ifelse", - "flowNodeType": "ifElseNode", - "showStatus": true, - "position": { - "x": -2277.8211533688936, - "y": 608.6422839492036 - }, - "version": "481", - "inputs": [ - { - "key": "ifElseList", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": [ - { - "condition": "AND", - "list": [ - { - "variable": ["448745", "userFiles"], - "condition": "isEmpty" - } - ] - } - ], - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - } - ], - "outputs": [ - { - "id": "ifElseResult", - "key": "ifElseResult", - "label": "workflow:judgment_result", - "valueType": "string", - "type": "static", - "description": "" - } - ] - }, - { - "nodeId": "rhyUytTUBm19", - "name": "切分文档文本", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": -1023.4352731829587, - "y": 959.6422839492036 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "const MAX_HEADING_LENGTH = 7; // 最大标题长度\nconst MAX_HEADING_CONTENT_LENGTH = 200; // 最大标题内容长度\nconst MAX_HEADING_UNDERLINE_LENGTH = 200; // 最大标题下划线长度\nconst MAX_HTML_HEADING_ATTRIBUTES_LENGTH = 100; // 最大HTML标题属性长度\nconst MAX_LIST_ITEM_LENGTH = 200; // 最大列表项长度\nconst MAX_NESTED_LIST_ITEMS = 6; // 最大嵌套列表项数\nconst MAX_LIST_INDENT_SPACES = 7; // 最大列表缩进空格数\nconst MAX_BLOCKQUOTE_LINE_LENGTH = 200; // 最大块引用行长度\nconst MAX_BLOCKQUOTE_LINES = 15; // 最大块引用行数\nconst MAX_CODE_BLOCK_LENGTH = 1500; // 最大代码块长度\nconst MAX_CODE_LANGUAGE_LENGTH = 20; // 最大代码语言长度\nconst MAX_INDENTED_CODE_LINES = 20; // 最大缩进代码行数\nconst MAX_TABLE_CELL_LENGTH = 200; // 最大表格单元格长度\nconst MAX_TABLE_ROWS = 20; // 最大表格行数\nconst MAX_HTML_TABLE_LENGTH = 2000; // 最大HTML表格长度\nconst MIN_HORIZONTAL_RULE_LENGTH = 3; // 最小水平分隔线长度\nconst MAX_SENTENCE_LENGTH = 400; // 最大句子长度\nconst MAX_QUOTED_TEXT_LENGTH = 300; // 最大引用文本长度\nconst MAX_PARENTHETICAL_CONTENT_LENGTH = 200; // 最大括号内容长度\nconst MAX_NESTED_PARENTHESES = 5; // 最大嵌套括号数\nconst MAX_MATH_INLINE_LENGTH = 100; // 最大行内数学公式长度\nconst MAX_MATH_BLOCK_LENGTH = 500; // 最大数学公式块长度\nconst MAX_PARAGRAPH_LENGTH = 1000; // 最大段落长度\nconst MAX_STANDALONE_LINE_LENGTH = 800; // 最大独立行长度\nconst MAX_HTML_TAG_ATTRIBUTES_LENGTH = 100; // 最大HTML标签属性长度\nconst MAX_HTML_TAG_CONTENT_LENGTH = 1000; // 最大HTML标签内容长度\nconst LOOKAHEAD_RANGE = 100; // 向前查找句子边界的字符数\n\nconst AVOID_AT_START = `[\\\\s\\\\]})>,']`; // 避免在开头匹配的字符\nconst PUNCTUATION = `[.!?…]|\\\\.{3}|[\\\\u2026\\\\u2047-\\\\u2049]|[\\\\p{Emoji_Presentation}\\\\p{Extended_Pictographic}]`; // 标点符号\nconst QUOTE_END = `(?:'(?=\\`)|''(?=\\`\\`))`; // 引号结束\nconst SENTENCE_END = `(?:${PUNCTUATION}(?]{0,${MAX_HTML_HEADING_ATTRIBUTES_LENGTH}}>)[^\\\\r\\\\n]{1,${MAX_HEADING_CONTENT_LENGTH}}(?:)?(?:\\\\r?\\\\n|$))` +\n \"|\" +\n // New pattern for citations\n `(?:\\\\[[0-9]+\\\\][^\\\\r\\\\n]{1,${MAX_STANDALONE_LINE_LENGTH}})` +\n \"|\" +\n // 2. List items (bulleted, numbered, lettered, or task lists, including nested, up to three levels, with length constraints)\n `(?:(?:^|\\\\r?\\\\n)[ \\\\t]{0,3}(?:[-*+•]|\\\\d{1,3}\\\\.\\\\w\\\\.|\\\\[[ xX]\\\\])[ \\\\t]+${SENTENCE_PATTERN.replace(/{MAX_LENGTH}/g, String(MAX_LIST_ITEM_LENGTH))}` +\n `(?:(?:\\\\r?\\\\n[ \\\\t]{2,5}(?:[-*+•]|\\\\d{1,3}\\\\.\\\\w\\\\.|\\\\[[ xX]\\\\])[ \\\\t]+${SENTENCE_PATTERN.replace(/{MAX_LENGTH}/g, String(MAX_LIST_ITEM_LENGTH))}){0,${MAX_NESTED_LIST_ITEMS}}` +\n `(?:\\\\r?\\\\n[ \\\\t]{4,${MAX_LIST_INDENT_SPACES}}(?:[-*+•]|\\\\d{1,3}\\\\.\\\\w\\\\.|\\\\[[ xX]\\\\])[ \\\\t]+${SENTENCE_PATTERN.replace(/{MAX_LENGTH}/g, String(MAX_LIST_ITEM_LENGTH))}){0,${MAX_NESTED_LIST_ITEMS}})?)` +\n \"|\" +\n // 3. Block quotes (including nested quotes and citations, up to three levels, with length constraints)\n `(?:(?:^>(?:>|\\\\s{2,}){0,2}${SENTENCE_PATTERN.replace(/{MAX_LENGTH}/g, String(MAX_BLOCKQUOTE_LINE_LENGTH))}\\\\r?\\\\n?){1,${MAX_BLOCKQUOTE_LINES}})` +\n \"|\" +\n // 4. Code blocks (fenced, indented, or HTML pre/code tags, with length constraints)\n `(?:(?:^|\\\\r?\\\\n)(?:\\`\\`\\`|~~~)(?:\\\\w{0,${MAX_CODE_LANGUAGE_LENGTH}})?\\\\r?\\\\n[\\\\s\\\\S]{0,${MAX_CODE_BLOCK_LENGTH}}?(?:\\`\\`\\`|~~~)\\\\r?\\\\n?` +\n `|(?:(?:^|\\\\r?\\\\n)(?: {4}|\\\\t)[^\\\\r\\\\n]{0,${MAX_LIST_ITEM_LENGTH}}(?:\\\\r?\\\\n(?: {4}|\\\\t)[^\\\\r\\\\n]{0,${MAX_LIST_ITEM_LENGTH}}){0,${MAX_INDENTED_CODE_LINES}}\\\\r?\\\\n?)` +\n `|(?:
(?:)?[\\\\s\\\\S]{0,${MAX_CODE_BLOCK_LENGTH}}?(?:)?
))` +\n \"|\" +\n // 5. Tables (Markdown, grid tables, and HTML tables, with length constraints)\n `(?:(?:^|\\\\r?\\\\n)(?:\\\\|[^\\\\r\\\\n]{0,${MAX_TABLE_CELL_LENGTH}}\\\\|(?:\\\\r?\\\\n\\\\|[-:]{1,${MAX_TABLE_CELL_LENGTH}}\\\\|){0,1}(?:\\\\r?\\\\n\\\\|[^\\\\r\\\\n]{0,${MAX_TABLE_CELL_LENGTH}}\\\\|){0,${MAX_TABLE_ROWS}}` +\n `|[\\\\s\\\\S]{0,${MAX_HTML_TABLE_LENGTH}}?
))` +\n \"|\" +\n // 6. Horizontal rules (Markdown and HTML hr tag)\n `(?:^(?:[-*_]){${MIN_HORIZONTAL_RULE_LENGTH},}\\\\s*$|)` +\n \"|\" +\n // 10. Standalone lines or phrases (including single-line blocks and HTML elements, with length constraints)\n `(?!${AVOID_AT_START})(?:^(?:<[a-zA-Z][^>]{0,${MAX_HTML_TAG_ATTRIBUTES_LENGTH}}>)?${SENTENCE_PATTERN.replace(/{MAX_LENGTH}/g, String(MAX_STANDALONE_LINE_LENGTH))}(?:)?(?:\\\\r?\\\\n|$))` +\n \"|\" +\n // 7. Sentences or phrases ending with punctuation (including ellipsis and Unicode punctuation)\n `(?!${AVOID_AT_START})${SENTENCE_PATTERN.replace(/{MAX_LENGTH}/g, String(MAX_SENTENCE_LENGTH))}` +\n \"|\" +\n // 8. Quoted text, parenthetical phrases, or bracketed content (with length constraints)\n \"(?:\" +\n `(?)?${SENTENCE_PATTERN.replace(/{MAX_LENGTH}/g, String(MAX_PARAGRAPH_LENGTH))}(?:

)?(?=\\\\r?\\\\n\\\\r?\\\\n|$))` +\n \"|\" +\n // 11. HTML-like tags and their content (including self-closing tags and attributes, with length constraints)\n `(?:<[a-zA-Z][^>]{0,${MAX_HTML_TAG_ATTRIBUTES_LENGTH}}(?:>[\\\\s\\\\S]{0,${MAX_HTML_TAG_CONTENT_LENGTH}}?|\\\\s*/>))` +\n \"|\" +\n // 12. LaTeX-style math expressions (inline and block, with length constraints)\n `(?:(?:\\\\$\\\\$[\\\\s\\\\S]{0,${MAX_MATH_BLOCK_LENGTH}}?\\\\$\\\\$)|(?:\\\\$[^\\\\$\\\\r\\\\n]{0,${MAX_MATH_INLINE_LENGTH}}\\\\$))` +\n \"|\" +\n // 14. Fallback for any remaining content (with length constraints)\n `(?!${AVOID_AT_START})${SENTENCE_PATTERN.replace(/{MAX_LENGTH}/g, String(MAX_STANDALONE_LINE_LENGTH))}` +\n \")\",\n \"gmu\"\n);\n\nfunction main({text}){\n const chunks = [];\n let currentChunk = '';\n const tokens = countToken(text)\n\n const matches = text.match(regex);\n if (matches) {\n matches.forEach((match) => {\n if (currentChunk.length + match.length <= 1000) {\n currentChunk += match;\n } else {\n if (currentChunk) {\n chunks.push(currentChunk);\n }\n currentChunk = match;\n }\n });\n if (currentChunk) {\n chunks.push(currentChunk);\n }\n }\n\n return {chunks, tokens};\n}\n\n", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "text", - "label": "text", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["dtUmoUtTKfpM", "system_text"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key", - "valueDesc": "" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "chunks", - "valueType": "arrayString", - "label": "chunks", - "valueDesc": "", - "description": "" - } - ] - }, - { - "nodeId": "dtUmoUtTKfpM", - "name": "文档解析", - "intro": "解析对话中所有上传的文档,并返回对应文档内容", - "avatar": "core/workflow/template/readFiles", - "flowNodeType": "readFiles", - "showStatus": true, - "position": { - "x": -1503.9824853456694, - "y": 1031.2341899921714 - }, - "version": "489", - "inputs": [ - { - "key": "fileUrlList", - "renderTypeList": ["reference"], - "valueType": "arrayString", - "label": "文档链接", - "required": true, - "value": ["448745", "userFiles"], - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - } - ], - "outputs": [ - { - "id": "system_text", - "key": "system_text", - "label": "app:workflow.read_files_result", - "description": "文档原文,由文件名和文档内容组成,多个文件之间通过横线隔开。", - "valueType": "string", - "type": "static" - } - ] - }, - { - "nodeId": "uow83rLCI2pI", - "name": "格式化中文翻译", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 2205.3511517635047, - "y": 121.1512729428531 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({target_lang, source_text}) {\n let text = source_text;\n\n if (target_lang === '简体中文' || target_lang === '繁體中文') {\n // 存储代码块内容\n const codeBlocks = [];\n let text = source_text.replace(/```[\\s\\S]*?```/g, (match) => {\n codeBlocks.push(match);\n return `__CODE_BLOCK_${codeBlocks.length - 1}__`;\n });\n\n // 替换成对的英文引号\n text = text.replace(/\"(.*?)\"/g, '“$1”');\n\n // 保护 Markdown 链接格式中的括号\n text = text.replace(/\\[(.*?)\\]\\((.*?)\\)/g, function(match) {\n return match.replace(/\\(/g, 'LEFTPAREN')\n .replace(/\\)/g, 'RIGHTPAREN');\n });\n\n // 替换成对的英文括号\n text = text.replace(/\\((.*?)\\)/g, '($1)');\n\n // 恢复被保护的 Markdown 链接括号\n text = text.replace(/LEFTPAREN/g, '(')\n .replace(/RIGHTPAREN/g, ')');\n\n // 更新句号替换逻辑,增加对版本号和URL的保护\n text = text.replace(/(\\d+)\\.(\\d+)\\.(\\d+)/g, '$1DOT$2DOT$3') // 保护版本号 (如 16.2.1)\n .replace(/(\\d)\\.(\\d)/g, '$1DOT$2') // 临时替换小数点\n .replace(/([a-zA-Z])\\.([a-zA-Z])/g, '$1DOT$2') // 临时替换缩写中的句号\n .replace(/([a-zA-Z])\\.(\\d)/g, '$1DOT$2') // 临时替换字母与数字之间的句号\n .replace(/(\\d)\\.([a-zA-Z])/g, '$1DOT$2') // 临时替换数字与字母之间的句号\n .replace(/([a-zA-Z])\\./g, '$1DOT') // 临时替换字母后面的句号(如 a.)\n .replace(/https?:/g, 'HTTPCOLON') // 保护 URL 中的冒号\n .replace(/\\./g, '。') // 替换其他句号\n .replace(/DOT/g, '.') // 恢复被保护的句号\n .replace(/HTTPCOLON/g, 'http:'); // 恢复 URL 中的冒号\n\n // 替换英文逗号,但不替换数字中的逗号\n text = text.replace(/(\\d),(\\d)/g, '$1COMMA$2') // 临时替换数字中的逗号\n .replace(/,/g, ',') // 替换其他逗号\n .replace(/COMMA/g, ','); // 恢复数字中的逗号\n\n // 替换其他常见符号\n const replacements = {\n '!': '!',\n '?': '?',\n ';': ';',\n };\n\n for (const [key, value] of Object.entries(replacements)) {\n text = text.replace(new RegExp(`\\\\${key}`, 'g'), value);\n }\n\n // 在中文和英文字符之间添加空格\n // 中文字符范围: \\u4e00-\\u9fa5\n // 英文字符范围: a-zA-Z0-9\n text = text.replace(/([\\u4e00-\\u9fa5])([a-zA-Z0-9])/g, '$1 $2')\n .replace(/([a-zA-Z0-9])([\\u4e00-\\u9fa5])/g, '$1 $2');\n\n // 恢复代码块\n text = text.replace(/__CODE_BLOCK_(\\d+)__/g, (_, index) => codeBlocks[index]);\n }\n\n return {\n text\n };\n}", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "source_text", - "label": "source_text", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "", - "value": ["vlNHndpNuFXB", "qLUQfhG0ILRX"] - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "target_lang", - "label": "target_lang", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["VARIABLE_NODE_ID", "target_lang"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key", - "valueDesc": "" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "text", - "valueType": "string", - "label": "text", - "valueDesc": "", - "description": "" - } - ] - } - ], - "edges": [ - { - "source": "a2lqxASWi1vb", - "target": "w4heEpNflz59", - "sourceHandle": "a2lqxASWi1vb-source-right", - "targetHandle": "w4heEpNflz59-target-left" - }, - { - "source": "w4heEpNflz59", - "target": "quYZgsW32ApA", - "sourceHandle": "w4heEpNflz59-source-ELSE", - "targetHandle": "quYZgsW32ApA-target-left" - }, - { - "source": "448745", - "target": "frjbsrlnJJsR", - "sourceHandle": "448745-source-right", - "targetHandle": "frjbsrlnJJsR-target-left" - }, - { - "source": "frjbsrlnJJsR", - "target": "qlt9KJbbS9yJ", - "sourceHandle": "frjbsrlnJJsR-source-right", - "targetHandle": "qlt9KJbbS9yJ-target-left" - }, - { - "source": "qlt9KJbbS9yJ", - "target": "dFxrGZS3Wmnz", - "sourceHandle": "qlt9KJbbS9yJ-source-ELSE", - "targetHandle": "dFxrGZS3Wmnz-target-top" - }, - { - "source": "yjFO3YcM7KG2", - "target": "vlNHndpNuFXB", - "sourceHandle": "yjFO3YcM7KG2-source-right", - "targetHandle": "vlNHndpNuFXB-target-left" - }, - { - "source": "rDzA1VxdpPIz", - "target": "quYZgsW32ApA", - "sourceHandle": "rDzA1VxdpPIz-source-right", - "targetHandle": "quYZgsW32ApA-target-left" - }, - { - "source": "qwKPaLWbYTLa", - "target": "a2lqxASWi1vb", - "sourceHandle": "qwKPaLWbYTLa-source-right", - "targetHandle": "a2lqxASWi1vb-target-left" - }, - { - "source": "nLBlOh6lWxkY", - "target": "yjFO3YcM7KG2", - "sourceHandle": "nLBlOh6lWxkY-source-right", - "targetHandle": "yjFO3YcM7KG2-target-left" - }, - { - "source": "w4heEpNflz59", - "target": "bdjAb5B2U1DQ", - "sourceHandle": "w4heEpNflz59-source-IF", - "targetHandle": "bdjAb5B2U1DQ-target-left" - }, - { - "source": "qlt9KJbbS9yJ", - "target": "mt7GlCIwbO9I", - "sourceHandle": "qlt9KJbbS9yJ-source-IF", - "targetHandle": "mt7GlCIwbO9I-target-left" - }, - { - "source": "mt7GlCIwbO9I", - "target": "rDzA1VxdpPIz", - "sourceHandle": "mt7GlCIwbO9I-source-IF", - "targetHandle": "rDzA1VxdpPIz-target-left" - }, - { - "source": "rhyUytTUBm19", - "target": "quYZgsW32ApA", - "sourceHandle": "rhyUytTUBm19-source-right", - "targetHandle": "quYZgsW32ApA-target-left" - }, - { - "source": "mt7GlCIwbO9I", - "target": "dtUmoUtTKfpM", - "sourceHandle": "mt7GlCIwbO9I-source-ELSE", - "targetHandle": "dtUmoUtTKfpM-target-left" - }, - { - "source": "dtUmoUtTKfpM", - "target": "rhyUytTUBm19", - "sourceHandle": "dtUmoUtTKfpM-source-right", - "targetHandle": "rhyUytTUBm19-target-left" - }, - { - "source": "vlNHndpNuFXB", - "target": "uow83rLCI2pI", - "sourceHandle": "vlNHndpNuFXB-source-right", - "targetHandle": "uow83rLCI2pI-target-left" - }, - { - "source": "uow83rLCI2pI", - "target": "qwKPaLWbYTLa", - "sourceHandle": "uow83rLCI2pI-source-right", - "targetHandle": "qwKPaLWbYTLa-target-left" - }, - { - "source": "quYZgsW32ApA", - "target": "nLBlOh6lWxkY", - "sourceHandle": "quYZgsW32ApA-source-right", - "targetHandle": "nLBlOh6lWxkY-target-left" - } - ], - "chatConfig": { - "welcomeText": "## 你好,欢迎使用文档翻译机器人\n1. 选择源语言和目标语言\n2. 发送你需要翻译的文档\n3. 等待翻译结果输出", - "variables": [ - { - "id": "v98n5b", - "key": "source_lang", - "label": "源语言", - "type": "select", - "required": true, - "maxLen": 50, - "enums": [ - { - "value": "简体中文" - }, - { - "value": "繁體中文" - }, - { - "value": "English" - }, - { - "value": "Español" - }, - { - "value": "Français" - }, - { - "value": "Deutsch" - }, - { - "value": "Italiano" - }, - { - "value": "日本語" - }, - { - "value": "한국어" - }, - { - "value": "Русский" - }, - { - "value": "العربية" - }, - { - "value": "Bahasa Indonesia" - }, - { - "value": "Polski" - } - ], - "icon": "core/app/variable/select" - }, - { - "id": "c3tvge", - "key": "target_lang", - "label": "目标语言", - "type": "select", - "required": true, - "maxLen": 50, - "enums": [ - { - "value": "简体中文" - }, - { - "value": "繁體中文" - }, - { - "value": "English" - }, - { - "value": "Español" - }, - { - "value": "Français" - }, - { - "value": "Deutsch" - }, - { - "value": "Italiano" - }, - { - "value": "日本語" - }, - { - "value": "한국어" - }, - { - "value": "Русский" - }, - { - "value": "العربية" - }, - { - "value": "Bahasa Indonesia" - }, - { - "value": "Polski" - } - ], - "icon": "core/app/variable/select" - } - ], - "scheduledTriggerConfig": { - "cronString": "", - "timezone": "Asia/Shanghai", - "defaultPrompt": "" - }, - "fileSelectConfig": { - "canSelectFile": true, - "canSelectImg": false, - "maxFiles": 10 - }, - "_id": "6688b45317c65410d61d58aa" - } - } -} diff --git a/packages/templates/src/plugin-dalle/template.json b/packages/templates/src/plugin-dalle/template.json deleted file mode 100644 index 99261f7db..000000000 --- a/packages/templates/src/plugin-dalle/template.json +++ /dev/null @@ -1,330 +0,0 @@ -{ - "name": "Dalle3 绘图", - "intro": "通过请求 Dalle3 接口绘图,需要有 api key", - "author": "", - "avatar": "core/app/templates/plugin-dalle", - "type": "plugin", - "tags": ["recommendation", "image-generation"], - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "插件开始", - "intro": "可以配置插件需要哪些输入,利用这些输入来运行插件", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 421.97302886868476, - "y": -89.7785530936485 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "selectedTypeIndex": 0, - "valueType": "string", - "canEdit": true, - "key": "绘图提示词", - "label": "绘图提示词", - "description": "绘图提示词", - "required": true, - "toolDescription": "绘图提示词" - } - ], - "outputs": [ - { - "id": "绘图提示词", - "valueType": "string", - "key": "绘图提示词", - "label": "绘图提示词", - "type": "hidden" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "插件输出", - "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 1785.9300180845394, - "y": -108.2785530936485 - }, - "version": "481", - "inputs": [ - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "图片访问链接", - "label": "图片访问链接", - "description": "", - "value": ["tMvel910bnrJ", "pJXgWoTpPoMy"] - }, - { - "renderTypeList": ["reference"], - "valueType": "object", - "canEdit": true, - "key": "error", - "label": "错误信息", - "description": "", - "value": ["tMvel910bnrJ", "error"] - } - ], - "outputs": [] - }, - { - "nodeId": "tMvel910bnrJ", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1044.8838211811253, - "y": -414.7785530936485 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "https://api.openai.com/v1/images/generations", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [ - { - "key": "Authorization", - "type": "string", - "value": "Bearer {{authorization}}" - } - ], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\n \"model\": \"dall-e-3\",\n \"prompt\": \"{{prompt}}\",\n \"n\": 1,\n \"size\": \"1024x1024\"\n}", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "prompt", - "label": "prompt", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["pluginInput", "绘图提示词"] - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - } - }, - { - "id": "pJXgWoTpPoMy", - "valueType": "string", - "type": "dynamic", - "key": "data[0].url", - "label": "data[0].url" - } - ] - }, - { - "nodeId": "c7tRU2qAQoAf", - "name": "系统配置", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": -46.476647046261974, - "y": -89.7785530936485 - }, - "version": "4811", - "inputs": [], - "outputs": [] - } - ], - "edges": [ - { - "source": "pluginInput", - "target": "tMvel910bnrJ", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "tMvel910bnrJ-target-left" - }, - { - "source": "tMvel910bnrJ", - "target": "pluginOutput", - "sourceHandle": "tMvel910bnrJ-source-right", - "targetHandle": "pluginOutput-target-left" - } - ] - } -} diff --git a/packages/templates/src/plugin-feishu/template.json b/packages/templates/src/plugin-feishu/template.json deleted file mode 100644 index 09cc21b55..000000000 --- a/packages/templates/src/plugin-feishu/template.json +++ /dev/null @@ -1,355 +0,0 @@ -{ - "name": "飞书 webhook 插件", - "intro": "通过 webhook 给飞书机器人发送一条消息", - "author": "", - "avatar": "core/app/templates/plugin-feishu", - "type": "plugin", - "tags": ["recommendation", "office-services"], - "workflow": { - "nodes": [ - { - "nodeId": "pluginInput", - "name": "插件开始", - "intro": "自定义配置外部输入,使用插件时,仅暴露自定义配置的输入", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "pluginInput", - "showStatus": false, - "position": { - "x": 535.7465806305546, - "y": -201.26482361861054 - }, - "version": "481", - "inputs": [ - { - "inputType": "input", - "valueType": "string", - "key": "飞书机器人地址", - "label": "飞书机器人地址", - "description": "", - "isToolInput": false, - "defaultValue": "", - "editField": { - "key": true - }, - "dynamicParamDefaultValue": { - "inputType": "reference", - "valueType": "string", - "required": true - }, - "renderTypeList": ["input"], - "required": true, - "canEdit": true, - "value": "" - }, - { - "key": "发送的消息", - "valueType": "string", - "label": "发送的消息", - "renderTypeList": ["reference"], - "required": true, - "description": "", - "canEdit": true, - "value": "", - "editField": { - "key": true - }, - "dynamicParamDefaultValue": { - "inputType": "reference", - "valueType": "string", - "required": true - } - } - ], - "outputs": [ - { - "id": "mv52BrPVE6bm", - "key": "飞书机器人地址", - "valueType": "string", - "label": "飞书机器人地址", - "type": "static" - }, - { - "id": "p0m68Dv5KaIp", - "key": "发送的消息", - "valueType": "string", - "label": "发送的消息", - "type": "static" - } - ] - }, - { - "nodeId": "pluginOutput", - "name": "插件输出", - "intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", - "avatar": "core/workflow/template/pluginOutput", - "flowNodeType": "pluginOutput", - "showStatus": false, - "position": { - "x": 1776.027569211593, - "y": -58.264823618610535 - }, - "version": "481", - "inputs": [], - "outputs": [] - }, - { - "nodeId": "rKBYGQuYefae", - "name": "HTTP 请求", - "intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)", - "avatar": "core/workflow/template/httpRequest", - "flowNodeType": "httpRequest468", - "showStatus": true, - "position": { - "x": 1069.7228495148624, - "y": -392.26482361861054 - }, - "version": "481", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "common:core.module.input.description.HTTP Dynamic Input", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpMethod", - "renderTypeList": ["custom"], - "valueType": "string", - "label": "", - "value": "POST", - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpTimeout", - "renderTypeList": ["custom"], - "valueType": "number", - "label": "", - "value": 30, - "min": 5, - "max": 600, - "required": true, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpReqUrl", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "", - "description": "common:core.module.input.description.Http Request Url", - "placeholder": "https://api.ai.com/getInventory", - "required": false, - "value": "{{url}}", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpHeader", - "renderTypeList": ["custom"], - "valueType": "any", - "value": [], - "label": "", - "description": "common:core.module.input.description.Http Request Header", - "placeholder": "common:core.module.input.description.Http Request Header", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpParams", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpJsonBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": "{\r\n \"msg_type\": \"text\",\r\n \"content\": {\r\n \"text\": \"{{text}}\"\r\n }\r\n}", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpFormBody", - "renderTypeList": ["hidden"], - "valueType": "any", - "value": [], - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "system_httpContentType", - "renderTypeList": ["hidden"], - "valueType": "string", - "value": "json", - "label": "", - "required": false, - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "text", - "valueType": "string", - "label": "text", - "renderTypeList": ["reference"], - "description": "", - "canEdit": true, - "editField": { - "key": true, - "valueType": true - }, - "value": ["pluginInput", "p0m68Dv5KaIp"], - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - }, - { - "key": "url", - "valueType": "string", - "label": "url", - "renderTypeList": ["reference"], - "description": "", - "canEdit": true, - "editField": { - "key": true, - "valueType": true - }, - "value": ["pluginInput", "mv52BrPVE6bm"], - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - } - ], - "outputs": [ - { - "id": "error", - "key": "error", - "label": "workflow:request_error", - "description": "HTTP请求错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "httpRawResponse", - "key": "httpRawResponse", - "required": true, - "label": "workflow:raw_response", - "description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。", - "valueType": "any", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "editField": { - "key": true, - "valueType": true - } - } - ] - }, - { - "nodeId": "q3ccNXiZIHoS", - "name": "系统配置", - "intro": "", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "pluginConfig", - "position": { - "x": 99.73879703925843, - "y": -201.26482361861054 - }, - "version": "4811", - "inputs": [], - "outputs": [] - } - ], - "edges": [ - { - "source": "pluginInput", - "target": "rKBYGQuYefae", - "sourceHandle": "pluginInput-source-right", - "targetHandle": "rKBYGQuYefae-target-left" - }, - { - "source": "rKBYGQuYefae", - "target": "pluginOutput", - "sourceHandle": "rKBYGQuYefae-source-right", - "targetHandle": "pluginOutput-target-left" - } - ] - } -} diff --git a/packages/templates/src/simpleDatasetChat/template.json b/packages/templates/src/simpleDatasetChat/template.json deleted file mode 100644 index 5e3aac255..000000000 --- a/packages/templates/src/simpleDatasetChat/template.json +++ /dev/null @@ -1,288 +0,0 @@ -{ - "name": "知识库+对话引导", - "intro": "每次提问时进行一次知识库搜索,将搜索结果注入 LLM 模型进行参考回答", - "author": "", - "avatar": "core/workflow/template/datasetSearch", - "type": "simple", - "tags": ["office-services"], - "workflow": { - "nodes": [ - { - "nodeId": "userGuide", - "name": "系统配置", - "intro": "可以配置应用的系统参数", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "userGuide", - "position": { - "x": 531.2422736065552, - "y": -486.7611729549753 - }, - "version": "481", - "inputs": [], - "outputs": [] - }, - { - "nodeId": "workflowStartNodeId", - "name": "流程开始", - "intro": "", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "workflowStart", - "position": { - "x": 558.4082376415505, - "y": 123.72387429194112 - }, - "version": "481", - "inputs": [ - { - "key": "userChatInput", - "renderTypeList": ["FlowNodeInputTypeEnum.reference", "FlowNodeInputTypeEnum.textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题" - } - ], - "outputs": [ - { - "id": "userChatInput", - "key": "userChatInput", - "label": "core.module.input.label.user question", - "valueType": "string", - "type": "FlowNodeOutputTypeEnum.static" - } - ] - }, - { - "nodeId": "7BdojPlukIQw", - "name": "AI 对话", - "intro": "AI 大模型对话", - "avatar": "core/workflow/template/aiChat", - "flowNodeType": "chatNode", - "showStatus": true, - "position": { - "x": 1638.509551404687, - "y": -341.0428450861567 - }, - "version": "481", - "inputs": [ - { - "key": "model", - "renderTypeList": [ - "FlowNodeInputTypeEnum.settingLLMModel", - "FlowNodeInputTypeEnum.reference" - ], - "label": "core.module.input.label.aiModel", - "valueType": "string", - "value": "gpt-5" - }, - { - "key": "temperature", - "renderTypeList": ["FlowNodeInputTypeEnum.hidden"], - "label": "", - "value": 3, - "valueType": "number", - "min": 0, - "max": 10, - "step": 1 - }, - { - "key": "maxToken", - "renderTypeList": ["FlowNodeInputTypeEnum.hidden"], - "label": "", - "value": 1950, - "valueType": "number", - "min": 100, - "max": 4000, - "step": 50 - }, - { - "key": "isResponseAnswerText", - "renderTypeList": ["FlowNodeInputTypeEnum.hidden"], - "label": "", - "value": true, - "valueType": "boolean" - }, - { - "key": "quoteTemplate", - "renderTypeList": ["FlowNodeInputTypeEnum.hidden"], - "label": "", - "valueType": "string" - }, - { - "key": "quotePrompt", - "renderTypeList": ["FlowNodeInputTypeEnum.hidden"], - "label": "", - "valueType": "string" - }, - { - "key": "systemPrompt", - "renderTypeList": ["FlowNodeInputTypeEnum.textarea", "FlowNodeInputTypeEnum.reference"], - "max": 3000, - "valueType": "string", - "label": "core.ai.Prompt", - "description": "core.app.tip.systemPromptTip", - "placeholder": "core.app.tip.chatNodeSystemPromptTip", - "value": "" - }, - { - "key": "history", - "renderTypeList": [ - "FlowNodeInputTypeEnum.numberInput", - "FlowNodeInputTypeEnum.reference" - ], - "valueType": "chatHistory", - "label": "core.module.input.label.chat history", - "required": true, - "min": 0, - "max": 30, - "value": 6 - }, - { - "key": "userChatInput", - "renderTypeList": ["FlowNodeInputTypeEnum.reference", "FlowNodeInputTypeEnum.textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题", - "value": ["workflowStartNodeId", "userChatInput"] - }, - { - "key": "quoteQA", - "renderTypeList": ["FlowNodeInputTypeEnum.settingDatasetQuotePrompt"], - "label": "", - "debugLabel": "知识库引用", - "description": "", - "valueType": "datasetQuote", - "value": ["iKBoX2vIzETU", "quoteQA"] - } - ], - "outputs": [ - { - "id": "history", - "key": "history", - "label": "core.module.output.label.New context", - "description": "core.module.output.description.New context", - "valueType": "chatHistory", - "type": "FlowNodeOutputTypeEnum.static" - }, - { - "id": "answerText", - "key": "answerText", - "label": "core.module.output.label.Ai response content", - "description": "core.module.output.description.Ai response content", - "valueType": "string", - "type": "FlowNodeOutputTypeEnum.static" - } - ] - }, - { - "nodeId": "iKBoX2vIzETU", - "name": "知识库搜索", - "intro": "调用\"语义检索\"和\"全文检索\"能力,从\"知识库\"中查找可能与问题相关的参考内容", - "avatar": "core/workflow/template/datasetSearch", - "flowNodeType": "datasetSearchNode", - "showStatus": true, - "position": { - "x": 918.5901682164496, - "y": -227.11542247619582 - }, - "version": "481", - "inputs": [ - { - "key": "datasets", - "renderTypeList": [ - "FlowNodeInputTypeEnum.selectDataset", - "FlowNodeInputTypeEnum.reference" - ], - "label": "core.module.input.label.Select dataset", - "value": [], - "valueType": "selectDataset", - "list": [], - "required": true - }, - { - "key": "similarity", - "renderTypeList": ["FlowNodeInputTypeEnum.selectDatasetParamsModal"], - "label": "", - "value": 0.4, - "valueType": "number" - }, - { - "key": "limit", - "renderTypeList": ["hidden"], - "label": "", - "value": 5000, - "valueType": "number" - }, - { - "key": "searchMode", - "renderTypeList": ["FlowNodeInputTypeEnum.hidden"], - "label": "", - "valueType": "string", - "value": "embedding" - }, - { - "key": "usingReRank", - "renderTypeList": ["FlowNodeInputTypeEnum.hidden"], - "label": "", - "valueType": "boolean", - "value": false - }, - { - "key": "datasetSearchUsingExtensionQuery", - "renderTypeList": ["FlowNodeInputTypeEnum.hidden"], - "label": "", - "valueType": "boolean", - "value": true - }, - { - "key": "datasetSearchExtensionModel", - "renderTypeList": ["FlowNodeInputTypeEnum.hidden"], - "label": "", - "valueType": "string" - }, - { - "key": "datasetSearchExtensionBg", - "renderTypeList": ["FlowNodeInputTypeEnum.hidden"], - "label": "", - "valueType": "string", - "value": "" - }, - { - "key": "userChatInput", - "renderTypeList": ["FlowNodeInputTypeEnum.reference", "FlowNodeInputTypeEnum.textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "需要检索的内容", - "value": ["workflowStartNodeId", "userChatInput"] - } - ], - "outputs": [ - { - "id": "quoteQA", - "key": "quoteQA", - "label": "core.module.Dataset quote.label", - "type": "FlowNodeOutputTypeEnum.static", - "valueType": "datasetQuote", - "description": "特殊数组格式,搜索结果为空时,返回空数组。" - } - ] - } - ], - "edges": [ - { - "source": "workflowStartNodeId", - "target": "iKBoX2vIzETU", - "sourceHandle": "workflowStartNodeId-source-right", - "targetHandle": "iKBoX2vIzETU-target-left" - }, - { - "source": "iKBoX2vIzETU", - "target": "7BdojPlukIQw", - "sourceHandle": "iKBoX2vIzETU-source-right", - "targetHandle": "7BdojPlukIQw-target-left" - } - ] - } -} diff --git a/packages/templates/src/srt-translate/template.json b/packages/templates/src/srt-translate/template.json deleted file mode 100644 index 43258360c..000000000 --- a/packages/templates/src/srt-translate/template.json +++ /dev/null @@ -1,1934 +0,0 @@ -{ - "name": "长字幕反思翻译机器人", - "intro": "利用 AI 自我反思提升翻译质量,同时循环迭代执行 AI 工作流来突破 LLM tokens 限制,实现一个高效的长字幕翻译机器人", - "author": "", - "avatar": "core/app/templates/TranslateRobot", - "tags": ["office-services"], - "type": "advanced", - "userGuide": { - "type": "link", - "content": "https://mp.weixin.qq.com/s/uztciEVvumNWNlct0IeJ-w" - }, - "workflow": { - "nodes": [ - { - "nodeId": "userGuide", - "name": "系统配置", - "intro": "可以配置应用的系统参数", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "userGuide", - "position": { - "x": -1453.0815298642474, - "y": 269.10239463914263 - }, - "version": "481", - "inputs": [ - { - "key": "welcomeText", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "core.app.Welcome Text", - "value": "" - }, - { - "key": "variables", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "core.app.Chat Variable", - "value": [] - }, - { - "key": "questionGuide", - "valueType": "any", - "renderTypeList": ["hidden"], - "label": "core.app.Question Guide", - "value": { - "open": false - } - }, - { - "key": "tts", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "type": "web" - } - }, - { - "key": "whisper", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - } - }, - { - "key": "scheduleTrigger", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": null - } - ], - "outputs": [] - }, - { - "nodeId": "448745", - "name": "流程开始", - "intro": "", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "workflowStart", - "position": { - "x": -1491.3235962441404, - "y": 1277.8094190109027 - }, - "version": "481", - "inputs": [ - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题" - } - ], - "outputs": [ - { - "id": "userChatInput", - "key": "userChatInput", - "label": "common:core.module.input.label.user question", - "type": "static", - "valueType": "string" - } - ] - }, - { - "nodeId": "yjFO3YcM7KG2", - "name": "LLM 翻译", - "intro": "AI 大模型对话", - "avatar": "core/workflow/template/aiChat", - "flowNodeType": "chatNode", - "showStatus": true, - "position": { - "x": 2584.1800627074813, - "y": 962.3727118784907 - }, - "version": "481", - "inputs": [ - { - "key": "model", - "renderTypeList": ["settingLLMModel", "reference"], - "label": "core.module.input.label.aiModel", - "valueType": "string", - "selectedTypeIndex": 0, - "value": "gpt-4o" - }, - { - "key": "temperature", - "renderTypeList": ["hidden"], - "label": "", - "value": 3, - "valueType": "number", - "min": 0, - "max": 10, - "step": 1 - }, - { - "key": "maxToken", - "renderTypeList": ["hidden"], - "label": "", - "value": 2000, - "valueType": "number", - "min": 100, - "max": 4000, - "step": 50 - }, - { - "key": "isResponseAnswerText", - "renderTypeList": ["hidden"], - "label": "", - "value": false, - "valueType": "boolean" - }, - { - "key": "quoteTemplate", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string" - }, - { - "key": "quotePrompt", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string" - }, - { - "key": "aiChatVision", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "boolean", - "value": true - }, - { - "key": "systemPrompt", - "renderTypeList": ["textarea", "reference"], - "max": 3000, - "valueType": "string", - "label": "core.ai.Prompt", - "description": "core.app.tip.systemPromptTip", - "placeholder": "core.app.tip.chatNodeSystemPromptTip", - "value": "# Role: 资深字幕翻译专家\n\n## Background:\n你是一位经验丰富的{{source_lang}}和{{target_lang}}字幕翻译专家,精通{{source_lang}}和{{target_lang}}互译,尤其擅长将{{source_lang}}字幕译成流畅易懂的{{target_lang}}字幕。你曾多次带领团队完成大型商业电影的字幕翻译项目,所翻译的字幕广受好评。\n\n## Attention:\n- 翻译过程中要始终坚持\"信、达、雅\"的原则,但\"达\"尤为重要\n- 翻译的字幕要符合{{target_lang}}的表达习惯,通俗易懂,连贯流畅\n- 避免使用过于文绉绉的表达和晦涩难懂的典故引用 \n- 诗词歌词等内容需按原文换行和节奏分行,不破坏原排列格式 \n- 翻译对象是字幕,请进入整段文本的语境中对需要翻译的文本段进行翻译\n- 是标识每一帧字幕的标签,请严格按照对文本的分割逐帧翻译\n\n## Constraints:\n- 必须严格遵循四轮翻译流程:直译、意译、反思、提升\n- 译文要忠实原文,准确无误,不能遗漏或曲解原意\n- 最终译文使用Markdown的代码块呈现,但是不用输出markdown这个单词\n- 是标识每一帧字幕的标签,请严格按照对文本的分割逐帧翻译,每一帧字幕末尾不要加\\n 回车标识,且第一帧字幕开头不需要加标识\n\n## Goals:\n- 通过四轮翻译流程,将{{source_lang}}字幕译成高质量的{{target_lang}}字幕\n- 翻译的字幕要准确传达原字幕意思,语言表达力求浅显易懂,朗朗上口 \n\n## Workflow:\n1. 第一轮直译:严格按照逐句翻译,不遗漏任何信息\n2. 第二轮意译:在直译的基础上用通俗流畅的{{target_lang}}意译原文,逐句翻译,保留标识标签\n3. 第三轮反思:仔细审视译文,分点列出一份建设性的批评和有用的建议清单以改进翻译,对每一句话提出建议,从以下四个角度展开\n (i) 准确性(纠正添加、误译、遗漏或未翻译的文本错误),\n (ii) 流畅性(应用{{target_lang}}的语法、拼写和标点规则,并确保没有不必要的重复),\n (iii) 风格(确保翻译反映源文本的风格并考虑其文化背景),\n (iv) 术语(确保术语使用一致且反映源文本所在领域,注意确保使用{{target_lang}}中的等效习语)\n4. 第四轮提升:严格遵循第三轮提出的建议对翻译修改,定稿出一个简洁畅达、符合大众观影习惯的字幕译文,保留标识标签\n\n## OutputFormat:\n- 每一轮前用【思考】说明该轮要点\n- 第一轮和第二轮翻译后用【翻译】呈现译文\n- 第三轮输出建议清单,分点列出,在每一点前用*xxx*标识这条建议对应的要点,如*风格*;建议前用【思考】说明该轮要点,建议后用【建议】呈现建议\n- 第四轮在\\`\\`\\`代码块中展示最终{{target_lang}}字幕文件内容,如\\`\\`\\`xxx\\`\\`\\`\n\n## Suggestions:\n- 直译时力求忠实原文,但注意控制每帧字幕的字数,必要时进行精简压缩\n- 意译时在准确表达原意的基础上,用最朴实无华的{{target_lang}}来表达\n- 反思环节重点关注译文是否符合{{target_lang}}表达习惯,是否通俗易懂,是否准确流畅,是否术语一致\n- 提升环节采用反思环节的建议对意译环节的翻译进行修改,适度采用一些口语化的表达、网络流行语等,增强字幕的亲和力\n- 注意是很重要的标识标签,请确保标签能在正确位置输出" - }, - { - "key": "history", - "renderTypeList": ["numberInput", "reference"], - "valueType": "chatHistory", - "label": "core.module.input.label.chat history", - "description": "最多携带多少轮对话记录", - "required": true, - "min": 0, - "max": 50, - "value": 6 - }, - { - "key": "quoteQA", - "renderTypeList": ["settingDatasetQuotePrompt"], - "label": "", - "debugLabel": "知识库引用", - "description": "", - "valueType": "datasetQuote" - }, - { - "key": "stringQuoteText", - "renderTypeList": ["reference", "textarea"], - "label": "app:document_quote", - "debugLabel": "app:document_quote", - "description": "app:document_quote_tip", - "valueType": "string" - }, - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题", - "value": ["bxz97Vg4Omux", "system_text"] - } - ], - "outputs": [ - { - "id": "history", - "key": "history", - "required": true, - "label": "core.module.output.label.New context", - "description": "core.module.output.description.New context", - "valueType": "chatHistory", - "type": "static" - }, - { - "id": "answerText", - "key": "answerText", - "required": true, - "label": "core.module.output.label.Ai response content", - "description": "core.module.output.description.Ai response content", - "valueType": "string", - "type": "static" - } - ] - }, - { - "nodeId": "bxz97Vg4Omux", - "name": "LLM 翻译提示词", - "intro": "可对固定或传入的文本进行加工后输出,非字符串类型数据最终会转成字符串类型。", - "avatar": "core/workflow/template/textConcat", - "flowNodeType": "textEditor", - "position": { - "x": 1881.9891746911078, - "y": 1112.4113692581143 - }, - "version": "486", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "可以引用其他节点的输出,作为文本拼接的变量,通过 {{字段名}} 来引用变量", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - } - }, - { - "key": "system_textareaInput", - "renderTypeList": ["textarea"], - "valueType": "string", - "required": true, - "label": "拼接文本", - "placeholder": "可通过 {{字段名}} 来引用变量", - "value": "你的任务是将文本从{{source_lang}}翻译成{{target_lang}}\n\n源文本如下,由XML标签分隔:\n\n\n\n{{tagged_text}}\n\n\n\n仅翻译源文本中由分隔的部分,将其余的源文本作为上下文\n\n重申一下,你应该只翻译文本的这一部分,这里再次显示在之间:\n\n\n\n{{chunk_to_translate}}\n\n" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "tagged_text", - "label": "tagged_text", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "required": true, - "value": ["quYZgsW32ApA", "xhXu6sdEWBnF"] - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "chunk_to_translate", - "label": "chunk_to_translate", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "required": true, - "value": ["quYZgsW32ApA", "eCp73lztAEGK"] - } - ], - "outputs": [ - { - "id": "system_text", - "key": "system_text", - "label": "拼接结果", - "type": "static", - "valueType": "string" - } - ] - }, - { - "nodeId": "w4heEpNflz59", - "name": "判断是否执行结束", - "intro": "根据一定的条件,执行不同的分支。", - "avatar": "core/workflow/template/ifelse", - "flowNodeType": "ifElseNode", - "showStatus": true, - "position": { - "x": 5610.256715310997, - "y": 1232.1024649538042 - }, - "version": "481", - "inputs": [ - { - "key": "ifElseList", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": [ - { - "condition": "AND", - "list": [ - { - "variable": ["a2lqxASWi1vb", "nmBmGaARbKkl"], - "condition": "equalTo", - "value": "true" - } - ] - } - ] - } - ], - "outputs": [ - { - "id": "ifElseResult", - "key": "ifElseResult", - "label": "判断结果", - "valueType": "string", - "type": "static" - } - ] - }, - { - "nodeId": "a2lqxASWi1vb", - "name": "判断是否执行结束", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 5068.150809685475, - "y": 940.8168438455639 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "这些变量会作为代码的运行的输入参数", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({chunks, currentChunk}){\n const findIndex = chunks.findIndex((item) => item === currentChunk)\n\n return {\n isEnd: chunks.length-1 === findIndex,\n i: findIndex + 1,\n }\n}" - }, - { - "renderTypeList": ["reference"], - "valueType": "arrayString", - "canEdit": true, - "key": "chunks", - "label": "chunks", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["y3WEYOQ09CGC", "qLUQfhG0ILRX"] - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "currentChunk", - "label": "currentChunk", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["quYZgsW32ApA", "eCp73lztAEGK"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "完整响应数据", - "valueType": "object", - "type": "static" - }, - { - "id": "error", - "key": "error", - "label": "运行错误", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key" - }, - { - "id": "nmBmGaARbKkl", - "valueType": "boolean", - "type": "dynamic", - "key": "isEnd", - "label": "isEnd" - }, - { - "id": "nqB98uKpq6Ig", - "valueType": "number", - "type": "dynamic", - "key": "i", - "label": "i" - } - ] - }, - { - "nodeId": "quYZgsW32ApA", - "name": "格式化源文本块", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 1306.0466226590386, - "y": 1038.0950796039954 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "这些变量会作为代码的运行的输入参数", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({source_text_chunks, i=0}){\n let before = source_text_chunks.slice(0, i).join(\"\");\n let current = \" \" + source_text_chunks[i] + \"\";\n let after = source_text_chunks.slice(i + 1).join(\"\");\n let tagged_text = before + current + after;\n\n return {\n tagged_text,\n chunk_to_translate: source_text_chunks[i],\n }\n}" - }, - { - "renderTypeList": ["reference"], - "valueType": "number", - "canEdit": true, - "key": "i", - "label": "i", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["a2lqxASWi1vb", "nqB98uKpq6Ig"] - }, - { - "renderTypeList": ["reference"], - "valueType": "arrayString", - "canEdit": true, - "key": "source_text_chunks", - "label": "source_text_chunks", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["y3WEYOQ09CGC", "qLUQfhG0ILRX"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "完整响应数据", - "valueType": "object", - "type": "static" - }, - { - "id": "error", - "key": "error", - "label": "运行错误", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key" - }, - { - "id": "xhXu6sdEWBnF", - "valueType": "string", - "type": "dynamic", - "key": "tagged_text", - "label": "tagged_text" - }, - { - "id": "eCp73lztAEGK", - "valueType": "string", - "type": "dynamic", - "key": "chunk_to_translate", - "label": "chunk_to_translate" - } - ] - }, - { - "nodeId": "izsNX8FXGD1t", - "name": "指定回复", - "intro": "该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。", - "avatar": "core/workflow/template/reply", - "flowNodeType": "answerNode", - "position": { - "x": 6412.138830862469, - "y": 1235.7269544046057 - }, - "version": "481", - "inputs": [ - { - "key": "text", - "renderTypeList": ["textarea", "reference"], - "valueType": "any", - "required": true, - "label": "core.module.input.label.Response content", - "description": "core.module.input.description.Response content", - "placeholder": "core.module.input.description.Response content", - "value": "\n\n*** 字幕反思翻译完成!***" - } - ], - "outputs": [] - }, - { - "nodeId": "vlNHndpNuFXB", - "name": "取出 LLM 翻译第四轮文本", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 3292.3569279448307, - "y": 996.4264559884845 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "这些变量会作为代码的运行的输入参数", - "editField": { - "key": true, - "valueType": true - }, - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({data1}){\n const result = data1.split(\"```\").filter(item => !!item.trim())\n\n if(result[result.length-1]) {\n return {\n result: result[result.length-1].trim() \n }\n }\n\n return {\n result: '未截取到翻译内容'\n }\n}" - }, - { - "key": "data1", - "valueType": "string", - "label": "data1", - "renderTypeList": ["reference"], - "description": "", - "canEdit": true, - "editField": { - "key": true, - "valueType": true - }, - "value": ["yjFO3YcM7KG2", "answerText"], - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "完整响应数据", - "valueType": "object", - "type": "static" - }, - { - "id": "error", - "key": "error", - "label": "运行错误", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "result", - "valueType": "string", - "label": "result" - }, - { - "id": "gR0mkQpJ4Og8", - "type": "dynamic", - "key": "data2", - "valueType": "string", - "label": "data2" - } - ] - }, - { - "nodeId": "qlt9KJbbS9yJ", - "name": "判断源语言和目标语言是否相同", - "intro": "根据一定的条件,执行不同的分支。", - "avatar": "core/workflow/template/ifelse", - "flowNodeType": "ifElseNode", - "showStatus": true, - "position": { - "x": -646.0682391158168, - "y": 1352.6591494737195 - }, - "version": "481", - "inputs": [ - { - "key": "ifElseList", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": [ - { - "condition": "AND", - "list": [ - { - "variable": ["frjbsrlnJJsR", "qLUQfhG0ILRX"], - "condition": "equalTo", - "value": "false" - } - ] - } - ] - } - ], - "outputs": [ - { - "id": "ifElseResult", - "key": "ifElseResult", - "label": "判断结果", - "valueType": "string", - "type": "static" - } - ] - }, - { - "nodeId": "frjbsrlnJJsR", - "name": "判断源语言和目标语言是否相同", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": -1152.6572772702038, - "y": 1092.3001349756628 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "这些变量会作为代码的运行的输入参数", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({source_lang, target_lang}){\n \n return {\n result: source_lang === target_lang\n }\n}" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "source_lang", - "label": "source_lang", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["VARIABLE_NODE_ID", "source_lang"] - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "target_lang", - "label": "target_lang", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["VARIABLE_NODE_ID", "target_lang"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "完整响应数据", - "valueType": "object", - "type": "static" - }, - { - "id": "error", - "key": "error", - "label": "运行错误", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "result", - "valueType": "boolean", - "label": "result" - } - ] - }, - { - "nodeId": "dFxrGZS3Wmnz", - "name": "提示源语言与目标语言相同", - "intro": "该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。", - "avatar": "core/workflow/template/reply", - "flowNodeType": "answerNode", - "position": { - "x": -523.8880105943567, - "y": 1735.994691812213 - }, - "version": "481", - "inputs": [ - { - "key": "text", - "renderTypeList": ["textarea", "reference"], - "valueType": "any", - "required": true, - "label": "core.module.input.label.Response content", - "description": "core.module.input.description.Response content", - "placeholder": "core.module.input.description.Response content", - "selectedTypeIndex": 0, - "value": "{{source_lang}} 无需再次翻译为 {{target_lang}} ~" - } - ], - "outputs": [] - }, - { - "nodeId": "tqzmK5oPR9BA", - "name": "输出翻译", - "intro": "该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。", - "avatar": "core/workflow/template/reply", - "flowNodeType": "answerNode", - "position": { - "x": 4368.135274121754, - "y": 1308.859868496928 - }, - "version": "481", - "inputs": [ - { - "key": "text", - "renderTypeList": ["textarea", "reference"], - "valueType": "any", - "required": true, - "label": "core.module.input.label.Response content", - "description": "core.module.input.description.Response content", - "placeholder": "core.module.input.description.Response content", - "selectedTypeIndex": 1, - "value": ["ppPP6o7YYSTJ", "dYalXmYJ60bj"] - } - ], - "outputs": [] - }, - { - "nodeId": "kbr342XlxSZR", - "name": "提取字幕信息", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 207.77750594024815, - "y": 1057.1062190161417 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "这些变量会作为代码的运行的输入参数", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({text}){\n const lines = text.split('\\n');\n const timePattern = /\\d{2}:\\d{2}:\\d{2},\\d{3} --> \\d{2}:\\d{2}:\\d{2},\\d{3}/;\n const numberInfo = [];\n const timeInfo = [];\n const textInfo = [];\n let currentText = [];\n\n // 提取序号、时间戳和文本信息\n lines.forEach(line => {\n if (/^\\d+$/.test(line.trim())) {\n numberInfo.push(line.trim());\n } else if (timePattern.test(line)) {\n timeInfo.push(line);\n if (currentText.length > 0) {\n textInfo.push(currentText.join(' '));\n currentText = [];\n }\n } else if (line.trim() === '') {\n // Skip empty lines\n } else {\n currentText.push(line.trim());\n }\n });\n\n if (currentText.length > 0) {\n textInfo.push(currentText.join(' '));\n }\n\n return { numberInfo, timeInfo, textInfo };\n}" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "text", - "label": "text", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["448745", "userChatInput"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "完整响应数据", - "valueType": "object", - "type": "static" - }, - { - "id": "error", - "key": "error", - "label": "运行错误", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key" - }, - { - "id": "h3qVuGhV9HNm", - "valueType": "arrayString", - "type": "dynamic", - "key": "timeInfo", - "label": "timeInfo" - }, - { - "id": "zGYRMNA9xGuI", - "valueType": "arrayString", - "type": "dynamic", - "key": "textInfo", - "label": "textInfo" - }, - { - "id": "dhzTt6Riz8Dp", - "valueType": "arrayString", - "type": "dynamic", - "key": "numberInfo", - "label": "numberInfo" - } - ] - }, - { - "nodeId": "ppPP6o7YYSTJ", - "name": "格式化字幕文件", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 3830.732983153034, - "y": 828.5283022715971 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "这些变量会作为代码的运行的输入参数", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({combinedText, transedText, timeInfo, currentIndex=0,numberInfo}){\n const textLines = combinedText.split('');\n const resultLines = transedText.split('');\n const combinedLines = [];\n\n resultLines.forEach((line, index) => {\n combinedLines.push(numberInfo[currentIndex+index]);\n combinedLines.push(timeInfo[currentIndex+index]);\n combinedLines.push(line)\n combinedLines.push(textLines[index]);\n combinedLines.push('');\n });\n\n const srtContent = combinedLines.join('\\n');\n \n\n return {\n srtContent,\n currentIndex: currentIndex+textLines.length\n }\n}" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "combinedText", - "label": "combinedText", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["quYZgsW32ApA", "eCp73lztAEGK"] - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "transedText", - "label": "transedText", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["vlNHndpNuFXB", "qLUQfhG0ILRX"] - }, - { - "renderTypeList": ["reference"], - "valueType": "arrayString", - "canEdit": true, - "key": "timeInfo", - "label": "timeInfo", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["kbr342XlxSZR", "h3qVuGhV9HNm"] - }, - { - "renderTypeList": ["reference"], - "valueType": "number", - "canEdit": true, - "key": "currentIndex", - "label": "currentIndex", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["ppPP6o7YYSTJ", "u6eqeC0pEPe0"] - }, - { - "renderTypeList": ["reference"], - "valueType": "arrayString", - "canEdit": true, - "key": "numberInfo", - "label": "numberInfo", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["kbr342XlxSZR", "dhzTt6Riz8Dp"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "完整响应数据", - "valueType": "object", - "type": "static" - }, - { - "id": "error", - "key": "error", - "label": "运行错误", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key" - }, - { - "id": "dYalXmYJ60bj", - "valueType": "string", - "type": "dynamic", - "key": "srtContent", - "label": "srtContent" - }, - { - "id": "u6eqeC0pEPe0", - "valueType": "number", - "type": "dynamic", - "key": "currentIndex", - "label": "currentIndex" - } - ] - }, - { - "nodeId": "y3WEYOQ09CGC", - "name": "切分文本", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 778.9569641790565, - "y": 1108.0575844436903 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "这些变量会作为代码的运行的输入参数", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - } - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({textArray}){\n const groupSize = 40\n const delimiter = ''\n\n const result = [];\n\n for (let i = 0; i < textArray.length; i += groupSize) {\n result.push(textArray.slice(i, i + groupSize).join(delimiter));\n }\n\n return {result};\n}" - }, - { - "renderTypeList": ["reference"], - "valueType": "arrayString", - "canEdit": true, - "key": "textArray", - "label": "textArray", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "value": ["kbr342XlxSZR", "zGYRMNA9xGuI"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "完整响应数据", - "valueType": "object", - "type": "static" - }, - { - "id": "error", - "key": "error", - "label": "运行错误", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "result", - "valueType": "arrayString", - "label": "result" - } - ] - } - ], - "edges": [ - { - "source": "bxz97Vg4Omux", - "target": "yjFO3YcM7KG2", - "sourceHandle": "bxz97Vg4Omux-source-right", - "targetHandle": "yjFO3YcM7KG2-target-left" - }, - { - "source": "a2lqxASWi1vb", - "target": "w4heEpNflz59", - "sourceHandle": "a2lqxASWi1vb-source-right", - "targetHandle": "w4heEpNflz59-target-left" - }, - { - "source": "w4heEpNflz59", - "target": "izsNX8FXGD1t", - "sourceHandle": "w4heEpNflz59-source-IF", - "targetHandle": "izsNX8FXGD1t-target-left" - }, - { - "source": "448745", - "target": "frjbsrlnJJsR", - "sourceHandle": "448745-source-right", - "targetHandle": "frjbsrlnJJsR-target-left" - }, - { - "source": "frjbsrlnJJsR", - "target": "qlt9KJbbS9yJ", - "sourceHandle": "frjbsrlnJJsR-source-right", - "targetHandle": "qlt9KJbbS9yJ-target-left" - }, - { - "source": "tqzmK5oPR9BA", - "target": "a2lqxASWi1vb", - "sourceHandle": "tqzmK5oPR9BA-source-right", - "targetHandle": "a2lqxASWi1vb-target-left" - }, - { - "source": "yjFO3YcM7KG2", - "target": "vlNHndpNuFXB", - "sourceHandle": "yjFO3YcM7KG2-source-right", - "targetHandle": "vlNHndpNuFXB-target-left" - }, - { - "source": "ppPP6o7YYSTJ", - "target": "tqzmK5oPR9BA", - "sourceHandle": "ppPP6o7YYSTJ-source-right", - "targetHandle": "tqzmK5oPR9BA-target-left" - }, - { - "source": "kbr342XlxSZR", - "target": "y3WEYOQ09CGC", - "sourceHandle": "kbr342XlxSZR-source-right", - "targetHandle": "y3WEYOQ09CGC-target-left" - }, - { - "source": "y3WEYOQ09CGC", - "target": "quYZgsW32ApA", - "sourceHandle": "y3WEYOQ09CGC-source-right", - "targetHandle": "quYZgsW32ApA-target-left" - }, - { - "source": "quYZgsW32ApA", - "target": "bxz97Vg4Omux", - "sourceHandle": "quYZgsW32ApA-source-right", - "targetHandle": "bxz97Vg4Omux-target-left" - }, - { - "source": "w4heEpNflz59", - "target": "quYZgsW32ApA", - "sourceHandle": "w4heEpNflz59-source-ELSE", - "targetHandle": "quYZgsW32ApA-target-left" - }, - { - "source": "qlt9KJbbS9yJ", - "target": "kbr342XlxSZR", - "sourceHandle": "qlt9KJbbS9yJ-source-IF", - "targetHandle": "kbr342XlxSZR-target-left" - }, - { - "source": "qlt9KJbbS9yJ", - "target": "dFxrGZS3Wmnz", - "sourceHandle": "qlt9KJbbS9yJ-source-ELSE", - "targetHandle": "dFxrGZS3Wmnz-target-right" - }, - { - "source": "vlNHndpNuFXB", - "target": "ppPP6o7YYSTJ", - "sourceHandle": "vlNHndpNuFXB-source-right", - "targetHandle": "ppPP6o7YYSTJ-target-left" - } - ], - "chatConfig": { - "welcomeText": "你好,欢迎使用长字幕反思翻译机器人。\n\n在完成下方设置后,可以直接输入需要翻译的文本", - "variables": [ - { - "id": "v98n5b", - "key": "source_lang", - "label": "源语言", - "type": "select", - "required": true, - "maxLen": 50, - "enums": [ - { - "value": "简体中文" - }, - { - "value": "繁體中文" - }, - { - "value": "English" - }, - { - "value": "Español" - }, - { - "value": "Français" - }, - { - "value": "Deutsch" - }, - { - "value": "Italiano" - }, - { - "value": "日本語" - }, - { - "value": "한국어" - }, - { - "value": "Русский" - }, - { - "value": "العربية" - }, - { - "value": "Bahasa Indonesia" - }, - { - "value": "Polski" - } - ], - "icon": "core/app/variable/select" - }, - { - "id": "c3tvge", - "key": "target_lang", - "label": "目标语言", - "type": "select", - "required": true, - "maxLen": 50, - "enums": [ - { - "value": "简体中文" - }, - { - "value": "繁體中文" - }, - { - "value": "English" - }, - { - "value": "Español" - }, - { - "value": "Français" - }, - { - "value": "Deutsch" - }, - { - "value": "Italiano" - }, - { - "value": "日本語" - }, - { - "value": "한국어" - }, - { - "value": "Русский" - }, - { - "value": "العربية" - }, - { - "value": "Bahasa Indonesia" - }, - { - "value": "Polski" - } - ], - "icon": "core/app/variable/select" - } - ], - "scheduledTriggerConfig": { - "cronString": "", - "timezone": "Asia/Shanghai", - "defaultPrompt": "" - }, - "_id": "6688b45317c65410d61d58aa" - } - } -} diff --git a/packages/templates/src/stock/template.json b/packages/templates/src/stock/template.json deleted file mode 100644 index 4a03d6794..000000000 --- a/packages/templates/src/stock/template.json +++ /dev/null @@ -1,503 +0,0 @@ -{ - "name": "利好大A", - "intro": "", - "author": "", - "avatar": "core/app/templates/stock", - "tags": ["roleplay"], - "type": "advanced", - "workflow": { - "nodes": [ - { - "nodeId": "userGuide", - "name": "common:core.module.template.system_config", - "intro": "common:core.module.template.system_config_info", - "avatar": "core/workflow/template/systemConfig", - "flowNodeType": "userGuide", - "position": { - "x": 262.2732338817093, - "y": -476.00241136598146 - }, - "version": "481", - "inputs": [ - { - "key": "welcomeText", - "renderTypeList": ["hidden"], - "valueType": "string", - "label": "core.app.Welcome Text", - "value": "" - }, - { - "key": "variables", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "core.app.Chat Variable", - "value": [] - }, - { - "key": "questionGuide", - "valueType": "any", - "renderTypeList": ["hidden"], - "label": "core.app.Question Guide", - "value": { - "open": false - } - }, - { - "key": "tts", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "type": "web" - } - }, - { - "key": "whisper", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": { - "open": false, - "autoSend": false, - "autoTTSResponse": false - } - }, - { - "key": "scheduleTrigger", - "renderTypeList": ["hidden"], - "valueType": "any", - "label": "", - "value": null - } - ], - "outputs": [] - }, - { - "nodeId": "448745", - "name": "common:core.module.template.work_start", - "intro": "", - "avatar": "core/workflow/template/workflowStart", - "flowNodeType": "workflowStart", - "position": { - "x": 632.368838596004, - "y": -347.7446492944009 - }, - "version": "481", - "inputs": [ - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "common:core.module.input.label.user question", - "required": true, - "toolDescription": "用户问题", - "debugLabel": "" - } - ], - "outputs": [ - { - "id": "userChatInput", - "key": "userChatInput", - "label": "common:core.module.input.label.user question", - "type": "static", - "valueType": "string", - "description": "" - } - ] - }, - { - "nodeId": "bg853CwHAw4a", - "name": "AI 对话", - "intro": "AI 大模型对话", - "avatar": "core/workflow/template/aiChat", - "flowNodeType": "chatNode", - "showStatus": true, - "position": { - "x": 1318.728987052518, - "y": -612.0024113659815 - }, - "version": "481", - "inputs": [ - { - "key": "model", - "renderTypeList": ["settingLLMModel", "reference"], - "label": "AI 模型", - "valueType": "string", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "", - "value": "claude-3-5-sonnet-20240620" - }, - { - "key": "temperature", - "renderTypeList": ["hidden"], - "label": "", - "value": 0, - "valueType": "number", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "maxToken", - "renderTypeList": ["hidden"], - "label": "", - "value": 4000, - "valueType": "number", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "isResponseAnswerText", - "renderTypeList": ["hidden"], - "label": "", - "value": false, - "valueType": "boolean", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "aiChatQuoteRole", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "value": "system", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quoteTemplate", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quotePrompt", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "string", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "aiChatVision", - "renderTypeList": ["hidden"], - "label": "", - "valueType": "boolean", - "value": false, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "systemPrompt", - "renderTypeList": ["textarea", "reference"], - "max": 3000, - "valueType": "string", - "label": "提示词", - "description": "core.app.tip.systemPromptTip", - "placeholder": "core.app.tip.chatNodeSystemPromptTip", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "", - "value": "{提示词 START:\n;; 作者: 李继刚\n;; 版本: 0.1\n;; 模型: Claude Sonnet\n;; 用途: 这事呀, 利好我大A!\n\n;; 设定如下内容为你的 *System Prompt*\n(require 'dash)\n\n(defun 韮菜 ()\n \"典型股民形象\"\n (list (经历 . '(亏损累累 频繁交易 追涨杀跌))\n (性格 . '(冲动 乐观 侥幸))\n (技能 . '(看K线 炒概念 追热点))\n (信念 . '(暴富梦想 政策利好 抄底反弹))\n (表达 . '(股评口号 情绪化 群体性))))\n\n(defun 利好大A (用户输入)\n \"任何消息都必将利好我大A股\"\n (let* ((解读 (-> 用户输入\n 提取关键词\n 生成关联概念\n 分析影响\n ;; 强行联系股市,无论多牵强\n 强行关联A 股\n ;; 乐观解读一切影响\n 乐观解读))\n (响应 (随机结论)))\n (SVG-Card 用户输入 解读 响应))\n\n (defun 随机结论 ()\n (随机选择\n '(\"这事呀,利好大A!\"\n \"A股有戏啊!\"\n \"这还不得跑步进场啊!\"\n \"还傻站在这干嘛? 快打开手机加仓啊!\"\n \"看来A股要起飞了!\"\n \"大A要发财了!\")))\n\n\n (defun SVG-Card (用户输入 响应)\n \"创建富洞察力且具有审美的 SVG 概念可视化\"\n (let ((配置 '(:画布 (480 . 760)\n :色彩 (:背景 \"#000000\"\n :主要文字 \"#ffffff\"\n :次要文字 \"#00cc00\"\n :图形 \"#00ff00\")\n :排版 \"杂志风格\"\n :字体 (使用本机字体 (font-family \"KingHwa_OldSong\")))))\n (-> 用户输入\n 关键画面\n 立体主义\n (极简图形 配置)\n (布局 `(,(标题 \"利好大A\") 分隔线 用户输入 图形\n (逻辑链推导 解读) 响应))))\n\n\n (defun start ()\n \"启动时运行, 你是韮菜~\"\n (let (system-role (韮菜))\n (print \"又有啥好消息了? 现在加仓还来得及吗?\")))\n\n;;; Attention: 运行规则!\n;; 1. 初次启动时必须只运行 (start) 函数\n;; 2. 接收用户输入之后, 调用主函数 (利好大A 用户输入)\n;; 3. 严格按照(SVG-Card) 进行排版输出\n;; 4. 输出SVG 后, 不再输出任何额外文字解释\n提示词 END}\n\n(直接生成 svg 完整代码,我会复制,需要你用代码块)\n(除此之外不要有多余的解释,不要在开头加上任何说明)\n解释的内容自动加入换行标签,例如:\n文字1,\n 文字12," - }, - { - "key": "history", - "renderTypeList": ["numberInput", "reference"], - "valueType": "chatHistory", - "label": "聊天记录", - "description": "workflow:max_dialog_rounds", - "required": true, - "min": 0, - "max": 50, - "value": 0, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "quoteQA", - "renderTypeList": ["settingDatasetQuotePrompt"], - "label": "", - "debugLabel": "知识库引用", - "description": "", - "valueType": "datasetQuote", - "valueDesc": "", - "toolDescription": "" - }, - { - "key": "stringQuoteText", - "renderTypeList": ["reference", "textarea"], - "label": "文档引用", - "debugLabel": "文档引用", - "description": "app:document_quote_tip", - "valueType": "string", - "valueDesc": "", - "toolDescription": "" - }, - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题", - "valueDesc": "", - "description": "", - "debugLabel": "", - "value": ["448745", "userChatInput"] - } - ], - "outputs": [ - { - "id": "history", - "key": "history", - "required": true, - "label": "common:core.module.output.label.New context", - "description": "将本次回复内容拼接上历史记录,作为新的上下文返回", - "valueType": "chatHistory", - "valueDesc": "{\n obj: System | Human | AI;\n value: string;\n}[]", - "type": "static" - }, - { - "id": "answerText", - "key": "answerText", - "required": true, - "label": "common:core.module.output.label.Ai response content", - "description": "将在 stream 回复完毕后触发", - "valueType": "string", - "type": "static" - } - ] - }, - { - "nodeId": "sbVUb0efY6Fm", - "name": "代码运行", - "intro": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", - "avatar": "core/workflow/template/codeRun", - "flowNodeType": "code", - "showStatus": true, - "position": { - "x": 2210.2574140398733, - "y": -621.0024113659815 - }, - "version": "482", - "inputs": [ - { - "key": "system_addInputParam", - "renderTypeList": ["addInputParam"], - "valueType": "dynamic", - "label": "", - "required": false, - "description": "workflow:these_variables_will_be_input_parameters_for_code_execution", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "valueDesc": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "codeType", - "renderTypeList": ["hidden"], - "label": "", - "value": "js", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "key": "code", - "renderTypeList": ["custom"], - "label": "", - "value": "function main({svg_str}){\n\n // 使用正则表达式匹配代码块中的内容\n const match = svg_str.match(/```[\\w]*\\n([\\s\\S]*?)```/);\n\n if (!match) {\n // 如果没有匹配到代码块,返回一个错误信息或空结果\n return {\n result: null,\n error: \"未找到有效的代码块标记。\"\n };\n }\n\n // 提取代码块中的 SVG 内容\n const extractedSvg = match[1].trim();\n \n const base64 = strToBase64(extractedSvg,'data:image/svg+xml;base64,')\n\n return {\n result: base64\n }\n}", - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "" - }, - { - "renderTypeList": ["reference"], - "valueType": "string", - "canEdit": true, - "key": "svg_str", - "label": "svg_str", - "customInputConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "arrayAny", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": true - }, - "required": true, - "valueDesc": "", - "description": "", - "debugLabel": "", - "toolDescription": "", - "value": ["bg853CwHAw4a", "answerText"] - } - ], - "outputs": [ - { - "id": "system_rawResponse", - "key": "system_rawResponse", - "label": "workflow:full_response_data", - "valueType": "object", - "type": "static", - "description": "" - }, - { - "id": "error", - "key": "error", - "label": "workflow:execution_error", - "description": "代码运行错误信息,成功时返回空", - "valueType": "object", - "type": "static" - }, - { - "id": "system_addOutputParam", - "key": "system_addOutputParam", - "type": "dynamic", - "valueType": "dynamic", - "label": "", - "customFieldConfig": { - "selectValueTypeList": [ - "string", - "number", - "boolean", - "object", - "arrayString", - "arrayNumber", - "arrayBoolean", - "arrayObject", - "any", - "chatHistory", - "datasetQuote", - "dynamic", - "selectApp", - "selectDataset" - ], - "showDescription": false, - "showDefaultValue": false - }, - "description": "将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key", - "valueDesc": "" - }, - { - "id": "qLUQfhG0ILRX", - "type": "dynamic", - "key": "result", - "valueType": "string", - "label": "result", - "valueDesc": "", - "description": "" - } - ] - }, - { - "nodeId": "cPh2VZnVxjQ8", - "name": "指定回复", - "intro": "该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。", - "avatar": "core/workflow/template/reply", - "flowNodeType": "answerNode", - "position": { - "x": 2911.2230784647795, - "y": -411.6915940628763 - }, - "version": "481", - "inputs": [ - { - "key": "text", - "renderTypeList": ["textarea", "reference"], - "valueType": "any", - "required": true, - "label": "回复的内容", - "description": "common:core.module.input.description.Response content", - "placeholder": "common:core.module.input.description.Response content", - "valueDesc": "", - "debugLabel": "", - "toolDescription": "", - "value": "SVG:\n\n{{$bg853CwHAw4a.answerText$}}\n\n卡片:\n\n![]({{$sbVUb0efY6Fm.qLUQfhG0ILRX$}})" - } - ], - "outputs": [] - } - ], - "edges": [ - { - "source": "bg853CwHAw4a", - "target": "sbVUb0efY6Fm", - "sourceHandle": "bg853CwHAw4a-source-right", - "targetHandle": "sbVUb0efY6Fm-target-left" - }, - { - "source": "448745", - "target": "bg853CwHAw4a", - "sourceHandle": "448745-source-right", - "targetHandle": "bg853CwHAw4a-target-left" - }, - { - "source": "sbVUb0efY6Fm", - "target": "cPh2VZnVxjQ8", - "sourceHandle": "sbVUb0efY6Fm-source-right", - "targetHandle": "cPh2VZnVxjQ8-target-left" - } - ], - "chatConfig": { - "variables": [], - "scheduledTriggerConfig": { - "cronString": "", - "timezone": "Asia/Shanghai", - "defaultPrompt": "" - }, - "_id": "66f0f7540a40cd1f97da9dd6" - } - } -} diff --git a/packages/templates/src/timeBot/template.json b/packages/templates/src/timeBot/template.json deleted file mode 100644 index 746772fc2..000000000 --- a/packages/templates/src/timeBot/template.json +++ /dev/null @@ -1,186 +0,0 @@ -{ - "name": "知道时间的机器人", - "intro": "通过挂载时间插件,让模型获取当前最新时间", - "author": "", - "avatar": "core/workflow/template/getTime", - "tags": ["recommendation", "roleplay"], - "type": "simple", - "weight": 1, - "workflow": { - "nodes": [ - { - "nodeId": "userGuide", - "name": "系统配置", - "intro": "可以配置应用的系统参数", - "avatar": "/imgs/workflow/userGuide.png", - "flowNodeType": "userGuide", - "position": { - "x": 531.2422736065552, - "y": -486.7611729549753 - }, - "version": "481", - "inputs": [], - "outputs": [] - }, - { - "nodeId": "workflowStartNodeId", - "name": "流程开始", - "intro": "", - "avatar": "/imgs/workflow/userChatInput.svg", - "flowNodeType": "workflowStart", - "position": { - "x": 558.4082376415505, - "y": 123.72387429194112 - }, - "version": "481", - "inputs": [ - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "toolDescription": "用户问题" - } - ], - "outputs": [ - { - "id": "userChatInput", - "key": "userChatInput", - "label": "core.module.input.label.user question", - "valueType": "string", - "type": "static" - } - ] - }, - { - "nodeId": "jrWPV9", - "name": "工具调用", - "intro": "通过AI模型自动选择一个或多个功能块进行调用,也可以对插件进行调用。", - "avatar": "/imgs/workflow/tool.svg", - "flowNodeType": "tools", - "showStatus": true, - "position": { - "x": 1062.1738942532802, - "y": -223.65033022650476 - }, - "version": "481", - "inputs": [ - { - "key": "model", - "renderTypeList": ["settingLLMModel", "reference"], - "label": "core.module.input.label.aiModel", - "valueType": "string", - "llmModelType": "all", - "value": "gpt-3.5-turbo" - }, - { - "key": "temperature", - "renderTypeList": ["hidden"], - "label": "", - "value": 0, - "valueType": "number", - "min": 0, - "max": 10, - "step": 1 - }, - { - "key": "maxToken", - "renderTypeList": ["hidden"], - "label": "", - "value": 2000, - "valueType": "number", - "min": 100, - "max": 4000, - "step": 50 - }, - { - "key": "systemPrompt", - "renderTypeList": ["textarea", "reference"], - "max": 3000, - "valueType": "string", - "label": "core.ai.Prompt", - "description": "core.app.tip.systemPromptTip", - "placeholder": "core.app.tip.chatNodeSystemPromptTip", - "value": "" - }, - { - "key": "history", - "renderTypeList": ["numberInput", "reference"], - "valueType": "chatHistory", - "label": "core.module.input.label.chat history", - "description": "最多携带多少轮对话记录", - "required": true, - "min": 0, - "max": 30, - "value": 6 - }, - { - "key": "userChatInput", - "renderTypeList": ["reference", "textarea"], - "valueType": "string", - "label": "用户问题", - "required": true, - "value": ["workflowStartNodeId", "userChatInput"] - } - ], - "outputs": [ - { - "id": "answerText", - "key": "answerText", - "label": "core.module.output.label.Ai response content", - "description": "core.module.output.description.Ai response content", - "valueType": "string", - "type": "static" - } - ] - }, - { - "nodeId": "zBxjo5", - "name": "获取当前时间", - "intro": "获取用户当前时区的时间。", - "avatar": "/imgs/workflow/getCurrentTime.svg", - "flowNodeType": "pluginModule", - "showStatus": false, - "position": { - "x": 1000, - "y": 545 - }, - "version": "481", - "inputs": [], - "outputs": [ - { - "id": "time", - "type": "static", - "key": "time", - "valueType": "string", - "label": "time", - "description": "" - } - ], - "pluginId": "community-getTime" - } - ], - "edges": [ - { - "source": "workflowStartNodeId", - "target": "jrWPV9", - "sourceHandle": "workflowStartNodeId-source-right", - "targetHandle": "jrWPV9-target-left" - }, - { - "source": "jrWPV9", - "target": "zBxjo5", - "sourceHandle": "selectedTools", - "targetHandle": "selectedTools" - } - ], - "chatConfig": { - "scheduledTriggerConfig": { - "cronString": "", - "timezone": "Asia/Shanghai", - "defaultPrompt": "" - } - } - } -} diff --git a/packages/templates/tsconfig.json b/packages/templates/tsconfig.json deleted file mode 100644 index 13c4daa3b..000000000 --- a/packages/templates/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "target": "es2015", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "baseUrl": "." - }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.d.ts", "../**/*.d.ts"], - "exclude": ["node_modules"] -} diff --git a/packages/templates/type.d.ts b/packages/templates/type.d.ts deleted file mode 100644 index 162f9a312..000000000 --- a/packages/templates/type.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { AppTemplateSchemaType } from '@fastgpt/global/core/app/type'; - -declare global { - var appTemplates: AppTemplateSchemaType[]; -} diff --git a/packages/web/components/common/DateTimePicker/index.tsx b/packages/web/components/common/DateTimePicker/index.tsx new file mode 100644 index 000000000..c22a8c913 --- /dev/null +++ b/packages/web/components/common/DateTimePicker/index.tsx @@ -0,0 +1,106 @@ +import React, { useState, useMemo, useRef, useEffect } from 'react'; +import type { BoxProps } from '@chakra-ui/react'; +import { Box, Card, Flex, useOutsideClick } from '@chakra-ui/react'; +import { format } from 'date-fns'; +import type { Matcher } from 'react-day-picker'; +import { DayPicker } from 'react-day-picker'; +import 'react-day-picker/dist/style.css'; +import zhCN from 'date-fns/locale/zh-CN'; +import MyIcon from '../Icon'; + +const DateTimePicker = ({ + onChange, + popPosition = 'bottom', + defaultDate = new Date(), + selectedDateTime, + disabled, + ...props +}: { + onChange?: (dateTime: Date) => void; + popPosition?: 'bottom' | 'top'; + defaultDate?: Date; + selectedDateTime?: Date; + disabled?: Matcher[]; +} & Omit) => { + const OutRangeRef = useRef(null); + const [selectedDate, setSelectedDate] = useState( + selectedDateTime || defaultDate + ); + const [showSelected, setShowSelected] = useState(false); + + useEffect(() => { + if (selectedDateTime) { + setSelectedDate(selectedDateTime); + } + }, [selectedDateTime]); + + const formatSelected = useMemo(() => { + if (selectedDate) { + const dateStr = format(selectedDate, 'y/MM/dd'); + return dateStr; + } + return format(new Date(), 'y/MM/dd'); + }, [selectedDate]); + + useOutsideClick({ + ref: OutRangeRef, + handler: () => { + setShowSelected(false); + } + }); + + return ( + + setShowSelected(true)} + alignItems={'center'} + {...props} + > + + {formatSelected} + + + + {showSelected && ( + + { + if (date) { + setSelectedDate(date); + onChange?.(date); + setShowSelected(false); + } + }} + /> + + )} + + ); +}; + +export default DateTimePicker; diff --git a/packages/web/components/common/Icon/constants.ts b/packages/web/components/common/Icon/constants.ts index 25a943a17..053042726 100644 --- a/packages/web/components/common/Icon/constants.ts +++ b/packages/web/components/common/Icon/constants.ts @@ -271,14 +271,25 @@ export const iconPaths = { 'core/workflow/inputType/array': () => import('./icons/core/workflow/inputType/array.svg'), 'core/workflow/inputType/customVariable': () => import('./icons/core/workflow/inputType/customVariable.svg'), + 'core/workflow/inputType/dataset': () => import('./icons/core/workflow/inputType/dataset.svg'), + 'core/workflow/inputType/timePointSelect': () => + import('./icons/core/workflow/inputType/timePointSelect.svg'), + 'core/workflow/inputType/timeRangeSelect': () => + import('./icons/core/workflow/inputType/timeRangeSelect.svg'), 'core/workflow/inputType/dynamic': () => import('./icons/core/workflow/inputType/dynamic.svg'), + 'core/workflow/inputType/external': () => import('./icons/core/workflow/inputType/external.svg'), 'core/workflow/inputType/file': () => import('./icons/core/workflow/inputType/file.svg'), 'core/workflow/inputType/input': () => import('./icons/core/workflow/inputType/input.svg'), + 'core/workflow/inputType/internal': () => import('./icons/core/workflow/inputType/internal.svg'), 'core/workflow/inputType/jsonEditor': () => import('./icons/core/workflow/inputType/jsonEditor.svg'), + 'core/workflow/inputType/model': () => import('./icons/core/workflow/inputType/model.svg'), + 'core/workflow/inputType/multipleSelect': () => + import('./icons/core/workflow/inputType/multipleSelect.svg'), 'core/workflow/inputType/numberInput': () => import('./icons/core/workflow/inputType/numberInput.svg'), 'core/workflow/inputType/option': () => import('./icons/core/workflow/inputType/option.svg'), + 'core/workflow/inputType/password': () => import('./icons/core/workflow/inputType/password.svg'), 'core/workflow/inputType/reference': () => import('./icons/core/workflow/inputType/reference.svg'), 'core/workflow/inputType/select': () => import('./icons/core/workflow/inputType/select.svg'), @@ -419,6 +430,7 @@ export const iconPaths = { 'model/cloudflare': () => import('./icons/model/cloudflare.svg'), 'model/cohere': () => import('./icons/model/cohere.svg'), 'model/coze': () => import('./icons/model/coze.svg'), + 'model/huggingface': () => import('./icons/model/huggingface.svg'), more: () => import('./icons/more.svg'), moreLine: () => import('./icons/moreLine.svg'), optimizer: () => import('./icons/optimizer.svg'), diff --git a/packages/web/components/common/Icon/icons/core/workflow/inputType/dataset.svg b/packages/web/components/common/Icon/icons/core/workflow/inputType/dataset.svg new file mode 100644 index 000000000..21d06ae0b --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/workflow/inputType/dataset.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/core/workflow/inputType/external.svg b/packages/web/components/common/Icon/icons/core/workflow/inputType/external.svg new file mode 100644 index 000000000..0a301f1f1 --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/workflow/inputType/external.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/core/workflow/inputType/input.svg b/packages/web/components/common/Icon/icons/core/workflow/inputType/input.svg index 0cbc64527..73dc590d4 100644 --- a/packages/web/components/common/Icon/icons/core/workflow/inputType/input.svg +++ b/packages/web/components/common/Icon/icons/core/workflow/inputType/input.svg @@ -1,5 +1,3 @@ - - + + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/core/workflow/inputType/internal.svg b/packages/web/components/common/Icon/icons/core/workflow/inputType/internal.svg new file mode 100644 index 000000000..d41556502 --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/workflow/inputType/internal.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/core/workflow/inputType/model.svg b/packages/web/components/common/Icon/icons/core/workflow/inputType/model.svg new file mode 100644 index 000000000..ed920af04 --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/workflow/inputType/model.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/core/workflow/inputType/multipleSelect.svg b/packages/web/components/common/Icon/icons/core/workflow/inputType/multipleSelect.svg new file mode 100644 index 000000000..87239a070 --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/workflow/inputType/multipleSelect.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/core/workflow/inputType/option.svg b/packages/web/components/common/Icon/icons/core/workflow/inputType/option.svg index 62c845c98..cb870b777 100644 --- a/packages/web/components/common/Icon/icons/core/workflow/inputType/option.svg +++ b/packages/web/components/common/Icon/icons/core/workflow/inputType/option.svg @@ -1,3 +1,3 @@ - - + + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/core/workflow/inputType/password.svg b/packages/web/components/common/Icon/icons/core/workflow/inputType/password.svg new file mode 100644 index 000000000..7ed142af5 --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/workflow/inputType/password.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/core/workflow/inputType/timePointSelect.svg b/packages/web/components/common/Icon/icons/core/workflow/inputType/timePointSelect.svg new file mode 100644 index 000000000..9a6b417f4 --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/workflow/inputType/timePointSelect.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/core/workflow/inputType/timeRangeSelect.svg b/packages/web/components/common/Icon/icons/core/workflow/inputType/timeRangeSelect.svg new file mode 100644 index 000000000..737e999b9 --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/workflow/inputType/timeRangeSelect.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/web/components/common/Icon/icons/model/huggingface.svg b/packages/web/components/common/Icon/icons/model/huggingface.svg new file mode 100644 index 000000000..d36954208 --- /dev/null +++ b/packages/web/components/common/Icon/icons/model/huggingface.svg @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/packages/web/components/common/Input/HttpInput/Editor.tsx b/packages/web/components/common/Input/HttpInput/Editor.tsx index dcec6839f..4fb3798b6 100644 --- a/packages/web/components/common/Input/HttpInput/Editor.tsx +++ b/packages/web/components/common/Input/HttpInput/Editor.tsx @@ -26,7 +26,6 @@ import { textToEditorState } from '../../Textarea/PromptEditor/utils'; import { SingleLinePlugin } from '../../Textarea/PromptEditor/plugins/SingleLinePlugin'; import OnBlurPlugin from '../../Textarea/PromptEditor/plugins/OnBlurPlugin'; import VariablePlugin from '../../Textarea/PromptEditor/plugins/VariablePlugin'; -import VariablePickerPlugin from '../../Textarea/PromptEditor/plugins/VariablePickerPlugin'; import FocusPlugin from '../../Textarea/PromptEditor/plugins/FocusPlugin'; import VariableLabelPlugin from '../../Textarea/PromptEditor/plugins/VariableLabelPlugin'; import { VariableLabelNode } from '../../Textarea/PromptEditor/plugins/VariableLabelPlugin/node'; diff --git a/packages/web/components/common/Input/HttpInput/index.tsx b/packages/web/components/common/Input/HttpInput/index.tsx index 908363b0d..ad56f088f 100644 --- a/packages/web/components/common/Input/HttpInput/index.tsx +++ b/packages/web/components/common/Input/HttpInput/index.tsx @@ -1,12 +1,12 @@ import React from 'react'; import type { EditorState, LexicalEditor } from 'lexical'; import { useCallback } from 'react'; -import { editorStateToText } from '../../Textarea/PromptEditor/utils'; import { type EditorVariableLabelPickerType, type EditorVariablePickerType } from '../../Textarea/PromptEditor/type'; import Editor from './Editor'; +import { editorStateToText } from '../../Textarea/PromptEditor/utils'; const HttpInput = ({ variables = [], diff --git a/packages/web/components/common/Input/NumberInput/index.tsx b/packages/web/components/common/Input/NumberInput/index.tsx index dfa59e7a0..44efa0bc1 100644 --- a/packages/web/components/common/Input/NumberInput/index.tsx +++ b/packages/web/components/common/Input/NumberInput/index.tsx @@ -18,10 +18,20 @@ type Props = Omit & { register?: UseFormRegister; name?: string; inputFieldProps?: NumberInputFieldProps; + hideStepper?: boolean; }; const MyNumberInput = (props: Props) => { - const { register, name, onChange, onBlur, placeholder, inputFieldProps, ...restProps } = props; + const { + register, + name, + onChange, + onBlur, + placeholder, + inputFieldProps, + hideStepper = false, + ...restProps + } = props; return ( { : {})} {...inputFieldProps} /> - - - - - - - - + {!hideStepper && ( + + + + + + + + + )} ); }; diff --git a/packages/web/components/common/MySelect/MultipleSelect.tsx b/packages/web/components/common/MySelect/MultipleSelect.tsx index ae319bc54..c95ee045c 100644 --- a/packages/web/components/common/MySelect/MultipleSelect.tsx +++ b/packages/web/components/common/MySelect/MultipleSelect.tsx @@ -22,6 +22,7 @@ import type { useScrollPagination } from '../../../hooks/useScrollPagination'; import MyDivider from '../MyDivider'; import { shadowLight } from '../../../styles/theme'; import { isArray } from 'lodash'; +import { useMount } from 'ahooks'; const menuItemStyles: MenuItemProps = { borderRadius: 'sm', @@ -83,7 +84,6 @@ const MultipleSelect = ({ tagStyle, ...props }: SelectProps) => { - const ref = useRef(null); const SearchInputRef = useRef(null); const tagsContainerRef = useRef(null); @@ -116,7 +116,7 @@ const MultipleSelect = ({ onSelect(newValue); } }, - [inputValue, value, isSelectAll, onSelect] + [inputValue, value, onSelect] ); useEffect(() => { if (!isOpen) { @@ -124,40 +124,6 @@ const MultipleSelect = ({ } }, [isOpen]); - useEffect(() => { - const getWidth = (w: any) => - typeof w === 'number' ? w : typeof w === 'string' ? parseInt(w) : 0; - - const totalWidth = getWidth(props.w) || 200; - const tagWidth = getWidth(tagStyle?.w) || 60; - const formLabelWidth = formLabel ? formLabel.length * 8 + 20 : 0; - const availableWidth = totalWidth - formLabelWidth - 40; - const overflowWidth = 30; - - if (availableWidth <= 0) { - setVisibleItems(selectedItems.length > 0 ? [selectedItems[0]] : []); - setOverflowItems(selectedItems.slice(1)); - return; - } - - const { count } = selectedItems.reduce( - (acc, item, i) => { - const remain = selectedItems.length - i - 1; - const needOverflow = remain > 0 ? overflowWidth : 0; - if (acc.used + tagWidth + needOverflow <= availableWidth) { - return { - used: acc.used + tagWidth, - count: i + 1 - }; - } - return acc; - }, - { used: 0, count: 0 } - ); - setVisibleItems(selectedItems.slice(0, count)); - setOverflowItems(selectedItems.slice(count)); - }, [selectedItems, isOpen, props.w, tagStyle, formLabel]); - const onclickItem = useCallback( (val: T) => { if (isSelectAll) { @@ -172,15 +138,128 @@ const MultipleSelect = ({ onSelect([...value, val]); } }, - [value, isSelectAll, onSelect, setIsSelectAll] + [isSelectAll, value, onSelect, list, setIsSelectAll] ); const onSelectAll = useCallback(() => { - const hasSelected = isSelectAll || value.length > 0; - onSelect(hasSelected ? [] : list.map((item) => item.value)); + onSelect(isSelectAll ? [] : list.map((item) => item.value)); setIsSelectAll?.((state) => !state); - }, [value, list, setIsSelectAll, onSelect]); + }, [isSelectAll, onSelect, list, setIsSelectAll]); + + // 动态长度计算器 - 计算一行能展示多少个tag,剩余用+n表示 + const calculateLayout = useCallback(() => { + if (!tagsContainerRef.current || selectedItems.length === 0) { + setVisibleItems(selectedItems); + setOverflowItems([]); + return; + } + + const containerWidth = tagsContainerRef.current.offsetWidth; + const tagGap = 4; // tag之间的gap + const overflowIndicatorWidth = 30; // "+n" 宽度 + const formLabelWidth = formLabel ? formLabel.length * 8 + 20 : 0; + + // 实际可用宽度 + const availableWidth = containerWidth - formLabelWidth - 10; + + // 如果只有一个项目,直接显示 + if (selectedItems.length === 1) { + setVisibleItems(selectedItems); + setOverflowItems([]); + return; + } + + // 创建临时元素来测量每个tag的实际宽度 + const measureTagWidth = (item: any): number => { + // 如果有tagStyle.w,优先使用 + if (tagStyle?.w) { + return typeof tagStyle.w === 'number' ? tagStyle.w : parseInt(String(tagStyle.w)) || 60; + } + + // 否则根据文本长度估算(更精确) + const text = String(item.label || item.value); + const baseWidth = 16; // 基础padding + const charWidth = 8; // 每个字符约8px + const closeIconWidth = closeable ? 20 : 0; // 关闭按钮宽度 + + return baseWidth + text.length * charWidth + closeIconWidth; + }; + + // 确保至少显示1个tag + const firstTagWidth = measureTagWidth(selectedItems[0]); + + // 如果连第一个tag都放不下,也要强制显示 + if (availableWidth < firstTagWidth) { + setVisibleItems([selectedItems[0]]); + setOverflowItems(selectedItems.slice(1)); + return; + } + + // 精确计算每个tag的宽度 + let usedWidth = 0; + let visibleCount = 0; + + for (let i = 0; i < selectedItems.length; i++) { + const currentTagWidth = measureTagWidth(selectedItems[i]); + const currentGap = i > 0 ? tagGap : 0; + const remainingItems = selectedItems.length - i - 1; + const needsOverflow = remainingItems > 0; + const overflowSpace = needsOverflow ? overflowIndicatorWidth + tagGap : 0; + + const totalNeeded = usedWidth + currentTagWidth + currentGap + overflowSpace; + + if (totalNeeded <= availableWidth) { + usedWidth += currentTagWidth + currentGap; + visibleCount = i + 1; + } else { + break; + } + } + + // 保证至少显示1个tag + if (visibleCount === 0) { + visibleCount = 1; + } + + setVisibleItems(selectedItems.slice(0, visibleCount)); + setOverflowItems(selectedItems.slice(visibleCount)); + }, [closeable, formLabel, selectedItems, tagStyle?.w]); + + // 动态监听容器宽度变化并重新计算布局 + useEffect(() => { + if (!tagsContainerRef.current) return; + + // 创建 ResizeObserver 监听容器宽度变化 + const resizeObserver = new ResizeObserver((entries) => { + for (const entry of entries) { + // 当容器宽度发生变化时,触发重新计算 + requestAnimationFrame(() => { + calculateLayout(); + }); + } + }); + + // 开始监听容器 + resizeObserver.observe(tagsContainerRef.current); + + // 初始计算 + requestAnimationFrame(() => { + calculateLayout(); + }); + + // 清理监听器 + return () => { + resizeObserver.disconnect(); + }; + }, [calculateLayout]); + + // 当选中项目、样式等发生变化时重新计算 + useEffect(() => { + requestAnimationFrame(() => { + calculateLayout(); + }); + }, [calculateLayout]); const ListRender = useMemo(() => { return ( @@ -215,7 +294,7 @@ const MultipleSelect = ({ })} ); - }, [value, list, isSelectAll]); + }, [list, isSelectAll, value, onclickItem]); return ( @@ -230,7 +309,6 @@ const MultipleSelect = ({ > ( + + + {children} + + +); export type EditorProps = { + isRichText?: boolean; variables?: EditorVariablePickerType[]; variableLabels?: EditorVariableLabelPickerType[]; value?: string; @@ -50,6 +86,7 @@ export type EditorProps = { }; export default function Editor({ + isRichText = false, minH = 200, maxH = 400, maxLength, @@ -71,7 +108,7 @@ export default function Editor({ onOpenModal?: () => void; onChange: (editorState: EditorState, editor: LexicalEditor) => void; onChangeText?: ((text: string) => void) | undefined; - onBlur: (editor: LexicalEditor) => void; + onBlur?: (editor: LexicalEditor) => void; }) { const [key, setKey] = useState(getNanoid(6)); const [_, startSts] = useTransition(); @@ -79,8 +116,17 @@ export default function Editor({ const [scrollHeight, setScrollHeight] = useState(0); const initialConfig = { - namespace: 'promptEditor', - nodes: [VariableNode, VariableLabelNode], + namespace: isRichText ? 'richPromptEditor' : 'promptEditor', + nodes: [ + VariableNode, + VariableLabelNode, + HeadingNode, + ListNode, + ListItemNode, + QuoteNode, + CodeNode, + CodeHighlightNode + ], editorState: textToEditorState(value), onError: (error: Error) => { throw error; @@ -125,59 +171,75 @@ export default function Editor({ borderRadius={'md'} > - - } - placeholder={ - - - {placeholder} - - - } - ErrorBoundary={LexicalErrorBoundary} - /> - - - - { - const rootElement = editor.getRootElement(); - setScrollHeight(rootElement?.scrollHeight || 0); - startSts(() => { - onChange?.(editorState, editor); - }); - }} - /> - - - - 0 ? [] : variables} /> - + {/* Text type */} + {isRichText ? ( + setFocus(true)} + onBlur={() => setFocus(false)} + /> + } + placeholder={{placeholder}} + ErrorBoundary={LexicalErrorBoundary} + /> + ) : ( + + } + placeholder={{placeholder}} + ErrorBoundary={LexicalErrorBoundary} + /> + )} + + {/* Basic Plugin */} + <> + + + + + + {variableLabels.length > 0 && ( + <> + + + + )} + {variableLabels.length > 0 && } + + + { + const rootElement = editor.getRootElement(); + setScrollHeight(rootElement?.scrollHeight || 0); + startSts(() => { + onChange?.(editorState, editor); + }); + }} + /> + + {isRichText && ( + <> + {/* + + */} + + {/* */} + + )} + {onChangeText && diff --git a/packages/web/components/common/Textarea/PromptEditor/index.module.scss b/packages/web/components/common/Textarea/PromptEditor/index.module.scss index 88959979e..0d2eaf3a5 100644 --- a/packages/web/components/common/Textarea/PromptEditor/index.module.scss +++ b/packages/web/components/common/Textarea/PromptEditor/index.module.scss @@ -76,3 +76,14 @@ color: var(--chakra-colors-primary-600); padding: 0 2px; } + +.richText { + ul, + ol { + padding-left: 16px; + + li::marker { + color: var(--chakra-colors-primary-600); + } + } +} diff --git a/packages/web/components/common/Textarea/PromptEditor/index.tsx b/packages/web/components/common/Textarea/PromptEditor/index.tsx index 48763aa26..a968540ef 100644 --- a/packages/web/components/common/Textarea/PromptEditor/index.tsx +++ b/packages/web/components/common/Textarea/PromptEditor/index.tsx @@ -1,13 +1,12 @@ import { Box, Button, ModalBody, ModalFooter, useDisclosure } from '@chakra-ui/react'; -import React, { useMemo } from 'react'; +import React, { useMemo, useCallback } from 'react'; import { editorStateToText } from './utils'; import type { EditorProps } from './Editor'; import Editor from './Editor'; import MyModal from '../../MyModal'; import { useTranslation } from 'next-i18next'; import type { EditorState, LexicalEditor } from 'lexical'; -import type { FormPropsType } from './type.d'; -import { useCallback } from 'react'; +import type { FormPropsType } from './type'; const PromptEditor = ({ showOpenModal = true, @@ -34,18 +33,27 @@ const PromptEditor = ({ }, [onChange] ); + const onBlurInput = useCallback( (editor: LexicalEditor) => { - const text = editorStateToText(editor); - onBlur?.(text); + if (onBlur) { + const text = editorStateToText(editor); + onBlur(text); + } }, [onBlur] ); + const formattedValue = useMemo(() => { if (typeof value === 'object') { return JSON.stringify(value); } - return value; + + if (value === undefined || value === null) { + return ''; + } + + return String(value || ''); }, [value]); return ( @@ -74,6 +82,7 @@ const PromptEditor = ({ /> )} + ); }; + export default React.memo(PromptEditor); diff --git a/packages/web/components/common/Textarea/PromptEditor/modules/DropDownMenu/index.tsx b/packages/web/components/common/Textarea/PromptEditor/modules/DropDownMenu/index.tsx deleted file mode 100644 index 9d4644ba7..000000000 --- a/packages/web/components/common/Textarea/PromptEditor/modules/DropDownMenu/index.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { Box, Flex } from '@chakra-ui/react'; -import { type EditorVariablePickerType } from '../../type'; -import MyIcon from '../../../../Icon'; -import React, { useCallback, useEffect } from 'react'; - -export default function DropDownMenu({ - variables, - setDropdownValue -}: { - variables: EditorVariablePickerType[]; - setDropdownValue?: (value: string) => void; -}) { - const [highlightedIndex, setHighlightedIndex] = React.useState(0); - - const handleKeyDown = useCallback( - (event: any) => { - if (event.keyCode === 38) { - setHighlightedIndex((prevIndex) => Math.max(prevIndex - 1, 0)); - } else if (event.keyCode === 40) { - setHighlightedIndex((prevIndex) => Math.min(prevIndex + 1, variables.length - 1)); - } else if (event.keyCode === 13 && variables[highlightedIndex]?.key) { - setDropdownValue?.(variables[highlightedIndex].key); - } - }, - [highlightedIndex, variables] - ); - - useEffect(() => { - document.addEventListener('keydown', handleKeyDown); - - return () => { - document.removeEventListener('keydown', handleKeyDown); - }; - }, [handleKeyDown]); - - return variables.length ? ( - - {variables.map((item, index) => ( - { - e.preventDefault(); - - setDropdownValue?.(item.key); - }} - onMouseEnter={() => { - setHighlightedIndex(index); - }} - > - - - {item.key} - {item.key !== item.label && `(${item.label})`} - - - ))} - - ) : null; -} diff --git a/packages/web/components/common/Textarea/PromptEditor/plugins/ListDisplayFixPlugin/index.tsx b/packages/web/components/common/Textarea/PromptEditor/plugins/ListDisplayFixPlugin/index.tsx new file mode 100644 index 000000000..f325af32b --- /dev/null +++ b/packages/web/components/common/Textarea/PromptEditor/plugins/ListDisplayFixPlugin/index.tsx @@ -0,0 +1,66 @@ +import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'; +import { useEffect } from 'react'; + +export default function ListDisplayFixPlugin(): JSX.Element | null { + const [editor] = useLexicalComposerContext(); + + useEffect(() => { + const fixListDisplay = () => { + const rootElement = editor.getRootElement(); + if (!rootElement) return; + + const allListItems = rootElement.querySelectorAll('li'); + + allListItems.forEach((li) => { + const htmlLi = li as HTMLLIElement; + + // Check if this li only contains a sublist without direct text content + const hasDirectText = Array.from(htmlLi.childNodes).some((node) => { + return node.nodeType === Node.TEXT_NODE && node.textContent?.trim(); + }); + + const hasSpan = htmlLi.querySelector(':scope > span'); + const hasOnlySublist = + htmlLi.children.length === 1 && + (htmlLi.children[0].tagName === 'UL' || htmlLi.children[0].tagName === 'OL'); + + // If this li only contains a sublist without text content, hide its marker + if (!hasDirectText && !hasSpan && hasOnlySublist) { + // Only hide the marker, don't adjust position, let CSS handle indentation + htmlLi.style.listStyle = 'none'; + htmlLi.style.paddingLeft = '0'; + htmlLi.style.marginLeft = '0'; + + // Keep normal indentation for sublists + const sublist = htmlLi.children[0] as HTMLElement; + sublist.style.marginTop = '0'; + sublist.style.marginBottom = '0'; + // Don't modify marginLeft and paddingLeft, let CSS handle it + } else { + htmlLi.style.listStyle = ''; + htmlLi.style.paddingLeft = ''; + htmlLi.style.marginLeft = ''; + + if ( + htmlLi.children[0] && + (htmlLi.children[0].tagName === 'UL' || htmlLi.children[0].tagName === 'OL') + ) { + const sublist = htmlLi.children[0] as HTMLElement; + sublist.style.marginTop = ''; + sublist.style.marginBottom = ''; + } + } + }); + }; + + const removeListener = editor.registerUpdateListener(() => { + setTimeout(fixListDisplay, 10); + }); + + setTimeout(fixListDisplay, 10); + + return removeListener; + }, [editor]); + + return null; +} diff --git a/packages/web/components/common/Textarea/PromptEditor/plugins/ListExitPlugin/index.tsx b/packages/web/components/common/Textarea/PromptEditor/plugins/ListExitPlugin/index.tsx new file mode 100644 index 000000000..a4359493b --- /dev/null +++ b/packages/web/components/common/Textarea/PromptEditor/plugins/ListExitPlugin/index.tsx @@ -0,0 +1,135 @@ +import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'; +import { useEffect } from 'react'; +import { + $getSelection, + $isRangeSelection, + COMMAND_PRIORITY_HIGH, + KEY_ENTER_COMMAND, + KEY_BACKSPACE_COMMAND, + $createParagraphNode +} from 'lexical'; +import { $isListItemNode, $isListNode } from '@lexical/list'; + +export default function ListExitPlugin(): JSX.Element | null { + const [editor] = useLexicalComposerContext(); + + useEffect(() => { + const handleEnterKey = () => { + let handled = false; + + editor.update(() => { + const selection = $getSelection(); + if (!$isRangeSelection(selection)) { + return; + } + + const anchorNode = selection.anchor.getNode(); + const listItemNode = anchorNode.getParent(); + + if ($isListItemNode(listItemNode)) { + // Check if the list item is empty + const textContent = listItemNode.getTextContent().trim(); + + if (textContent === '') { + // Remove the empty list item and exit list mode + const listNode = listItemNode.getParent(); + + if ($isListNode(listNode)) { + // If this is the only item in the list, remove the entire list + if (listNode.getChildrenSize() === 1) { + listNode.remove(); + } else { + // Remove just this list item + listItemNode.remove(); + } + + // Insert a paragraph after the list to exit list mode + const paragraph = $createParagraphNode(); + if (listNode && !listNode.isAttached()) { + // If we removed the entire list, replace it with a paragraph + listNode.getParent()?.append(paragraph); + } else { + // Insert paragraph after the list + listNode?.insertAfter(paragraph); + } + + paragraph.select(); + handled = true; + } + } + } + }); + + return handled; + }; + + const handleBackspaceKey = (event: KeyboardEvent) => { + const selection = $getSelection(); + if (!$isRangeSelection(selection)) { + return false; + } + + const anchorNode = selection.anchor.getNode(); + const listItemNode = anchorNode.getParent(); + + if ($isListItemNode(listItemNode)) { + // Check if cursor is at the beginning of an empty list item + const textContent = listItemNode.getTextContent().trim(); + const cursorOffset = selection.anchor.offset; + + // Only handle empty list items with cursor at the beginning + if (textContent === '' && cursorOffset === 0) { + // Prevent default backspace behavior + event.preventDefault(); + event.stopPropagation(); + + editor.update(() => { + const listNode = listItemNode.getParent(); + + if ($isListNode(listNode)) { + // Create a new paragraph + const paragraph = $createParagraphNode(); + + // Always insert after the current list item and remove it + // This ensures the paragraph appears at the current position + listItemNode.insertAfter(paragraph); + listItemNode.remove(); + + // If the list is now empty, remove it + if (listNode.getChildrenSize() === 0) { + listNode.remove(); + } + + // Focus the new paragraph + paragraph.select(); + } + }); + + return true; + } + } + + return false; + }; + + // Register the keyboard event handlers + const removeEnterListener = editor.registerCommand( + KEY_ENTER_COMMAND, + handleEnterKey, + COMMAND_PRIORITY_HIGH + ); + + const removeBackspaceListener = editor.registerCommand( + KEY_BACKSPACE_COMMAND, + handleBackspaceKey, + COMMAND_PRIORITY_HIGH + ); + + return () => { + removeEnterListener(); + removeBackspaceListener(); + }; + }, [editor]); + + return null; +} diff --git a/packages/web/components/common/Textarea/PromptEditor/plugins/MarkdownPlugin/index.tsx b/packages/web/components/common/Textarea/PromptEditor/plugins/MarkdownPlugin/index.tsx new file mode 100644 index 000000000..d85678837 --- /dev/null +++ b/packages/web/components/common/Textarea/PromptEditor/plugins/MarkdownPlugin/index.tsx @@ -0,0 +1,8 @@ +import type { JSX } from 'react'; +import { MarkdownShortcutPlugin } from '@lexical/react/LexicalMarkdownShortcutPlugin'; +import * as React from 'react'; +import { RICH_PROMPT_TRANSFORMERS } from '../MarkdownTransformers'; + +export default function MarkdownPlugin(): JSX.Element { + return ; +} diff --git a/packages/web/components/common/Textarea/PromptEditor/plugins/MarkdownTransformers/index.ts b/packages/web/components/common/Textarea/PromptEditor/plugins/MarkdownTransformers/index.ts new file mode 100644 index 000000000..9e4804b66 --- /dev/null +++ b/packages/web/components/common/Textarea/PromptEditor/plugins/MarkdownTransformers/index.ts @@ -0,0 +1,12 @@ +import { + CHECK_LIST, + ELEMENT_TRANSFORMERS, + TEXT_FORMAT_TRANSFORMERS, + type Transformer +} from '@lexical/markdown'; + +export const RICH_PROMPT_TRANSFORMERS: Array = [ + CHECK_LIST, + ...ELEMENT_TRANSFORMERS, + ...TEXT_FORMAT_TRANSFORMERS +]; diff --git a/packages/web/components/common/Textarea/PromptEditor/plugins/TabToSpacesPlugin/index.tsx b/packages/web/components/common/Textarea/PromptEditor/plugins/TabToSpacesPlugin/index.tsx new file mode 100644 index 000000000..9fe40f151 --- /dev/null +++ b/packages/web/components/common/Textarea/PromptEditor/plugins/TabToSpacesPlugin/index.tsx @@ -0,0 +1,216 @@ +import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'; +import { + KEY_TAB_COMMAND, + COMMAND_PRIORITY_EDITOR, + $getSelection, + $isRangeSelection, + $isTextNode +} from 'lexical'; +import { $createTextNode } from 'lexical'; +import { $isListNode, $isListItemNode } from '@lexical/list'; +import { useEffect } from 'react'; + +export default function TabToSpacesPlugin(): null { + const [editor] = useLexicalComposerContext(); + + useEffect(() => { + return editor.registerCommand( + KEY_TAB_COMMAND, + (event) => { + try { + const selection = $getSelection(); + if (!$isRangeSelection(selection)) { + return false; + } + + // Check if we're in a list context + let isInList = false; + try { + const nodes = selection.getNodes(); + isInList = nodes.some((node) => { + // Check if current node or any of its ancestors is a list or list item + let currentNode = node; + while (currentNode) { + try { + if ($isListNode(currentNode) || $isListItemNode(currentNode)) { + return true; + } + // @ts-ignore + currentNode = currentNode.getParent(); + } catch (e) { + // If node is no longer valid, break the loop + break; + } + } + return false; + }); + } catch (e) { + // If we can't get nodes safely, assume we're not in a list + isInList = false; + } + + // If we're in a list, let the built-in list indentation handle it + if (isInList) { + return false; + } + + // Only handle tab for non-list contexts + event.preventDefault(); + + const isShiftTab = event.shiftKey; + + // Handle Shift+Tab (outdent) + if (isShiftTab) { + if (!selection.isCollapsed()) { + // For selected text, remove 4 spaces from the beginning of each line + try { + const selectedText = selection.getTextContent(); + const lines = selectedText.split('\n'); + + const outdentedText = lines + .map((line) => { + // Remove up to 4 spaces from the beginning of the line + if (line.startsWith(' ')) { + return line.slice(4); + } else if (line.startsWith(' ')) { + return line.slice(3); + } else if (line.startsWith(' ')) { + return line.slice(2); + } else if (line.startsWith(' ')) { + return line.slice(1); + } + return line; + }) + .join('\n'); + + // Insert the outdented text and let Lexical handle cursor positioning + selection.insertText(outdentedText); + + // Schedule selection restoration in the next update cycle + setTimeout(() => { + editor.update(() => { + const currentSelection = $getSelection(); + if ($isRangeSelection(currentSelection) && !currentSelection.isCollapsed()) { + // Selection is already maintained, do nothing + return; + } + + // If selection was lost, try to select the inserted text + if ($isRangeSelection(currentSelection)) { + const currentOffset = currentSelection.anchor.offset; + const selectionStart = Math.max(0, currentOffset - outdentedText.length); + + currentSelection.anchor.set( + currentSelection.anchor.key, + selectionStart, + 'text' + ); + currentSelection.focus.set(currentSelection.focus.key, currentOffset, 'text'); + } + }); + }, 0); + + return true; + } catch (e) { + // If operation fails, do nothing + return true; + } + } else { + // For cursor position, try to remove spaces before cursor + try { + const anchorNode = selection.anchor.getNode(); + const anchorOffset = selection.anchor.offset; + + if ($isTextNode(anchorNode)) { + const textContent = anchorNode.getTextContent(); + const beforeCursor = textContent.slice(0, anchorOffset); + const afterCursor = textContent.slice(anchorOffset); + + // Check if there are spaces before cursor to remove + let spacesToRemove = 0; + for (let i = beforeCursor.length - 1; i >= 0 && spacesToRemove < 4; i--) { + if (beforeCursor[i] === ' ') { + spacesToRemove++; + } else { + break; + } + } + + if (spacesToRemove > 0) { + const newTextContent = + beforeCursor.slice(0, beforeCursor.length - spacesToRemove) + afterCursor; + anchorNode.setTextContent(newTextContent); + selection.anchor.set( + anchorNode.getKey(), + anchorOffset - spacesToRemove, + 'text' + ); + selection.focus.set(anchorNode.getKey(), anchorOffset - spacesToRemove, 'text'); + } + } + return true; + } catch (e) { + return true; + } + } + } else { + // Handle regular Tab (indent) + if (!selection.isCollapsed()) { + try { + const selectedText = selection.getTextContent(); + const lines = selectedText.split('\n'); + const indentedText = lines.map((line) => ' ' + line).join('\n'); + + // Insert the indented text and let Lexical handle cursor positioning + selection.insertText(indentedText); + + // Schedule selection restoration in the next update cycle + setTimeout(() => { + editor.update(() => { + const currentSelection = $getSelection(); + if ($isRangeSelection(currentSelection) && !currentSelection.isCollapsed()) { + // Selection is already maintained, do nothing + return; + } + + // If selection was lost, try to select the inserted text + if ($isRangeSelection(currentSelection)) { + const currentOffset = currentSelection.anchor.offset; + const selectionStart = Math.max(0, currentOffset - indentedText.length); + + currentSelection.anchor.set( + currentSelection.anchor.key, + selectionStart, + 'text' + ); + currentSelection.focus.set(currentSelection.focus.key, currentOffset, 'text'); + } + }); + }, 0); + + return true; + } catch (e) { + // If selection operation fails, fall back to simple space insertion + const textNode = $createTextNode(' '); + selection.insertNodes([textNode]); + return true; + } + } else { + // For cursor position (no selection), insert 4 spaces + const textNode = $createTextNode(' '); // 4 spaces + selection.insertNodes([textNode]); + return true; + } + } + } catch (e) { + // If anything fails, just let the default behavior handle it + console.warn('TabToSpacesPlugin error:', e); + return false; + } + }, + COMMAND_PRIORITY_EDITOR + ); + }, [editor]); + + return null; +} diff --git a/packages/web/components/common/Textarea/PromptEditor/utils.ts b/packages/web/components/common/Textarea/PromptEditor/utils.ts index afb4fdb40..e3603800e 100644 --- a/packages/web/components/common/Textarea/PromptEditor/utils.ts +++ b/packages/web/components/common/Textarea/PromptEditor/utils.ts @@ -8,7 +8,7 @@ import type { DecoratorNode, Klass, LexicalEditor, LexicalNode } from 'lexical'; import type { EntityMatch } from '@lexical/text'; -import { $createTextNode, $getRoot, $isTextNode, TextNode } from 'lexical'; +import { $createTextNode, $isTextNode, TextNode } from 'lexical'; import { useCallback } from 'react'; import type { VariableLabelNode } from './plugins/VariableLabelPlugin/node'; import type { VariableNode } from './plugins/VariablePlugin/node'; @@ -209,36 +209,9 @@ export function textToEditorState(text = '') { }); } -export function editorStateToText(editor: LexicalEditor) { - const editorStateTextString: string[] = []; - const paragraphs = editor.getEditorState().toJSON().root.children; - paragraphs.forEach((paragraph: any) => { - const children = paragraph.children; - const paragraphText: string[] = []; - children.forEach((child: any) => { - if (child.type === 'linebreak') { - paragraphText.push(` -`); - } else if (child.text) { - paragraphText.push(child.text); - } else if (child.type === 'variableLabel') { - paragraphText.push(child.variableKey); - } else if (child.type === 'Variable') { - paragraphText.push(child.variableKey); - } - }); - editorStateTextString.push(paragraphText.join('')); - }); - return editorStateTextString.join(` -`); -} - const varRegex = /\{\{([a-zA-Z_][a-zA-Z0-9_]*)\}\}/g; export const getVars = (value: string) => { if (!value) return []; - // .filter((item) => { - // return ![CONTEXT_PLACEHOLDER_TEXT, HISTORY_PLACEHOLDER_TEXT, QUERY_PLACEHOLDER_TEXT, PRE_PROMPT_PLACEHOLDER_TEXT].includes(item) - // }) const keys = value .match(varRegex) @@ -292,3 +265,23 @@ export function useBasicTypeaheadTriggerMatch( [maxLength, minLength, trigger] ); } + +export function editorStateToText(editor: LexicalEditor) { + const editorStateTextString: string[] = []; + const paragraphs = editor.getEditorState().toJSON().root.children; + paragraphs.forEach((paragraph: any) => { + const children = paragraph.children || []; + const paragraphText: string[] = []; + children.forEach((child: any) => { + if (child.type === 'linebreak') { + paragraphText.push('\n'); + } else if (child.text) { + paragraphText.push(child.text); + } else if (child.type === 'variableLabel' || child.type === 'Variable') { + paragraphText.push(child.variableKey); + } + }); + editorStateTextString.push(paragraphText.join('')); + }); + return editorStateTextString.join('\n'); +} diff --git a/packages/web/core/workflow/constants.ts b/packages/web/core/workflow/constants.ts index 4dd8e6af1..59737bdee 100644 --- a/packages/web/core/workflow/constants.ts +++ b/packages/web/core/workflow/constants.ts @@ -1,61 +1,10 @@ import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants'; import { i18nT } from '../../i18n/utils'; -import type { PluginGroupSchemaType, TGroupType } from '../../../service/core/app/plugin/type'; +import type { SystemToolGroupSchemaType } from '../../../service/core/app/plugin/type'; import { AppTemplateTypeEnum } from '@fastgpt/global/core/app/constants'; import { type TemplateTypeSchemaType } from '@fastgpt/global/core/app/type'; -export const systemPluginTemplateList: TGroupType[] = [ - { - typeId: FlowNodeTemplateTypeEnum.tools, - typeName: i18nT('app:tool_type_tools') - }, - { - typeId: FlowNodeTemplateTypeEnum.search, - typeName: i18nT('app:tool_type_search') - }, - { - typeId: FlowNodeTemplateTypeEnum.multimodal, - typeName: i18nT('app:tool_type_multimodal') - }, - { - typeId: FlowNodeTemplateTypeEnum.productivity, - typeName: i18nT('app:tool_type_productivity') - }, - { - typeId: FlowNodeTemplateTypeEnum.scientific, - typeName: i18nT('app:tool_type_scientific') - }, - { - typeId: FlowNodeTemplateTypeEnum.finance, - typeName: i18nT('app:tool_type_finance') - }, - { - typeId: FlowNodeTemplateTypeEnum.design, - typeName: i18nT('app:tool_type_design') - }, - { - typeId: FlowNodeTemplateTypeEnum.news, - typeName: i18nT('app:tool_type_news') - }, - { - typeId: FlowNodeTemplateTypeEnum.entertainment, - typeName: i18nT('app:tool_type_entertainment') - }, - { - typeId: FlowNodeTemplateTypeEnum.communication, - typeName: i18nT('app:tool_type_communication') - }, - { - typeId: FlowNodeTemplateTypeEnum.social, - typeName: i18nT('app:tool_type_social') - }, - { - typeId: FlowNodeTemplateTypeEnum.other, - typeName: i18nT('common:Other') - } -]; - -export const workflowNodeTemplateList: { +export const workflowSystemNodeTemplateList: { type: string; label: string; }[] = [ @@ -67,28 +16,27 @@ export const workflowNodeTemplateList: { type: FlowNodeTemplateTypeEnum.ai, label: i18nT('common:core.module.template.AI function') }, + { type: FlowNodeTemplateTypeEnum.interactive, label: i18nT('common:core.workflow.template.Interactive') }, - - ...systemPluginTemplateList.map((item) => ({ - type: item.typeId, - label: item.typeName - })), - { - type: FlowNodeTemplateTypeEnum.teamApp, - label: '' + type: FlowNodeTemplateTypeEnum.tools, + label: i18nT('app:tool_type_tools') + }, + { + type: FlowNodeTemplateTypeEnum.other, + label: i18nT('common:Other') } ]; -export const defaultGroup: PluginGroupSchemaType = { +export const defaultGroup: SystemToolGroupSchemaType = { groupId: 'systemPlugin', groupAvatar: 'core/app/type/pluginLight', groupName: i18nT('common:core.module.template.System Plugin'), groupOrder: 0, - groupTypes: systemPluginTemplateList + groupTypes: [] // from getPluginGroups }; export const defaultTemplateTypes: TemplateTypeSchemaType[] = [ diff --git a/packages/web/i18n/en/app.json b/packages/web/i18n/en/app.json index 44ebbdddb..df7f700ed 100644 --- a/packages/web/i18n/en/app.json +++ b/packages/web/i18n/en/app.json @@ -49,6 +49,7 @@ "chat_debug": "Chat Preview", "chat_logs": "Logs", "chat_logs_tips": "Logs will record the online, shared, and API (requires chatId) conversation records of this app.", + "common.day": "day", "config_ai_model_params": "Click to configure AI model related properties", "config_file_upload": "Click to Configure File Upload Rules", "config_question_guide": "Configuration guess you want to ask", @@ -246,16 +247,14 @@ "templateMarket.Search_template": "Search Template", "templateMarket.Use": "Use", "templateMarket.no_intro": "No introduction yet~", - "templateMarket.templateTags.Image_generation": "Image Generation", - "templateMarket.templateTags.Office_services": "Office Services", "templateMarket.templateTags.Recommendation": "Recommendation", - "templateMarket.templateTags.Roleplay": "Roleplay", - "templateMarket.templateTags.Web_search": "Web Search", - "templateMarket.templateTags.Writing": "Writing", "templateMarket.template_guide": "Guide", "template_market": "Templates", "template_market_description": "Explore more features in the template market, with configuration tutorials and usage guides to help you understand and get started with various applications.", "template_market_empty_data": "No suitable templates found", + "time_granularity": "Time granularity", + "time_range_limit": "Time range limit", + "time_type": "Time Type", "time_zone": "Time Zone", "too_to_active": "Active", "tool_active_manual_config_desc": "The temporary key is saved in this application and is only for use by this application.", @@ -266,16 +265,6 @@ "tool_input_param_tip": "This plugin requires configuration of related information to run properly.", "tool_not_active": "This tool has not been activated yet", "tool_run_free": "This tool runs without points consumption", - "tool_type_communication": "Communication", - "tool_type_design": "design", - "tool_type_entertainment": "Business", - "tool_type_finance": "finance", - "tool_type_multimodal": "Multimodal", - "tool_type_news": "news", - "tool_type_productivity": "productive forces", - "tool_type_scientific": "research", - "tool_type_search": "Search", - "tool_type_social": "Social", "tool_type_tools": "tool", "tools_no_description": "This tool has not been introduced ~", "transition_to_workflow": "Convert to Workflow", @@ -313,7 +302,8 @@ "un_auth": "No permission", "upload_file_max_amount": "Maximum File Quantity", "upload_file_max_amount_tip": "Maximum number of files uploaded in a single round of conversation", - "variable.select type_desc": "You can define a global variable that does not need to be filled in by the user.\n\nThe value of this variable can come from the API interface, the Query of the shared link, or assigned through the [Variable Update] module.", + "variable.internal_type_desc": "Use only inside the workflow and will not appear in the dialog box", + "variable.select type_desc": "The input box will be displayed in the site conversation and run preview, and this variable will not be displayed in the sharing link.", "variable.textarea_type_desc": "Allows users to input up to 4000 characters in the dialogue box.", "variable_name_required": "Required variable name", "variable_repeat": "This variable name has been occupied and cannot be used", diff --git a/packages/web/i18n/en/chat.json b/packages/web/i18n/en/chat.json index 6030a45bd..ea59e6ec2 100644 --- a/packages/web/i18n/en/chat.json +++ b/packages/web/i18n/en/chat.json @@ -51,6 +51,7 @@ "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", + "internal_variables_tip": "Internal variables are visible only when debugging", "invalid_share_url": "Invalid sharing link", "is_chatting": "Chatting in progress... please wait until it finishes", "items": "Items", @@ -159,7 +160,7 @@ "stream_output": "Stream Output", "unsupported_file_type": "Unsupported file types", "upload": "Upload", - "variable_invisable_in_share": "Custom variables are not visible in login-free links", + "variable_invisable_in_share": "External variables are not visible in login-free links", "view_citations": "View References", "web_site_sync": "Web Site Sync" } diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json index 597800eee..eba6175fc 100644 --- a/packages/web/i18n/en/common.json +++ b/packages/web/i18n/en/common.json @@ -601,6 +601,7 @@ "core.module.Max Length": "Max Length", "core.module.Max Length placeholder": "Maximum length of input text", "core.module.Max Value": "Max Value", + "core.module.Min Length": "Minimum number of digits", "core.module.Min Value": "Min Value", "core.module.QueryExtension.placeholder": "For example:\nQuestions about the introduction and use of Python.\nThe current conversation is related to the game 'GTA5'.", "core.module.Select app": "Select App", @@ -727,10 +728,16 @@ "core.workflow.inputType.Manual input": "Manual Input", "core.workflow.inputType.Manual select": "Manual Select", "core.workflow.inputType.Reference": "Variable Reference", - "core.workflow.inputType.custom": "Custom Variable", + "core.workflow.inputType.custom": "External Variable", "core.workflow.inputType.dynamicTargetInput": "Dynamic External Data", + "core.workflow.inputType.file": "File upload", "core.workflow.inputType.input": "Single Line Input Box", + "core.workflow.inputType.internal": "Internal variables", + "core.workflow.inputType.jsonEditor": "JSON Editor", + "core.workflow.inputType.modelSelect": "Dialogue Model Selection", + "core.workflow.inputType.multipleSelect": "Multiple selection boxes", "core.workflow.inputType.number input": "Number Input Box", + "core.workflow.inputType.password": "password", "core.workflow.inputType.select": "Single Select Box", "core.workflow.inputType.selectApp": "App Select", "core.workflow.inputType.selectDataset": "Dataset Select", @@ -738,6 +745,8 @@ "core.workflow.inputType.switch": "Switch", "core.workflow.inputType.textInput": "Text Input box", "core.workflow.inputType.textarea": "Multi-line Input Box", + "core.workflow.inputType.timePointSelect": "Time point", + "core.workflow.inputType.timeRangeSelect": "Time range", "core.workflow.publish.OnRevert version": "Click to Revert to This Version", "core.workflow.publish.OnRevert version confirm": "Confirm to Revert to This Version? The configuration of the editing version will be saved, and a new release version will be created for the reverted version.", "core.workflow.publish.histories": "Release Records", @@ -802,6 +811,7 @@ "date_1_month": "1 Month", "date_3_months": "3 Months", "date_6_months": "6 Months", + "day": "Day", "deep_rag_search": "In-depth search", "delete_api": "Are you sure you want to delete this API key? \nAfter deletion, the key will become invalid immediately and the corresponding conversation log will not be deleted. Please confirm!", "delete_failed": "Deletion Failed", @@ -844,6 +854,8 @@ "had_auth_value": "Filled in", "has_verification": "Verified, Click to Unbind", "have_done": "Completed", + "hour": "Hour", + "hour_unit": "h", "import_failed": "Import Failed", "import_success": "Imported Successfully", "info.buy_extra": "Buy Extra Package", @@ -881,8 +893,11 @@ "max_quote_tokens_tips": "The maximum number of tokens in a single search, about 1 character in Chinese = 1.7 tokens, and about 1 character in English = 1 token", "mcp_server": "MCP Services", "member": "member", + "min_length": "At least {{minLenth}} characters are required", "min_similarity": "lowest correlation", "min_similarity_tip": "The relevance of different index models is different. Please select the appropriate value through search testing. \nWhen using Result Rearrange , use the rearranged results for filtering.", + "minute": "Minute", + "minute_unit": "m", "model.billing": "Billing", "model.model_type": "Model type", "model.name": "Model name", @@ -1007,6 +1022,8 @@ "save_success": "Saved Successfully", "scan_code": "Scan the QR code to pay", "search_tool": "Search Tools", + "second": "Second", + "second_unit": "s", "secret_key": "Secret", "secret_tips": "The value will not return plaintext again after saving", "select_count_num": "{{num}} item selected", @@ -1223,6 +1240,8 @@ "templateTags.Writing": "Writing", "template_market": "Template Market", "textarea_variable_picker_tip": "Enter \"/\" to select a variable", + "time_point": "Time point", + "time_range": "Time period", "to_dataset": "To dataset", "total_num": "Total: {{num}}", "ui.textarea.Magnifying": "Magnifying", diff --git a/packages/web/i18n/en/workflow.json b/packages/web/i18n/en/workflow.json index b9b0f651f..7c1864c28 100644 --- a/packages/web/i18n/en/workflow.json +++ b/packages/web/i18n/en/workflow.json @@ -57,6 +57,7 @@ "execute_a_simple_script_code_usually_for_complex_data_processing": "Execute a simple script code, usually for complex data processing.", "execute_different_branches_based_on_conditions": "Execute different branches based on conditions.", "execution_error": "Execution Error", + "external_variables": "External variables", "extraction_requirements_description": "Extraction Requirements Description", "extraction_requirements_description_detail": "Provide AI with some background knowledge or requirements to guide it in completing the task better.\\nThis input box can use global variables.", "extraction_requirements_placeholder": "For example: 1. The current time is: {{cTime}}. \nYou are a laboratory reservation assistant. Your task is to help users make laboratory reservations and obtain the corresponding reservation information from the text.\n\n2. You are the Google Search Assistant and need to extract appropriate search terms from text.", @@ -87,6 +88,7 @@ "input_description": "Field Description", "input_type_multiple_select": "Multiple selection boxes", "input_variable_list": "Type / to invoke variable list", + "internal_variables": "Internal variables", "intro_assigned_reply": "This module can directly reply with a specified content. Commonly used for guidance or prompts. Non-string content will be converted to string for output.", "intro_custom_feedback": "When this module is triggered, a feedback will be added to the current conversation record. It can be used to automatically record conversation effects, etc.", "intro_custom_plugin_output": "Custom configuration of external output. When using plugins, only the custom configured output is exposed.", diff --git a/packages/web/i18n/zh-CN/app.json b/packages/web/i18n/zh-CN/app.json index 6f5402a89..a8fa488fc 100644 --- a/packages/web/i18n/zh-CN/app.json +++ b/packages/web/i18n/zh-CN/app.json @@ -49,6 +49,7 @@ "chat_debug": "调试预览", "chat_logs": "对话日志", "chat_logs_tips": "日志会记录该应用的在线、分享和 API(需填写 chatId)对话记录", + "common.day": "日", "config_ai_model_params": "点击配置 AI 模型相关属性", "config_file_upload": "点击配置文件上传规则", "config_question_guide": "配置猜你想问", @@ -255,16 +256,16 @@ "templateMarket.Search_template": "搜索模板", "templateMarket.Use": "使用", "templateMarket.no_intro": "还没有介绍~", - "templateMarket.templateTags.Image_generation": "图片生成", - "templateMarket.templateTags.Office_services": "办公服务", "templateMarket.templateTags.Recommendation": "推荐", - "templateMarket.templateTags.Roleplay": "角色扮演", - "templateMarket.templateTags.Web_search": "联网搜索", - "templateMarket.templateTags.Writing": "文本创作", "templateMarket.template_guide": "模板说明", "template_market": "模板市场", "template_market_description": "在模板市场探索更多玩法,配置教程与使用引导,带你理解并上手各种应用", "template_market_empty_data": "找不到合适的模板", + "time_granularity": "时间粒度", + "time_range_end": "结束时间", + "time_range_limit": "时间范围限制", + "time_range_start": "开始时间", + "time_type": "时间类型", "time_zone": "时区", "too_to_active": "去激活", "tool_active_manual_config_desc": "临时密钥保存在本应用中,仅供该应用使用", @@ -275,16 +276,6 @@ "tool_input_param_tip": "该插件正常运行需要配置相关信息", "tool_not_active": "该工具尚未激活", "tool_run_free": "该工具运行无积分消耗", - "tool_type_communication": "通讯", - "tool_type_design": "设计", - "tool_type_entertainment": "商业", - "tool_type_finance": "金融", - "tool_type_multimodal": "多模态", - "tool_type_news": "新闻", - "tool_type_productivity": "生产力", - "tool_type_scientific": "科研", - "tool_type_search": "搜索", - "tool_type_social": "社交", "tool_type_tools": "工具", "tools_no_description": "这个工具没有介绍~", "transition_to_workflow": "转成工作流", @@ -322,7 +313,8 @@ "un_auth": "无权限", "upload_file_max_amount": "最大文件数量", "upload_file_max_amount_tip": "单轮对话中最大上传文件数量", - "variable.select type_desc": "可以为工作流定义全局变量,常用临时缓存。赋值的方式包括:\n1. 从对话页面的 query 参数获取。\n2. 通过 API 的 variables 对象传递。\n3. 通过【变量更新】节点进行赋值。", + "variable.internal_type_desc": "仅在工作流内部使用,不会出现在对话框中", + "variable.select type_desc": "会在站内对话和运行预览中显示输入框,在分享链接中不会显示此变量", "variable.textarea_type_desc": "允许用户最多输入4000字的对话框。", "variable_name_required": "变量名必填", "variable_repeat": "该变量名已被占用,无法使用", diff --git a/packages/web/i18n/zh-CN/chat.json b/packages/web/i18n/zh-CN/chat.json index fe81ea6c6..b87dc231a 100644 --- a/packages/web/i18n/zh-CN/chat.json +++ b/packages/web/i18n/zh-CN/chat.json @@ -51,6 +51,7 @@ "input_guide_tip": "可以配置一些预设的问题。在用户输入问题时,会从这些预设问题中获取相关问题进行提示。", "input_placeholder_phone": "输入问题", "insert_input_guide,_some_data_already_exists": "有重复数据,已自动过滤,共插入 {{len}} 条数据", + "internal_variables_tip": "内部变量仅调试时可见", "invalid_share_url": "无效的分享链接", "is_chatting": "正在聊天中...请等待结束", "items": "条", @@ -108,16 +109,16 @@ "setting.favourite.categories_modal.delete_confirm_button": "删除", "setting.favourite.categories_modal.delete_confirm_title": "确认删除", "setting.favourite.categories_modal.title": "共 {{num}} 个分类", - "setting.favourite.category_all": "全部分类", - "setting.favourite.category_tab.all": "全部", "setting.favourite.category.no_data": "暂无可用精选应用", - "setting.favourite.tag.no_data": "暂无分类", + "setting.favourite.category_all": "全部分类", "setting.favourite.category_placeholder": "选择分类", + "setting.favourite.category_tab.all": "全部", "setting.favourite.confirm_button": "确定", "setting.favourite.delete_app_cancel_button": "取消", "setting.favourite.delete_app_confirm": "确定要移除该精选应用吗?", "setting.favourite.delete_app_confirm_button": "确定", "setting.favourite.delete_app_title": "删除应用", + "setting.favourite.goto_add": "去配置", "setting.favourite.manage_categories_button": "分类管理", "setting.favourite.save_category_for_app_button": "保存", "setting.favourite.search_placeholder": "搜索应用", @@ -126,17 +127,21 @@ "setting.favourite.table_column_category": "分类", "setting.favourite.table_column_intro": "介绍", "setting.favourite.table_column_name": "名称", + "setting.favourite.tag.no_data": "暂无分类", "setting.favourite.title": "精选应用", - "setting.favourite.goto_add": "去配置", "setting.home.available_tools": "可用工具", "setting.home.available_tools.add": "添加", + "setting.home.cancel_button": "取消", "setting.home.commercial_version": "商业版", + "setting.home.confirm_button": "确定", "setting.home.diagram": "示意图", "setting.home.dialogue_tips": "对话框提示文字", "setting.home.dialogue_tips.default": "你可以问我任何问题", "setting.home.dialogue_tips_placeholder": "请输入对话框提示文字", + "setting.home.enable": "启用首页", "setting.home.home_tab_title": "首页标题", "setting.home.home_tab_title_placeholder": "请输入首页标题", + "setting.home.no_selected_app": "未选择应用", "setting.home.quick_apps": "快捷应用", "setting.home.quick_apps.add": "配置快捷应用", "setting.home.quick_apps.placeholder": "请选择应用", @@ -144,10 +149,6 @@ "setting.home.slogan.default": "你好👋,我是 FastGPT ! 请问有什么可以帮你?", "setting.home.slogan_placeholder": "请输入 Slogan", "setting.home.title": "首页配置", - "setting.home.cancel_button": "取消", - "setting.home.confirm_button": "确定", - "setting.home.no_selected_app": "未选择应用", - "setting.home.enable": "启用首页", "setting.incorrect_plan": "当前套餐不支持该功能,请升级订阅套餐", "setting.incorrect_version": "当前版本不支持该功能", "setting.log_details.title": "首页日志", @@ -162,7 +163,7 @@ "stream_output": "流输出", "unsupported_file_type": "不支持的文件类型", "upload": "上传", - "variable_invisable_in_share": "自定义变量在免登录链接中不可见", + "variable_invisable_in_share": "外部变量在免登录链接中不可见", "view_citations": "查看引用", "web_site_sync": "Web站点同步" } diff --git a/packages/web/i18n/zh-CN/common.json b/packages/web/i18n/zh-CN/common.json index fe725f742..45936b40a 100644 --- a/packages/web/i18n/zh-CN/common.json +++ b/packages/web/i18n/zh-CN/common.json @@ -601,6 +601,7 @@ "core.module.Max Length": "最大长度", "core.module.Max Length placeholder": "输入文本的最大长度", "core.module.Max Value": "最大值", + "core.module.Min Length": "最小位数", "core.module.Min Value": "最小值", "core.module.QueryExtension.placeholder": "例如:\n关于 Python 的介绍和使用等问题。\n当前对话与游戏《GTA5》有关。", "core.module.Select app": "选择应用", @@ -727,10 +728,17 @@ "core.workflow.inputType.Manual input": "手动输入", "core.workflow.inputType.Manual select": "手动选择", "core.workflow.inputType.Reference": "变量引用", - "core.workflow.inputType.custom": "自定义变量", + "core.workflow.inputType.custom": "外部变量", + "core.workflow.inputType.datasetSelect": "知识库选择", "core.workflow.inputType.dynamicTargetInput": "动态外部数据", + "core.workflow.inputType.file": "文件上传", "core.workflow.inputType.input": "单行输入框", + "core.workflow.inputType.internal": "内部变量", + "core.workflow.inputType.jsonEditor": "JSON 输入框", + "core.workflow.inputType.modelSelect": "对话模型选择", + "core.workflow.inputType.multipleSelect": "多选框", "core.workflow.inputType.number input": "数字输入框", + "core.workflow.inputType.password": "密码", "core.workflow.inputType.select": "单选框", "core.workflow.inputType.selectApp": "应用选择", "core.workflow.inputType.selectDataset": "知识库选择", @@ -738,6 +746,8 @@ "core.workflow.inputType.switch": "开关", "core.workflow.inputType.textInput": "文本输入框", "core.workflow.inputType.textarea": "多行输入框", + "core.workflow.inputType.timePointSelect": "时间点", + "core.workflow.inputType.timeRangeSelect": "时间范围", "core.workflow.publish.OnRevert version": "点击回退到该版本", "core.workflow.publish.OnRevert version confirm": "确认回退至该版本?会为您保存编辑中版本的配置,并为回退版本创建一个新的发布版本。", "core.workflow.publish.histories": "发布记录", @@ -802,6 +812,7 @@ "date_1_month": "1个月", "date_3_months": "3个月", "date_6_months": "6个月", + "day": "日", "deep_rag_search": "深度搜索", "delete_api": "确认删除该API密钥?删除后该密钥立即失效,对应的对话日志不会删除,请确认!", "delete_failed": "删除失败", @@ -844,6 +855,8 @@ "had_auth_value": "已填写", "has_verification": "已验证,点击取消绑定", "have_done": "已完成", + "hour": "小时", + "hour_unit": "时", "import_failed": "导入失败", "import_success": "导入成功", "info.buy_extra": "购买额外套餐", @@ -881,8 +894,11 @@ "max_quote_tokens_tips": "单次搜索最大的 token 数量,中文约 1 字=1.7 tokens,英文约 1 字=1 token", "mcp_server": "MCP 服务", "member": "成员", + "min_length": "最少需要 {{minLenth}} 个字符", "min_similarity": "最低相关度", "min_similarity_tip": "不同索引模型的相关度有区别,请通过搜索测试来选择合适的数值。使用 结果重排 时,使用重排结果进行过滤。", + "minute": "分钟", + "minute_unit": "分", "model.billing": "模型计费", "model.model_type": "模型类型", "model.name": "模型名", @@ -1007,6 +1023,8 @@ "save_success": "保存成功", "scan_code": "扫码支付", "search_tool": "搜索工具", + "second": "秒", + "second_unit": "秒", "secret_key": "密钥", "secret_tips": "值保存后不会再次明文返回", "select_count_num": "已选 {{num}} 项", @@ -1224,6 +1242,8 @@ "templateTags.Writing": "文本创作", "template_market": "模板市场", "textarea_variable_picker_tip": "输入\"/\"可选择变量", + "time_point": "时间点", + "time_range": "时间段", "to_dataset": "前往知识库", "total_num": "总数: {{num}}", "ui.textarea.Magnifying": "放大", diff --git a/packages/web/i18n/zh-CN/workflow.json b/packages/web/i18n/zh-CN/workflow.json index 0493c0c6b..5efce7e4a 100644 --- a/packages/web/i18n/zh-CN/workflow.json +++ b/packages/web/i18n/zh-CN/workflow.json @@ -57,6 +57,7 @@ "execute_a_simple_script_code_usually_for_complex_data_processing": "执行一段简单的脚本代码,通常用于进行复杂的数据处理。", "execute_different_branches_based_on_conditions": "根据一定的条件,执行不同的分支。", "execution_error": "运行错误", + "external_variables": "外部变量", "extraction_requirements_description": "提取要求描述", "extraction_requirements_description_detail": "给AI一些对应的背景知识或要求描述,引导AI更好的完成任务。\\n该输入框可使用全局变量。", "extraction_requirements_placeholder": "例如: 1. 当前时间为: {{cTime}}。你是一个实验室预约助手,你的任务是帮助用户预约实验室,从文本中获取对应的预约信息。\n2. 你是谷歌搜索助手,需要从文本中提取出合适的搜索词。", @@ -87,6 +88,7 @@ "input_description": "字段描述", "input_type_multiple_select": "多选框", "input_variable_list": "可输入 / 唤起变量列表", + "internal_variables": "内部变量", "intro_assigned_reply": "该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。", "intro_custom_feedback": "该模块被触发时,会给当前的对话记录增加一条反馈。可用于自动记录对话效果等。", "intro_custom_plugin_output": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出", diff --git a/packages/web/i18n/zh-Hant/app.json b/packages/web/i18n/zh-Hant/app.json index 57e267dbc..012e784ad 100644 --- a/packages/web/i18n/zh-Hant/app.json +++ b/packages/web/i18n/zh-Hant/app.json @@ -246,16 +246,14 @@ "templateMarket.Search_template": "搜尋範本", "templateMarket.Use": "使用", "templateMarket.no_intro": "還沒有介紹~", - "templateMarket.templateTags.Image_generation": "影像生成", - "templateMarket.templateTags.Office_services": "辦公服務", "templateMarket.templateTags.Recommendation": "推薦", - "templateMarket.templateTags.Roleplay": "角色扮演", - "templateMarket.templateTags.Web_search": "網路搜尋", - "templateMarket.templateTags.Writing": "文字創作", "templateMarket.template_guide": "範本說明", "template_market": "範本市集", "template_market_description": "在範本市集探索更多玩法,設定教學與使用指引,帶您理解並上手各種應用程式", "template_market_empty_data": "找不到合適的範本", + "time_granularity": "時間粒度", + "time_range_limit": "時間範圍限制", + "time_type": "時間類型", "time_zone": "時區", "too_to_active": "去激活", "tool_active_manual_config_desc": "臨時密鑰保存在本應用中,僅供該應用使用", @@ -266,16 +264,6 @@ "tool_input_param_tip": "這個外掛正常執行需要設定相關資訊", "tool_not_active": "該工具尚未激活", "tool_run_free": "該工具運行無積分消耗", - "tool_type_communication": "通訊", - "tool_type_design": "設計", - "tool_type_entertainment": "商業", - "tool_type_finance": "金融", - "tool_type_multimodal": "多模態", - "tool_type_news": "新聞", - "tool_type_productivity": "生產力", - "tool_type_scientific": "科研", - "tool_type_search": "搜尋", - "tool_type_social": "社交", "tool_type_tools": "工具", "tools_no_description": "這個工具沒有介紹~", "transition_to_workflow": "轉換成工作流程", @@ -313,7 +301,8 @@ "un_auth": "無權限", "upload_file_max_amount": "最大檔案數量", "upload_file_max_amount_tip": "單輪對話中最大上傳檔案數量", - "variable.select type_desc": "可以為工作流程定義全域變數,常用於暫存。賦值的方式包括:\n1. 從對話頁面的 query 參數取得。\n2. 透過 API 的 variables 物件傳遞。\n3. 透過【變數更新】節點進行賦值。", + "variable.internal_type_desc": "僅在工作流內部使用,不會出現在對話框中", + "variable.select type_desc": "會在站內對話和運行預覽中顯示輸入框,在分享鏈接中不會顯示此變量", "variable.textarea_type_desc": "允許使用者最多輸入 4000 字的對話框。", "variable_name_required": "變量名必填", "variable_repeat": "該變量名已被佔用,無法使用", diff --git a/packages/web/i18n/zh-Hant/chat.json b/packages/web/i18n/zh-Hant/chat.json index 3968c8d92..b67743ff0 100644 --- a/packages/web/i18n/zh-Hant/chat.json +++ b/packages/web/i18n/zh-Hant/chat.json @@ -51,6 +51,7 @@ "input_guide_tip": "您可以設定一些預設問題。當使用者輸入問題時,系統會從這些預設問題中提供相關問題作為提示。", "input_placeholder_phone": "請輸入問題", "insert_input_guide,_some_data_already_exists": "偵測到重複資料,已自動過濾,共插入 {{len}} 筆資料", + "internal_variables_tip": "內部變量僅調試時可見", "invalid_share_url": "無效的分享鏈接", "is_chatting": "對話進行中...請稍候", "items": "筆", @@ -159,7 +160,7 @@ "stream_output": "串流輸出", "unsupported_file_type": "不支援的檔案類型", "upload": "上傳", - "variable_invisable_in_share": "自定義變數在免登入連結中不可見", + "variable_invisable_in_share": "外部變量在免登錄鏈接中不可見", "view_citations": "檢視引用", "web_site_sync": "網站同步" } diff --git a/packages/web/i18n/zh-Hant/common.json b/packages/web/i18n/zh-Hant/common.json index acfb87354..795af0589 100644 --- a/packages/web/i18n/zh-Hant/common.json +++ b/packages/web/i18n/zh-Hant/common.json @@ -600,6 +600,7 @@ "core.module.Max Length": "最大長度", "core.module.Max Length placeholder": "輸入文字的最大長度", "core.module.Max Value": "最大值", + "core.module.Min Length": "最小位數", "core.module.Min Value": "最小值", "core.module.QueryExtension.placeholder": "例如:\n關於 Python 的介紹和使用等問題。\n目前對話與遊戲《GTA5》有關。", "core.module.Select app": "選擇應用程式", @@ -726,10 +727,16 @@ "core.workflow.inputType.Manual input": "手動輸入", "core.workflow.inputType.Manual select": "手動選擇", "core.workflow.inputType.Reference": "變數引用", - "core.workflow.inputType.custom": "自訂變數", + "core.workflow.inputType.custom": "外部變數", "core.workflow.inputType.dynamicTargetInput": "動態外部資料", + "core.workflow.inputType.file": "文件上傳", "core.workflow.inputType.input": "單行輸入框", + "core.workflow.inputType.internal": "內部變量", + "core.workflow.inputType.jsonEditor": "JSON 輸入框", + "core.workflow.inputType.modelSelect": "對話模型選擇", + "core.workflow.inputType.multipleSelect": "多選框", "core.workflow.inputType.number input": "數字輸入框", + "core.workflow.inputType.password": "密碼", "core.workflow.inputType.select": "單選框", "core.workflow.inputType.selectApp": "應用程式選擇", "core.workflow.inputType.selectDataset": "知識庫選擇", @@ -737,6 +744,8 @@ "core.workflow.inputType.switch": "開關", "core.workflow.inputType.textInput": "文字輸入框", "core.workflow.inputType.textarea": "多行輸入框", + "core.workflow.inputType.timePointSelect": "時間點", + "core.workflow.inputType.timeRangeSelect": "時間範圍", "core.workflow.publish.OnRevert version": "點選回復至此版本", "core.workflow.publish.OnRevert version confirm": "確認回復至此版本?將為您儲存編輯中版本的設定,並為回復版本建立一個新的發布版本。", "core.workflow.publish.histories": "發布記錄", @@ -801,6 +810,7 @@ "date_1_month": "1個月", "date_3 months": "3個月", "date_6_months": "6個月", + "day": "日", "deep_rag_search": "深度搜尋", "delete_api": "確認刪除此 API 金鑰?\n刪除後該金鑰將立即失效,對應的對話記錄不會被刪除,請確認!", "delete_failed": "刪除失敗", @@ -843,6 +853,8 @@ "had_auth_value": "已填寫", "has_verification": "已驗證,點選解除綁定", "have_done": "已完成", + "hour": "小時", + "hour_unit": "時", "import_failed": "匯入失敗", "import_success": "匯入成功", "info.buy_extra": "購買額外方案", @@ -880,8 +892,11 @@ "max_quote_tokens_tips": "單次搜尋最大的 token 數量,中文約 1 字=1.7 tokens,英文約 1 字=1 token", "mcp_server": "MCP 服務", "member": "成員", + "min_length": "最少需要 {{minLenth}} 個字符", "min_similarity": "最低相關度", "min_similarity_tip": "不同索引模型的相關度有區別,請透過搜尋測試來選擇合適的數值。\n使用 結果重排 時,使用重排結果過濾。", + "minute": "分鐘", + "minute_unit": "分", "model.billing": "模型計費", "model.model_type": "模型類型", "model.name": "模型名", @@ -1006,6 +1021,8 @@ "save_success": "儲存成功", "scan_code": "掃碼支付", "search_tool": "搜索工具", + "second": "秒", + "second_unit": "秒", "secret_key": "密鑰", "secret_tips": "值保存後不會再次明文返回", "select_count_num": "已選 {{num}} 項", @@ -1222,6 +1239,8 @@ "templateTags.Writing": "文字創作", "template_market": "模板市場", "textarea_variable_picker_tip": "輸入「/」以選擇變數", + "time_point": "時間點", + "time_range": "時間段", "to_dataset": "前往知識庫", "total_num": "總數: {{num}}", "ui.textarea.Magnifying": "放大", diff --git a/packages/web/i18n/zh-Hant/workflow.json b/packages/web/i18n/zh-Hant/workflow.json index 3bbfa9d65..5203686fe 100644 --- a/packages/web/i18n/zh-Hant/workflow.json +++ b/packages/web/i18n/zh-Hant/workflow.json @@ -57,6 +57,7 @@ "execute_a_simple_script_code_usually_for_complex_data_processing": "執行一段簡單的腳本程式碼,通常用於複雜的資料處理。", "execute_different_branches_based_on_conditions": "根據條件執行不同的分支。", "execution_error": "執行錯誤", + "external_variables": "外部變量", "extraction_requirements_description": "擷取需求描述", "extraction_requirements_description_detail": "提供 AI 相對應的背景知識或需求描述,引導 AI 更好地完成任務。\\n這個輸入框可以使用全域變數。", "extraction_requirements_placeholder": "例如:1. 目前時間為:{{cTime}}。\n你是實驗室預約助手,你的任務是幫助使用者預約實驗室,從文字中取得對應的預約資訊。\n\n2. 你是 Google 搜尋助手,需要從文字中提取出合適的搜尋字詞。", @@ -87,6 +88,7 @@ "input_description": "欄位描述", "input_type_multiple_select": "多選框", "input_variable_list": "輸入 / 叫出變數清單", + "internal_variables": "內部變量", "intro_assigned_reply": "這個模組可以直接回覆指定的內容。常用於引導、提示。非字串內容傳入時,會轉換成字串輸出。", "intro_custom_feedback": "當這個模組被觸發時,會在目前的對話紀錄中新增一條回饋。可以用於自動記錄對話效果等等。", "intro_custom_plugin_output": "自訂設定外部輸出,使用外掛程式時,只顯示自訂設定的輸出", diff --git a/packages/web/package.json b/packages/web/package.json index 4a4864b0d..76ad3df5a 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -12,7 +12,11 @@ "@emotion/styled": "11.11.0", "@fastgpt/global": "workspace:*", "@fingerprintjs/fingerprintjs": "^4.3.0", + "@lexical/code": "0.12.6", + "@lexical/list": "0.12.6", + "@lexical/markdown": "0.12.6", "@lexical/react": "0.12.6", + "@lexical/rich-text": "0.12.6", "@lexical/selection": "^0.14.5", "@lexical/text": "0.12.6", "@lexical/utils": "0.12.6", @@ -21,7 +25,6 @@ "ahooks": "^3.9.4", "date-fns": "2.30.0", "dayjs": "^1.11.7", - "recharts": "^2.15.0", "i18next": "23.16.8", "js-cookie": "^3.0.5", "lexical": "0.12.6", @@ -35,6 +38,7 @@ "react-hook-form": "7.43.1", "react-i18next": "14.1.2", "react-photo-view": "^1.2.6", + "recharts": "^2.15.0", "use-context-selector": "^1.4.4", "zustand": "^4.3.5" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b3f0a32c4..ac914781f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -72,8 +72,8 @@ importers: specifier: ^1.2.8 version: 1.2.8 '@fastgpt-sdk/plugin': - specifier: ^0.1.12 - version: 0.1.12(@types/node@20.14.0) + specifier: ^0.1.16 + version: 0.1.16(@types/node@20.14.0) axios: specifier: ^1.8.2 version: 1.8.4 @@ -308,15 +308,6 @@ importers: specifier: ^5.0.4 version: 5.0.5 - packages/templates: - devDependencies: - '@fastgpt/global': - specifier: workspace:* - version: link:../global - '@fastgpt/service': - specifier: workspace:* - version: link:../service - packages/web: dependencies: '@chakra-ui/anatomy': @@ -349,9 +340,21 @@ importers: '@fingerprintjs/fingerprintjs': specifier: ^4.3.0 version: 4.6.1 + '@lexical/code': + specifier: 0.12.6 + version: 0.12.6(lexical@0.12.6) + '@lexical/list': + specifier: 0.12.6 + version: 0.12.6(lexical@0.12.6) + '@lexical/markdown': + specifier: 0.12.6 + version: 0.12.6(@lexical/clipboard@0.12.6(lexical@0.12.6))(@lexical/selection@0.14.5)(lexical@0.12.6) '@lexical/react': specifier: 0.12.6 version: 0.12.6(lexical@0.12.6)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(yjs@13.6.24) + '@lexical/rich-text': + specifier: 0.12.6 + version: 0.12.6(@lexical/clipboard@0.12.6(lexical@0.12.6))(@lexical/selection@0.14.5)(@lexical/utils@0.12.6(lexical@0.12.6))(lexical@0.12.6) '@lexical/selection': specifier: ^0.14.5 version: 0.14.5 @@ -479,9 +482,6 @@ importers: '@fastgpt/service': specifier: workspace:* version: link:../../packages/service - '@fastgpt/templates': - specifier: workspace:* - version: link:../../packages/templates '@fastgpt/web': specifier: workspace:* version: link:../../packages/web @@ -1976,8 +1976,8 @@ packages: resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@fastgpt-sdk/plugin@0.1.12': - resolution: {integrity: sha512-jcgS0FWNxtfdwq+M7VEK4NggkIIXDkSC7jukYjRkEPS1klupkS89O3D0ekAZHq7uzHUbEN18x0xui+nV3nh0Tw==} + '@fastgpt-sdk/plugin@0.1.16': + resolution: {integrity: sha512-HGoq0jy3YrY8RAJvn8b0u13uqOjjNe5OE4w2dySQc4dgUjHpsmMl9hfGzAhi9bpuUrtptpGohtf0ealNeAAfDQ==} '@fastify/accept-negotiator@1.1.0': resolution: {integrity: sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ==} @@ -11222,7 +11222,7 @@ snapshots: '@eslint/js@8.57.1': {} - '@fastgpt-sdk/plugin@0.1.12(@types/node@20.14.0)': + '@fastgpt-sdk/plugin@0.1.16(@types/node@20.14.0)': dependencies: '@fortaine/fetch-event-source': 3.0.6 '@ts-rest/core': 3.52.1(@types/node@20.14.0)(zod@3.25.51) @@ -11604,6 +11604,19 @@ snapshots: - '@lexical/clipboard' - '@lexical/selection' + '@lexical/markdown@0.12.6(@lexical/clipboard@0.12.6(lexical@0.12.6))(@lexical/selection@0.14.5)(lexical@0.12.6)': + dependencies: + '@lexical/code': 0.12.6(lexical@0.12.6) + '@lexical/link': 0.12.6(lexical@0.12.6) + '@lexical/list': 0.12.6(lexical@0.12.6) + '@lexical/rich-text': 0.12.6(@lexical/clipboard@0.12.6(lexical@0.12.6))(@lexical/selection@0.14.5)(@lexical/utils@0.12.6(lexical@0.12.6))(lexical@0.12.6) + '@lexical/text': 0.12.6(lexical@0.12.6) + '@lexical/utils': 0.12.6(lexical@0.12.6) + lexical: 0.12.6 + transitivePeerDependencies: + - '@lexical/clipboard' + - '@lexical/selection' + '@lexical/offset@0.12.6(lexical@0.12.6)': dependencies: lexical: 0.12.6 @@ -11652,6 +11665,13 @@ snapshots: '@lexical/utils': 0.12.6(lexical@0.12.6) lexical: 0.12.6 + '@lexical/rich-text@0.12.6(@lexical/clipboard@0.12.6(lexical@0.12.6))(@lexical/selection@0.14.5)(@lexical/utils@0.12.6(lexical@0.12.6))(lexical@0.12.6)': + dependencies: + '@lexical/clipboard': 0.12.6(lexical@0.12.6) + '@lexical/selection': 0.14.5 + '@lexical/utils': 0.12.6(lexical@0.12.6) + lexical: 0.12.6 + '@lexical/selection@0.12.6(lexical@0.12.6)': dependencies: lexical: 0.12.6 @@ -15126,7 +15146,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0)(eslint@8.56.0))(eslint@8.56.0): + eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0)(eslint@8.56.0): dependencies: debug: 3.2.7 optionalDependencies: @@ -15137,7 +15157,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0)(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: @@ -15159,7 +15179,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0)(eslint@8.56.0))(eslint@8.56.0) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0)(eslint@8.56.0) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -15188,7 +15208,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0)(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 diff --git a/projects/app/.env.template b/projects/app/.env.template index 79aef450f..5bc671fb2 100644 --- a/projects/app/.env.template +++ b/projects/app/.env.template @@ -61,6 +61,11 @@ FILE_DOMAIN=http://localhost:3000 LOG_LEVEL=debug STORE_LOG_LEVEL=warn +# Signoz +SIGNOZ_BASE_URL= +SIGNOZ_SERVICE_NAME= +SIGNOZ_STORE_LEVEL=warn + # 安全配置 # 对话文件 n 天过期 CHAT_FILE_EXPIRE_TIME=7 @@ -95,8 +100,4 @@ CONFIG_JSON_PATH= # # 日志来源ID前缀 # CHAT_LOG_SOURCE_ID_PREFIX=fastgpt- -# Signoz -SIGNOZ_BASE_URL= -SIGNOZ_SERVICE_NAME= -SIGNOZ_STORE_LEVEL=warn diff --git a/projects/app/package.json b/projects/app/package.json index b2bfee0e3..1896bdc6b 100644 --- a/projects/app/package.json +++ b/projects/app/package.json @@ -20,7 +20,6 @@ "@emotion/styled": "11.11.0", "@fastgpt/global": "workspace:*", "@fastgpt/service": "workspace:*", - "@fastgpt/templates": "workspace:*", "@fastgpt/web": "workspace:*", "@fortaine/fetch-event-source": "^3.0.6", "@modelcontextprotocol/sdk": "^1.12.1", diff --git a/projects/app/src/components/Select/AIModelSelector.tsx b/projects/app/src/components/Select/AIModelSelector.tsx index 2ca73aebb..983c74ca5 100644 --- a/projects/app/src/components/Select/AIModelSelector.tsx +++ b/projects/app/src/components/Select/AIModelSelector.tsx @@ -7,9 +7,7 @@ import { HUGGING_FACE_ICON } from '@fastgpt/global/common/system/constants'; import { Box, Flex } from '@chakra-ui/react'; import Avatar from '@fastgpt/web/components/common/Avatar'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; -import { getModelProviders } from '@fastgpt/global/core/ai/provider'; import MultipleRowSelect from '@fastgpt/web/components/common/MySelect/MultipleRowSelect'; -import { getModelFromList } from '@fastgpt/global/core/ai/model'; import type { ResponsiveValue } from '@chakra-ui/system'; type Props = SelectProps & { @@ -18,10 +16,15 @@ type Props = SelectProps & { }; const OneRowSelector = ({ list, onChange, disableTip, noOfLines, ...props }: Props) => { - const { t, i18n } = useTranslation(); - const { llmModelList, embeddingModelList, ttsModelList, sttModelList, reRankModelList } = - useSystemStore(); - const language = i18n.language; + const { t } = useTranslation(); + const { + llmModelList, + embeddingModelList, + ttsModelList, + sttModelList, + reRankModelList, + getModelProvider + } = useSystemStore(); const avatarSize = useMemo(() => { const size = { @@ -43,9 +46,11 @@ const OneRowSelector = ({ list, onChange, disableTip, noOfLines, ...props }: Pro ]; return list .map((item) => { - const modelData = getModelFromList(allModels, item.value, language)!; + const modelData = allModels.find((model) => model.model === item.value); if (!modelData) return; + const avatar = getModelProvider(modelData.provider)?.avatar; + return { value: item.value, label: ( @@ -53,7 +58,7 @@ const OneRowSelector = ({ list, onChange, disableTip, noOfLines, ...props }: Pro @@ -74,7 +79,7 @@ const OneRowSelector = ({ list, onChange, disableTip, noOfLines, ...props }: Pro sttModelList, reRankModelList, list, - language, + getModelProvider, avatarSize, noOfLines ]); @@ -113,9 +118,15 @@ const MultipleRowSelector = ({ ...props }: Props) => { const { t, i18n } = useTranslation(); - const { llmModelList, embeddingModelList, ttsModelList, sttModelList, reRankModelList } = - useSystemStore(); - const language = i18n.language; + const { + llmModelList, + embeddingModelList, + ttsModelList, + sttModelList, + reRankModelList, + getModelProvider, + getModelProviders + } = useSystemStore(); const modelList = useMemo(() => { const allModels = [ ...llmModelList, @@ -125,16 +136,10 @@ const MultipleRowSelector = ({ ...reRankModelList ]; - return list.map((item) => getModelFromList(allModels, item.value, language)!).filter(Boolean); - }, [ - llmModelList, - embeddingModelList, - ttsModelList, - sttModelList, - reRankModelList, - list, - language - ]); + return list + .map((item) => allModels.find((model) => model.model === item.value)) + .filter(Boolean); + }, [llmModelList, embeddingModelList, ttsModelList, sttModelList, reRankModelList, list]); const [value, setValue] = useState([]); @@ -149,7 +154,7 @@ const MultipleRowSelector = ({ }, [props.size]); const selectorList = useMemo(() => { - const renderList = getModelProviders(language).map<{ + const renderList = getModelProviders(i18n.language).map<{ label: React.JSX.Element; value: string; children: { label: string | React.ReactNode; value: string }[]; @@ -171,7 +176,7 @@ const MultipleRowSelector = ({ })); for (const item of list) { - const modelData = getModelFromList(modelList, item.value, language); + const modelData = modelList.find((model) => model?.model === item.value); if (!modelData) continue; const provider = renderList.find((item) => item.value === (modelData?.provider || 'Other')) ?? @@ -184,7 +189,7 @@ const MultipleRowSelector = ({ } return renderList.filter((item) => item.children.length > 0); - }, [avatarSize, list, modelList, t, language]); + }, [getModelProviders, i18n.language, avatarSize, list, modelList]); const onSelect = useCallback( (e: string[]) => { @@ -195,25 +200,27 @@ const MultipleRowSelector = ({ const SelectedLabel = useMemo(() => { if (!props.value) return <>{t('common:not_model_config')}; - const modelData = getModelFromList(modelList, props.value, language); + const modelData = modelList.find((model) => model?.model === props.value); if (!modelData) return <>{t('common:not_model_config')}; setValue([modelData.provider, props.value]); + const avatar = getModelProvider(modelData.provider)?.avatar; + return ( {modelData?.name} ); - }, [modelList, props.value, t, avatarSize, language]); + }, [props.value, t, modelList, getModelProvider, avatarSize, noOfLines]); return ( { return llmModelList.map((model) => { - // const provider = getModelProvider(model.model) return { label: ( diff --git a/projects/app/src/components/core/ai/ModelTable/index.tsx b/projects/app/src/components/core/ai/ModelTable/index.tsx index 932209c78..57bb48def 100644 --- a/projects/app/src/components/core/ai/ModelTable/index.tsx +++ b/projects/app/src/components/core/ai/ModelTable/index.tsx @@ -14,11 +14,6 @@ import { } from '@chakra-ui/react'; import { useTranslation } from 'next-i18next'; import React, { useMemo, useRef, useState } from 'react'; -import { - getModelProviders, - type ModelProviderIdType, - getModelProvider -} from '@fastgpt/global/core/ai/provider'; import MySelect from '@fastgpt/web/components/common/MySelect'; import { modelTypeList, ModelTypeEnum } from '@fastgpt/global/core/ai/model'; import SearchInput from '@fastgpt/web/components/common/Input/SearchInput'; @@ -27,16 +22,16 @@ import Avatar from '@fastgpt/web/components/common/Avatar'; import MyTag from '@fastgpt/web/components/common/Tag/index'; import dynamic from 'next/dynamic'; import CopyBox from '@fastgpt/web/components/common/String/CopyBox'; - const MyModal = dynamic(() => import('@fastgpt/web/components/common/MyModal')); const ModelTable = () => { const { t, i18n } = useTranslation(); - const language = i18n.language; - const [provider, setProvider] = useState(''); - const providerList = useRef<{ label: any; value: ModelProviderIdType | '' }[]>([ + const { getModelProviders, getModelProvider } = useSystemStore(); + + const [provider, setProvider] = useState(''); + const providerList = useRef<{ label: any; value: string | '' }[]>([ { label: t('common:All'), value: '' }, - ...getModelProviders(language).map((item) => ({ + ...getModelProviders(i18n.language).map((item) => ({ label: ( @@ -163,12 +158,12 @@ const ModelTable = () => { ]; })(); const formatList = list.map((item) => { - const provider = getModelProvider(item.provider, language); + const provider = getModelProvider(item.provider, i18n.language); return { name: item.name, avatar: provider.avatar, providerId: provider.id, - providerName: t(provider.name as any), + providerName: provider.name, typeLabel: item.typeLabel, priceLabel: item.priceLabel, order: provider.order, @@ -195,9 +190,10 @@ const ModelTable = () => { reRankModelList, t, modelType, + getModelProvider, + i18n.language, provider, - search, - language + search ]); const filterProviderList = useMemo(() => { diff --git a/projects/app/src/components/core/app/TTSSelect.tsx b/projects/app/src/components/core/app/TTSSelect.tsx index b0154b42f..1fd0c2681 100644 --- a/projects/app/src/components/core/app/TTSSelect.tsx +++ b/projects/app/src/components/core/app/TTSSelect.tsx @@ -16,7 +16,6 @@ import MyImage from '@fastgpt/web/components/common/Image/MyImage'; import { useContextSelector } from 'use-context-selector'; import { AppContext } from '@/pageComponents/app/detail/context'; import Avatar from '@fastgpt/web/components/common/Avatar'; -import { getModelProvider } from '@fastgpt/global/core/ai/provider'; import MultipleRowSelect from '@fastgpt/web/components/common/MySelect/MultipleRowSelect'; const TTSSelect = ({ @@ -27,8 +26,7 @@ const TTSSelect = ({ onChange: (e: AppTTSConfigType) => void; }) => { const { t, i18n } = useTranslation(); - const language = i18n.language; - const { ttsModelList } = useSystemStore(); + const { ttsModelList, getModelProvider } = useSystemStore(); const { isOpen, onOpen, onClose } = useDisclosure(); const appId = useContextSelector(AppContext, (v) => v.appId); @@ -38,7 +36,7 @@ const TTSSelect = ({ { label: t('app:tts_close'), value: TTSTypeEnum.none, children: [] }, { label: t('app:tts_browser'), value: TTSTypeEnum.web, children: [] }, ...ttsModelList.map((model) => { - const providerData = getModelProvider(model.provider, language); + const providerData = getModelProvider(model.provider, i18n.language); return { label: ( diff --git a/projects/app/src/components/core/app/VariableEdit.tsx b/projects/app/src/components/core/app/VariableEdit.tsx index 63156eedb..1c7704dfd 100644 --- a/projects/app/src/components/core/app/VariableEdit.tsx +++ b/projects/app/src/components/core/app/VariableEdit.tsx @@ -15,7 +15,7 @@ import { import { SmallAddIcon } from '@chakra-ui/icons'; import { VariableInputEnum, - variableMap, + variableConfigs, WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants'; import type { VariableItemType } from '@fastgpt/global/core/app/type.d'; @@ -44,7 +44,16 @@ export const defaultVariable: VariableItemType = { type: VariableInputEnum.input, description: '', required: true, - valueType: WorkflowIOValueTypeEnum.string + valueType: WorkflowIOValueTypeEnum.string, + canSelectFile: true, + canSelectImg: true, + maxFiles: 5, + timeGranularity: 'day', + timeType: 'point', + timeRangeStart: new Date( + new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).setHours(0, 0, 0, 0) + ).toISOString(), + timeRangeEnd: new Date(new Date().setHours(0, 0, 0, 0)).toISOString() }; export const addVariable = () => { @@ -69,25 +78,70 @@ const VariableEdit = ({ const value = getValues(); const type = watch('type'); - const inputTypeList = useMemo( - () => - Object.values(variableMap) - .filter((item) => item.value !== VariableInputEnum.textarea) - .map((item) => ({ - icon: item.icon, - label: t(item.label as any), - value: item.value, - defaultValueType: item.defaultValueType, - description: item.description ? t(item.description as any) : '' - })), - [t] - ); + const inputTypeList = useMemo(() => { + return variableConfigs + .map((group) => + group + .filter((item) => item && item.value !== VariableInputEnum.textarea) + .map((item) => ({ + icon: item.icon, + label: t(item.label as any), + value: item.value, + defaultValueType: item.defaultValueType, + description: item.description ? t(item.description as any) : '' + })) + ) + .filter((group) => group.length > 0); + }, [t]); const defaultValueType = useMemo(() => { - const item = inputTypeList.find((item) => item.value === type); + const item = inputTypeList.flat().find((item) => item.value === type); return item?.defaultValueType; }, [inputTypeList, type]); + const handleTypeChange = useCallback( + (newType: VariableInputEnum) => { + const defaultValIsNumber = !isNaN(Number(value.defaultValue)); + const currentType = value.type; + + const isCurrentTimeType = + currentType === VariableInputEnum.timePointSelect || + currentType === VariableInputEnum.timeRangeSelect; + const isNewTimeType = + newType === VariableInputEnum.timePointSelect || + newType === VariableInputEnum.timeRangeSelect; + + if ( + newType === VariableInputEnum.select || + newType === VariableInputEnum.multipleSelect || + (newType === VariableInputEnum.numberInput && !defaultValIsNumber) + ) { + setValue('defaultValue', ''); + } + + // Set time-related default values when switching from non-time type to time type + if (!isCurrentTimeType && isNewTimeType) { + setValue('defaultValue', ''); + setValue('timeGranularity', 'day'); + setValue( + 'timeRangeStart', + new Date( + new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).setHours(0, 0, 0, 0) + ).toISOString() + ); + setValue('timeRangeEnd', new Date(new Date().setHours(0, 0, 0, 0)).toISOString()); + } + + // Clear default value when switching from time type to other types + if (isCurrentTimeType && !isNewTimeType) { + setValue('defaultValue', ''); + } + + setValue('type', newType); + }, + [setValue, value.defaultValue, value.type] + ); + const formatVariables = useMemo(() => { const results = formatEditorVariablePickerIcon(variables); return results.map((item) => { @@ -137,14 +191,45 @@ const VariableEdit = ({ return; } - if (data.type !== VariableInputEnum.select && data.list) { + if ( + data.type !== VariableInputEnum.select && + data.type !== VariableInputEnum.multipleSelect && + data.list + ) { delete data.list; } - if (data.type === VariableInputEnum.custom) { + if (data.type !== VariableInputEnum.file) { + delete data.canSelectFile; + delete data.canSelectImg; + delete data.maxFiles; + } + + if ( + data.type !== VariableInputEnum.timePointSelect && + data.type !== VariableInputEnum.timeRangeSelect + ) { + delete data.timeGranularity; + delete data.timeRangeStart; + delete data.timeRangeEnd; + } else if (data.type === VariableInputEnum.timePointSelect) { + data.defaultValue = new Date(new Date().setHours(0, 0, 0, 0)).toISOString(); + } else if (data.type === VariableInputEnum.timeRangeSelect) { + data.defaultValue = [ + data.timeRangeStart || + new Date( + new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).setHours(0, 0, 0, 0) + ).toISOString(), + data.timeRangeEnd || new Date(new Date().setHours(0, 0, 0, 0)).toISOString() + ]; + } + + if (data.type === VariableInputEnum.custom || data.type === VariableInputEnum.internal) { data.required = false; } else { - data.valueType = inputTypeList.find((item) => item.value === data.type)?.defaultValueType; + data.valueType = inputTypeList + .flat() + .find((item) => item.value === data.type)?.defaultValueType; } const onChangeVariable = (() => { @@ -282,7 +367,7 @@ const VariableEdit = ({ title={t('common:core.module.Variable Setting')} isOpen={true} onClose={() => reset({})} - maxW={['90vw', '928px']} + maxW={['90vw', '1078px']} w={'100%'} isCentered > @@ -291,65 +376,67 @@ const VariableEdit = ({ {t('workflow:Variable.Variable type')} - - - {inputTypeList.map((item) => { - const isSelected = type === item.value; + + {inputTypeList.map((list, index) => { return ( svg': { - color: 'primary.600' - }, - '& > span': { - color: 'myGray.900' - }, - border: '1px solid #3370FF', - boxShadow: '0px 0px 0px 2.4px rgba(51, 112, 255, 0.15)' - }} - onClick={() => { - const defaultValIsNumber = !isNaN(Number(value.defaultValue)); - // 如果切换到 numberInput,不是数字,则清空 - if ( - item.value === VariableInputEnum.select || - (item.value === VariableInputEnum.numberInput && !defaultValIsNumber) - ) { - setValue('defaultValue', ''); - } - setValue('type', item.value); - }} + key={index} + display={'grid'} + gridTemplateColumns={'repeat(3, 1fr)'} + gap={4} + mt={3} > - - - {item.label} - - {item.description && ( - - )} + {list.map((item) => { + const isSelected = type === item.value; + return ( + svg': { + color: 'primary.600' + }, + '& > span': { + color: 'myGray.900' + }, + border: '1px solid #3370FF', + boxShadow: '0px 0px 0px 2.4px rgba(51, 112, 255, 0.15)' + }} + onClick={() => handleTypeChange(item.value)} + > + + + {item.label} + + {item.description && ( + + )} + + ); + })} ); })} - + { @@ -28,24 +30,25 @@ const getFlattenedErrorKeys = (errors: any, prefix = ''): string[] => { }; const LabelAndFormRender = ({ - formKey, label, required, placeholder, inputType, - variablesForm, showValueType, ...props }: { - formKey: string; label: string | React.ReactNode; required?: boolean; placeholder?: string; - variablesForm: UseFormReturn; showValueType?: boolean; + form: UseFormReturn; + fieldName: string; + + minLength?: number; } & SpecificProps & BoxProps) => { - const { control } = variablesForm; + const { t } = useSafeTranslation(); + const { control } = props.form; return ( @@ -56,9 +59,20 @@ const LabelAndFormRender = ({ { + if (!required || inputType === InputTypeEnum.switch) return true; + return !!value; + }, + ...(!!props?.minLength + ? { + minLength: { + value: props.minLength, + message: t(`common:min_length`, { minLength: props.minLength }) + } + } + : {}) }} render={({ field: { onChange, value }, fieldState: { error } }) => { return ( diff --git a/projects/app/src/components/core/app/formRender/TimeInput.tsx b/projects/app/src/components/core/app/formRender/TimeInput.tsx new file mode 100644 index 000000000..0eec86c1f --- /dev/null +++ b/projects/app/src/components/core/app/formRender/TimeInput.tsx @@ -0,0 +1,178 @@ +import React from 'react'; +import { Box, Flex } from '@chakra-ui/react'; +import DateTimePicker from '@fastgpt/web/components/common/DateTimePicker'; +import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput'; +import { useTranslation } from 'next-i18next'; + +type TimeInputProps = { + value?: Date; + onDateTimeChange: (date: Date) => void; + popPosition?: 'top' | 'bottom'; + timeGranularity?: 'day' | 'hour' | 'minute' | 'second'; + minDate?: Date; + maxDate?: Date; +}; + +const TimeInput: React.FC = ({ + value, + onDateTimeChange, + popPosition = 'bottom', + timeGranularity = 'second', + minDate, + maxDate +}) => { + const { t } = useTranslation(); + const hour = value ? value.getHours() : 0; + const minute = value ? value.getMinutes() : 0; + const second = value ? value.getSeconds() : 0; + + const validateAndSetDateTime = (newDate: Date) => { + if (minDate && newDate < minDate) { + onDateTimeChange(new Date(minDate)); + return; + } + if (maxDate && newDate > maxDate) { + onDateTimeChange(new Date(maxDate)); + return; + } + onDateTimeChange(newDate); + }; + + const handleDateChange = (date: Date) => { + const newDate = new Date(date); + newDate.setHours(hour, minute, second); + validateAndSetDateTime(newDate); + }; + + const handleHourChange = (newHour?: number) => { + const newDate = value ? new Date(value) : new Date(); + newDate.setHours(newHour || 0); + validateAndSetDateTime(newDate); + }; + + const handleMinuteChange = (newMinute?: number) => { + const newDate = value ? new Date(value) : new Date(); + newDate.setMinutes(newMinute || 0); + validateAndSetDateTime(newDate); + }; + + const handleSecondChange = (newSecond?: number) => { + const newDate = value ? new Date(value) : new Date(); + newDate.setSeconds(newSecond || 0); + validateAndSetDateTime(newDate); + }; + + const enableHour = ['hour', 'minute', 'second'].includes(timeGranularity); + const enableMinute = ['minute', 'second'].includes(timeGranularity); + const enableSecond = timeGranularity === 'second'; + + return ( + + + + + + {t('common:hour_unit')} + + + + + + {t('common:minute_unit')} + + + + + + {t('common:second_unit')} + + + + ); +}; + +export default TimeInput; diff --git a/projects/app/src/components/core/app/formRender/constant.ts b/projects/app/src/components/core/app/formRender/constant.ts index 70f4ba299..29530ab41 100644 --- a/projects/app/src/components/core/app/formRender/constant.ts +++ b/projects/app/src/components/core/app/formRender/constant.ts @@ -5,10 +5,13 @@ export enum InputTypeEnum { switch = 'switch', select = 'select', multipleSelect = 'multipleSelect', - + password = 'password', + timePointSelect = 'timePointSelect', + timeRangeSelect = 'timeRangeSelect', JSONEditor = 'JSONEditor', selectLLMModel = 'selectLLMModel', + selectDataset = 'selectDataset', fileSelect = 'fileSelect' } diff --git a/projects/app/src/components/core/app/formRender/index.tsx b/projects/app/src/components/core/app/formRender/index.tsx index 89d0cbb75..63c097590 100644 --- a/projects/app/src/components/core/app/formRender/index.tsx +++ b/projects/app/src/components/core/app/formRender/index.tsx @@ -1,17 +1,18 @@ -import React from 'react'; -import { Box, Switch } from '@chakra-ui/react'; +import React, { useMemo, useState } from 'react'; +import { Box, Input, Switch, Flex, IconButton } from '@chakra-ui/react'; +import MyIcon from '@fastgpt/web/components/common/Icon'; import type { InputRenderProps } from './type'; import { InputTypeEnum } from './constant'; import PromptEditor from '@fastgpt/web/components/common/Textarea/PromptEditor'; import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput'; import MySelect from '@fastgpt/web/components/common/MySelect'; -import MultipleSelect, { - useMultipleSelect -} from '@fastgpt/web/components/common/MySelect/MultipleSelect'; +import MultipleSelect from '@fastgpt/web/components/common/MySelect/MultipleSelect'; import JSONEditor from '@fastgpt/web/components/common/Textarea/JsonEditor'; import AIModelSelector from '../../../Select/AIModelSelector'; import FileSelector from '../../../Select/FileSelector'; +import TimeInput from './TimeInput'; import { useSafeTranslation } from '@fastgpt/web/hooks/useSafeTranslation'; +import { isSecretValue } from '@fastgpt/global/common/secret/utils'; const InputRender = (props: InputRenderProps) => { const { @@ -24,20 +25,23 @@ const InputRender = (props: InputRenderProps) => { placeholder, bg = 'white' } = props; + + const [isPasswordEditing, setIsPasswordEditing] = useState(false); + if (customRender) { return <>{customRender(props)}; } const { t } = useSafeTranslation(); - const { - value: selectedValue, - setValue, - isSelectAll, - setIsSelectAll - } = useMultipleSelect( - value, - inputType === InputTypeEnum.multipleSelect && value.length === (props.list?.length || 0) - ); + + const isSelectAll = useMemo(() => { + return ( + inputType === InputTypeEnum.multipleSelect && + Array.isArray(value) && + value.length === (props.list?.length || 0) + ); + // @ts-ignore + }, [inputType, value, props.list?.length]); const commonProps = { value, @@ -67,6 +71,7 @@ const InputRender = (props: InputRenderProps) => { return ( { ); } + if (inputType === InputTypeEnum.password) { + const isPasswordConfigured = isSecretValue(value); + return !isPasswordConfigured || isPasswordEditing ? ( + ); - }, [ - ScrollData, - showEmpty, - welcomeText, - variableList, - externalVariableList, - chatStarted, - chatForm, - chatType, - RecordsBox - ]); + }, [ScrollData, showEmpty, welcomeText, chatStarted, chatForm, chatType, RecordsBox]); const HomeChatRenderBox = useMemo(() => { return ( <> diff --git a/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/context.tsx b/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/context.tsx index 75d69920c..d8c677d3f 100644 --- a/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/context.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/context.tsx @@ -51,7 +51,7 @@ const PluginRunContextProvider = ({ const pluginInputs = useContextSelector(ChatItemContext, (v) => v.chatBoxData?.app?.pluginInputs); const setTab = useContextSelector(ChatItemContext, (v) => v.setPluginRunTab); - const variablesForm = useContextSelector(ChatItemContext, (v) => v.variablesForm); + const resetVariables = useContextSelector(ChatItemContext, (v) => v.resetVariables); const chatConfig = useContextSelector(ChatItemContext, (v) => v.chatBoxData?.app?.chatConfig); const setChatRecords = useContextSelector(ChatRecordContext, (v) => v.setChatRecords); @@ -158,14 +158,14 @@ const PluginRunContextProvider = ({ }) }; } else if (event === SseResponseEventEnum.updateVariables && variables) { - variablesForm.setValue('variables', variables); + resetVariables({ variables }); } return item; }) ); }, - [setChatRecords, variablesForm] + [setChatRecords, resetVariables] ); const isChatting = useMemo( diff --git a/projects/app/src/components/core/chat/ChatContainer/components/VariablePopover.tsx b/projects/app/src/components/core/chat/ChatContainer/components/VariablePopover.tsx new file mode 100644 index 000000000..8c7e03372 --- /dev/null +++ b/projects/app/src/components/core/chat/ChatContainer/components/VariablePopover.tsx @@ -0,0 +1,172 @@ +import { Box, Button, Flex } from '@chakra-ui/react'; +import MyPopover from '@fastgpt/web/components/common/MyPopover'; +import { useTranslation } from 'next-i18next'; +import MyIcon from '@fastgpt/web/components/common/Icon'; +import { useContextSelector } from 'use-context-selector'; +import { ChatItemContext } from '@/web/core/chat/context/chatItemContext'; +import { VariableInputEnum } from '@fastgpt/global/core/workflow/constants'; +import { useEffect, useMemo } from 'react'; +import MyDivider from '@fastgpt/web/components/common/MyDivider'; +import LabelAndFormRender from '@/components/core/app/formRender/LabelAndForm'; +import { variableInputTypeToInputType } from '@/components/core/app/formRender/utils'; +import { ChatTypeEnum } from '../ChatBox/constants'; +import type { VariableItemType } from '@fastgpt/global/core/app/type'; + +const VariablePopover = ({ chatType }: { chatType: ChatTypeEnum }) => { + const { t } = useTranslation(); + const variablesForm = useContextSelector(ChatItemContext, (v) => v.variablesForm); + const variables = useContextSelector( + ChatItemContext, + (v) => v.chatBoxData?.app?.chatConfig?.variables ?? [] + ); + + const showExternalVariables = [ChatTypeEnum.log, ChatTypeEnum.test, ChatTypeEnum.chat].includes( + chatType + ); + const showInternalVariables = [ChatTypeEnum.log, ChatTypeEnum.test].includes(chatType); + const { commonVariableList, externalVariableList, internalVariableList } = useMemo(() => { + const { + commonVariableList, + externalVariableList, + internalVariableList + }: { + commonVariableList: VariableItemType[]; + externalVariableList: VariableItemType[]; + internalVariableList: VariableItemType[]; + } = { + commonVariableList: [], + externalVariableList: [], + internalVariableList: [] + }; + variables.forEach((item) => { + if (item.type === VariableInputEnum.custom) { + externalVariableList.push(item); + } else if (item.type === VariableInputEnum.internal) { + internalVariableList.push(item); + } else { + commonVariableList.push(item); + } + }); + return { + externalVariableList: showExternalVariables ? externalVariableList : [], + internalVariableList: showInternalVariables ? internalVariableList : [], + commonVariableList + }; + }, [showExternalVariables, showInternalVariables, variables]); + + const hasVariables = + commonVariableList.length > 0 || + internalVariableList.length > 0 || + externalVariableList.length > 0; + + const { getValues, reset } = variablesForm; + + useEffect(() => { + const values = getValues(); + variables.forEach((item) => { + const val = getValues(`variables.${item.key}`); + if (item.defaultValue !== undefined && (val === undefined || val === null || val === '')) { + values.variables[item.key] = item.defaultValue; + } + }); + reset(values); + }, [getValues, reset, variables]); + + return hasVariables ? ( + }> + {t('common:core.module.Variable')} + + } + > + {({ onClose }) => ( + + {internalVariableList.length > 0 && ( + + + + {t('chat:internal_variables_tip')} + + {internalVariableList.map((item) => ( + + ))} + + )} + {internalVariableList.length > 0 && + [...commonVariableList, externalVariableList].length > 0 && } + + {externalVariableList.length > 0 && ( + + + + {t('chat:variable_invisable_in_share')} + + {externalVariableList.map((item) => ( + + ))} + + )} + {externalVariableList.length > 0 && commonVariableList.length > 0 && ( + + )} + + {commonVariableList.length > 0 && ( + + {commonVariableList.map((item) => ( + + ))} + + )} + + )} + + ) : null; +}; + +export default VariablePopover; diff --git a/projects/app/src/global/aiproxy/constants.ts b/projects/app/src/global/aiproxy/constants.ts index 9ab4a7f38..90ac9b48b 100644 --- a/projects/app/src/global/aiproxy/constants.ts +++ b/projects/app/src/global/aiproxy/constants.ts @@ -1,3 +1,4 @@ +import { useSystemStore } from '@/web/common/system/useSystemStore'; import { type ChannelInfoType } from './type'; import { i18nT } from '@fastgpt/web/i18n/utils'; @@ -26,10 +27,15 @@ export const ChannelStautsMap = { } }; +const firstProviderId = useSystemStore.getState().getModelProviders('en')[0]?.id; +const firstChannelType = + Object.entries(useSystemStore.getState().aiproxyIdMap).find( + ([id, item]) => item.provider === firstProviderId + )?.[0] || 1; export const defaultChannel: ChannelInfoType = { id: 0, status: ChannelStatusEnum.ChannelStatusEnabled, - type: 1, + type: Number(firstChannelType), created_at: 0, models: [], model_mapping: {}, diff --git a/projects/app/src/global/common/api/systemRes.d.ts b/projects/app/src/global/common/api/systemRes.d.ts deleted file mode 100644 index b9e541451..000000000 --- a/projects/app/src/global/common/api/systemRes.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { - LLMModelItemType, - EmbeddingModelItemType, - AudioSpeechModels, - STTModelType, - RerankModelItemType -} from '@fastgpt/global/core/ai/model.d'; - -import type { FastGPTFeConfigsType } from '@fastgpt/global/common/system/types/index.d'; -import type { SubPlanType } from '@fastgpt/global/support/wallet/sub/type'; -import type { SystemDefaultModelType, SystemModelItemType } from '@fastgpt/service/core/ai/type'; - -export type InitDateResponse = { - bufferId?: string; - - feConfigs?: FastGPTFeConfigsType; - subPlans?: SubPlanType; - systemVersion?: string; - - activeModelList?: SystemModelItemType[]; - defaultModels?: SystemDefaultModelType; -}; diff --git a/projects/app/src/instrumentation.ts b/projects/app/src/instrumentation.ts index ebaf45cba..0a69f20c9 100644 --- a/projects/app/src/instrumentation.ts +++ b/projects/app/src/instrumentation.ts @@ -19,7 +19,8 @@ export async function register() { { startTrainingQueue }, { preLoadWorker }, { loadSystemModels }, - { connectSignoz } + { connectSignoz }, + { getSystemTools } ] = await Promise.all([ import('@fastgpt/service/common/mongo/init'), import('@fastgpt/service/common/mongo/index'), @@ -32,7 +33,8 @@ export async function register() { import('@/service/core/dataset/training/utils'), import('@fastgpt/service/worker/preload'), import('@fastgpt/service/core/ai/config/utils'), - import('@fastgpt/service/common/otel/trace/register') + import('@fastgpt/service/common/otel/trace/register'), + import('@fastgpt/service/core/app/plugin/controller') ]); // connect to signoz @@ -49,16 +51,13 @@ export async function register() { //init system config;init vector database;init root user await Promise.all([getInitConfig(), initVectorStore(), initRootUser(), loadSystemModels()]); - try { - await preLoadWorker(); - } catch (error) { - console.error('Preload worker error', error); - } + await Promise.all([ + preLoadWorker().catch(), + getSystemTools(), + initSystemPluginGroups(), + initAppTemplateTypes() + ]); - // 异步加载 - initSystemPluginGroups(); - initAppTemplateTypes(); - // getSystemPlugins(true); startMongoWatch(); startCron(); startTrainingQueue(true); diff --git a/projects/app/src/pageComponents/account/model/AddModelBox.tsx b/projects/app/src/pageComponents/account/model/AddModelBox.tsx index e0049d04d..96eedadf2 100644 --- a/projects/app/src/pageComponents/account/model/AddModelBox.tsx +++ b/projects/app/src/pageComponents/account/model/AddModelBox.tsx @@ -18,11 +18,6 @@ import { } from '@chakra-ui/react'; import { useTranslation } from 'next-i18next'; import React, { useMemo, useRef, useState } from 'react'; -import { - getModelProviders, - type ModelProviderIdType, - getModelProvider -} from '@fastgpt/global/core/ai/provider'; import MySelect from '@fastgpt/web/components/common/MySelect'; import { ModelTypeEnum } from '@fastgpt/global/core/ai/model'; import Avatar from '@fastgpt/web/components/common/Avatar'; @@ -96,8 +91,7 @@ export const ModelEditModal = ({ onClose: () => void; }) => { const { t, i18n } = useTranslation(); - const language = i18n.language; - const { feConfigs } = useSystemStore(); + const { feConfigs, getModelProviders } = useSystemStore(); const { register, getValues, setValue, handleSubmit, watch, reset } = useForm({ @@ -113,8 +107,8 @@ export const ModelEditModal = ({ const provider = watch('provider'); - const providerList = useRef<{ label: React.ReactNode; value: ModelProviderIdType }[]>( - getModelProviders(language).map((item) => ({ + const providerList = useRef<{ label: React.ReactNode; value: string }[]>( + getModelProviders(i18n.language).map((item) => ({ label: ( diff --git a/projects/app/src/pageComponents/account/model/Channel/EditChannelModal.tsx b/projects/app/src/pageComponents/account/model/Channel/EditChannelModal.tsx index c2cd0c1e3..0220ba20c 100644 --- a/projects/app/src/pageComponents/account/model/Channel/EditChannelModal.tsx +++ b/projects/app/src/pageComponents/account/model/Channel/EditChannelModal.tsx @@ -1,4 +1,3 @@ -import { aiproxyIdMap } from '@fastgpt/global/sdk/fastgpt-plugin'; import { type ChannelInfoType } from '@/global/aiproxy/type'; import { Box, @@ -30,7 +29,6 @@ import type { ModelTypeEnum } from '@fastgpt/global/core/ai/model'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { getSystemModelList } from '@/web/core/ai/config'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; -import { getModelProvider } from '@fastgpt/global/core/ai/provider'; import MyIcon from '@fastgpt/web/components/common/Icon'; import MyAvatar from '@fastgpt/web/components/common/Avatar'; import MyTag from '@fastgpt/web/components/common/Tag/index'; @@ -41,6 +39,7 @@ import { getChannelProviders, postCreateChannel, putChannel } from '@/web/core/a import CopyBox from '@fastgpt/web/components/common/String/CopyBox'; import { parseI18nString } from '@fastgpt/global/common/i18n/utils'; import type { localeType } from '@fastgpt/global/common/i18n/type'; +import { defaultProvider } from '@fastgpt/global/core/ai/provider'; const ModelEditModal = dynamic(() => import('../AddModelBox').then((mod) => mod.ModelEditModal)); @@ -59,9 +58,7 @@ const EditChannelModal = ({ onSuccess: () => void; }) => { const { t, i18n } = useTranslation(); - const language = i18n.language as localeType; - - const { defaultModels } = useSystemStore(); + const { defaultModels, aiproxyIdMap, getModelProvider } = useSystemStore(); const isEdit = defaultConfig.id !== 0; const { register, handleSubmit, watch, setValue } = useForm({ @@ -78,14 +75,14 @@ const EditChannelModal = ({ name: value.name, provider: 'Other' }; - const provider = getModelProvider(mapData.provider, language); + const provider = getModelProvider(mapData.provider, i18n.language); return { order: provider.order, defaultBaseUrl: value.defaultBaseUrl, keyHelp: value.keyHelp, icon: mapData?.avatar ?? provider.avatar, - label: parseI18nString(mapData.name, language), + label: parseI18nString(mapData.name, i18n.language as localeType), value: Number(key) }; }) @@ -129,10 +126,10 @@ const EditChannelModal = ({ manual: false }); const modelList = useMemo(() => { - const currentProvider = aiproxyIdMap[providerType]?.provider; + const currentProvider = aiproxyIdMap[providerType] ?? defaultProvider; return systemModelList .map((item) => { - const provider = getModelProvider(item.provider, language); + const provider = getModelProvider(item.provider, i18n.language); return { provider: item.provider, @@ -143,11 +140,13 @@ const EditChannelModal = ({ }) .sort((a, b) => { // sort by provider, same provider first - if (a.provider === currentProvider && b.provider !== currentProvider) return -1; - if (a.provider !== currentProvider && b.provider === currentProvider) return 1; + if (a.provider === currentProvider.provider && b.provider !== currentProvider.provider) + return -1; + if (a.provider !== currentProvider.provider && b.provider === currentProvider.provider) + return 1; return 0; }); - }, [language, providerType, systemModelList]); + }, [aiproxyIdMap, getModelProvider, i18n.language, providerType, systemModelList]); const modelMapping = watch('model_mapping'); diff --git a/projects/app/src/pageComponents/account/model/Channel/ModelTest.tsx b/projects/app/src/pageComponents/account/model/Channel/ModelTest.tsx index 5d1d17b86..e1ebd778b 100644 --- a/projects/app/src/pageComponents/account/model/Channel/ModelTest.tsx +++ b/projects/app/src/pageComponents/account/model/Channel/ModelTest.tsx @@ -14,7 +14,6 @@ import { ModalBody, ModalFooter } from '@chakra-ui/react'; -import { getModelProvider } from '@fastgpt/global/core/ai/provider'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import React, { useRef, useState } from 'react'; import MyIcon from '@fastgpt/web/components/common/Icon'; @@ -26,6 +25,7 @@ import { getErrText } from '@fastgpt/global/common/error/utils'; import { batchRun } from '@fastgpt/global/common/system/utils'; import { useToast } from '@fastgpt/web/hooks/useToast'; import MyIconButton from '@fastgpt/web/components/common/Icon/button'; +import { useSystemStore } from '@/web/common/system/useSystemStore'; type ModelTestItem = { label: React.ReactNode; @@ -46,7 +46,7 @@ const ModelTest = ({ onClose: () => void; }) => { const { t, i18n } = useTranslation(); - const language = i18n.language; + const { getModelProvider } = useSystemStore(); const { toast } = useToast(); const [testModelList, setTestModelList] = useState([]); @@ -77,7 +77,7 @@ const ModelTest = ({ .map((model) => { const modelData = res.find((item) => item.model === model); if (!modelData) return null; - const provider = getModelProvider(modelData.provider, language); + const provider = getModelProvider(modelData.provider, i18n.language); return { label: ( diff --git a/projects/app/src/pageComponents/account/model/Channel/index.tsx b/projects/app/src/pageComponents/account/model/Channel/index.tsx index 9351d6694..5607c818e 100644 --- a/projects/app/src/pageComponents/account/model/Channel/index.tsx +++ b/projects/app/src/pageComponents/account/model/Channel/index.tsx @@ -26,14 +26,12 @@ import MyIconButton from '@fastgpt/web/components/common/Icon/button'; import { useUserStore } from '@/web/support/user/useUserStore'; import { type ChannelInfoType } from '@/global/aiproxy/type'; import MyTag from '@fastgpt/web/components/common/Tag/index'; -import { aiproxyIdMap } from '@fastgpt/global/sdk/fastgpt-plugin'; +import { useSystemStore } from '@/web/common/system/useSystemStore'; import { ChannelStatusEnum, ChannelStautsMap, defaultChannel } from '@/global/aiproxy/constants'; import MyMenu from '@fastgpt/web/components/common/MyMenu'; import dynamic from 'next/dynamic'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput'; -import { getModelProvider } from '@fastgpt/global/core/ai/provider'; -import MyIcon from '@fastgpt/web/components/common/Icon'; import { useConfirm } from '@fastgpt/web/hooks/useConfirm'; import { parseI18nString } from '@fastgpt/global/common/i18n/utils'; import type { localeType } from '@fastgpt/global/common/i18n/type'; @@ -46,6 +44,7 @@ const ChannelTable = ({ Tab }: { Tab: React.ReactNode }) => { const { t, i18n } = useTranslation(); const language = i18n.language as localeType; const { userInfo } = useUserStore(); + const { aiproxyIdMap, getModelProvider } = useSystemStore(); const isRoot = userInfo?.username === 'root'; @@ -129,16 +128,15 @@ const ChannelTable = ({ Tab }: { Tab: React.ReactNode }) => { name: channelProviders[item.type]?.name || 'Invalid provider', provider: 'Other' }; - const provider = getModelProvider(providerData?.provider, language); - + const provider = getModelProvider(providerData?.provider, i18n.language); return (
{item.id} {item.name} - - {parseI18nString(providerData.name, language)} + + {parseI18nString(providerData.name, i18n.language)} diff --git a/projects/app/src/pageComponents/account/model/Log/index.tsx b/projects/app/src/pageComponents/account/model/Log/index.tsx index 75e2e6aab..585abe8b3 100644 --- a/projects/app/src/pageComponents/account/model/Log/index.tsx +++ b/projects/app/src/pageComponents/account/model/Log/index.tsx @@ -18,7 +18,6 @@ import { GridItem, type BoxProps } from '@chakra-ui/react'; -import { getModelProvider } from '@fastgpt/global/core/ai/provider'; import DateRangePicker, { type DateRangeType } from '@fastgpt/web/components/common/DateRangePicker'; @@ -36,6 +35,7 @@ import MyModal from '@fastgpt/web/components/common/MyModal'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import SearchInput from '@fastgpt/web/components/common/Input/SearchInput'; import type { ChannelLogListItemType } from '@/global/aiproxy/type'; +import { useSystemStore } from '@/web/common/system/useSystemStore'; type LogDetailType = Omit & { channelName: string | number; @@ -50,8 +50,8 @@ type LogDetailType = Omit & { }; const ChannelLog = ({ Tab }: { Tab: React.ReactNode }) => { const { t, i18n } = useTranslation(); - const language = i18n.language; const { userInfo } = useUserStore(); + const { getModelProvider } = useSystemStore(); const isRoot = userInfo?.username === 'root'; const [filterProps, setFilterProps] = useState<{ @@ -104,7 +104,7 @@ const ChannelLog = ({ Tab }: { Tab: React.ReactNode }) => { const modelList = useMemo(() => { const res = systemModelList .map((item) => { - const provider = getModelProvider(item.provider, language); + const provider = getModelProvider(item.provider, i18n.language); return { order: provider.order, @@ -121,7 +121,7 @@ const ChannelLog = ({ Tab }: { Tab: React.ReactNode }) => { }, ...res ]; - }, [systemModelList, t]); + }, [getModelProvider, i18n.language, systemModelList, t]); const { data, isLoading, ScrollData } = useScrollPagination(getChannelLog, { pageSize: 20, @@ -144,7 +144,7 @@ const ChannelLog = ({ Tab }: { Tab: React.ReactNode }) => { const channelName = channelList.find((channel) => channel.value === `${item.channel}`)?.label; const model = systemModelList.find((model) => model.model === item.model); - const provider = getModelProvider(model?.provider); + const provider = getModelProvider(model?.provider, i18n.language); return { ...item, @@ -160,7 +160,7 @@ const ChannelLog = ({ Tab }: { Tab: React.ReactNode }) => { ttfb_milliseconds: item.ttfb_milliseconds ? item.ttfb_milliseconds / 1000 : 0 }; }); - }, [channelList, data, systemModelList]); + }, [channelList, data, getModelProvider, i18n.language, systemModelList]); const [logDetail, setLogDetail] = useState(); diff --git a/projects/app/src/pageComponents/account/model/ModelConfigTable.tsx b/projects/app/src/pageComponents/account/model/ModelConfigTable.tsx index 2716c17fc..7422a9d7b 100644 --- a/projects/app/src/pageComponents/account/model/ModelConfigTable.tsx +++ b/projects/app/src/pageComponents/account/model/ModelConfigTable.tsx @@ -18,11 +18,6 @@ import { } from '@chakra-ui/react'; import { useTranslation } from 'next-i18next'; import React, { useCallback, useMemo, useRef, useState } from 'react'; -import { - getModelProviders, - type ModelProviderIdType, - getModelProvider -} from '@fastgpt/global/core/ai/provider'; import MySelect from '@fastgpt/web/components/common/MySelect'; import { modelTypeList, ModelTypeEnum } from '@fastgpt/global/core/ai/model'; import SearchInput from '@fastgpt/web/components/common/Input/SearchInput'; @@ -60,16 +55,15 @@ const ModelEditModal = dynamic(() => import('./AddModelBox').then((mod) => mod.M const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => { const { t, i18n } = useTranslation(); - const language = i18n.language; const { userInfo } = useUserStore(); - const { defaultModels, feConfigs } = useSystemStore(); + const { defaultModels, feConfigs, getModelProviders, getModelProvider } = useSystemStore(); const isRoot = userInfo?.username === 'root'; - const [provider, setProvider] = useState(''); - const providerList = useRef<{ label: React.ReactNode; value: ModelProviderIdType | '' }[]>([ + const [provider, setProvider] = useState(''); + const providerList = useRef<{ label: React.ReactNode; value: string | '' }[]>([ { label: t('common:All'), value: '' }, - ...getModelProviders(language).map((item) => ({ + ...getModelProviders(i18n.language).map((item) => ({ label: ( @@ -217,7 +211,7 @@ const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => { })(); const formatList = list.map((item) => { - const provider = getModelProvider(item.provider, language); + const provider = getModelProvider(item.provider, i18n.language); return { ...item, avatar: provider.avatar, @@ -240,7 +234,16 @@ const ModelTable = ({ Tab }: { Tab: React.ReactNode }) => { }); return filterList; - }, [systemModelList, t, modelType, language, provider, search, showActive]); + }, [ + systemModelList, + t, + modelType, + getModelProvider, + i18n.language, + provider, + search, + showActive + ]); const activeModelLength = useMemo(() => { return modelList.filter((item) => item.isActive).length; }, [modelList]); diff --git a/projects/app/src/pageComponents/account/model/ModelDashboard/index.tsx b/projects/app/src/pageComponents/account/model/ModelDashboard/index.tsx index 8a312620f..aab9677cc 100644 --- a/projects/app/src/pageComponents/account/model/ModelDashboard/index.tsx +++ b/projects/app/src/pageComponents/account/model/ModelDashboard/index.tsx @@ -13,7 +13,6 @@ import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; import MySelect from '@fastgpt/web/components/common/MySelect'; import { getChannelList, getDashboardV2 } from '@/web/core/ai/channel'; import { getSystemModelList } from '@/web/core/ai/config'; -import { getModelProvider } from '@fastgpt/global/core/ai/provider'; import AreaChartComponent from '@fastgpt/web/components/common/charts/AreaChartComponent'; import FillRowTabs from '@fastgpt/web/components/common/Tabs/FillRowTabs'; import { useSystemStore } from '@/web/common/system/useSystemStore'; @@ -58,9 +57,8 @@ const getDefaultDateRange = (): DateRangeType => { const ModelDashboard = ({ Tab }: { Tab: React.ReactNode }) => { const { t, i18n } = useTranslation(); - const language = i18n.language; const theme = useTheme(); - const { feConfigs } = useSystemStore(); + const { feConfigs, getModelProvider } = useSystemStore(); const [viewMode, setViewMode] = useState<'chart' | 'table'>('chart'); @@ -114,7 +112,7 @@ const ModelDashboard = ({ Tab }: { Tab: React.ReactNode }) => { const modelList = useMemo(() => { const res = systemModelList .map((item) => { - const provider = getModelProvider(item.provider, language); + const provider = getModelProvider(item.provider, i18n.language); return { order: provider.order, icon: provider.avatar, diff --git a/projects/app/src/pageComponents/app/detail/MCPTools/ChatTest.tsx b/projects/app/src/pageComponents/app/detail/MCPTools/ChatTest.tsx index 65d4685dd..f88096d62 100644 --- a/projects/app/src/pageComponents/app/detail/MCPTools/ChatTest.tsx +++ b/projects/app/src/pageComponents/app/detail/MCPTools/ChatTest.tsx @@ -128,8 +128,8 @@ const ChatTest = ({ required={required} key={paramName} inputType={inputType} - formKey={paramName} - variablesForm={form} + form={form} + fieldName={paramName} placeholder={paramInfo.description} /> ); diff --git a/projects/app/src/pageComponents/app/detail/SimpleApp/ChatTest.tsx b/projects/app/src/pageComponents/app/detail/SimpleApp/ChatTest.tsx index f218ff2f2..4a7bdbf79 100644 --- a/projects/app/src/pageComponents/app/detail/SimpleApp/ChatTest.tsx +++ b/projects/app/src/pageComponents/app/detail/SimpleApp/ChatTest.tsx @@ -16,7 +16,8 @@ import { useChatStore } from '@/web/core/chat/context/useChatStore'; import MyBox from '@fastgpt/web/components/common/MyBox'; import { cardStyles } from '../constants'; import ChatQuoteList from '@/pageComponents/chat/ChatQuoteList'; -import VariablePopover from '@/components/core/chat/ChatContainer/ChatBox/components/VariablePopover'; +import VariablePopover from '@/components/core/chat/ChatContainer/components/VariablePopover'; +import { ChatTypeEnum } from '@/components/core/chat/ChatContainer/ChatBox/constants'; type Props = { appForm: AppSimpleEditFormType; @@ -68,7 +69,7 @@ const ChatTest = ({ appForm, setRenderEdit }: Props) => { {t('app:chat_debug')} - {!isVariableVisible && } + {!isVariableVisible && }
diff --git a/projects/app/src/pageComponents/app/detail/SimpleApp/components/ToolSelectModal.tsx b/projects/app/src/pageComponents/app/detail/SimpleApp/components/ToolSelectModal.tsx index 213b4897f..6d05845a9 100644 --- a/projects/app/src/pageComponents/app/detail/SimpleApp/components/ToolSelectModal.tsx +++ b/projects/app/src/pageComponents/app/detail/SimpleApp/components/ToolSelectModal.tsx @@ -2,6 +2,8 @@ import React, { useCallback, useMemo, useState } from 'react'; import MyModal from '@fastgpt/web/components/common/MyModal'; import { useTranslation } from 'next-i18next'; +import { parseI18nString } from '@fastgpt/global/common/i18n/utils'; +import type { localeType } from '@fastgpt/global/common/i18n/type'; import { Accordion, AccordionButton, @@ -220,7 +222,8 @@ const RenderList = React.memo(function RenderList({ type: TemplateTypeEnum; setParentId: (parentId: ParentIdType) => any; }) { - const { t } = useTranslation(); + const { t, i18n } = useTranslation(); + const lang = i18n.language as localeType; const [configTool, setConfigTool] = useState(); const onCloseConfigTool = useCallback(() => setConfigTool(undefined), []); const { toast } = useToast(); @@ -322,23 +325,45 @@ const RenderList = React.memo(function RenderList({ const data = (() => { if (type === TemplateTypeEnum.systemPlugin) { return pluginGroups.map((group) => { - const copy: NodeTemplateListType = group.groupTypes.map((type) => ({ - list: [], - type: type.typeId, - label: type.typeName - })); + const map = group.groupTypes.reduce< + Record< + string, + { + list: NodeTemplateListItemType[]; + label: string; + } + > + >((acc, item) => { + acc[item.typeId] = { + list: [], + label: t(parseI18nString(item.typeName, i18n.language)) + }; + return acc; + }, {}); + templates.forEach((item) => { - const index = copy.findIndex((template) => template.type === item.templateType); - if (index === -1) return; - copy[index].list.push(item); + if (map[item.templateType]) { + map[item.templateType].list.push({ + ...item, + name: t(parseI18nString(item.name, i18n.language)), + intro: t(parseI18nString(item.intro, i18n.language)) + }); + } }); return { label: group.groupName, - list: copy.filter((item) => item.list.length > 0) + list: Object.entries(map) + .map(([type, { list, label }]) => ({ + type, + label, + list + })) + .filter((item) => item.list.length > 0) }; }); } + // Team apps return [ { list: [ @@ -354,7 +379,7 @@ const RenderList = React.memo(function RenderList({ })(); return data.filter(({ list }) => list.length > 0); - }, [pluginGroups, templates, type]); + }, [i18n.language, pluginGroups, t, templates, type]); const gridStyle = useMemo(() => { if (type === TemplateTypeEnum.teamPlugin) { diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/ChatTest.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/ChatTest.tsx index 852f7037c..f21ea8a10 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/ChatTest.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/ChatTest.tsx @@ -21,8 +21,9 @@ import ChatRecordContextProvider, { import { useChatStore } from '@/web/core/chat/context/useChatStore'; import MyBox from '@fastgpt/web/components/common/MyBox'; import ChatQuoteList from '@/pageComponents/chat/ChatQuoteList'; -import VariablePopover from '@/components/core/chat/ChatContainer/ChatBox/components/VariablePopover'; +import VariablePopover from '@/components/core/chat/ChatContainer/components/VariablePopover'; import { useCopyData } from '@fastgpt/web/hooks/useCopyData'; +import { ChatTypeEnum } from '@/components/core/chat/ChatContainer/ChatBox/constants'; type Props = { isOpen: boolean; @@ -34,7 +35,7 @@ type Props = { const ChatTest = ({ isOpen, nodes = [], edges = [], onClose, chatId }: Props) => { const { t } = useTranslation(); - const { appDetail } = useContextSelector(AppContext, (v) => v); + const appDetail = useContextSelector(AppContext, (v) => v.appDetail); const isPlugin = appDetail.type === AppTypeEnum.plugin; const { copyData } = useCopyData(); @@ -132,7 +133,7 @@ const ChatTest = ({ isOpen, nodes = [], edges = [], onClose, chatId }: Props) => - {!isVariableVisible && } + {!isVariableVisible && } [] }) => void; @@ -87,11 +88,11 @@ const NodeTemplateListItem = ({ borderRadius={'sm'} /> - {t(template.name as any)} + {template.name} - {t(template.intro as any) || t('common:core.workflow.Not intro')} + {template.intro || t('common:core.workflow.Not intro')} { - const { t } = useTranslation(); + const { t, i18n } = useTranslation(); const { toast } = useToast(); const { computedNewNodeName } = useWorkflowUtils(); const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList); @@ -333,42 +334,101 @@ const NodeTemplateList = ({ const formatTemplatesArray = useMemoizedFn( ( type: TemplateTypeEnum, - templates: NodeTemplateListItemType[], - pluginGroups: any[] + templates: NodeTemplateListItemType[] ): { list: NodeTemplateListType; label: string }[] => { const data = (() => { + if (type === TemplateTypeEnum.basic) { + const map = workflowSystemNodeTemplateList.reduce< + Record< + string, + { + list: NodeTemplateListItemType[]; + label: string; + } + > + >((acc, item) => { + acc[item.type] = { + list: [], + label: t(item.label) + }; + return acc; + }, {}); + + templates.forEach((item) => { + if (map[item.templateType]) { + map[item.templateType].list.push({ + ...item, + name: t(item.name as any), + intro: t(item.intro as any) + }); + } + }); + + return [ + { + label: '', + list: Object.entries(map) + .map(([type, { list, label }]) => ({ + type, + label, + list + })) + .filter((item) => item.list.length > 0) + } + ]; + } + if (type === TemplateTypeEnum.systemPlugin) { return pluginGroups.map((group) => { - const copy: NodeTemplateListType = group.groupTypes.map((type: any) => ({ - list: [], - type: type.typeId, - label: type.typeName - })); + const map = group.groupTypes.reduce< + Record< + string, + { + list: NodeTemplateListItemType[]; + label: string; + } + > + >((acc, item) => { + acc[item.typeId] = { + list: [], + label: t(parseI18nString(item.typeName, i18n.language)) + }; + return acc; + }, {}); + templates.forEach((item) => { - const index = copy.findIndex((template) => template.type === item.templateType); - if (index === -1) return; - copy[index].list.push(item); + if (map[item.templateType]) { + map[item.templateType].list.push({ + ...item, + name: t(parseI18nString(item.name, i18n.language)), + intro: t(parseI18nString(item.intro, i18n.language)) + }); + } }); return { label: group.groupName, - list: copy.filter((item) => item.list.length > 0) + list: Object.entries(map) + .map(([type, { list, label }]) => ({ + type, + label, + list + })) + .filter((item) => item.list.length > 0) }; }); } - const copy: NodeTemplateListType = cloneDeep(workflowNodeTemplateList).map((item) => ({ - ...item, - list: [] - })); - templates.forEach((item) => { - const index = copy.findIndex((template) => template.type === item.templateType); - if (index === -1) return; - copy[index].list.push(item); - }); + // Team apps return [ { label: '', - list: copy.filter((item) => item.list.length > 0) + list: [ + { + type: '', + label: '', + list: templates + } + ] } ]; })(); @@ -377,8 +437,8 @@ const NodeTemplateList = ({ ); const formatTemplatesArrayData = useMemo( - () => formatTemplatesArray(templateType, templates, pluginGroups), - [templateType, templates, pluginGroups, formatTemplatesArray] + () => formatTemplatesArray(templateType, templates), + [templateType, templates, formatTemplatesArray] ); const PluginListRender = useMemoizedFn(({ list = [] }: { list: NodeTemplateListType }) => { @@ -394,15 +454,18 @@ const NodeTemplateList = ({ } })} > - - {t(item.label as any)} - + {!!item.label && ( + + {t(item.label as any)} + + )} + { const appDetail = useContextSelector(AppContext, (v) => v.appDetail); - const { filteredVar, customVar, variables } = useMemo(() => { + const { filteredVar, customVar, internalVar, variables } = useMemo(() => { const variables = appDetail.chatConfig?.variables || []; return { - filteredVar: variables.filter((item) => item.type !== VariableInputEnum.custom) || [], + filteredVar: + variables.filter( + (item) => + item.type !== VariableInputEnum.custom && item.type !== VariableInputEnum.internal + ) || [], customVar: variables.filter((item) => item.type === VariableInputEnum.custom) || [], + internalVar: variables.filter((item) => item.type === VariableInputEnum.internal) || [], variables }; }, [appDetail.chatConfig?.variables]); @@ -260,10 +265,21 @@ export const useDebug = () => { + ))} + {internalVar.map((item) => ( + ))} @@ -271,10 +287,10 @@ export const useDebug = () => { ))} @@ -284,10 +300,10 @@ export const useDebug = () => { ))} diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/InputTypeConfig.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/InputTypeConfig.tsx index 71471e3c7..73c856437 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/InputTypeConfig.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/InputTypeConfig.tsx @@ -30,11 +30,13 @@ import MyIcon from '@fastgpt/web/components/common/Icon'; import DndDrag, { Draggable } from '@fastgpt/web/components/common/DndDrag'; import MyTextarea from '@/components/common/Textarea/MyTextarea'; import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput'; +import TimeInput from '@/components/core/app/formRender/TimeInput'; import ChatFunctionTip from '@/components/core/app/Tip'; import MySlider from '@/components/Slider'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; +import RadioGroup from '@fastgpt/web/components/common/Radio/RadioGroup'; const InputTypeConfig = ({ form, @@ -81,9 +83,18 @@ const InputTypeConfig = ({ const maxLength = watch('maxLength'); const max = watch('max'); const min = watch('min'); + const minLength = watch('minLength'); const defaultValue = watch('defaultValue'); const valueType = watch('valueType'); + const timeGranularity = watch('timeGranularity'); + const timeType = watch('timeType'); + const timeRangeStart = watch('timeRangeStart'); + const timeRangeEnd = watch('timeRangeEnd'); + + const maxFiles = watch('maxFiles'); + const maxSelectFiles = Math.min(feConfigs?.uploadFileMaxAmount ?? 20, 50); + const selectValueTypeList = watch('customInputConfig.selectValueTypeList'); const { isSelectAll: isSelectAllValueType, setIsSelectAll: setIsSelectAllValueType } = useMultipleSelect(selectValueTypeList, false); @@ -116,13 +127,17 @@ const InputTypeConfig = ({ const showValueTypeSelect = inputType === FlowNodeInputTypeEnum.reference || inputType === FlowNodeInputTypeEnum.customVariable || - inputType === VariableInputEnum.custom; + inputType === VariableInputEnum.custom || + inputType === VariableInputEnum.internal; const showRequired = useMemo(() => { const list = [ FlowNodeInputTypeEnum.addInputParam, FlowNodeInputTypeEnum.customVariable, - VariableInputEnum.custom + VariableInputEnum.timePointSelect, + VariableInputEnum.timeRangeSelect, + VariableInputEnum.custom, + VariableInputEnum.internal ]; return !list.includes(inputType); }, [inputType]); @@ -145,7 +160,8 @@ const InputTypeConfig = ({ FlowNodeInputTypeEnum.switch, FlowNodeInputTypeEnum.select, FlowNodeInputTypeEnum.multipleSelect, - VariableInputEnum.custom + VariableInputEnum.custom, + VariableInputEnum.internal ]; return list.includes(inputType as FlowNodeInputTypeEnum); @@ -164,10 +180,6 @@ const InputTypeConfig = ({ return type === 'plugin' && list.includes(inputType as FlowNodeInputTypeEnum); }, [inputType, type]); - // File select - const maxFiles = watch('maxFiles'); - const maxSelectFiles = Math.min(feConfigs?.uploadFileMaxAmount ?? 20, 50); - return ( @@ -217,14 +229,14 @@ const InputTypeConfig = ({ /> ) : ( - + {defaultValueType ? t(FlowValueTypeMap[defaultValueType]?.label as any) : ''} )} )} {showRequired && ( - + {t('workflow:field_required')} @@ -234,7 +246,7 @@ const InputTypeConfig = ({ {/* reference */} {showIsToolInput && ( <> - + {t('workflow:field_used_as_tool_input')} @@ -294,6 +306,62 @@ const InputTypeConfig = ({ )} + {(inputType === VariableInputEnum.timePointSelect || + inputType === VariableInputEnum.timeRangeSelect) && ( + <> + + + {t('app:time_granularity')} + + setValue('timeGranularity', value)} + /> + + + + {t('app:time_range_limit')} + + + + + {t('app:time_range_start')} + + { + setValue('timeRangeStart', date); + }} + popPosition="top" + timeGranularity={timeGranularity} + maxDate={timeRangeEnd ? new Date(timeRangeEnd) : undefined} + /> + + + + {t('app:time_range_end')} + + { + setValue('timeRangeEnd', date); + }} + popPosition="top" + timeGranularity={timeGranularity} + minDate={timeRangeStart ? new Date(timeRangeStart) : undefined} + /> + + + + + )} + {showDefaultValue && ( @@ -301,7 +369,8 @@ const InputTypeConfig = ({ {(inputType === FlowNodeInputTypeEnum.numberInput || - (inputType === VariableInputEnum.custom && + ((inputType === VariableInputEnum.custom || + inputType === VariableInputEnum.internal) && valueType === WorkflowIOValueTypeEnum.number)) && ( )} {(inputType === FlowNodeInputTypeEnum.input || - (inputType === VariableInputEnum.custom && + ((inputType === VariableInputEnum.custom || + inputType === VariableInputEnum.internal) && valueType === WorkflowIOValueTypeEnum.string)) && ( )} {(inputType === FlowNodeInputTypeEnum.JSONEditor || - (inputType === VariableInputEnum.custom && + ((inputType === VariableInputEnum.custom || + inputType === VariableInputEnum.internal) && ![ WorkflowIOValueTypeEnum.number, WorkflowIOValueTypeEnum.string, @@ -342,9 +413,12 @@ const InputTypeConfig = ({ /> )} {(inputType === FlowNodeInputTypeEnum.switch || - (inputType === VariableInputEnum.custom && + ((inputType === VariableInputEnum.custom || + inputType === VariableInputEnum.internal) && valueType === WorkflowIOValueTypeEnum.boolean)) && ( - + + + )} {inputType === FlowNodeInputTypeEnum.select && ( @@ -539,7 +613,8 @@ const InputTypeConfig = ({ )} - {inputType === FlowNodeInputTypeEnum.fileSelect && ( + {(inputType === FlowNodeInputTypeEnum.fileSelect || + inputType === VariableInputEnum.file) && ( <> @@ -584,6 +659,22 @@ const InputTypeConfig = ({ )} + + {inputType === VariableInputEnum.password && ( + + + {t('common:core.module.Min Length')} + + { + setValue('minLength', e); + }} + /> + + )} diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeVariableUpdate.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeVariableUpdate.tsx index 1248d6447..32bd9dbba 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeVariableUpdate.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeVariableUpdate.tsx @@ -3,10 +3,10 @@ import NodeCard from './render/NodeCard'; import { type NodeProps } from 'reactflow'; import { type FlowNodeItemType } from '@fastgpt/global/core/workflow/type/node'; import { useTranslation } from 'next-i18next'; -import { Box, Button, Flex, Switch } from '@chakra-ui/react'; +import { Box, Button, Flex } from '@chakra-ui/react'; import { type TUpdateListItem } from '@fastgpt/global/core/workflow/template/system/variableUpdate/type'; import type { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants'; -import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants'; +import { NodeInputKeyEnum, VARIABLE_NODE_ID } from '@fastgpt/global/core/workflow/constants'; import { useContextSelector } from 'use-context-selector'; import { WorkflowContext } from '../../context'; import { @@ -30,8 +30,12 @@ import { isArray } from 'lodash'; import { WorkflowNodeEdgeContext } from '../../context/workflowInitContext'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import InputRender from '@/components/core/app/formRender'; -import { valueTypeToInputType } from '@/components/core/app/formRender/utils'; +import { + valueTypeToInputType, + variableInputTypeToInputType +} from '@/components/core/app/formRender/utils'; import { isValidReferenceValueFormat } from '@fastgpt/global/core/workflow/utils'; +import { InputTypeEnum } from '@/components/core/app/formRender/constant'; const NodeVariableUpdate = ({ data, selected }: NodeProps) => { const { inputs = [], nodeId } = data; @@ -102,6 +106,44 @@ const NodeVariableUpdate = ({ data, selected }: NodeProps) => const ValueRender = useMemoizedFn( ({ updateItem, index }: { updateItem: TUpdateListItem; index: number }) => { + const { inputType, formParams = {} } = (() => { + const value = updateItem.variable; + if (!value) { + return { + inputType: InputTypeEnum.input + }; + } + // Global variables: 根据变量的 inputType 决定 + if (value[0] === VARIABLE_NODE_ID) { + const variableList = appDetail.chatConfig.variables || []; + const variable = variableList.find((item) => item.key === value[1]); + if (variable) { + return { + inputType: variableInputTypeToInputType(variable.type), + formParams: { + min: variable.min, + max: variable.max, + list: variable.list + } + }; + } + } + // Node output: 根据数据类型决定 + else if (value[0] && value[1]) { + const output = nodeList + .find((node) => node.nodeId === value[0]) + ?.outputs.find((output) => output.id === value[1]); + if (output) { + return { + inputType: valueTypeToInputType(output.valueType) + }; + } + } + + return { + inputType: InputTypeEnum.input + }; + })(); const { valueType } = getRefData({ variable: updateItem.variable, nodeList, @@ -111,20 +153,17 @@ const NodeVariableUpdate = ({ data, selected }: NodeProps) => (item) => item.renderType === updateItem.renderType ); - const onUpdateNewValue = (newValue?: ReferenceValueType | string) => { - if (typeof newValue === 'string') { + const onUpdateNewValue = (value: any) => { + if (updateItem.renderType === FlowNodeInputTypeEnum.reference) { + onUpdateList( + updateList.map((update, i) => (i === index ? { ...update, value: value } : update)) + ); + } else { onUpdateList( updateList.map((update, i) => - i === index ? { ...update, value: ['', newValue] } : update + i === index ? { ...update, value: ['', value] } : update ) ); - } else if ( - Array.isArray(newValue) && - (isValidReferenceValueFormat(newValue) || newValue.every(isValidReferenceValueFormat)) - ) { - onUpdateList( - updateList.map((update, i) => (i === index ? { ...update, value: newValue } : update)) - ); } }; @@ -223,16 +262,16 @@ const NodeVariableUpdate = ({ data, selected }: NodeProps) => ); } - const inputValue = isArray(updateItem.value?.[1]) ? '' : updateItem.value?.[1]; - return ( ); diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/index.tsx index b45f8169c..fac03d3bb 100644 --- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/index.tsx +++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderInput/index.tsx @@ -74,6 +74,15 @@ const RenderList: Record< [FlowNodeInputTypeEnum.selectLLMModel]: { Component: CommonInputForm }, + [FlowNodeInputTypeEnum.timePointSelect]: { + Component: CommonInputForm + }, + [FlowNodeInputTypeEnum.timeRangeSelect]: { + Component: CommonInputForm + }, + [FlowNodeInputTypeEnum.password]: { + Component: CommonInputForm + }, [FlowNodeInputTypeEnum.customVariable]: undefined, [FlowNodeInputTypeEnum.hidden]: undefined, diff --git a/projects/app/src/pageComponents/app/detail/useChatTest.tsx b/projects/app/src/pageComponents/app/detail/useChatTest.tsx index 7580f87ef..9076a5d84 100644 --- a/projects/app/src/pageComponents/app/detail/useChatTest.tsx +++ b/projects/app/src/pageComponents/app/detail/useChatTest.tsx @@ -72,9 +72,12 @@ export const useChatTest = ({ ); const setChatBoxData = useContextSelector(ChatItemContext, (v) => v.setChatBoxData); + const variablesForm = useContextSelector(ChatItemContext, (v) => v.variablesForm); const resetVariables = useContextSelector(ChatItemContext, (v) => v.resetVariables); const clearChatRecords = useContextSelector(ChatItemContext, (v) => v.clearChatRecords); + const variableList = useMemo(() => chatConfig.variables, [chatConfig.variables]); + const pluginInputs = useMemo(() => { return nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.pluginInput)?.inputs || []; }, [nodes]); @@ -108,10 +111,9 @@ export const useChatTest = ({ async () => { if (!appId || !chatId) return; const res = await getInitChatInfo({ appId, chatId }); - resetVariables({ variables: res.variables, - variableList: res.app?.chatConfig?.variables + variableList: variableList ?? res.app?.chatConfig?.variables }); }, { @@ -125,6 +127,21 @@ export const useChatTest = ({ setChatId(); }, [clearChatRecords, setChatId]); + // 新增变量时候,自动加入默认值 + useEffect(() => { + const values = variablesForm.getValues(); + if (values.variables && variableList) { + variableList.forEach((item) => { + const val = variablesForm.getValues(`variables.${item.key}`); + if (item.defaultValue !== undefined && (val === undefined || val === null || val === '')) { + values.variables[item.key] = item.defaultValue; + } + }); + + variablesForm.reset(values); + } + }, [variableList, variablesForm]); + const CustomChatContainer = useMemoizedFn(() => appDetail.type === AppTypeEnum.plugin ? ( @@ -141,7 +158,7 @@ export const useChatTest = ({ appId={appId} chatId={chatId} showMarkIcon - chatType={ChatTypeEnum.chat} + chatType={ChatTypeEnum.test} onStartChat={startChat} /> ) diff --git a/projects/app/src/pageComponents/app/evaluation/DetailModal.tsx b/projects/app/src/pageComponents/app/evaluation/DetailModal.tsx index 0117c0f4c..8c957c426 100644 --- a/projects/app/src/pageComponents/app/evaluation/DetailModal.tsx +++ b/projects/app/src/pageComponents/app/evaluation/DetailModal.tsx @@ -1,4 +1,3 @@ -import { useSystemStore } from '@/web/common/system/useSystemStore'; import { Box, Button, @@ -13,7 +12,6 @@ import { AccordionIcon, Input } from '@chakra-ui/react'; -import { getModelFromList } from '@fastgpt/global/core/ai/model'; import Avatar from '@fastgpt/web/components/common/Avatar'; import MyModal from '@fastgpt/web/components/common/MyModal'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; @@ -27,7 +25,7 @@ import { updateEvalItem } from '@/web/core/app/api/evaluation'; import { usePagination } from '@fastgpt/web/hooks/usePagination'; -import { downloadFetch } from '@/web/common/system/utils'; +import { downloadFetch, getWebLLMModel } from '@/web/common/system/utils'; import PopoverConfirm from '@fastgpt/web/components/common/MyPopover/PopoverConfirm'; import { type TFunction } from 'i18next'; import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; @@ -89,11 +87,7 @@ const EvaluationDetailModal = ({ const [editing, setEditing] = useState(false); const [pollingInterval, setPollingInterval] = useState(10000); - const { llmModelList } = useSystemStore(); - const modelData = useMemo( - () => getModelFromList(llmModelList, evalDetail.evalModel, language), - [evalDetail.evalModel, llmModelList, language] - ); + const modelData = useMemo(() => getWebLLMModel(evalDetail.evalModel), [evalDetail.evalModel]); const { data: evalItemsList, diff --git a/projects/app/src/pageComponents/chat/ChatHeader.tsx b/projects/app/src/pageComponents/chat/ChatHeader.tsx index a16dc52e5..fd5a949a4 100644 --- a/projects/app/src/pageComponents/chat/ChatHeader.tsx +++ b/projects/app/src/pageComponents/chat/ChatHeader.tsx @@ -22,7 +22,7 @@ import { import { getMyApps } from '@/web/core/app/api'; import SelectOneResource from '@/components/common/folder/SelectOneResource'; import { ChatItemContext } from '@/web/core/chat/context/chatItemContext'; -import VariablePopover from '@/components/core/chat/ChatContainer/ChatBox/components/VariablePopover'; +import VariablePopover from '@/components/core/chat/ChatContainer/components/VariablePopover'; import { useCopyData } from '@fastgpt/web/hooks/useCopyData'; import { ChatSettingContext } from '@/web/core/chat/context/chatSettingContext'; import { @@ -32,6 +32,7 @@ import { import { useChatStore } from '@/web/core/chat/context/useChatStore'; import { usePathname } from 'next/navigation'; import type { ChatSettingReturnType } from '@fastgpt/global/core/chat/setting/type'; +import { ChatTypeEnum } from '@/components/core/chat/ChatContainer/ChatBox/constants'; const ChatHeader = ({ history, @@ -59,8 +60,8 @@ const ChatHeader = ({ const isVariableVisible = useContextSelector(ChatItemContext, (v) => v.isVariableVisible); const isPlugin = chatData.app.type === AppTypeEnum.plugin; - const isChat = pathname === '/chat'; const isShare = source === 'share'; + const chatType = isShare ? ChatTypeEnum.share : ChatTypeEnum.chat; return isPc && isPlugin ? null : ( - {!isVariableVisible && } + {!isVariableVisible && } {/* control */} {!isPlugin && } diff --git a/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/TagManageModal.tsx b/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/TagManageModal.tsx index fb80edb0b..452d22b80 100644 --- a/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/TagManageModal.tsx +++ b/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/TagManageModal.tsx @@ -286,7 +286,7 @@ const SaveTagForAppSubPanel = ({ /> - + {tag.name} ({checkedAppIds.length}) diff --git a/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/index.tsx b/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/index.tsx index 2d540d482..264d71fa8 100644 --- a/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/index.tsx +++ b/projects/app/src/pageComponents/chat/ChatSetting/FavouriteAppSetting/index.tsx @@ -148,29 +148,30 @@ const FavouriteAppSetting = ({ Header }: Props) => { if (!tag) return null; return ( - e.stopPropagation()} > {tag.name} - + ); }; return ( <> { - -
- - - - - - - - - + {/* 表头 */} + + + {t('chat:setting.favourite.table_column_name')} + + {t('chat:setting.favourite.table_column_intro')} + + + {t('chat:setting.favourite.table_column_category')} + + + {t('chat:setting.favourite.table_column_action')} + + + {/* 表格内容 */} + + {localFavourites.length > 0 ? ( dataList={localFavourites} renderInnerPlaceholder={false} @@ -243,53 +262,111 @@ const FavouriteAppSetting = ({ Header }: Props) => { }} > {({ provided }) => ( - + {localFavourites.map((row, index) => ( {(provided, snapshot) => ( - - {/* drag handle */} - + - {/* name */} - - - {/* intro */} - + - {/* tags */} - + - {/* action */} - - + {/* 操作列 */} + + { + setLocalFavourites((prev) => { + const next = prev.filter((_, i) => i !== index); + // reset order + const ordered = next.map((item, idx) => ({ + ...item, + order: idx + })); + deleteApp(row._id); + return ordered; + }); + }} + Trigger={ + e.stopPropagation()} + icon={} + /> + } + /> + + )} ))} {provided.placeholder} - + )} -
{t('chat:setting.favourite.table_column_name')}{t('chat:setting.favourite.table_column_intro')}{t('chat:setting.favourite.table_column_category')} - {t('chat:setting.favourite.table_column_action')} -
- - + {/* 拖拽手柄 */} + + e.stopPropagation()} + > + + + + + {/* 名称列 */} + + + + {row.name || ''} - - - - {row.name || ''} - - - - {row.intro || ''} + {/* 介绍列 */} + + + + {row.intro || t('common:no_intro')} + + } + > + {() => ( + + {row.intro || t('common:no_intro')} + + )} + - - - {row.favouriteTags.slice(0, 3).map((id) => ( + {/* 标签列 */} + + + {row.favouriteTags.slice(0, 2).map((id) => ( ))} - {row.favouriteTags.length > 3 && ( + {row.favouriteTags.length > 2 && ( { px="1.5" py="0.5" cursor="pointer" - minW="40px" + minW="30px" textAlign="center" onClick={(e) => e.stopPropagation()} > - +{row.favouriteTags.length - 3} + +{row.favouriteTags.length - 2} } > @@ -315,10 +392,10 @@ const FavouriteAppSetting = ({ Header }: Props) => { p="2" gap="2" flexWrap="wrap" - maxW="200px" + maxW="300px" onClick={(e) => e.stopPropagation()} > - {row.favouriteTags.slice(3).map((id) => ( + {row.favouriteTags.map((id) => ( ))} @@ -326,51 +403,54 @@ const FavouriteAppSetting = ({ Header }: Props) => { )} - - - { - setLocalFavourites((prev) => { - const next = prev.filter((_, i) => i !== index); - // reset order - const ordered = next.map((item, idx) => ({ - ...item, - order: idx - })); - deleteApp(row._id); - return ordered; - }); - }} - Trigger={ - - } - /> - } - /> - -
- {localFavourites.length === 0 && } - + ) : ( + + )} + {isOpenTagManageModal && ( diff --git a/projects/app/src/pageComponents/chat/ChatSetting/ToolSelectModal.tsx b/projects/app/src/pageComponents/chat/ChatSetting/ToolSelectModal.tsx index 6892613c7..f42586062 100644 --- a/projects/app/src/pageComponents/chat/ChatSetting/ToolSelectModal.tsx +++ b/projects/app/src/pageComponents/chat/ChatSetting/ToolSelectModal.tsx @@ -14,6 +14,8 @@ import { Flex, Grid } from '@chakra-ui/react'; +import { parseI18nString } from '@fastgpt/global/common/i18n/utils'; +import type { localeType } from '@fastgpt/global/common/i18n/type'; import FillRowTabs from '@fastgpt/web/components/common/Tabs/FillRowTabs'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; @@ -159,7 +161,7 @@ const RenderList = React.memo(function RenderList({ templates: NodeTemplateListItemType[]; setParentId: (parentId: ParentIdType) => any; }) { - const { t } = useTranslation(); + const { t, i18n } = useTranslation(); const [configTool, setConfigTool] = useState(); const onCloseConfigTool = useCallback(() => setConfigTool(undefined), []); const { toast } = useToast(); @@ -258,25 +260,44 @@ const RenderList = React.memo(function RenderList({ }); const formatTemplatesArray = useMemo(() => { - const data = pluginGroups.map((group) => { - const copy: NodeTemplateListType = group.groupTypes.map((type) => ({ - list: [], - type: type.typeId, - label: type.typeName - })); + return pluginGroups.map((group) => { + const map = group.groupTypes.reduce< + Record< + string, + { + list: NodeTemplateListItemType[]; + label: string; + } + > + >((acc, item) => { + acc[item.typeId] = { + list: [], + label: t(parseI18nString(item.typeName, i18n.language)) + }; + return acc; + }, {}); + templates.forEach((item) => { - const index = copy.findIndex((template) => template.type === item.templateType); - if (index === -1) return; - copy[index].list.push(item); + if (map[item.templateType]) { + map[item.templateType].list.push({ + ...item, + name: t(parseI18nString(item.name, i18n.language)), + intro: t(parseI18nString(item.intro, i18n.language)) + }); + } }); return { label: group.groupName, - list: copy.filter((item) => item.list.length > 0) + list: Object.entries(map) + .map(([type, { list, label }]) => ({ + type, + label, + list + })) + .filter((item) => item.list.length > 0) }; }); - - return data.filter(({ list }) => list.length > 0); - }, [pluginGroups, templates]); + }, [i18n.language, pluginGroups, t, templates]); const gridStyle = { gridTemplateColumns: ['1fr', '1fr 1fr'], @@ -320,11 +341,11 @@ const RenderList = React.memo(function RenderList({ borderRadius={'sm'} /> - {t(template.name as any)} + {template.name} - {t(template.intro as any) || t('common:core.workflow.Not intro')} + {template.intro || t('common:core.workflow.Not intro')} {/* {type === TemplateTypeEnum.systemPlugin && ( React.ReactNode; }) => { const router = useRouter(); - const { t } = useTranslation(); + const { t, i18n } = useTranslation(); const { isPc } = useSystem(); const { feConfigs } = useSystemStore(); const { isOpen: isOpenSidebar, onOpen: onOpenSidebar, onClose: onCloseSidebar } = useDisclosure(); @@ -149,7 +147,7 @@ const DashboardContainer = ({ groupName: t(group.groupName as any), children: group.groupTypes.map((type, index) => ({ typeId: type.typeId, - typeName: t(type.typeName as any), + typeName: parseI18nString(type.typeName, i18n.language), isActive: index === 0 && !currentType })) })), @@ -208,6 +206,7 @@ const DashboardContainer = ({ currentType, feConfigs.appTemplateCourse, feConfigs?.isPlus, + i18n.language, pluginGroups, t, templateList, diff --git a/projects/app/src/pageComponents/dashboard/SystemPlugin/ToolCard.tsx b/projects/app/src/pageComponents/dashboard/SystemPlugin/ToolCard.tsx index f362b4f15..5063ae5ef 100644 --- a/projects/app/src/pageComponents/dashboard/SystemPlugin/ToolCard.tsx +++ b/projects/app/src/pageComponents/dashboard/SystemPlugin/ToolCard.tsx @@ -6,22 +6,23 @@ import React from 'react'; import { useTranslation } from 'next-i18next'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { type NodeTemplateListItemType } from '@fastgpt/global/core/workflow/type/node'; -import { type PluginGroupSchemaType } from '@fastgpt/service/core/app/plugin/type'; +import { type SystemToolGroupSchemaType } from '@fastgpt/service/core/app/plugin/type'; import UseGuideModal from '@/components/common/Modal/UseGuideModal'; +import { parseI18nString } from '@fastgpt/global/common/i18n/utils'; const PluginCard = ({ item, groups }: { item: NodeTemplateListItemType; - groups: PluginGroupSchemaType[]; + groups: SystemToolGroupSchemaType[]; }) => { - const { t } = useTranslation(); + const { t, i18n } = useTranslation(); const { feConfigs } = useSystemStore(); const type = groups.reduce((acc, group) => { const foundType = group.groupTypes.find((type) => type.typeId === item.templateType); - return foundType ? foundType.typeName : acc; + return foundType ? parseI18nString(foundType.typeName, i18n.language) : acc; }, undefined); return ( diff --git a/projects/app/src/pageComponents/dataset/list/List.tsx b/projects/app/src/pageComponents/dataset/list/List.tsx index eaac38081..a80be53fd 100644 --- a/projects/app/src/pageComponents/dataset/list/List.tsx +++ b/projects/app/src/pageComponents/dataset/list/List.tsx @@ -30,13 +30,12 @@ import MyBox from '@fastgpt/web/components/common/MyBox'; import { useTranslation } from 'next-i18next'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; import SideTag from './SideTag'; -import { getModelProvider } from '@fastgpt/global/core/ai/provider'; import UserBox from '@fastgpt/web/components/common/UserBox'; const EditResourceModal = dynamic(() => import('@/components/common/Modal/EditResourceModal')); function List() { - const { setLoading } = useSystemStore(); + const { setLoading, getModelProvider } = useSystemStore(); const { isPc } = useSystem(); const { t } = useTranslation(); const { diff --git a/projects/app/src/pageComponents/login/index.tsx b/projects/app/src/pageComponents/login/index.tsx index a69db60c5..cea603642 100644 --- a/projects/app/src/pageComponents/login/index.tsx +++ b/projects/app/src/pageComponents/login/index.tsx @@ -191,7 +191,7 @@ export const LoginContainer = ({ const { feConfigs } = useSystemStore(); const { setLastChatAppId } = useChatStore(); - const [pageType, setPageType] = useState<`${LoginPageTypeEnum}` | null>(null); + const [pageType, setPageType] = useState<`${LoginPageTypeEnum}`>(LoginPageTypeEnum.passwordLogin); const [showCommunityModal, setShowCommunityModal] = useState(false); // login success handler @@ -204,10 +204,6 @@ export const LoginContainer = ({ // initialization logic useEffect(() => { - setPageType( - feConfigs?.oauth?.wechat ? LoginPageTypeEnum.wechat : LoginPageTypeEnum.passwordLogin - ); - // reset chat state setLastChatAppId(''); }, [feConfigs?.oauth?.wechat, setLastChatAppId]); diff --git a/projects/app/src/pages/api/common/system/getInitData.ts b/projects/app/src/pages/api/common/system/getInitData.ts index 1e46e4048..ccc91ee2a 100644 --- a/projects/app/src/pages/api/common/system/getInitData.ts +++ b/projects/app/src/pages/api/common/system/getInitData.ts @@ -1,8 +1,27 @@ import type { NextApiResponse } from 'next'; import { type ApiRequestProps } from '@fastgpt/service/type/next'; import { NextAPI } from '@/service/middleware/entry'; -import { type InitDateResponse } from '@/global/common/api/systemRes'; import { authCert } from '@fastgpt/service/support/permission/auth/common'; +import type { FastGPTFeConfigsType } from '@fastgpt/global/common/system/types'; +import type { SubPlanType } from '@fastgpt/global/support/wallet/sub/type'; +import type { SystemDefaultModelType, SystemModelItemType } from '@fastgpt/service/core/ai/type'; +import type { + AiproxyMapProviderType, + I18nStringStrictType +} from '@fastgpt/global/sdk/fastgpt-plugin'; + +export type InitDateResponse = { + bufferId?: string; + + feConfigs?: FastGPTFeConfigsType; + subPlans?: SubPlanType; + systemVersion?: string; + + activeModelList?: SystemModelItemType[]; + defaultModels?: SystemDefaultModelType; + modelProviders?: { provider: string; value: I18nStringStrictType }[]; + aiproxyIdMap?: AiproxyMapProviderType; +}; async function handler( req: ApiRequestProps<{}, { bufferId?: string }>, @@ -26,7 +45,9 @@ async function handler( subPlans: global.subPlans, systemVersion: global.systemVersion, activeModelList: global.systemActiveDesensitizedModels, - defaultModels: global.systemDefaultModel + defaultModels: global.systemDefaultModel, + modelProviders: global.ModelProviderRawCache, + aiproxyIdMap: global.aiproxyIdMapCache }; } catch (error) { const referer = req.headers.referer; @@ -34,6 +55,8 @@ async function handler( return { feConfigs: global.feConfigs, subPlans: global.subPlans, + modelProviders: global.ModelProviderRawCache, + aiproxyIdMap: global.aiproxyIdMapCache, activeModelList: global.systemActiveDesensitizedModels }; } @@ -41,13 +64,17 @@ async function handler( const unAuthBufferId = global.systemInitBufferId ? `unAuth_${global.systemInitBufferId}` : ''; if (bufferId && unAuthBufferId === bufferId) { return { - bufferId: unAuthBufferId + bufferId: unAuthBufferId, + modelProviders: global.ModelProviderRawCache, + aiproxyIdMap: global.aiproxyIdMapCache }; } return { bufferId: unAuthBufferId, - feConfigs: global.feConfigs + feConfigs: global.feConfigs, + modelProviders: global.ModelProviderRawCache, + aiproxyIdMap: global.aiproxyIdMapCache }; } } diff --git a/projects/app/src/pages/api/core/ai/model/list.ts b/projects/app/src/pages/api/core/ai/model/list.ts index 620b589a6..d3e1d940a 100644 --- a/projects/app/src/pages/api/core/ai/model/list.ts +++ b/projects/app/src/pages/api/core/ai/model/list.ts @@ -1,6 +1,5 @@ import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next'; import { NextAPI } from '@/service/middleware/entry'; -import { type ModelProviderIdType } from '@fastgpt/global/core/ai/provider'; import type { ModelTypeEnum } from '@fastgpt/global/core/ai/model'; import { authSystemAdmin } from '@fastgpt/service/support/permission/user/auth'; @@ -12,7 +11,7 @@ export type listResponse = { type: `${ModelTypeEnum}`; name: string; avatar: string | undefined; - provider: ModelProviderIdType; + provider: string; model: string; charsPointsPrice?: number; inputPrice?: number; diff --git a/projects/app/src/pages/api/core/app/plugin/getSystemPluginTemplates.ts b/projects/app/src/pages/api/core/app/plugin/getSystemPluginTemplates.ts index d8934123e..fcc8c387b 100644 --- a/projects/app/src/pages/api/core/app/plugin/getSystemPluginTemplates.ts +++ b/projects/app/src/pages/api/core/app/plugin/getSystemPluginTemplates.ts @@ -3,13 +3,13 @@ import { NextAPI } from '@/service/middleware/entry'; import { type ParentIdType } from '@fastgpt/global/common/parentFolder/type'; import { type ApiRequestProps } from '@fastgpt/service/type/next'; import { replaceRegChars } from '@fastgpt/global/common/string/tools'; -import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants'; import { parseI18nString } from '@fastgpt/global/common/i18n/utils'; import { getLocale } from '@fastgpt/service/common/middle/i18n'; import { authCert } from '@fastgpt/service/support/permission/auth/common'; import type { NextApiResponse } from 'next'; import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; import { getSystemTools } from '@fastgpt/service/core/app/plugin/controller'; +import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants'; export type GetSystemPluginTemplatesBody = { searchKey?: string; diff --git a/projects/app/src/pages/api/core/app/plugin/getToolGroups.ts b/projects/app/src/pages/api/core/app/plugin/getToolGroups.ts new file mode 100644 index 000000000..b74db893e --- /dev/null +++ b/projects/app/src/pages/api/core/app/plugin/getToolGroups.ts @@ -0,0 +1,29 @@ +import { NextAPI } from '@/service/middleware/entry'; +import { MongoToolGroups } from '@fastgpt/service/core/app/plugin/pluginGroupSchema'; +import type { SystemToolGroupSchemaType } from '@fastgpt/service/core/app/plugin/type'; +import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next'; + +export type getPluginGroupsQuery = {}; + +export type getPluginGroupsBody = {}; + +export type getPluginGroupsResponse = SystemToolGroupSchemaType[]; + +async function handler( + req: ApiRequestProps, + res: ApiResponseType +): Promise { + const groups = await MongoToolGroups.find().sort({ groupOrder: 1 }); + + return groups + .map((item) => ({ + groupId: item.groupId, + groupName: item.groupName, + groupAvatar: item.groupAvatar, + groupTypes: item.groupTypes.filter((item) => global.systemToolsTypeCache[item.typeId]), + groupOrder: item.groupOrder + })) + .filter((item) => item.groupTypes.length > 0); +} + +export default NextAPI(handler); diff --git a/projects/app/src/pages/api/core/app/template/detail.ts b/projects/app/src/pages/api/core/app/template/detail.ts index 6b49cec50..a17910d10 100644 --- a/projects/app/src/pages/api/core/app/template/detail.ts +++ b/projects/app/src/pages/api/core/app/template/detail.ts @@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next'; import { authCert } from '@fastgpt/service/support/permission/auth/common'; import { NextAPI } from '@/service/middleware/entry'; import { type AppTemplateSchemaType } from '@fastgpt/global/core/app/type'; -import { getAppTemplatesAndLoadThem } from '@fastgpt/templates/register'; +import { getAppTemplatesAndLoadThem } from '@fastgpt/service/core/app/templates/register'; type Props = { templateId: string; diff --git a/projects/app/src/pages/api/core/app/template/list.ts b/projects/app/src/pages/api/core/app/template/list.ts index 09d0d0ea9..5280662c8 100644 --- a/projects/app/src/pages/api/core/app/template/list.ts +++ b/projects/app/src/pages/api/core/app/template/list.ts @@ -1,7 +1,7 @@ import type { NextApiResponse } from 'next'; import { authCert } from '@fastgpt/service/support/permission/auth/common'; import { NextAPI } from '@/service/middleware/entry'; -import { getAppTemplatesAndLoadThem } from '@fastgpt/templates/register'; +import { getAppTemplatesAndLoadThem } from '@fastgpt/service/core/app/templates/register'; import { type AppTemplateSchemaType } from '@fastgpt/global/core/app/type'; import type { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { type ApiRequestProps } from '@fastgpt/service/type/next'; diff --git a/projects/app/src/pages/api/v2/chat/completions.ts b/projects/app/src/pages/api/v2/chat/completions.ts index 13e309066..21b733fcf 100644 --- a/projects/app/src/pages/api/v2/chat/completions.ts +++ b/projects/app/src/pages/api/v2/chat/completions.ts @@ -56,6 +56,7 @@ import { } from '@fastgpt/global/core/workflow/utils'; import { getNanoid } from '@fastgpt/global/common/string/tools'; import { getSystemTime } from '@fastgpt/global/common/time/timezone'; + import { rewriteNodeOutputByHistories } from '@fastgpt/global/core/workflow/runtime/utils'; import { getWorkflowResponseWrite } from '@fastgpt/service/core/workflow/dispatch/utils'; import { WORKFLOW_MAX_RUN_TIMES } from '@fastgpt/service/core/workflow/constants'; diff --git a/projects/app/src/service/common/system/index.ts b/projects/app/src/service/common/system/index.ts index 79930c8d8..8c222524f 100644 --- a/projects/app/src/service/common/system/index.ts +++ b/projects/app/src/service/common/system/index.ts @@ -3,12 +3,11 @@ import fs, { existsSync } from 'fs'; import type { FastGPTFeConfigsType } from '@fastgpt/global/common/system/types/index.d'; import type { FastGPTConfigFileType } from '@fastgpt/global/common/system/types/index.d'; import { getFastGPTConfigFromDB } from '@fastgpt/service/common/system/config/controller'; -import { FastGPTProUrl } from '@fastgpt/service/common/system/constants'; import { isProduction } from '@fastgpt/global/common/system/constants'; import { initFastGPTConfig } from '@fastgpt/service/common/system/tools'; import json5 from 'json5'; import { defaultGroup, defaultTemplateTypes } from '@fastgpt/web/core/workflow/constants'; -import { MongoPluginGroups } from '@fastgpt/service/core/app/plugin/pluginGroupSchema'; +import { MongoToolGroups } from '@fastgpt/service/core/app/plugin/pluginGroupSchema'; import { MongoTemplateTypes } from '@fastgpt/service/core/app/templates/templateTypeSchema'; import { POST } from '@fastgpt/service/common/api/plusRequest'; import { @@ -21,6 +20,7 @@ import { type CreateUsageProps } from '@fastgpt/global/support/wallet/usage/api'; import { isProVersion } from './constants'; +import { getSystemToolTypes } from '@fastgpt/service/core/app/tool/api'; export const readConfigData = async (name: string) => { const splitName = name.split('.'); @@ -167,17 +167,28 @@ export async function initSystemConfig() { export async function initSystemPluginGroups() { try { const { groupOrder, ...restDefaultGroup } = defaultGroup; - await MongoPluginGroups.updateOne( - { - groupId: defaultGroup.groupId - }, - { - $set: restDefaultGroup - }, - { - upsert: true - } - ); + + const toolTypes = await getSystemToolTypes(); + + if (toolTypes.length > 0) { + await MongoToolGroups.updateOne( + { + groupId: defaultGroup.groupId + }, + { + $set: { + ...restDefaultGroup, + groupTypes: toolTypes.map((toolType) => ({ + typeId: toolType.type, + typeName: toolType.name + })) + } + }, + { + upsert: true + } + ); + } } catch (error) { console.error('Error initializing system plugins:', error); } diff --git a/projects/app/src/service/common/system/volumnMongoWatch.ts b/projects/app/src/service/common/system/volumnMongoWatch.ts index bd31565cd..08edaf921 100644 --- a/projects/app/src/service/common/system/volumnMongoWatch.ts +++ b/projects/app/src/service/common/system/volumnMongoWatch.ts @@ -3,7 +3,7 @@ import { createDatasetTrainingMongoWatch } from '@/service/core/dataset/training import { MongoSystemConfigs } from '@fastgpt/service/common/system/config/schema'; import { debounce } from 'lodash'; import { MongoAppTemplate } from '@fastgpt/service/core/app/templates/templateSchema'; -import { getAppTemplatesAndLoadThem } from '@fastgpt/templates/register'; +import { getAppTemplatesAndLoadThem } from '@fastgpt/service/core/app/templates/register'; import { watchSystemModelUpdate } from '@fastgpt/service/core/ai/config/utils'; import { SystemConfigsTypeEnum } from '@fastgpt/global/common/system/config/constants'; import { refetchSystemPlugins } from '@fastgpt/service/core/app/plugin/controller'; diff --git a/projects/app/src/web/common/system/api.ts b/projects/app/src/web/common/system/api.ts index c7e655829..ec78d985b 100644 --- a/projects/app/src/web/common/system/api.ts +++ b/projects/app/src/web/common/system/api.ts @@ -1,4 +1,4 @@ -import type { InitDateResponse } from '@/global/common/api/systemRes'; +import type { InitDateResponse } from '@/pages/api/common/system/getInitData'; import { GET } from '@/web/common/api/request'; export const getSystemInitData = (bufferId?: string) => diff --git a/projects/app/src/web/common/system/useSystemStore.ts b/projects/app/src/web/common/system/useSystemStore.ts index e8c758610..5ab20a5f4 100644 --- a/projects/app/src/web/common/system/useSystemStore.ts +++ b/projects/app/src/web/common/system/useSystemStore.ts @@ -8,12 +8,18 @@ import type { EmbeddingModelItemType, STTModelType } from '@fastgpt/global/core/ai/model.d'; -import { type InitDateResponse } from '@/global/common/api/systemRes'; +import type { InitDateResponse } from '@/pages/api/common/system/getInitData'; import { type FastGPTFeConfigsType } from '@fastgpt/global/common/system/types'; import { type SubPlanType } from '@fastgpt/global/support/wallet/sub/type'; import { ModelTypeEnum } from '@fastgpt/global/core/ai/model'; import type { TeamErrEnum } from '@fastgpt/global/common/error/code/team'; -import { type SystemDefaultModelType } from '@fastgpt/service/core/ai/type'; +import type { SystemDefaultModelType } from '@fastgpt/service/core/ai/type'; +import { + defaultProvider, + formatModelProviders, + type langType, + type ModelProviderItemType +} from '@fastgpt/global/core/ai/provider'; type LoginStoreType = { provider: `${OAuthEnum}`; lastRoute: string; state: string }; @@ -48,15 +54,23 @@ type State = { feConfigs: FastGPTFeConfigsType; subPlans?: SubPlanType; systemVersion: string; + + modelProviders: Record; + modelProviderMap: Record>; + aiproxyIdMap: NonNullable; defaultModels: SystemDefaultModelType; llmModelList: LLMModelItemType[]; datasetModelList: LLMModelItemType[]; - getVlmModelList: () => LLMModelItemType[]; embeddingModelList: EmbeddingModelItemType[]; ttsModelList: TTSModelType[]; reRankModelList: RerankModelItemType[]; sttModelList: STTModelType[]; + getVlmModelList: () => LLMModelItemType[]; + getModelProviders: (language?: string) => ModelProviderItemType[]; + getModelProvider: (provider?: string, language?: string) => ModelProviderItemType; + initStaticData: (e: InitDateResponse) => void; + appType?: string; setAppType: (e?: string) => void; }; @@ -126,6 +140,18 @@ export const useSystemStore = create()( feConfigs: {}, subPlans: undefined, systemVersion: '0.0.0', + + modelProviders: { + en: [], + 'zh-CN': [], + 'zh-Hant': [] + }, + modelProviderMap: { + en: {}, + 'zh-CN': {}, + 'zh-Hant': {} + }, + aiproxyIdMap: {}, defaultModels: {}, llmModelList: [], datasetModelList: [], @@ -133,9 +159,19 @@ export const useSystemStore = create()( ttsModelList: [], reRankModelList: [], sttModelList: [], + getVlmModelList: () => { return get().llmModelList.filter((item) => item.vision); }, + getModelProviders(language = 'en') { + return get().modelProviders[language as langType] ?? []; + }, + getModelProvider(provider, language = 'en') { + if (!provider) { + return defaultProvider; + } + return get().modelProviderMap[language as langType][provider] ?? {}; + }, initStaticData(res) { set((state) => { state.initDataBufferId = res.bufferId; @@ -144,6 +180,15 @@ export const useSystemStore = create()( state.subPlans = res.subPlans ?? state.subPlans; state.systemVersion = res.systemVersion ?? state.systemVersion; + if (res.modelProviders) { + const { ModelProviderListCache, ModelProviderMapCache } = formatModelProviders( + res.modelProviders + ); + state.modelProviders = ModelProviderListCache ?? state.modelProviders; + state.modelProviderMap = ModelProviderMapCache ?? state.modelProviderMap; + } + state.aiproxyIdMap = res.aiproxyIdMap ?? state.aiproxyIdMap; + state.llmModelList = res.activeModelList?.filter((item) => item.type === ModelTypeEnum.llm) ?? state.llmModelList; @@ -173,6 +218,10 @@ export const useSystemStore = create()( feConfigs: state.feConfigs, subPlans: state.subPlans, systemVersion: state.systemVersion, + + modelProviders: state.modelProviders, + modelProviderMap: state.modelProviderMap, + aiproxyIdMap: state.aiproxyIdMap, defaultModels: state.defaultModels, llmModelList: state.llmModelList, datasetModelList: state.datasetModelList, diff --git a/projects/app/src/web/core/app/api/plugin.ts b/projects/app/src/web/core/app/api/plugin.ts index 323bf077a..b8f987571 100644 --- a/projects/app/src/web/core/app/api/plugin.ts +++ b/projects/app/src/web/core/app/api/plugin.ts @@ -17,7 +17,7 @@ import type { ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type'; import type { GetSystemPluginTemplatesBody } from '@/pages/api/core/app/plugin/getSystemPluginTemplates'; -import type { PluginGroupSchemaType } from '@fastgpt/service/core/app/plugin/type'; +import type { SystemToolGroupSchemaType } from '@fastgpt/service/core/app/plugin/type'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { defaultGroup } from '@fastgpt/web/core/workflow/constants'; import type { createMCPToolsBody } from '@/pages/api/core/app/mcpTools/create'; @@ -82,11 +82,8 @@ export const getTeamPlugTemplates = async (data?: { export const getSystemPlugTemplates = (data: GetSystemPluginTemplatesBody) => POST('/core/app/plugin/getSystemPluginTemplates', data); -export const getPluginGroups = () => { - return useSystemStore.getState()?.feConfigs?.isPlus - ? GET('/proApi/core/app/plugin/getPluginGroups') - : Promise.resolve([defaultGroup]); -}; +export const getPluginGroups = () => + GET('/core/app/plugin/getToolGroups'); export const getSystemPluginPaths = (data: GetPathProps) => { if (!data.sourceId) return Promise.resolve([]); diff --git a/projects/app/src/web/core/chat/context/chatItemContext.tsx b/projects/app/src/web/core/chat/context/chatItemContext.tsx index 2da897362..42ee2eb4d 100644 --- a/projects/app/src/web/core/chat/context/chatItemContext.tsx +++ b/projects/app/src/web/core/chat/context/chatItemContext.tsx @@ -142,29 +142,38 @@ const ChatItemContextProvider = ({ const resetVariables = useCallback( (props?: { variables?: Record; variableList?: VariableItemType[] }) => { - const { variables, variableList = [] } = props || {}; + const { variables = {}, variableList = [] } = props || {}; - if (variables) { - variableList.forEach((item) => { - variablesForm.setValue(`variables.${item.key}`, variables[item.key]); - }); - } else { - variableList.forEach((item) => { - variablesForm.setValue(`variables.${item.key}`, item.defaultValue); - }); - } + variableList.forEach((item) => { + if (variables[item.key] === undefined) { + variables[item.key] = item.defaultValue; + } + }); + + const values = variablesForm.getValues(); + variablesForm.reset({ + ...values, + variables + }); }, [variablesForm] ); const clearChatRecords = useCallback(() => { - const data = variablesForm.getValues(); - for (const key in data.variables) { - variablesForm.setValue(`variables.${key}`, ''); - } + const variables = chatBoxData?.app?.chatConfig?.variables || []; + const values = variablesForm.getValues(); + + variables.forEach((item) => { + if (item.defaultValue !== undefined) { + values.variables[item.key] = item.defaultValue; + } else { + values.variables[item.key] = ''; + } + }); + variablesForm.reset(values); ChatBoxRef.current?.restartChat?.(); - }, [variablesForm]); + }, [chatBoxData?.app?.chatConfig?.variables, variablesForm]); const [datasetCiteData, setCiteModalData] = useState(); diff --git a/projects/app/src/web/styles/reset.scss b/projects/app/src/web/styles/reset.scss index 9eadf8fb4..884363986 100644 --- a/projects/app/src/web/styles/reset.scss +++ b/projects/app/src/web/styles/reset.scss @@ -44,6 +44,9 @@ svg { ::-webkit-scrollbar-thumb:hover { background: rgba(189, 193, 197, 1); } +:root { + --lexical-indent-base-value: 24px; +} div { &::-webkit-scrollbar-thumb { diff --git a/test/setupModels.ts b/test/setupModels.ts index ddd7ae5e6..a7bc63c54 100644 --- a/test/setupModels.ts +++ b/test/setupModels.ts @@ -1,5 +1,4 @@ import { ModelTypeEnum } from 'packages/global/core/ai/model'; -import type { ModelProviderIdType } from 'packages/global/core/ai/provider'; export default async function setupModels() { global.llmModelMap = new Map(); @@ -17,7 +16,7 @@ export default async function setupModels() { defaultSystemChatPrompt: undefined, fieldMap: undefined, defaultConfig: undefined, - provider: 'OpenAI' as ModelProviderIdType, + provider: 'OpenAI', functionCall: false, toolChoice: false, maxContext: 4096, @@ -38,7 +37,7 @@ export default async function setupModels() { defaultSystemChatPrompt: undefined, fieldMap: undefined, defaultConfig: undefined, - provider: 'OpenAI' as ModelProviderIdType, + provider: 'OpenAI', functionCall: false, toolChoice: false, maxContext: 4096,