From 3ba9c21828092a682303d3f7bc15a08edaf276bf Mon Sep 17 00:00:00 2001 From: Archer <545436317@qq.com> Date: Thu, 8 Aug 2024 10:07:24 +0800 Subject: [PATCH] 4.8.9 test fix (#2291) * perf: read file icon * perf:icon * fix: i18n * perf: hide pro api * perf: upload expired time * perf: upload file frequency limit * perf: upload file ux * perf: input file tip * perf: qa custom chunk size * feat: dataset openapi * fix: auth dataset list * fix: openapi doc * perf: zero temperature change to 0.01 * perf: read file prompt * perf: read file prompt * perf: free plan tip * feat: cron job usage --- .../zh-cn/docs/development/openapi/dataset.md | 6 +- .../zh-cn/docs/development/upgrading/489.md | 20 +- packages/global/common/error/utils.ts | 2 +- packages/global/common/file/constants.ts | 6 +- packages/global/common/file/type.d.ts | 1 - .../global/common/frequenctLimit/type.d.ts | 5 + packages/global/core/ai/prompt/agent.ts | 4 +- .../template/system/readFiles/index.tsx | 2 +- .../global/support/wallet/usage/constants.ts | 8 +- packages/service/common/file/gridfs/utils.ts | 2 +- packages/service/common/file/multer.ts | 1 - .../core/workflow/dispatch/agent/extract.ts | 4 +- .../core/workflow/dispatch/tools/readFiles.ts | 46 +- .../dispatchV1/agent/classifyQuestion.ts | 4 +- .../service/support/permission/controller.ts | 14 +- .../web/components/common/Avatar/index.tsx | 2 +- .../web/components/common/Icon/constants.ts | 1 + .../Icon/icons/core/app/simpleMode/tts.svg | 2 +- .../core/workflow/template/readFiles.svg | 10 + packages/web/i18n/en/app.json | 6 +- packages/web/i18n/en/common.json | 9 +- packages/web/i18n/zh/app.json | 72 +- packages/web/i18n/zh/common.json | 308 ++++---- packages/web/i18n/zh/user.json | 2 +- .../public/imgs/app/fileUploadPlaceholder.png | Bin 0 -> 31782 bytes .../public/imgs/app/fileUploadPlaceholder.svg | 167 ----- projects/app/public/imgs/app/question.svg | 4 + projects/app/public/imgs/app/visionModel.png | Bin 0 -> 38002 bytes .../src/components/core/app/FileSelect.tsx | 21 +- .../app/src/components/core/app/TTSSelect.tsx | 8 +- projects/app/src/components/core/app/Tip.tsx | 15 +- .../ChatContainer/ChatBox/Input/ChatInput.tsx | 676 ++++++++++-------- .../core/chat/ChatContainer/ChatBox/type.d.ts | 1 + .../app/src/pages/account/components/Info.tsx | 4 - .../app/src/pages/api/common/file/upload.ts | 44 +- .../app/src/pages/api/core/dataset/list.ts | 1 + .../detail/components/Import/Context.tsx | 23 +- .../Import/commonProgress/DataProcess.tsx | 19 +- .../src/service/common/frequencyLimit/api.ts | 8 + projects/app/src/service/core/app/utils.ts | 12 +- .../dataset/context/datasetPageContext.tsx | 4 + .../src/web/support/user/hooks/useSendCode.ts | 5 +- 42 files changed, 779 insertions(+), 770 deletions(-) create mode 100644 packages/global/common/frequenctLimit/type.d.ts create mode 100644 packages/web/components/common/Icon/icons/core/workflow/template/readFiles.svg create mode 100644 projects/app/public/imgs/app/fileUploadPlaceholder.png delete mode 100644 projects/app/public/imgs/app/fileUploadPlaceholder.svg create mode 100644 projects/app/public/imgs/app/question.svg create mode 100644 projects/app/public/imgs/app/visionModel.png create mode 100644 projects/app/src/service/common/frequencyLimit/api.ts diff --git a/docSite/content/zh-cn/docs/development/openapi/dataset.md b/docSite/content/zh-cn/docs/development/openapi/dataset.md index d6ca1ba284fa..d0fc0b508126 100644 --- a/docSite/content/zh-cn/docs/development/openapi/dataset.md +++ b/docSite/content/zh-cn/docs/development/openapi/dataset.md @@ -531,6 +531,8 @@ data 为集合的 ID。 {{< tab tabName="请求示例" >}} {{< markdownify >}} +使用代码上传时,请注意中文 filename 需要进行 encode 处理,否则容易乱码。 + ```bash curl --location --request POST 'http://localhost:3000/api/core/dataset/collection/create/localFile' \ --header 'Authorization: Bearer {{authorization}}' \ @@ -1173,7 +1175,7 @@ curl --location --request PUT 'http://localhost:3000/api/core/dataset/data/updat --header 'Authorization: Bearer {{authorization}}' \ --header 'Content-Type: application/json' \ --data-raw '{ - "id":"65abd4b29d1448617cba61db", + "dataId":"65abd4b29d1448617cba61db", "q":"测试111", "a":"sss", "indexes":[ @@ -1196,7 +1198,7 @@ curl --location --request PUT 'http://localhost:3000/api/core/dataset/data/updat {{< markdownify >}} {{% alert icon=" " context="success" %}} -- id: 数据的id +- dataId: 数据的id - q: 主要数据(选填) - a: 辅助数据(选填) - indexes: 自定义索引(选填),类型参考`为集合批量添加添加数据`。如果创建时候有自定义索引, diff --git a/docSite/content/zh-cn/docs/development/upgrading/489.md b/docSite/content/zh-cn/docs/development/upgrading/489.md index 95f470ebe88b..46ea842a5cd1 100644 --- a/docSite/content/zh-cn/docs/development/upgrading/489.md +++ b/docSite/content/zh-cn/docs/development/upgrading/489.md @@ -38,12 +38,14 @@ curl --location --request POST 'https://{{host}}/api/admin/init/489' \ 6. 商业版新增 - 知识库搜索节点支持标签过滤和创建时间过滤。 7. 商业版新增 - 转移 App owner 权限。 8. 新增 - 删除所有对话引导内容。 -9. 优化 - 对话框信息懒加载,减少网络传输。 -10. 优化 - 清除选文件缓存,支持重复选择同一个文件。 -11. 修复 - 知识库上传文件,网络不稳定或文件较多情况下,进度无法到 100%。 -12. 修复 - 删除应用后回到聊天选择最后一次对话的应用为删除的应用时提示无该应用问题。 -13. 修复 - 插件动态变量配置默认值时,无法正常显示默认值。 -14. 修复 - 工具调用温度和最大回复值未生效。 -15. 修复 - 函数调用模式,assistant role 中,GPT 模型必须传入 content 参数。(不影响大部分模型,目前基本都改用用 ToolChoice 模式,FC 模式已弃用)。 -16. 修复 - 知识库文件上传进度更新可能异常。 -17. 修复 - 知识库 rebuilding 时候,页面总是刷新到第一页。 +9. 新增 - QA 拆分支持自定义 chunk 大小,并优化 gpt4o-mini 拆分时,chunk 太大导致生成内容很少的问题。 +10. 优化 - 对话框信息懒加载,减少网络传输。 +11. 优化 - 清除选文件缓存,支持重复选择同一个文件。 +12. 修复 - 知识库上传文件,网络不稳定或文件较多情况下,进度无法到 100%。 +13. 修复 - 删除应用后回到聊天选择最后一次对话的应用为删除的应用时提示无该应用问题。 +14. 修复 - 插件动态变量配置默认值时,无法正常显示默认值。 +15. 修复 - 工具调用温度和最大回复值未生效。 +16. 修复 - 函数调用模式,assistant role 中,GPT 模型必须传入 content 参数。(不影响大部分模型,目前基本都改用用 ToolChoice 模式,FC 模式已弃用)。 +17. 修复 - 知识库文件上传进度更新可能异常。 +18. 修复 - 知识库 rebuilding 时候,页面总是刷新到第一页。 +19. 修复 - 知识库 list openapi 鉴权问题。 diff --git a/packages/global/common/error/utils.ts b/packages/global/common/error/utils.ts index 73f0ec646749..54a47ed01c3e 100644 --- a/packages/global/common/error/utils.ts +++ b/packages/global/common/error/utils.ts @@ -1,6 +1,6 @@ import { replaceSensitiveText } from '../string/tools'; -export const getErrText = (err: any, def = '') => { +export const getErrText = (err: any, def = ''): any => { const msg: string = typeof err === 'string' ? err diff --git a/packages/global/common/file/constants.ts b/packages/global/common/file/constants.ts index e1f7eac1d77e..d92144c37719 100644 --- a/packages/global/common/file/constants.ts +++ b/packages/global/common/file/constants.ts @@ -7,10 +7,12 @@ export enum BucketNameEnum { } export const bucketNameMap = { [BucketNameEnum.dataset]: { - label: i18nT('file:bucket_file') + label: i18nT('file:bucket_file'), + previewExpireMinutes: 30 // 30 minutes }, [BucketNameEnum.chat]: { - label: i18nT('file:bucket_chat') + label: i18nT('file:bucket_chat'), + previewExpireMinutes: 7 * 24 * 60 // 7 days } }; diff --git a/packages/global/common/file/type.d.ts b/packages/global/common/file/type.d.ts index 56fe0876e541..dfe8b21c6dfe 100644 --- a/packages/global/common/file/type.d.ts +++ b/packages/global/common/file/type.d.ts @@ -5,5 +5,4 @@ export type FileTokenQuery = { teamId: string; tmbId: string; fileId: string; - expiredTime?: number; }; diff --git a/packages/global/common/frequenctLimit/type.d.ts b/packages/global/common/frequenctLimit/type.d.ts new file mode 100644 index 000000000000..3f326a40cd1e --- /dev/null +++ b/packages/global/common/frequenctLimit/type.d.ts @@ -0,0 +1,5 @@ +export type AuthFrequencyLimitProps = { + eventId: string; + maxAmount: number; + expiredTime: Date; +}; diff --git a/packages/global/core/ai/prompt/agent.ts b/packages/global/core/ai/prompt/agent.ts index 2477696e18be..3c6a4fb12b0c 100644 --- a/packages/global/core/ai/prompt/agent.ts +++ b/packages/global/core/ai/prompt/agent.ts @@ -1,9 +1,9 @@ export const Prompt_AgentQA = { description: ` 标记中是一段文本,学习和分析它,并整理学习成果: - 提出问题并给出每个问题的答案。 -- 答案需详细完整,尽可能保留原文描述。 +- 答案需详细完整,尽可能保留原文描述,可以适当扩展答案描述。 - 答案可以包含普通文字、链接、代码、表格、公示、媒体链接等 Markdown 元素。 -- 最多提出 30 个问题。 +- 最多提出 50 个问题。 `, fixedText: `请按以下格式整理学习成果: diff --git a/packages/global/core/workflow/template/system/readFiles/index.tsx b/packages/global/core/workflow/template/system/readFiles/index.tsx index eb2ea9d767d9..cbff1d219409 100644 --- a/packages/global/core/workflow/template/system/readFiles/index.tsx +++ b/packages/global/core/workflow/template/system/readFiles/index.tsx @@ -19,7 +19,7 @@ export const ReadFilesNodes: FlowNodeTemplateType = { flowNodeType: FlowNodeTypeEnum.readFiles, sourceHandle: getHandleConfig(true, true, true, true), targetHandle: getHandleConfig(true, true, true, true), - avatar: 'core/app/simpleMode/file', + avatar: 'core/workflow/template/readFiles', name: i18nT('app:workflow.read_files'), intro: i18nT('app:workflow.read_files_tip'), showStatus: true, diff --git a/packages/global/support/wallet/usage/constants.ts b/packages/global/support/wallet/usage/constants.ts index 13dae786e95e..9e7a1b92a578 100644 --- a/packages/global/support/wallet/usage/constants.ts +++ b/packages/global/support/wallet/usage/constants.ts @@ -1,8 +1,11 @@ +import { i18nT } from '../../../../web/i18n/utils'; + export enum UsageSourceEnum { fastgpt = 'fastgpt', api = 'api', shareLink = 'shareLink', - training = 'training' + training = 'training', + cronJob = 'cronJob' } export const UsageSourceMap = { @@ -17,5 +20,8 @@ export const UsageSourceMap = { }, [UsageSourceEnum.training]: { label: 'dataset.Training Name' + }, + [UsageSourceEnum.cronJob]: { + label: i18nT('common:cron_job_run_app') } }; diff --git a/packages/service/common/file/gridfs/utils.ts b/packages/service/common/file/gridfs/utils.ts index 231a5622d031..8f27a07187cc 100644 --- a/packages/service/common/file/gridfs/utils.ts +++ b/packages/service/common/file/gridfs/utils.ts @@ -45,7 +45,7 @@ export const stream2Encoding = async (stream: NodeJS.ReadableStream) => { })(); const enc = detectFileEncoding(buffer); - console.log('Get encoding time', Date.now() - start, enc); + return { encoding: enc, stream: copyStream diff --git a/packages/service/common/file/multer.ts b/packages/service/common/file/multer.ts index 344bb5c8988e..a1c531d1a46d 100644 --- a/packages/service/common/file/multer.ts +++ b/packages/service/common/file/multer.ts @@ -3,7 +3,6 @@ import multer from 'multer'; import path from 'path'; import { BucketNameEnum, bucketNameMap } from '@fastgpt/global/common/file/constants'; import { getNanoid } from '@fastgpt/global/common/string/tools'; -import { tmpFileDirPath } from './constants'; type FileType = { fieldname: string; diff --git a/packages/service/core/workflow/dispatch/agent/extract.ts b/packages/service/core/workflow/dispatch/agent/extract.ts index e8004f7590bb..a37540920778 100644 --- a/packages/service/core/workflow/dispatch/agent/extract.ts +++ b/packages/service/core/workflow/dispatch/agent/extract.ts @@ -228,7 +228,7 @@ const toolChoice = async (props: ActionProps) => { const response = await ai.chat.completions.create({ model: extractModel.model, - temperature: 0, + temperature: 0.01, messages: filterMessages, tools, tool_choice: { type: 'function', function: { name: agentFunName } } @@ -273,7 +273,7 @@ const functionCall = async (props: ActionProps) => { const response = await ai.chat.completions.create({ model: extractModel.model, - temperature: 0, + temperature: 0.01, messages: filterMessages, function_call: { name: agentFunName diff --git a/packages/service/core/workflow/dispatch/tools/readFiles.ts b/packages/service/core/workflow/dispatch/tools/readFiles.ts index 6f4bffce3fe0..3a2b85a72be2 100644 --- a/packages/service/core/workflow/dispatch/tools/readFiles.ts +++ b/packages/service/core/workflow/dispatch/tools/readFiles.ts @@ -49,7 +49,7 @@ export const dispatchReadFiles = async (props: Props): Promise => { chatConfig, params: { fileUrlList = [] } } = props; - const maxFiles = chatConfig?.fileSelectConfig?.maxFiles || 0; + const maxFiles = chatConfig?.fileSelectConfig?.maxFiles || 20; // Get files from histories const filesFromHistories = histories @@ -70,29 +70,35 @@ export const dispatchReadFiles = async (props: Props): Promise => { }) .flat(); - const parseUrlList = [...fileUrlList, ...filesFromHistories].slice(0, maxFiles); - - const readFilesResult = await Promise.all( - parseUrlList - .map(async (url) => { - // System file - if (url.startsWith('/') || (requestOrigin && url.startsWith(requestOrigin))) { - // Parse url, get filename query. Keep only documents that can be parsed - const parseUrl = new URL(url); - const filenameQuery = parseUrl.searchParams.get('filename'); - if (filenameQuery) { - const extensionQuery = filenameQuery.split('.').pop()?.toLowerCase() || ''; - if (!documentFileType.includes(extensionQuery)) { - return; - } + // Concat fileUrlList and filesFromHistories; remove not supported files + const parseUrlList = [...fileUrlList, ...filesFromHistories] + .map((url) => { + // System file + if (url.startsWith('/') || (requestOrigin && url.startsWith(requestOrigin))) { + // Parse url, get filename query. Keep only documents that can be parsed + const parseUrl = new URL(url); + const filenameQuery = parseUrl.searchParams.get('filename'); + if (filenameQuery) { + const extensionQuery = filenameQuery.split('.').pop()?.toLowerCase() || ''; + if (!documentFileType.includes(extensionQuery)) { + return ''; } + } - // Remove the origin(Make intranet requests directly) - if (requestOrigin && url.startsWith(requestOrigin)) { - url = url.replace(requestOrigin, ''); - } + // Remove the origin(Make intranet requests directly) + if (requestOrigin && url.startsWith(requestOrigin)) { + url = url.replace(requestOrigin, ''); } + } + return url; + }) + .filter(Boolean) + .slice(0, maxFiles); + console.log(parseUrlList); + const readFilesResult = await Promise.all( + parseUrlList + .map(async (url) => { // Get from buffer const fileBuffer = await MongoRawTextBuffer.findOne({ sourceId: url }, undefined, { ...readFromSecondary diff --git a/packages/service/core/workflow/dispatchV1/agent/classifyQuestion.ts b/packages/service/core/workflow/dispatchV1/agent/classifyQuestion.ts index 7b60303e2b13..376e16389b1a 100644 --- a/packages/service/core/workflow/dispatchV1/agent/classifyQuestion.ts +++ b/packages/service/core/workflow/dispatchV1/agent/classifyQuestion.ts @@ -188,7 +188,7 @@ const toolChoice = async (props: ActionProps) => { const response = await ai.chat.completions.create({ model: cqModel.model, - temperature: 0, + temperature: 0.01, messages: filterMessages, tools, tool_choice: { type: 'function', function: { name: agentFunName } } @@ -235,7 +235,7 @@ const functionCall = async (props: ActionProps) => { const response = await ai.chat.completions.create({ model: cqModel.model, - temperature: 0, + temperature: 0.01, messages: filterMessages, function_call: { name: agentFunName diff --git a/packages/service/support/permission/controller.ts b/packages/service/support/permission/controller.ts index 9be1f868f6ee..f96b5ffdaf25 100644 --- a/packages/service/support/permission/controller.ts +++ b/packages/service/support/permission/controller.ts @@ -10,6 +10,8 @@ import { MongoResourcePermission } from './schema'; import { ClientSession } from 'mongoose'; import { ParentIdType } from '@fastgpt/global/common/parentFolder/type'; import { ResourcePermissionType } from '@fastgpt/global/support/permission/type'; +import { bucketNameMap } from '@fastgpt/global/common/file/constants'; +import { addMinutes } from 'date-fns'; export const getResourcePermission = async ({ resourceType, @@ -250,15 +252,15 @@ export const clearCookie = (res: NextApiResponse) => { }; /* file permission */ -export const createFileToken = ({ - expiredTime = Math.floor(Date.now() / 1000) + 60 * 30, - ...data -}: FileTokenQuery) => { +export const createFileToken = (data: FileTokenQuery) => { if (!process.env.FILE_TOKEN_KEY) { return Promise.reject('System unset FILE_TOKEN_KEY'); } - const key = process.env.FILE_TOKEN_KEY as string; + const expireMinutes = bucketNameMap[data.bucketName].previewExpireMinutes; + const expiredTime = Math.floor(addMinutes(new Date(), expireMinutes).getTime() / 1000); + + const key = (process.env.FILE_TOKEN_KEY as string) ?? 'filetoken'; const token = jwt.sign( { ...data, @@ -274,7 +276,7 @@ export const authFileToken = (token?: string) => if (!token) { return reject(ERROR_ENUM.unAuthFile); } - const key = process.env.FILE_TOKEN_KEY as string; + const key = (process.env.FILE_TOKEN_KEY as string) ?? 'filetoken'; jwt.verify(token, key, function (err, decoded: any) { if (err || !decoded.bucketName || !decoded?.teamId || !decoded?.tmbId || !decoded?.fileId) { diff --git a/packages/web/components/common/Avatar/index.tsx b/packages/web/components/common/Avatar/index.tsx index 11b69e4ae744..141f20e47161 100644 --- a/packages/web/components/common/Avatar/index.tsx +++ b/packages/web/components/common/Avatar/index.tsx @@ -10,7 +10,7 @@ const Avatar = ({ w = '30px', src, ...props }: ImageProps) => { const isIcon = !!iconPaths[src as any]; return isIcon ? ( - + ) : ( diff --git a/packages/web/components/common/Icon/constants.ts b/packages/web/components/common/Icon/constants.ts index ffa3cf15bd07..4587b979bfbc 100644 --- a/packages/web/components/common/Icon/constants.ts +++ b/packages/web/components/common/Icon/constants.ts @@ -199,6 +199,7 @@ export const iconPaths = { import('./icons/core/workflow/template/queryExtension.svg'), 'core/workflow/template/questionClassify': () => import('./icons/core/workflow/template/questionClassify.svg'), + 'core/workflow/template/readFiles': () => import('./icons/core/workflow/template/readFiles.svg'), 'core/workflow/template/reply': () => import('./icons/core/workflow/template/reply.svg'), 'core/workflow/template/runApp': () => import('./icons/core/workflow/template/runApp.svg'), 'core/workflow/template/stopTool': () => import('./icons/core/workflow/template/stopTool.svg'), diff --git a/packages/web/components/common/Icon/icons/core/app/simpleMode/tts.svg b/packages/web/components/common/Icon/icons/core/app/simpleMode/tts.svg index 4b9be223ca3e..4f8fae23600a 100644 --- a/packages/web/components/common/Icon/icons/core/app/simpleMode/tts.svg +++ b/packages/web/components/common/Icon/icons/core/app/simpleMode/tts.svg @@ -1,4 +1,4 @@ - + diff --git a/packages/web/components/common/Icon/icons/core/workflow/template/readFiles.svg b/packages/web/components/common/Icon/icons/core/workflow/template/readFiles.svg new file mode 100644 index 000000000000..709a93c285b7 --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/workflow/template/readFiles.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/packages/web/i18n/en/app.json b/packages/web/i18n/en/app.json index 6e443e5cde4b..9b846b8c7d16 100644 --- a/packages/web/i18n/en/app.json +++ b/packages/web/i18n/en/app.json @@ -103,10 +103,12 @@ "Simple bot": "Simple bot", "Workflow bot": "Workflow" }, - "upload_file_max_amount": "Maximum number of files to be uploaded in a single round", + "upload_file_max_amount": "Max files", + "upload_file_max_amount_tip": "1. The maximum number of files to be uploaded at a time.\n2. The maximum number of files that can be remembered in the dialog window: Files in the history are automatically retrieved for each round of conversation, and files that are out of range are forgotten.", "version": { "Revert success": "Revert success" }, + "vision_model_title": "Enable image recognition", "week": { "Friday": "Friday", "Monday": "Monday", @@ -122,7 +124,7 @@ "read_files": "Documents parse", "read_files_result": "Document parsing results", "read_files_result_desc": "The original text of the document consists of the file name and the document content. Multiple files are separated by horizontal lines.", - "read_files_tip": "Parse the document link passed in the conversation and return the corresponding document content", + "read_files_tip": "Parse all uploaded documents in the conversation and return the corresponding document content", "template": { "communication": "Communication" }, diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json index fb7065fc702f..68d2bb1c581f 100644 --- a/packages/web/i18n/en/common.json +++ b/packages/web/i18n/en/common.json @@ -223,6 +223,7 @@ }, "error": { "Select avatar failed": "Avatar selection failed", + "too_many_request": "Too many requests, please try again later.", "unKnow": "An unexpected error occurred~" }, "failed": "fail", @@ -650,7 +651,7 @@ "Down load csv template": "Click to download CSV template", "Embedding Estimated Price Tips": "Only using the index model, consumes a small amount of AI points: {{price}} points/1k Tokens", "Ideal chunk length": "Ideal chunk length", - "Ideal chunk length Tips": "Segment by end symbols. We recommend that your document should reasonably use punctuation to ensure that each complete sentence does not exceed this value\nChinese documents recommend 400~1000\nEnglish documents recommend 600~1200", + "Ideal chunk length Tips": "Segment according to the end symbol, and combine the segments into a block. This value determines the estimated size of the block.", "Import success": "Import successful, please wait for training", "Link name": "Network link", "Link name placeholder": "Only supports static links, if the data is empty after upload, the link may not be readable\nOne per line, up to 10 links at a time", @@ -957,6 +958,7 @@ } }, "create": "to create", + "cron_job_run_app": "Cron job", "dataset": { "Confirm move the folder": "Confirm moving to the folder", "Confirm to delete the data": "Confirm to delete the data?", @@ -1017,7 +1019,8 @@ "missingParams": "Insufficient parameters", "team": { "overSize": "Team members exceed the limit" - } + }, + "upload_file_error_filename": "{{name}} upload failed" }, "extraction_results": "Extract results", "field_name": "Name", @@ -1030,7 +1033,7 @@ "csv_download": "Click to download batch test template", "csv_message": "Read the first column of the CSV file for batch testing, supporting up to 100 sets of data at a time.", "felid_message": "The field key must be pure English letters or numbers, and cannot start with a number.", - "free_plan": "When free version users have no usage records for 30 days, the system will automatically clean up the account knowledge base.", + "free_plan": "When a free version user does not log in to the system for 30 consecutive days, the system will automatically clean up the account knowledge base.", "include": "Includes standard package and additional resource package", "node_info": "Adjusting this module will have an impact on the timing of tool calls.\n\nYou can guide the model to make tool calls by accurately describing the function of the module.", "old_version_attention": "If it is detected that your advanced arrangement is an old version, the system will automatically format it into a new version of the workflow for you.\n\n\nDue to large version differences, some workflows may not be arranged normally. Please reconnect the workflows manually. \nIf the error persists, try deleting the corresponding node and adding it again.\n\n\nYou can directly click Debug to perform workflow testing, and click Publish after debugging is completed. \nThe new workflow will not actually save and take effect until you click Publish.\n\n\nAutosave will not take effect until you publish the new workflow.", diff --git a/packages/web/i18n/zh/app.json b/packages/web/i18n/zh/app.json index 30cfed1a438b..e43f1d358fe3 100644 --- a/packages/web/i18n/zh/app.json +++ b/packages/web/i18n/zh/app.json @@ -8,7 +8,6 @@ "has new version": "有新版本" } }, - "intro": "是一个大模型应用编排系统,提供开箱即用的数据处理、模型调用等能力,可以快速的构建知识库并通过 Flow 可视化进行工作流编排,实现复杂的知识库场景!", "app_detail": "应用详情", "chat_debug": "调试预览", "chat_logs": "对话日志", @@ -19,10 +18,20 @@ "confirm_delete_folder_tip": "确认删除该文件夹?将会删除它下面所有应用及对应的聊天记录,请确认!", "copy_one_app": "创建副本", "create_copy_success": "创建副本成功", + "cron": { + "every_day": "每天执行", + "every_month": "每月执行", + "every_week": "每周执行", + "interval": "间隔执行" + }, "current_settings": "当前配置", + "day": "日", + "document_quote": "文档引用", + "document_quote_tip": "通常用于接受用户上传的文档内容(这需要文档解析),也可以用于引用其他字符串数据。", "document_upload": "文档上传", "edit_app": "编辑应用", "edit_info": "编辑信息", + "execute_time": "执行时间", "export_config_successful": "已复制配置,自动过滤部分敏感信息,请注意检查是否仍有敏感数据", "export_configs": "导出配置", "feedback_count": "用户反馈", @@ -34,6 +43,15 @@ "image_upload_tip": "请确保选择可处理图片的视觉模型", "import_configs": "导入配置", "import_configs_failed": "导入配置失败,请确保配置正常!", + "interval": { + "12_hours": "每12小时", + "2_hours": "每2小时", + "3_hours": "每3小时", + "4_hours": "每4小时", + "6_hours": "每6小时", + "per_hour": "每小时" + }, + "intro": "是一个大模型应用编排系统,提供开箱即用的数据处理、模型调用等能力,可以快速的构建知识库并通过 Flow 可视化进行工作流编排,实现复杂的知识库场景!", "llm_not_support_vision": "该模型不支持图片识别", "llm_use_vision": "启用图片识别", "llm_use_vision_tip": "启用图片识别后,该模型会自动接收来自“对话框上传”的图片,以及“用户问题”中的图片链接。", @@ -50,6 +68,9 @@ "modules": { "Title is required": "模块名不能为空" }, + "month": { + "unit": "号" + }, "move_app": "移动应用", "paste_config": "粘贴配置", "plugin_cost_per_times": "{{cost}}/次", @@ -63,6 +84,7 @@ "template": { "simple_robot": "简易机器人" }, + "time_zone": "时区", "tool_input_param_tip": "该插件正常运行需要配置相关信息", "transition_to_workflow": "转成工作流", "transition_to_workflow_create_new_placeholder": "创建一个新的应用,而不是修改当前应用", @@ -81,52 +103,32 @@ "Simple bot": "简易应用", "Workflow bot": "工作流" }, - "upload_file_max_amount": "单轮最大文件上传数量", + "upload_file_max_amount": "最大文件数量", + "upload_file_max_amount_tip": "1.单次上传文件的最大数量。\n2.对话窗口记忆的最大文件数量:每轮对话会自动获取历史中的文件,超出范围的文件会被遗忘。", "version": { "Revert success": "回滚成功" }, + "vision_model_title": "启用图片识别", + "week": { + "Friday": "星期五", + "Monday": "星期一", + "Saturday": "星期六", + "Sunday": "星期日", + "Thursday": "星期四", + "Tuesday": "星期二", + "Wednesday": "星期三" + }, "workflow": { "Input guide": "填写说明", "file_url": "文档链接", "read_files": "文档解析", "read_files_result": "文档解析结果", "read_files_result_desc": "文档原文,由文件名和文档内容组成,多个文件之间通过横线隔开。", - "read_files_tip": "解析对话中上传的文档,返回对应文档内容", + "read_files_tip": "解析对话中所有上传的文档,并返回对应文档内容", "template": { "communication": "通信" }, "user_file_input": "文件链接", "user_file_input_desc": "用户上传的文档和图片链接" - }, - "interval": { - "per_hour": "每小时", - "2_hours": "每2小时", - "3_hours": "每3小时", - "4_hours": "每4小时", - "6_hours": "每6小时", - "12_hours": "每12小时" - }, - "week": { - "Monday": "星期一", - "Tuesday": "星期二", - "Wednesday": "星期三", - "Thursday": "星期四", - "Friday": "星期五", - "Saturday": "星期六", - "Sunday": "星期日" - }, - "month": { - "unit": "号" - }, - "cron": { - "every_day": "每天执行", - "every_month": "每月执行", - "every_week": "每周执行", - "interval": "间隔执行" - }, - "day": "日", - "execute_time": "执行时间", - "time_zone": "时区", - "document_quote": "文档引用", - "document_quote_tip": "通常用于接受用户上传的文档内容(这需要文档解析),也可以用于引用其他字符串数据。" + } } diff --git a/packages/web/i18n/zh/common.json b/packages/web/i18n/zh/common.json index fbb8d9c63bc6..d84df2354183 100644 --- a/packages/web/i18n/zh/common.json +++ b/packages/web/i18n/zh/common.json @@ -1,68 +1,45 @@ { "App": "应用", - "click_to_resume": "点击恢复", - "code_editor": "代码编辑", "Export": "导出", + "FAQ": { + "ai_point_a": "每次调用AI模型时,都会消耗一定的AI积分。具体的计算标准可参考上方的“AI 积分计算标准”。\nToken计算采用GPT3.5相同公式,1Token≈0.7中文字符≈0.9英文单词,连续出现的字符可能被认为是1个Tokens。", + "ai_point_expire_a": "会过期。当前套餐过期后,AI积分将会清空,并更新为新套餐的AI积分。年度套餐的AI积分时长为1年,而不是每个月。", + "ai_point_expire_q": "AI积分会过期么?", + "ai_point_q": "什么是AI积分?", + "auto_renew_a": "当前套餐过期后,系统会自动根据“未来套餐”进行续费,系统会尝试从账户余额进行扣费,如果您需要自动续费,请在账户余额中预留额度。", + "auto_renew_q": "订阅套餐会自动续费么?", + "change_package_a": "当前套餐价格大于新套餐时,无法立即切换,将会在当前套餐过期后以“续费”形式进行切换。\n当前套餐价格小于新套餐时,系统会自动计算当前套餐剩余余额,您可支付差价进行套餐切换。", + "change_package_q": "能否切换订阅套餐?", + "dataset_compute_a": "1条知识库存储等于1条知识库索引。一条知识库数据可以包含1条或多条知识库索引。增强训练中,1条数据会生成5条索引。", + "dataset_compute_q": "知识库存储怎么计算?", + "dataset_index_a": "不会。但知识库索引超出时,无法插入和更新知识库内容。", + "dataset_index_q": "知识库索引超出会删除么?", + "free_user_clean_a": "免费版团队(免费版且未购买额外套餐)连续 30 天未登录系统,系统会自动清除该团队下所有知识库内容。", + "free_user_clean_q": "免费版数据会清除么?", + "package_overlay_a": "可以的。每次购买的资源包都是独立的,在其有效期内将会叠加使用。AI积分会优先扣除最先过期的资源包。", + "package_overlay_q": "额外资源包可以叠加么?" + }, "Folder": "文件夹", "Login": "登录", - "chosen": "已选", - "chose_condition": "选择条件", - "confirm_choice": "确认选择", "Move": "移动", "Name": "名称", - "create": "去创建", - "required": "必须", - "extraction_results": "提取结果", - "item_description": "字段描述", - "item_name": "字段名", - "tool_field": "工具字段参数配置", - "classification": "分类", - "get_laf_failed": "获取Laf函数列表失败", - "no_laf_env": "系统未配置Laf环境", - "get_app_failed": "获取应用失败", "Rename": "重命名", "Resume": "恢复", - "resume_failed": "恢复失败", "Running": "运行中", "UnKnow": "未知", "Warning": "提示", - "default_reply": "默认回复", - "reply_now": "立即回复", "add_new": "新增", - "verification": "验证", - "key_repetition": "key 重复", - "has_verification": "已验证,点击取消绑定", - "undefined_var": "引用了未定义的变量,是否自动添加?", - "not_yet_introduced": "暂无介绍", - "get_QR_failed": "获取二维码失败", - "unit": { - "character": "字符", - "minute": "分钟" - }, - "FAQ": { - "auto_renew_q": "订阅套餐会自动续费么?", - "auto_renew_a": "当前套餐过期后,系统会自动根据“未来套餐”进行续费,系统会尝试从账户余额进行扣费,如果您需要自动续费,请在账户余额中预留额度。", - "change_package_q": "能否切换订阅套餐?", - "change_package_a": "当前套餐价格大于新套餐时,无法立即切换,将会在当前套餐过期后以“续费”形式进行切换。\n当前套餐价格小于新套餐时,系统会自动计算当前套餐剩余余额,您可支付差价进行套餐切换。", - "ai_point_q": "什么是AI积分?", - "ai_point_a": "每次调用AI模型时,都会消耗一定的AI积分。具体的计算标准可参考上方的“AI 积分计算标准”。\nToken计算采用GPT3.5相同公式,1Token≈0.7中文字符≈0.9英文单词,连续出现的字符可能被认为是1个Tokens。", - "ai_point_expire_q": "AI积分会过期么?", - "ai_point_expire_a": "会过期。当前套餐过期后,AI积分将会清空,并更新为新套餐的AI积分。年度套餐的AI积分时长为1年,而不是每个月。", - "dataset_compute_q": "知识库存储怎么计算?", - "dataset_compute_a": "1条知识库存储等于1条知识库索引。一条知识库数据可以包含1条或多条知识库索引。增强训练中,1条数据会生成5条索引。", - "dataset_index_q": "知识库索引超出会删除么?", - "dataset_index_a": "不会。但知识库索引超出时,无法插入和更新知识库内容。", - "package_overlay_q": "额外资源包可以叠加么?", - "package_overlay_a": "可以的。每次购买的资源包都是独立的,在其有效期内将会叠加使用。AI积分会优先扣除最先过期的资源包。", - "free_user_clean_q": "免费版数据会清除么?", - "free_user_clean_a": "免费版用户(免费版且未购买额外套餐)30天无使用记录后,系统会自动清除账号下所有知识库内容。" - }, + "chose_condition": "选择条件", + "chosen": "已选", + "classification": "分类", + "click_to_resume": "点击恢复", + "code_editor": "代码编辑", "code_error": { "app_error": { - "not_exist": "应用不存在", - "un_auth_app": "无权操作该应用", + "invalid_app_type": "错误的应用类型", "invalid_owner": "非法的应用所有者", - "invalid_app_type": "错误的应用类型" + "not_exist": "应用不存在", + "un_auth_app": "无权操作该应用" }, "chat_error": { "un_auth": "没有权限操作此对话记录" @@ -88,17 +65,14 @@ "513": "没有权限读取该文件", "514": "Api Key 不合法" }, - "token_error_code": { - "403": "登录状态无效,请重新登录" - }, "openapi_error": { "api_key_not_exist": "Api Key 不存在", - "un_auth": "无权操作该 Api Key", - "exceed_limit": "最多 10 组 API 密钥" + "exceed_limit": "最多 10 组 API 密钥", + "un_auth": "无权操作该 Api Key" }, "outlink_error": { - "link_not_exist": "分享链接不存在", "invalid_link": "分享链接无效", + "link_not_exist": "分享链接不存在", "un_auth_user": "身份校验失败" }, "plugin_error": { @@ -109,54 +83,27 @@ "community_version_num_limit": "超出开源版数量限制,请升级商业版: https://fastgpt.in" }, "team_error": { - "over_size": "error.team.overSize", - "un_auth": "无权操作该团队", "ai_points_not_enough": "", - "dataset_size_not_enough": "知识库容量不足,请先扩容~", - "dataset_amount_not_enough": "知识库数量已达上限~", "app_amount_not_enough": "应用数量已达上限~", + "dataset_amount_not_enough": "知识库数量已达上限~", + "dataset_size_not_enough": "知识库容量不足,请先扩容~", + "over_size": "error.team.overSize", "plugin_amount_not_enough": "插件数量已达上限~", - "website_sync_not_enough": "无权使用Web站点同步~", - "re_rank_not_enough": "无权使用检索重排~" + "re_rank_not_enough": "无权使用检索重排~", + "un_auth": "无权操作该团队", + "website_sync_not_enough": "无权使用Web站点同步~" + }, + "token_error_code": { + "403": "登录状态无效,请重新登录" }, "user_error": { - "un_auth_user": "找不到该用户", + "balance_not_enough": "账号余额不足~", "bin_visitor": "您的身份校验未通过", "bin_visitor_guest": "您当前身份为游客,无权操作", - "balance_not_enough": "账号余额不足~" + "un_auth_user": "找不到该用户" } }, - "pay": { - "wechat": "请微信扫码支付: {{price}}元,请勿关闭页面", - "yuan": "{{amount}}元", - "notice": "请勿关闭页面", - "get_pay_QR": "获取充值二维码", - "other": "其他金额,请取整数", - "amount": "金额", - "new_package_price": "新套餐价格", - "old_package_price": "旧套餐价格", - "need_pay": "需支付", - "balance": "账号余额", - "confirm_pay": "确认支付", - "balance_notice": "账号余额不足", - "to_recharge": "余额不足,去充值" - }, - "info": { - "free_plan": "免费版用户30天无任何使用记录时,系统会自动清理账号知识库。", - "resource": "资源用量", - "include": "包含标准套餐与额外资源包", - "buy_extra": "购买额外套餐", - "open_api_notice": "可以填写 OpenAI/OneAPI的相关秘钥。如果你填写了该内容,在线上平台使用【AI对话】、【问题分类】和【内容提取】将会走你填写的Key,不会计费。请注意你的Key 是否有访问对应模型的权限。GPT模型可以选择 FastAI。", - "open_api_placeholder": "请求地址,默认为 openai 官方。可填中转地址,未自动补全 \"v1\"", - "old_version_attention": "检测到您的高级编排为旧版,系统将为您自动格式化成新版工作流。\n\n由于版本差异较大,会导致一些工作流无法正常排布,请重新手动连接工作流。如仍异常,可尝试删除对应节点后重新添加。\n\n你可以直接点击调试进行工作流测试,调试完毕后点击发布。直到你点击发布,新工作流才会真正保存生效。\n\n在你发布新工作流前,自动保存不会生效。", - "node_info": "调整该模块会对工具调用时机有影响。\n你可以通过精确的描述该模块功能,引导模型进行工具调用。", - "felid_message": "字段key必须是纯英文字母或数字,并且不能以数字开头。", - "csv_message": "读取 CSV 文件第一列进行批量测试,单次最多支持 100 组数据。", - "csv_download": "点击下载批量测试模板" - }, "common": { - "support": "支持", - "not_support": "不支持", "Action": "操作", "Add": "添加", "Add New": "新增", @@ -201,14 +148,12 @@ "Input folder description": "文件夹描述", "Input name": "取个名字", "Intro": "介绍", - "no_intro": "暂无介绍", "Last Step": "上一步", "Last use time": "最后使用时间", "Load Failed": "加载失败", "Loading": "加载中...", "More": "更多", "Move": "移动", - "page_center": "页面居中", "MultipleRowSelect": { "No data": "没有可选值" }, @@ -221,7 +166,6 @@ "Operation": "操作", "Other": "其他", "Output": "输出", - "all_result": "完整结果", "Params": "参数", "Password inconsistency": "两次密码不一致", "Permission": "权限", @@ -231,9 +175,6 @@ "Remove": "移除", "Rename": "重命名", "Request Error": "请求异常", - "is_requesting": "请求中……", - "request_end": "已加载全部", - "request_more": "点击加载更多", "Require Input": "必填", "Restart": "重新开始", "Role": "权限", @@ -251,7 +192,6 @@ "Status": "状态", "Submit failed": "提交失败", "Success": "成功", - "failed": "失败", "Sync success": "同步成功", "Team": "团队", "Team Tags Set": "标签", @@ -268,6 +208,7 @@ "Waiting": "等待中", "Warning": "警告", "Website": "网站", + "all_result": "完整结果", "avatar": { "Select Avatar": "点击选择头像", "Select Failed": "选择头像异常" @@ -284,21 +225,24 @@ }, "error": { "Select avatar failed": "头像选择异常", + "too_many_request": "请求太频繁了,请稍后重试。", "unKnow": "出现了点意外~" }, + "failed": "失败", "folder": { "Drag Tip": "点我可拖动", "Move Success": "移动成功", "Move to": "移动到", "No Folder": "没有子目录了,就放这里吧", "Open folder": "打开文件夹", - "open_dataset": "打开知识库", "Root Path": "根目录", - "empty": "这个目录已经没东西可选了~" + "empty": "这个目录已经没东西可选了~", + "open_dataset": "打开知识库" }, "input": { "Repeat Value": "有重复的值" }, + "is_requesting": "请求中……", "jsonEditor": { "Parse error": "JSON 可能有误,请仔细检查" }, @@ -307,10 +251,16 @@ }, "month": "月", "name_is_empty": "名称不能为空", + "no_intro": "暂无介绍", + "not_support": "不支持", + "page_center": "页面居中", + "request_end": "已加载全部", + "request_more": "点击加载更多", "speech": { "error tip": "语音转文字失败", "not support": "您的浏览器不支持语音输入" }, + "support": "支持", "system": { "Commercial version function": "请升级商业版后使用该功能:https://fastgpt.in", "Help Chatbot": "机器人助手", @@ -322,9 +272,9 @@ } } }, + "confirm_choice": "确认选择", "core": { "Chat": "对话", - "view_chat_detail": "查看对话详情", "Max Token": "单条数据上限", "ai": { "AI settings": "AI 配置", @@ -342,9 +292,6 @@ }, "app": { "Ai response": "返回 AI 内容", - "loading": "加载中", - "no_app": "还没有应用,快去创建一个吧!", - "edit_content": "应用信息编辑", "Api request": "API 访问", "Api request desc": "通过 API 接入到已有系统中,或企微、飞书等", "App intro": "应用介绍", @@ -360,8 +307,6 @@ "Name and avatar": "头像 & 名称", "Onclick to save": "点击保存", "Publish": "发布", - "have_publish": "已发布", - "not_published": "未发布", "Publish Confirm": "确认发布应用?会立即更新所有发布渠道的应用状态。", "Publish app tip": "发布应用后,所有发布渠道将会立即使用该版本", "Question Guide": "猜你想问", @@ -391,11 +336,6 @@ "System": "系统", "Team": "团队" }, - "tool_label": { - "github": "GitHub地址", - "doc": "使用文档", - "price": "计费说明" - }, "Welcome Text": "对话开场白", "Whisper": "语音输入", "Whisper config": "语音输入配置", @@ -405,6 +345,7 @@ "Query extension background prompt": "对话背景描述", "Query extension background tip": "描述当前对话的范围,便于 AI 为当前问题进行补全和扩展。填写的内容,通常为该助手" }, + "edit_content": "应用信息编辑", "error": { "App name can not be empty": "应用名不能为空", "Get app failed": "获取应用异常" @@ -413,9 +354,13 @@ "Custom feedback": "自定义反馈", "close custom feedback": "关闭反馈" }, + "have_publish": "已发布", + "loading": "加载中", "logs": { "Source And Time": "来源 & 时间" }, + "no_app": "还没有应用,快去创建一个吧!", + "not_published": "未发布", "outLink": { "Can Drag": "图标可拖拽", "Default open": "默认打开", @@ -458,6 +403,11 @@ "variableTip": "可以在对话开始前,要求用户填写一些内容作为本轮对话的特定变量。该模块位于开场引导之后。\n变量可以通过 {{变量key}} 的形式注入到其他模块 string 类型的输入中,例如:提示词、限定词等", "welcomeTextTip": "每次对话开始前,发送一个初始内容。支持标准 Markdown 语法,可使用的额外标记:\n[快捷按键]:用户点击后可以直接发送该问题" }, + "tool_label": { + "doc": "使用文档", + "github": "GitHub地址", + "price": "计费说明" + }, "tts": { "Close": "不使用", "Speech model": "语音模型", @@ -522,10 +472,10 @@ "You need to a chat app": "你没有可用的应用", "error": { "Chat error": "对话出现异常", - "data_error": "获取数据异常", "Messages empty": "接口内容为空,可能文本超长了~", "Select dataset empty": "你没有选择知识库", - "User input empty": "传入的用户问题为空" + "User input empty": "传入的用户问题为空", + "data_error": "获取数据异常" }, "feedback": { "Close User Like": "用户表示赞同\n点击关闭该标记", @@ -665,21 +615,21 @@ "Search data placeholder": "搜索相关数据", "Too Long": "总长度超长了", "Total Amount": "{{total}} 组", - "unit": "条", - "group": "组" + "group": "组", + "unit": "条" }, "embedding model tip": "索引模型可以将自然语言转成向量,用于进行语义检索。\n注意,不同索引模型无法一起使用,选择完索引模型后将无法修改。", "error": { "Data not found": "数据不存在或已被删除", "Start Sync Failed": "开始同步失败", "Template does not exist": "模板不存在", + "invalidVectorModelOrQAModel": "VectorModel 或 QA 模型错误", "unAuthDataset": "无权操作该知识库", "unAuthDatasetCollection": "无权操作该数据集", "unAuthDatasetData": "无权操作该数据", "unAuthDatasetFile": "无权操作该文件", "unCreateCollection": "无权操作该数据", - "unLinkCollection": "不是网络链接集合", - "invalidVectorModelOrQAModel": "VectorModel 或 QA 模型错误" + "unLinkCollection": "不是网络链接集合" }, "externalFile": "外部文件库", "file": "文件", @@ -703,7 +653,7 @@ "Down load csv template": "点击下载 CSV 模板", "Embedding Estimated Price Tips": "仅使用索引模型,消耗少量 AI 积分:{{price}} 积分/1K tokens", "Ideal chunk length": "理想分块长度", - "Ideal chunk length Tips": "按结束符号进行分段。我们建议您的文档应合理的使用标点符号,以确保每个完整的句子长度不要超过该值\n中文文档建议 400~1000\n英文文档建议 600~1200", + "Ideal chunk length Tips": "按结束符号进行分段,并将多个分段组成一个分块,该值决定了分块的预估大小。", "Import success": "导入成功,请等待训练", "Link name": "网络链接", "Link name placeholder": "仅支持静态链接,如果上传后数据为空,可能该链接无法被读取\n每行一个,每次最多 10 个链接", @@ -814,8 +764,8 @@ "Confirm Delete Node": "确认删除该节点?", "Data Type": "数据类型", "Dataset quote": { - "select": "选择知识库引用", - "label": "知识库引用" + "label": "知识库引用", + "select": "选择知识库引用" }, "Default Value": "默认值", "Default value": "默认值", @@ -839,8 +789,6 @@ "Setting quote prompt": "配置引用提示词", "Variable": "全局变量", "Variable Setting": "变量设置", - "variable_update": "变量更新", - "variable_update_info": "可以更新指定节点的输出值或更新全局变量", "edit": { "Field Name Cannot Be Empty": "字段名不能为空" }, @@ -940,7 +888,9 @@ "variable option is value is required": "选项内容不能为空", "variable options": "选项" }, - "variable add option": "添加选项" + "variable add option": "添加选项", + "variable_update": "变量更新", + "variable_update_info": "可以更新指定节点的输出值或更新全局变量" }, "plugin": { "Custom headers": "自定义请求头", @@ -949,6 +899,7 @@ "Http plugin intro placeholder": "仅做展示,无实际效果", "cost": "积分消耗:" }, + "view_chat_detail": "查看对话详情", "workflow": { "Can not delete node": "该节点不允许删除", "Change input type tip": "修改输入类型会清空已填写的值,请确认!", @@ -1008,6 +959,8 @@ "variable": "变量" } }, + "create": "去创建", + "cron_job_run_app": "定时任务", "dataset": { "Confirm move the folder": "确认移动到该目录", "Confirm to delete the data": "确认删除该数据?", @@ -1060,6 +1013,7 @@ "noResult": "搜索结果为空" } }, + "default_reply": "默认回复", "error": { "Create failed": "创建失败", "fileNotFound": "文件找不到了~", @@ -1067,11 +1021,33 @@ "missingParams": "参数缺失", "team": { "overSize": "团队成员超出上限" - } + }, + "upload_file_error_filename": "{{name}} 上传失败" }, + "extraction_results": "提取结果", "field_name": "字段名", + "get_QR_failed": "获取二维码失败", + "get_app_failed": "获取应用失败", + "get_laf_failed": "获取Laf函数列表失败", + "has_verification": "已验证,点击取消绑定", + "info": { + "buy_extra": "购买额外套餐", + "csv_download": "点击下载批量测试模板", + "csv_message": "读取 CSV 文件第一列进行批量测试,单次最多支持 100 组数据。", + "felid_message": "字段key必须是纯英文字母或数字,并且不能以数字开头。", + "free_plan": "免费版团队连续30天未登录系统时,系统会自动清理账号知识库。", + "include": "包含标准套餐与额外资源包", + "node_info": "调整该模块会对工具调用时机有影响。\n你可以通过精确的描述该模块功能,引导模型进行工具调用。", + "old_version_attention": "检测到您的高级编排为旧版,系统将为您自动格式化成新版工作流。\n\n由于版本差异较大,会导致一些工作流无法正常排布,请重新手动连接工作流。如仍异常,可尝试删除对应节点后重新添加。\n\n你可以直接点击调试进行工作流测试,调试完毕后点击发布。直到你点击发布,新工作流才会真正保存生效。\n\n在你发布新工作流前,自动保存不会生效。", + "open_api_notice": "可以填写 OpenAI/OneAPI的相关秘钥。如果你填写了该内容,在线上平台使用【AI对话】、【问题分类】和【内容提取】将会走你填写的Key,不会计费。请注意你的Key 是否有访问对应模型的权限。GPT模型可以选择 FastAI。", + "open_api_placeholder": "请求地址,默认为 openai 官方。可填中转地址,未自动补全 \"v1\"", + "resource": "资源用量" + }, "invalid_variable": "无效变量", "is_open": "是否开启", + "item_description": "字段描述", + "item_name": "字段名", + "key_repetition": "key 重复", "navbar": { "Account": "账号", "Chat": "聊天", @@ -1081,6 +1057,23 @@ }, "new_create": "新建", "no_data": "暂无数据", + "no_laf_env": "系统未配置Laf环境", + "not_yet_introduced": "暂无介绍", + "pay": { + "amount": "金额", + "balance": "账号余额", + "balance_notice": "账号余额不足", + "confirm_pay": "确认支付", + "get_pay_QR": "获取充值二维码", + "need_pay": "需支付", + "new_package_price": "新套餐价格", + "notice": "请勿关闭页面", + "old_package_price": "旧套餐价格", + "other": "其他金额,请取整数", + "to_recharge": "余额不足,去充值", + "wechat": "请微信扫码支付: {{price}}元,请勿关闭页面", + "yuan": "{{amount}}元" + }, "permission": { "Collaborator": "协作者", "Default permission": "默认权限", @@ -1099,16 +1092,15 @@ "Resume InheritPermission Failed": "恢复失败", "Resume InheritPermission Success": "恢复成功", "change_owner": "转移所有权", - "change_owner_to": "转移给", + "change_owner_failed": "转移所有权失败", "change_owner_placeholder": "输入用户名查找账号", - "change_owner_tip": "转移后将保留您的管理员权限", "change_owner_success": "成功转移所有权", - "change_owner_failed": "转移所有权失败" + "change_owner_tip": "转移后将保留您的管理员权限", + "change_owner_to": "转移给" }, "plugin": { "App": "选择应用", "Currentapp": "当前应用", - "contribute": "贡献插件", "Description": "描述", "Edit Http Plugin": "编辑 HTTP 插件", "Enter PAT": "请输入访问凭证(PAT)", @@ -1125,9 +1117,13 @@ "Plugin List": "插件列表", "Search plugin": "搜索插件", "Set Name": "给插件取个名字", + "contribute": "贡献插件", "go to laf": "去编写", "path": "路径" }, + "reply_now": "立即回复", + "required": "必须", + "resume_failed": "恢复失败", "select_reference_variable": "选择引用变量", "share_link": "分享链接", "support": { @@ -1183,9 +1179,6 @@ "inform": { "System message": "系统消息" }, - "logout": { - "confirm": "确认退出登录?" - }, "login": { "And": "和", "Email": "邮箱", @@ -1205,10 +1198,13 @@ "Terms": "服务协议", "Username": "用户名", "Wechat": "微信登录", - "wx_qr_login": "微信扫码登录", - "error": "登录异常", "can_not_login": "无法登录,点击联系", - "security_failed": "安全校验失败" + "error": "登录异常", + "security_failed": "安全校验失败", + "wx_qr_login": "微信扫码登录" + }, + "logout": { + "confirm": "确认退出登录?" }, "team": { "Dataset usage": "知识库容量", @@ -1221,14 +1217,13 @@ "Amount": "金额", "Bills": "账单", "Buy": "购买", - "buy_resource": "购买资源包", - "amount_0": "购买数量不能为0", "Confirm pay": "支付确认", "Not sufficient": "您的 AI 积分不足,请先升级套餐或购买额外 AI 积分后继续使用。", "Plan expired time": "套餐到期时间", "Plan reset time": "套餐重置时间", "Standard Plan Detail": "套餐详情", "To read plan": "查看套餐", + "amount_0": "购买数量不能为0", "bill": { "Number": "订单号", "Status": "状态", @@ -1245,15 +1240,14 @@ "success": "支付成功" } }, + "buy_resource": "购买资源包", "moduleName": { "index": "索引生成", "qa": "QA 拆分" }, "noBill": "无账单记录~", "subscription": { - "point": "积分", "AI points": "AI 积分", - "ai_model": "AI语言模型", "AI points click to read tip": "每次调用 AI 模型时,都会消耗一定的 AI 积分(类似于 token)。点击可查看详细计算规则。", "AI points usage": "AI 积分使用量", "AI points usage tip": "每次调用 AI 模型时,都会消耗一定的 AI 积分。具体的计算标准可参考上方的“计费标准”", @@ -1265,7 +1259,6 @@ "Extra plan": "额外资源包", "Extra plan tip": "标准套餐不够时,您可以购买额外资源包继续使用", "FAQ": "常见问题", - "token_compute": "点击查看在线 Tokens 计算器", "Month amount": "月数", "Next plan": "未来套餐", "Nonsupport": "无法切换", @@ -1279,7 +1272,7 @@ "Update extra ai points": "额外 AI 积分", "Update extra dataset size": "额外存储量", "Upgrade plan": "升级套餐", - + "ai_model": "AI语言模型", "function": { "History store": "{{amount}} 天对话记录保留", "Max app": "{{amount}} 个应用&插件", @@ -1294,13 +1287,15 @@ "Year": "按年", "Year sale": "赠送两个月" }, + "point": "积分", "standardSubLevel": { "enterprise": "企业版", "experience": "体验版", "free": "免费版", - "free desc": "每月均可免费使用基础功能,30 天无使用记录时,将会清除知识库", + "free desc": "每月均可免费使用基础功能,连续 30 天未登录系统,将会自动清除知识库", "team": "团队版" }, + "token_compute": "点击查看在线 Tokens 计算器", "type": { "balance": "余额充值", "extraDatasetSize": "知识库扩容", @@ -1339,6 +1334,12 @@ "Quote Prompt Tip": "可以用 {{quote}} 来插入引用内容模板,使用 {{question}} 来插入问题。下面是默认值:\n{{default}}" }, "textarea_variable_picker_tip": "输入 / 可选择变量", + "tool_field": "工具字段参数配置", + "undefined_var": "引用了未定义的变量,是否自动添加?", + "unit": { + "character": "字符", + "minute": "分钟" + }, "unusable_variable": "无可用变量", "upload_file_error": "上传文件失败", "user": { @@ -1351,7 +1352,6 @@ "Copy invite url": "复制邀请链接", "Edit name": "点击修改昵称", "Invite Url": "邀请链接", - "no_invite_records": "暂无邀请记录", "Invite url tip": "通过该链接注册的好友将永久与你绑定,其充值时你会获得一定余额奖励。\n此外,好友使用手机号注册时,你将立即获得 5 元奖励。\n奖励会发送到您的默认团队中。", "Laf Account Setting": "laf 账号配置", "Language": "语言", @@ -1359,14 +1359,9 @@ "Notice": "通知", "Notification Receive": "通知接收", "Notification Receive Bind": "请先绑定通知接收途径", - "no_notice": "暂无通知", "Old password is error": "旧密码错误", "OpenAI Account Setting": "OpenAI 账号配置", "Password": "密码", - "new_password": "新密码", - "old_password": "旧密码", - "confirm_password": "确认密码", - "password_message": "密码最少 4 位最多 60 位", "Pay": "充值", "Personal Information": "个人信息", "Promotion": "促销", @@ -1378,16 +1373,21 @@ "Sign Out": "登出", "Team": "团队", "Time": "时间", - "type": "类型", "Timezone": "时区", "Update Password": "修改密码", "Update password failed": "修改密码异常", "Update password successful": "修改密码成功", "Usage Record": "使用记录", - "no_usage_records": "暂无使用记录", "apikey": { "key": "API 秘钥" }, + "confirm_password": "确认密码", + "new_password": "新密码", + "no_invite_records": "暂无邀请记录", + "no_notice": "暂无通知", + "no_usage_records": "暂无使用记录", + "old_password": "旧密码", + "password_message": "密码最少 4 位最多 60 位", "team": { "Balance": "团队余额", "Check Team": "切换", @@ -1435,6 +1435,8 @@ "Owner": "创建者", "Visitor": "访客" } - } - } + }, + "type": "类型" + }, + "verification": "验证" } diff --git a/packages/web/i18n/zh/user.json b/packages/web/i18n/zh/user.json index 662094c31c86..3a20dfc258a1 100644 --- a/packages/web/i18n/zh/user.json +++ b/packages/web/i18n/zh/user.json @@ -50,7 +50,7 @@ "verification_code": "验证码", "confirm": "确认密码", "not_match": "两次密码不一致", - "to_login": "去登陆", + "to_login": "去登录", "get_code": "获取验证码", "get_code_again": "s后重新获取", "code_sended": "验证码已发送", diff --git a/projects/app/public/imgs/app/fileUploadPlaceholder.png b/projects/app/public/imgs/app/fileUploadPlaceholder.png new file mode 100644 index 0000000000000000000000000000000000000000..e4f0a7a82e5cec849254d8bae921fe2fcf44a393 GIT binary patch literal 31782 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 Dd}CB9 literal 0 HcmV?d00001 diff --git a/projects/app/public/imgs/app/fileUploadPlaceholder.svg b/projects/app/public/imgs/app/fileUploadPlaceholder.svg deleted file mode 100644 index 46df70c78aa7..000000000000 --- a/projects/app/public/imgs/app/fileUploadPlaceholder.svg +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/projects/app/public/imgs/app/question.svg b/projects/app/public/imgs/app/question.svg new file mode 100644 index 000000000000..f82406b28906 --- /dev/null +++ b/projects/app/public/imgs/app/question.svg @@ -0,0 +1,4 @@ + + + + diff --git a/projects/app/public/imgs/app/visionModel.png b/projects/app/public/imgs/app/visionModel.png new file mode 100644 index 0000000000000000000000000000000000000000..16cc046aac52f08a1bcdfe257c0b325452c888b7 GIT binary patch literal 38002 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 literal 0 HcmV?d00001 diff --git a/projects/app/src/components/core/app/FileSelect.tsx b/projects/app/src/components/core/app/FileSelect.tsx index 94695c7dd3aa..4ccba4f8cdd2 100644 --- a/projects/app/src/components/core/app/FileSelect.tsx +++ b/projects/app/src/components/core/app/FileSelect.tsx @@ -20,6 +20,8 @@ import { defaultAppSelectFileConfig } from '@fastgpt/global/core/app/constants'; import ChatFunctionTip from './Tip'; import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; import { useMount } from 'ahooks'; +import { useSystemStore } from '@/web/common/system/useSystemStore'; +import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; const FileSelect = ({ forbidVision = false, @@ -31,7 +33,9 @@ const FileSelect = ({ onChange: (e: AppFileSelectConfigType) => void; }) => { const { t } = useTranslation(); + const { feConfigs } = useSystemStore(); const { isOpen, onOpen, onClose } = useDisclosure(); + const maxSelectFiles = Math.min(feConfigs?.uploadFileMaxAmount ?? 20, 30); const formLabel = useMemo( () => @@ -106,22 +110,27 @@ const FileSelect = ({ )} {!forbidVision && ( - - {t('app:image_upload_tip')} - + + {t('app:image_upload_tip')} + + )} - {t('app:upload_file_max_amount')} + + {t('app:upload_file_max_amount')} + + + { diff --git a/projects/app/src/components/core/app/TTSSelect.tsx b/projects/app/src/components/core/app/TTSSelect.tsx index 8680847fd4c4..7cb506c651ef 100644 --- a/projects/app/src/components/core/app/TTSSelect.tsx +++ b/projects/app/src/components/core/app/TTSSelect.tsx @@ -97,12 +97,8 @@ const TTSSelect = ({ - - {t('common:core.app.TTS')} - - } + iconSrc="core/app/simpleMode/tts" + title={t('common:core.app.TTS')} isOpen={isOpen} onClose={onCloseTTSModal} w={'500px'} diff --git a/projects/app/src/components/core/app/Tip.tsx b/projects/app/src/components/core/app/Tip.tsx index 68e15535349d..3222e8fa0ed2 100644 --- a/projects/app/src/components/core/app/Tip.tsx +++ b/projects/app/src/components/core/app/Tip.tsx @@ -10,7 +10,8 @@ enum FnTypeEnum { tts = 'tts', variable = 'variable', welcome = 'welcome', - file = 'file' + file = 'file', + visionModel = 'visionModel' } const ChatFunctionTip = ({ type }: { type: `${FnTypeEnum}` }) => { @@ -52,7 +53,13 @@ const ChatFunctionTip = ({ type }: { type: `${FnTypeEnum}` }) => { icon: '/imgs/app/welcome-icon.svg', title: t('app:file_upload'), desc: t('app:file_upload_tip'), - imgUrl: '/imgs/app/fileUploadPlaceholder.svg' + imgUrl: '/imgs/app/fileUploadPlaceholder.png' + }, + [FnTypeEnum.visionModel]: { + icon: '/imgs/app/question.svg', + title: t('app:vision_model_title'), + desc: t('app:llm_use_vision_tip'), + imgUrl: '/imgs/app/visionModel.png' } }); const data = map.current[type]; @@ -62,8 +69,8 @@ const ChatFunctionTip = ({ type }: { type: `${FnTypeEnum}` }) => { maxW={'420px'} ml={1} label={ - - + + {''} {data.title} diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/Input/ChatInput.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/Input/ChatInput.tsx index 1327d92798ec..671aba68a2d2 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/Input/ChatInput.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/Input/ChatInput.tsx @@ -1,6 +1,15 @@ import { useSpeech } from '@/web/common/hooks/useSpeech'; import { useSystemStore } from '@/web/common/system/useSystemStore'; -import { Box, Flex, HStack, Image, Spinner, Textarea } from '@chakra-ui/react'; +import { + Box, + CircularProgress, + CircularProgressLabel, + Flex, + HStack, + Image, + Spinner, + Textarea +} from '@chakra-ui/react'; import React, { useRef, useEffect, useCallback, useMemo } from 'react'; import { useTranslation } from 'next-i18next'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; @@ -22,6 +31,8 @@ import { getFileIcon } from '@fastgpt/global/common/file/icon'; import { useToast } from '@fastgpt/web/hooks/useToast'; import { clone } from 'lodash'; import { formatFileSize } from '@fastgpt/global/common/file/tools'; +import MyBox from '@fastgpt/web/components/common/MyBox'; +import { getErrText } from '@fastgpt/global/common/error/utils'; const InputGuideBox = dynamic(() => import('./InputGuideBox')); @@ -103,6 +114,7 @@ const ChatInput = ({ multiple: true, maxCount: maxSelectFiles }); + // Upload files useRequest2( async () => { const filterFiles = fileList.filter((item) => item.status === 0); @@ -110,30 +122,48 @@ const ChatInput = ({ if (filterFiles.length === 0) return; replaceFiles(fileList.map((item) => ({ ...item, status: 1 }))); + let errorFileIndex: number[] = []; - for (const file of filterFiles) { - if (!file.rawFile) continue; + await Promise.allSettled( + filterFiles.map(async (file) => { + const copyFile = clone(file); + copyFile.status = 1; + if (!copyFile.rawFile) return; - try { - const { fileId, previewUrl } = await uploadFile2DB({ - file: file.rawFile, - bucketName: 'chat', - metadata: { - chatId - } - }); - - updateFiles(fileList.findIndex((item) => item.id === file.id)!, { - ...file, - status: 1, - url: `${location.origin}${previewUrl}` - }); - } catch (error) { - removeFiles(fileList.findIndex((item) => item.id === file.id)!); - console.log(error); - return Promise.reject(error); - } - } + try { + const fileIndex = fileList.findIndex((item) => item.id === file.id)!; + + // Start upload and update process + const { previewUrl } = await uploadFile2DB({ + file: copyFile.rawFile, + bucketName: 'chat', + metadata: { + chatId + }, + percentListen(e) { + copyFile.process = e; + if (!copyFile.url) { + updateFiles(fileIndex, copyFile); + } + } + }); + + // Update file url + copyFile.url = `${location.origin}${previewUrl}`; + updateFiles(fileIndex, copyFile); + } catch (error) { + errorFileIndex.push(fileList.findIndex((item) => item.id === file.id)!); + toast({ + status: 'warning', + title: t( + getErrText(error, t('common:error.upload_file_error_filename', { name: file.name })) + ) + }); + } + }) + ); + + removeFiles(errorFileIndex); }, { manual: false, @@ -211,20 +241,23 @@ const ChatInput = ({ ); replaceFiles(concatFileList); }, - [fileList, maxSelectFiles, replaceFiles, toast, t] + [fileList, maxSelectFiles, replaceFiles, toast, t, maxSize] ); /* on send */ - const handleSend = async (val?: string) => { - if (!canSendMessage) return; - const textareaValue = val || TextareaDom.current?.value || ''; + const handleSend = useCallback( + async (val?: string) => { + if (!canSendMessage) return; + const textareaValue = val || TextareaDom.current?.value || ''; - onSendMessage({ - text: textareaValue.trim(), - files: fileList - }); - replaceFiles([]); - }; + onSendMessage({ + text: textareaValue.trim(), + files: fileList + }); + replaceFiles([]); + }, + [TextareaDom, canSendMessage, fileList, onSendMessage, replaceFiles] + ); /* whisper init */ const { whisperModel } = useSystemStore(); @@ -278,96 +311,53 @@ const ChatInput = ({ startSpeak(finishWhisperTranscription); }, [finishWhisperTranscription, isSpeaking, startSpeak, stopSpeak]); - return ( - - 0 ? '10px' : ['14px', '18px']} - pb={['14px', '18px']} - position={'relative'} - boxShadow={isSpeaking ? `0 0 10px rgba(54,111,255,0.4)` : `0 0 10px rgba(0,0,0,0.2)`} - borderRadius={['none', 'md']} + const RenderTranslateLoading = useMemo( + () => ( + - {/* Chat input guide box */} - {chatInputGuide.open && ( - { - setValue('input', e); - }} - onSend={(e) => { - handleSend(e); - }} - /> - )} - - {/* translate loading */} - - - {t('common:core.chat.Converting to text')} - - - {/* file preview */} + + {t('common:core.chat.Converting to text')} + + ), + [isSpeaking, isTransCription, t] + ); + const RenderFilePreview = useMemo( + () => + fileList.length > 0 ? ( 0 ? 2 : 0} > {fileList.map((item, index) => ( - - {/* uploading */} - {!item.url && ( - - - - )} { - removeFiles(index); - }} + onClick={() => removeFiles(index)} className="close-icon" display={['', 'none']} + zIndex={10} /> {item.type === ChatFileTypeEnum.image && ( )} - + {/* Process */} + {!item.url && ( + + + {/* {item.process ?? 0}% */} + + + )} + ))} + ) : null, + [fileList, isPc, removeFiles] + ); + const RenderTextarea = useMemo( + () => ( + 0 ? 1 : 0} pl={[2, 4]}> + {/* file selector */} + {(showSelectFile || showSelectImg) && ( + { + if (isSpeaking) return; + onOpenSelectFile(); + }} + > + + + + + + )} - 0 ? 1 : 0} pl={[2, 4]}> - {/* file selector */} - {(showSelectFile || showSelectImg) && ( - { - if (isSpeaking) return; - onOpenSelectFile(); - }} - > - - - - - - )} + {/* input area */} +