diff --git a/docSite/content/docs/agreement/privacy.md b/docSite/content/docs/agreement/privacy.md index 1863bd95a..03f789699 100644 --- a/docSite/content/docs/agreement/privacy.md +++ b/docSite/content/docs/agreement/privacy.md @@ -9,7 +9,7 @@ weight: 1221 最后更新时间:2024年3月3日 -我们非常重视您的隐私保护,在您使用FastGPT云服务时,我们将按照以下政策收集、使用、披露和保护您的个人信息。请您仔细阅读并充分理解本隐私政策。 +我们非常重视您的隐私保护,在您使用FastGPT云服务时(以下简称为“本服务”),我们将按照以下政策收集、使用、披露和保护您的个人信息。请您仔细阅读并充分理解本隐私政策。 **我们可能需要收集的信息** @@ -39,7 +39,7 @@ weight: 1221 2. 我们会定期对收集、存储和处理的个人信息进行安全评估,以确保个人信息安全。 3. 在发生个人信息泄露等安全事件时,我们会立即启动应急预案,并在法律法规规定的范围内向您及时告知。 4. 我们不会使用您的数据进行额外的备份存储或用于模型训练。 -5. 您在本服务进行的数据删除均为物理删除,不可恢复。如有有非物理删除的操作,我们会在服务中特别指出。 +5. 您在本服务进行的数据删除均为物理删除,不可恢复。如有非物理删除的操作,我们会在服务中特别指出。 **用户权利** diff --git a/docSite/content/docs/development/openapi/share.md b/docSite/content/docs/development/openapi/share.md index 2c839b3af..1033d4390 100644 --- a/docSite/content/docs/development/openapi/share.md +++ b/docSite/content/docs/development/openapi/share.md @@ -169,6 +169,8 @@ curl --location --request POST '{{host}}/shareAuth/start' \ 响应值与[chat 接口格式相同](/docs/development/openapi/chat/#响应),仅多了一个`token`。 +重点关注:`totalPoints`(总消耗AI积分),`token`(Token消耗总数) + ```bash curl --location --request POST '{{host}}/shareAuth/finish' \ --header 'Content-Type: application/json' \ diff --git a/docSite/content/docs/development/upgrading/469.md b/docSite/content/docs/development/upgrading/469.md index 7f25bd592..da4eda478 100644 --- a/docSite/content/docs/development/upgrading/469.md +++ b/docSite/content/docs/development/upgrading/469.md @@ -20,15 +20,21 @@ curl --location --request POST 'https://{{host}}/api/init/v469' \ 1. 重置计量表。 2. 执行脏数据清理(清理无效的文件、清理无效的图片、清理无效的知识库集合、清理无效的向量) +## 外部接口更新 + +1. 由于计费系统变更,[分享链接对话上报接口](/docs/development/openapi/share/#5-编写对话结果上报接口可选)需要做一些调整,price字段被totalPoints字段取代。inputToken和outputToken不再提供,只提供`token`字段(总token数量)。 ## V4.6.9 更新说明 1. 商业版新增 - 知识库新增“增强处理”训练模式,可生成更多类型索引。 2. 新增 - 完善了HTTP模块的变量提示。 3. 新增 - HTTP模块支持OpenAI单接口导入。 -4. 优化 - 问题补全。增加英文类型。同时可以设置为单独模块,方便复用。 -5. 优化 - 重写了计量模式 -6. 优化 - Token 过滤历史记录,保持偶数条,防止部分模型报错。 -7. 优化 - 分享链接SEO,可直接展示应用名和头像。 -8. 修复 - 标注功能。 -9. 修复 - qa生成线程计数错误。 +4. 新增 - 全局变量支持增加外部变量。可通过分享链接的Query或 API 的 variables 参数传入。 +5. 新增 - 内容提取模块增加默认值。 +6. 优化 - 问题补全。增加英文类型。同时可以设置为单独模块,方便复用。 +7. 优化 - 重写了计量模式 +8. 优化 - Token 过滤历史记录,保持偶数条,防止部分模型报错。 +9. 优化 - 分享链接SEO,可直接展示应用名和头像。 +10. 修复 - 标注功能。 +11. 修复 - qa生成线程计数错误。 +12. 修复 - 问题分类连线类型错误 diff --git a/packages/global/core/module/constants.ts b/packages/global/core/module/constants.ts index 0eaa7e76f..16098f51f 100644 --- a/packages/global/core/module/constants.ts +++ b/packages/global/core/module/constants.ts @@ -116,17 +116,29 @@ export enum ModuleOutputKeyEnum { export enum VariableInputEnum { input = 'input', textarea = 'textarea', - select = 'select' + select = 'select', + external = 'external' } export const variableMap = { [VariableInputEnum.input]: { - icon: 'core/app/variable/input' + icon: 'core/app/variable/input', + title: 'core.module.variable.input type', + desc: '' }, [VariableInputEnum.textarea]: { - icon: 'core/app/variable/textarea' + icon: 'core/app/variable/textarea', + title: 'core.module.variable.textarea type', + desc: '允许用户最多输入4000字的对话框。' }, [VariableInputEnum.select]: { - icon: 'core/app/variable/select' + icon: 'core/app/variable/select', + title: 'core.module.variable.select type', + desc: '' + }, + [VariableInputEnum.external]: { + icon: 'core/app/variable/external', + title: 'core.module.variable.External type', + desc: '可以通过API接口或分享链接的Query传递变量。增加该类型变量的主要目的是用于变量提示。使用例子: 你可以通过分享链接Query中拼接Token,来实现内部系统身份鉴权。' } }; diff --git a/packages/global/core/module/template/system/contextExtract.ts b/packages/global/core/module/template/system/contextExtract.ts index ef85f78f2..86a1bb7bc 100644 --- a/packages/global/core/module/template/system/contextExtract.ts +++ b/packages/global/core/module/template/system/contextExtract.ts @@ -57,7 +57,7 @@ export const ContextExtractModule: FlowModuleTemplateType = { { key: ModuleInputKeyEnum.extractKeys, type: FlowNodeInputTypeEnum.custom, - label: '目标字段', + label: '', valueType: ModuleIOValueTypeEnum.any, description: "由 '描述' 和 'key' 组成一个目标字段,可提取多个目标字段", value: [], // {desc: string; key: string; required: boolean; enum: string[]}[] @@ -76,6 +76,7 @@ export const ContextExtractModule: FlowModuleTemplateType = { { key: ModuleOutputKeyEnum.failed, label: '提取字段缺失', + description: '存在一个或多个字段未提取成功。尽管使用了默认值也算缺失。', valueType: ModuleIOValueTypeEnum.boolean, type: FlowNodeOutputTypeEnum.source, targets: [] diff --git a/packages/global/core/module/type.d.ts b/packages/global/core/module/type.d.ts index dfb630d64..7ffc5bbfe 100644 --- a/packages/global/core/module/type.d.ts +++ b/packages/global/core/module/type.d.ts @@ -80,6 +80,7 @@ export type ContextExtractAgentItemType = { desc: string; key: string; required: boolean; + defaultValue?: string; enum?: string; }; diff --git a/packages/service/common/vectorStore/pg/index.ts b/packages/service/common/vectorStore/pg/index.ts index 567b5541b..1aed65587 100644 --- a/packages/service/common/vectorStore/pg/index.ts +++ b/packages/service/common/vectorStore/pg/index.ts @@ -1,3 +1,5 @@ +import { delay } from '@fastgpt/global/common/system/utils'; +import { addLog } from '../../system/log'; import { Pool } from 'pg'; import type { QueryResultRow } from 'pg'; @@ -15,10 +17,13 @@ export const connectPg = async (): Promise => { connectionTimeoutMillis: 20000 }); - global.pgClient.on('error', (err) => { + global.pgClient.on('error', async (err) => { console.log(err); global.pgClient?.end(); global.pgClient = null; + + await delay(1000); + addLog.info(`Retry connect pg`); connectPg(); }); @@ -27,7 +32,12 @@ export const connectPg = async (): Promise => { console.log('pg connected'); return global.pgClient; } catch (error) { + global.pgClient?.end(); global.pgClient = null; + + await delay(1000); + addLog.info(`Retry connect pg`); + return connectPg(); } }; diff --git a/packages/web/components/common/MyModal/index.tsx b/packages/web/components/common/CustomModal/index.tsx similarity index 100% rename from packages/web/components/common/MyModal/index.tsx rename to packages/web/components/common/CustomModal/index.tsx diff --git a/packages/web/components/common/Icon/constants.ts b/packages/web/components/common/Icon/constants.ts index 2d6260b6a..2417e7e69 100644 --- a/packages/web/components/common/Icon/constants.ts +++ b/packages/web/components/common/Icon/constants.ts @@ -69,6 +69,7 @@ export const iconPaths = { 'core/app/simpleMode/tts': () => import('./icons/core/app/simpleMode/tts.svg'), 'core/app/simpleMode/variable': () => import('./icons/core/app/simpleMode/variable.svg'), 'core/app/ttsFill': () => import('./icons/core/app/ttsFill.svg'), + 'core/app/variable/external': () => import('./icons/core/app/variable/external.svg'), 'core/app/variable/input': () => import('./icons/core/app/variable/input.svg'), 'core/app/variable/select': () => import('./icons/core/app/variable/select.svg'), 'core/app/variable/textarea': () => import('./icons/core/app/variable/textarea.svg'), diff --git a/packages/web/components/common/Icon/icons/core/app/variable/external.svg b/packages/web/components/common/Icon/icons/core/app/variable/external.svg new file mode 100644 index 000000000..990b0f75c --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/app/variable/external.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/packages/web/components/common/Textarea/PromptEditor/index.tsx b/packages/web/components/common/Textarea/PromptEditor/index.tsx index 25b9ddac4..0d9fbf212 100644 --- a/packages/web/components/common/Textarea/PromptEditor/index.tsx +++ b/packages/web/components/common/Textarea/PromptEditor/index.tsx @@ -2,7 +2,7 @@ import { Button, ModalBody, ModalFooter, useDisclosure } from '@chakra-ui/react' import React, { useEffect } from 'react'; import { editorStateToText } from './utils'; import Editor from './Editor'; -import MyModal from '../../MyModal'; +import MyModal from '../../CustomModal'; import { useTranslation } from 'next-i18next'; import { $getRoot, EditorState, type LexicalEditor } from 'lexical'; import { EditorVariablePickerType } from './type.d'; diff --git a/projects/app/src/web/styles/theme.ts b/packages/web/styles/theme.ts similarity index 100% rename from projects/app/src/web/styles/theme.ts rename to packages/web/styles/theme.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fc4737c2d..36e7148ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -317,6 +317,9 @@ importers: jschardet: specifier: ^3.0.0 version: 3.0.0 + json5: + specifier: ^2.2.3 + version: 2.2.3 jsonwebtoken: specifier: ^9.0.2 version: 9.0.2 @@ -5128,7 +5131,7 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001591 + caniuse-lite: 1.0.30001593 electron-to-chromium: 1.4.690 node-releases: 2.0.14 update-browserslist-db: 1.0.13(browserslist@4.23.0) @@ -5196,8 +5199,8 @@ packages: engines: {node: '>=10'} dev: true - /caniuse-lite@1.0.30001591: - resolution: {integrity: sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==} + /caniuse-lite@1.0.30001593: + resolution: {integrity: sha512-UWM1zlo3cZfkpBysd7AS+z+v007q9G1+fLTUU42rQnY6t2axoogPW/xol6T7juU5EUoOhML4WgBIdG+9yYqAjQ==} /canvas@2.11.2: resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==} @@ -9124,7 +9127,7 @@ packages: '@next/env': 13.5.2 '@swc/helpers': 0.5.2 busboy: 1.6.0 - caniuse-lite: 1.0.30001591 + caniuse-lite: 1.0.30001593 postcss: 8.4.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) diff --git a/projects/app/package.json b/projects/app/package.json index 1d61f447e..aac4c38cd 100644 --- a/projects/app/package.json +++ b/projects/app/package.json @@ -37,6 +37,7 @@ "immer": "^9.0.19", "js-yaml": "^4.1.0", "jschardet": "^3.0.0", + "json5": "^2.2.3", "jsonwebtoken": "^9.0.2", "lodash": "^4.17.21", "mermaid": "^10.2.3", diff --git a/projects/app/public/docs/versionIntro.md b/projects/app/public/docs/versionIntro.md index a3b9cc714..ab085da11 100644 --- a/projects/app/public/docs/versionIntro.md +++ b/projects/app/public/docs/versionIntro.md @@ -3,7 +3,9 @@ 1. 新增 - 知识库新增“增强处理”训练模式,可生成更多类型索引。 2. 新增 - 完善了HTTP模块的变量提示。 3. 新增 - HTTP模块支持OpenAI单接口导入。 -4. 优化 - 问题补全。增加英文类型。同时可以设置为单独模块,方便复用。 -5. [点击查看高级编排介绍文档](https://doc.fastgpt.in/docs/workflow/intro) -6. [使用文档](https://doc.fastgpt.in/docs/intro/) -7. [点击查看商业版](https://doc.fastgpt.in/docs/commercial/) \ No newline at end of file +4. 新增 - 全局变量支持增加外部变量。可通过分享链接的Query或 API 的 variables 参数传入。 +5. 新增 - 内容提取模块增加默认值。 +6. 优化 - 问题补全。增加英文类型。同时可以设置为单独模块,方便复用。 +7. [点击查看高级编排介绍文档](https://doc.fastgpt.in/docs/workflow/intro) +8. [使用文档](https://doc.fastgpt.in/docs/intro/) +9. [点击查看商业版](https://doc.fastgpt.in/docs/commercial/) \ No newline at end of file diff --git a/projects/app/public/locales/en/common.json b/projects/app/public/locales/en/common.json index 15e8d5a24..162667aac 100644 --- a/projects/app/public/locales/en/common.json +++ b/projects/app/public/locales/en/common.json @@ -774,6 +774,8 @@ "Input description": "", "label": "Dataset quote" }, + "Default value": "Default ", + "Default value placeholder": "Null characters are returned by default", "Field Description": "Description", "Field Name": "Name", "Field Type": "Type", @@ -795,10 +797,14 @@ "Field Edit": "Field Edit" }, "extract": { + "Add field": "Add", "Enum Description": "Lists the possible values for the field, one per row", "Enum Value": "Enum", "Field Description Placeholder": "Name/age /sql statement......", - "Field Setting Title": "Extract field configuration" + "Field Setting Title": "Extract field configuration", + "Required": "Required", + "Required Description": "Even if the field cannot be extracted, it is returned with the default value", + "Target field": "Field" }, "http": { "Add props": "Add props", @@ -939,6 +945,7 @@ "string": "String" }, "variable": { + "External type": "External", "add option": "Add Option", "input type": "Text", "key": "Key", diff --git a/projects/app/public/locales/zh/common.json b/projects/app/public/locales/zh/common.json index cbf9b5e57..19990533f 100644 --- a/projects/app/public/locales/zh/common.json +++ b/projects/app/public/locales/zh/common.json @@ -776,6 +776,8 @@ "Input description": "可接收知识库搜索的结果。", "label": "知识库引用" }, + "Default value": "默认值", + "Default value placeholder": "不填则默认返回空字符", "Field Description": "字段描述", "Field Name": "字段名", "Field Type": "字段类型", @@ -797,10 +799,14 @@ "Field Edit": "字段编辑" }, "extract": { + "Add field": "新增字段", "Enum Description": "列举出该字段可能的值,每行一个", "Enum Value": "枚举值", "Field Description Placeholder": "姓名/年龄/sql语句……", - "Field Setting Title": "提取字段配置" + "Field Setting Title": "提取字段配置", + "Required": "必须返回", + "Required Description": "即使无法提取该字段,也会使用默认值进行返回", + "Target field": "目标字段" }, "http": { "Add props": "添加参数", @@ -941,6 +947,7 @@ "string": "字符串" }, "variable": { + "External type": "外部传入", "add option": "添加选项", "input type": "文本", "key": "变量 key", diff --git a/projects/app/src/components/ChatBox/index.tsx b/projects/app/src/components/ChatBox/index.tsx index ef4f25529..076dca504 100644 --- a/projects/app/src/components/ChatBox/index.tsx +++ b/projects/app/src/components/ChatBox/index.tsx @@ -186,6 +186,10 @@ const ChatBox = ( () => splitGuideModule(userGuideModule), [userGuideModule] ); + const filterVariableModules = useMemo( + () => variableModules.filter((item) => item.type !== VariableInputEnum.external), + [variableModules] + ); // compute variable input is finish. const chatForm = useForm<{ @@ -200,17 +204,18 @@ const ChatBox = ( const [variableInputFinish, setVariableInputFinish] = useState(false); // clicked start chat button const variableIsFinish = useMemo(() => { - if (!variableModules || variableModules.length === 0 || chatHistory.length > 0) return true; + if (!filterVariableModules || filterVariableModules.length === 0 || chatHistory.length > 0) + return true; - for (let i = 0; i < variableModules.length; i++) { - const item = variableModules[i]; + for (let i = 0; i < filterVariableModules.length; i++) { + const item = filterVariableModules[i]; if (item.required && !variables[item.key]) { return false; } } return variableInputFinish; - }, [chatHistory.length, variableInputFinish, variableModules, variables]); + }, [chatHistory.length, variableInputFinish, filterVariableModules, variables]); // 滚动到底部 const scrollToBottom = (behavior: 'smooth' | 'auto' = 'smooth') => { @@ -495,7 +500,7 @@ const ChatBox = ( getChatHistories: () => chatHistory, resetVariables(e) { const defaultVal: Record = {}; - variableModules?.forEach((item) => { + filterVariableModules?.forEach((item) => { defaultVal[item.key] = ''; }); @@ -519,13 +524,13 @@ const ChatBox = ( feConfigs?.show_emptyChat && showEmptyIntro && chatHistory.length === 0 && - !variableModules?.length && + !filterVariableModules?.length && !welcomeText, [ chatHistory.length, feConfigs?.show_emptyChat, showEmptyIntro, - variableModules?.length, + filterVariableModules?.length, welcomeText ] ); @@ -604,10 +609,10 @@ const ChatBox = ( {showEmpty && } {!!welcomeText && } {/* variable input */} - {!!variableModules?.length && ( + {!!filterVariableModules?.length && ( node.id === connect.source)?.data; const sourceType = (() => { if (source?.flowType === FlowNodeTypeEnum.classifyQuestion) { - return ModuleIOValueTypeEnum.string; + return ModuleIOValueTypeEnum.boolean; } if (source?.flowType === FlowNodeTypeEnum.pluginInput) { return source?.inputs.find((input) => input.key === connect.sourceHandle)?.valueType; @@ -189,7 +189,7 @@ export const FlowProvider = ({ const targetType = nodes .find((node) => node.id === connect.target) ?.data?.inputs.find((input) => input.key === connect.targetHandle)?.valueType; - + console.log(source, targetType); if (!sourceType || !targetType) { return toast({ status: 'warning', diff --git a/projects/app/src/components/core/module/Flow/components/modules/VariableEdit.tsx b/projects/app/src/components/core/module/Flow/components/modules/VariableEdit.tsx index a7db0abd6..933bca3be 100644 --- a/projects/app/src/components/core/module/Flow/components/modules/VariableEdit.tsx +++ b/projects/app/src/components/core/module/Flow/components/modules/VariableEdit.tsx @@ -25,7 +25,7 @@ import { useDisclosure } from '@chakra-ui/react'; import { QuestionOutlineIcon, SmallAddIcon } from '@chakra-ui/icons'; -import { VariableInputEnum } from '@fastgpt/global/core/module/constants'; +import { VariableInputEnum, variableMap } from '@fastgpt/global/core/module/constants'; import type { VariableItemType } from '@fastgpt/global/core/module/type.d'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { useForm } from 'react-hook-form'; @@ -52,23 +52,12 @@ const VariableEdit = ({ const [refresh, setRefresh] = useState(false); const VariableTypeList = useMemo( - () => [ - { - title: t('core.module.variable.input type'), - icon: 'core/app/variable/input', - value: VariableInputEnum.input - }, - { - title: t('core.module.variable.textarea type'), - icon: 'core/app/variable/textarea', - value: VariableInputEnum.textarea - }, - { - title: t('core.module.variable.select type'), - icon: 'core/app/variable/select', - value: VariableInputEnum.select - } - ], + () => + Object.entries(variableMap).map(([key, value]) => ({ + title: t(value.title), + icon: value.icon, + value: key + })), [t] ); @@ -79,9 +68,12 @@ const VariableEdit = ({ getValues: getValuesEdit, setValue: setValuesEdit, control: editVariableController, - handleSubmit: handleSubmitEdit + handleSubmit: handleSubmitEdit, + watch } = useForm<{ variable: VariableItemType }>(); + const variableType = watch('variable.type'); + const { fields: selectEnums, append: appendEnums, @@ -140,11 +132,11 @@ const VariableEdit = ({ - - - - + + + + @@ -188,12 +180,15 @@ const VariableEdit = ({ title={t('core.module.Variable Setting')} isOpen={isOpenEdit} onClose={onCloseEdit} + maxW={['90vw', '500px']} > - - {t('common.Require Input')} - - + {variableType !== VariableInputEnum.external && ( + + {t('common.Require Input')} + + + )} {t('core.module.variable.variable name')} - {getValuesEdit('variable.type') === VariableInputEnum.input && ( + {/* desc */} + {variableMap[variableType]?.desc && ( + + {t(variableMap[variableType].desc)} + + )} + + {variableType === VariableInputEnum.input && ( <> {t('core.module.variable.text max length')} @@ -251,7 +253,7 @@ const VariableEdit = ({ )} - {getValuesEdit('variable.type') === VariableInputEnum.select && ( + {variableType === VariableInputEnum.select && ( <> {t('core.module.variable.variable options')} diff --git a/projects/app/src/components/core/module/Flow/components/nodes/NodeExtract/ExtractFieldModal.tsx b/projects/app/src/components/core/module/Flow/components/nodes/NodeExtract/ExtractFieldModal.tsx index 3a51eb677..1a4868f79 100644 --- a/projects/app/src/components/core/module/Flow/components/nodes/NodeExtract/ExtractFieldModal.tsx +++ b/projects/app/src/components/core/module/Flow/components/nodes/NodeExtract/ExtractFieldModal.tsx @@ -16,10 +16,11 @@ import { useTranslation } from 'next-i18next'; import MyTooltip from '@/components/MyTooltip'; import { QuestionOutlineIcon } from '@chakra-ui/icons'; -export const defaultField = { +export const defaultField: ContextExtractAgentItemType = { + required: false, + defaultValue: '', desc: '', key: '', - required: true, enum: '' }; @@ -33,9 +34,10 @@ const ExtractFieldModal = ({ onSubmit: (data: ContextExtractAgentItemType) => void; }) => { const { t } = useTranslation(); - const { register, handleSubmit } = useForm({ + const { register, handleSubmit, watch } = useForm({ defaultValues: defaultField }); + const required = watch('required'); return ( - - {t('common.Require Input')} + + + {t('core.module.extract.Required')} + + + + + {required && ( + + {t('core.module.Default value')} + + + )} + - {t('core.module.Field key')} - + {t('core.module.Field key')} + - {t('core.module.Field Description')} + {t('core.module.Field Description')} @@ -68,14 +92,16 @@ const ExtractFieldModal = ({ -
- {t('core.module.variable.variable name')}{t('core.module.variable.key')}{t('common.Require Input')} + {t('core.module.variable.variable name')}{t('core.module.variable.key')}{t('common.Require Input')}