diff --git a/docSite/content/zh-cn/docs/development/upgrading/4820.md b/docSite/content/zh-cn/docs/development/upgrading/4820.md index 5da394a42fc4..07f86b464d06 100644 --- a/docSite/content/zh-cn/docs/development/upgrading/4820.md +++ b/docSite/content/zh-cn/docs/development/upgrading/4820.md @@ -34,4 +34,5 @@ curl --location --request POST 'https://{{host}}/api/admin/initv4820' \ 2. 新增 - 使用记录导出和仪表盘。 3. 新增 - markdown 语法扩展,支持音视频(代码块 audio 和 video)。 4. 优化 - 页面组件抽离,减少页面组件路由。 -5. 优化 - 全文检索,忽略大小写。 \ No newline at end of file +5. 优化 - 全文检索,忽略大小写。 +6. 优化 - 问答生成和增强索引改成流输出,避免部分模型超时。 \ No newline at end of file diff --git a/packages/service/core/ai/utils.ts b/packages/service/core/ai/utils.ts index aad1cb1efeab..74b4e718f919 100644 --- a/packages/service/core/ai/utils.ts +++ b/packages/service/core/ai/utils.ts @@ -2,7 +2,8 @@ import { LLMModelItemType } from '@fastgpt/global/core/ai/model.d'; import { ChatCompletionCreateParamsNonStreaming, ChatCompletionCreateParamsStreaming, - ChatCompletionMessageParam + ChatCompletionMessageParam, + StreamChatType } from '@fastgpt/global/core/ai/type'; import { countGptMessagesTokens } from '../../common/string/tiktoken'; import { getLLMModel } from './model'; @@ -87,3 +88,12 @@ export const llmCompletionsBodyFormat = ( return requestBody as InferCompletionsBody; }; + +export const llmStreamResponseToText = async (response: StreamChatType) => { + let answer = ''; + for await (const part of response) { + const content = part.choices?.[0]?.delta?.content || ''; + answer += content; + } + return answer; +}; diff --git a/packages/web/hooks/useRequest.tsx b/packages/web/hooks/useRequest.tsx index 4e2346ed1623..ff7d6efbc841 100644 --- a/packages/web/hooks/useRequest.tsx +++ b/packages/web/hooks/useRequest.tsx @@ -63,7 +63,7 @@ export const useRequest2 = ( ...rest, onError: (err, params) => { rest?.onError?.(err, params); - if (errorToast !== undefined) { + if (errorToast !== '') { const errText = t(getErrText(err, errorToast || '') as any); if (errText) { toast({ diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json index 1fe98c8c4c87..5b1fbbd32823 100644 --- a/packages/web/i18n/en/common.json +++ b/packages/web/i18n/en/common.json @@ -93,10 +93,10 @@ "code_error.team_error.org_parent_not_exist": "Parent organization does not exist", "code_error.team_error.over_size": "error.team.overSize", "code_error.team_error.plugin_amount_not_enough": "Plugin Limit Reached", - "code_error.team_error.re_rank_not_enough": "Unauthorized to Use Re-Rank", + "code_error.team_error.re_rank_not_enough": "Search rearrangement cannot be used in the free version~", "code_error.team_error.un_auth": "Unauthorized to Operate This Team", "code_error.team_error.user_not_active": "The user did not accept or has left the team", - "code_error.team_error.website_sync_not_enough": "Unauthorized to Use Website Sync", + "code_error.team_error.website_sync_not_enough": "The free version cannot be synchronized with the web site ~", "code_error.token_error_code.403": "Invalid Login Status, Please Re-login", "code_error.user_error.balance_not_enough": "Insufficient Account Balance", "code_error.user_error.bin_visitor_guest": "You Are Currently a Guest, Unauthorized to Operate", diff --git a/packages/web/i18n/zh-CN/common.json b/packages/web/i18n/zh-CN/common.json index fdbe61c45ebc..c79e0fa0f51d 100644 --- a/packages/web/i18n/zh-CN/common.json +++ b/packages/web/i18n/zh-CN/common.json @@ -97,10 +97,10 @@ "code_error.team_error.org_parent_not_exist": "父部门不存在", "code_error.team_error.over_size": "error.team.overSize", "code_error.team_error.plugin_amount_not_enough": "插件数量已达上限~", - "code_error.team_error.re_rank_not_enough": "无权使用检索重排~", + "code_error.team_error.re_rank_not_enough": "免费版无法使用检索重排~", "code_error.team_error.un_auth": "无权操作该团队", "code_error.team_error.user_not_active": "用户未接受或已离开团队", - "code_error.team_error.website_sync_not_enough": "无权使用Web站点同步~", + "code_error.team_error.website_sync_not_enough": "免费版无法使用Web站点同步~", "code_error.token_error_code.403": "登录状态无效,请重新登录", "code_error.user_error.balance_not_enough": "账号余额不足~", "code_error.user_error.bin_visitor_guest": "您当前身份为游客,无权操作", diff --git a/packages/web/i18n/zh-Hant/common.json b/packages/web/i18n/zh-Hant/common.json index da6880e7b7e9..bab85faa0419 100644 --- a/packages/web/i18n/zh-Hant/common.json +++ b/packages/web/i18n/zh-Hant/common.json @@ -92,10 +92,10 @@ "code_error.team_error.org_parent_not_exist": "父組織不存在", "code_error.team_error.over_size": "error.team.overSize", "code_error.team_error.plugin_amount_not_enough": "已達外掛程式數量上限", - "code_error.team_error.re_rank_not_enough": "無權使用結果重新排名", + "code_error.team_error.re_rank_not_enough": "免費版無法使用檢索重排~", "code_error.team_error.un_auth": "無權操作此團隊", "code_error.team_error.user_not_active": "使用者未接受或已離開團隊", - "code_error.team_error.website_sync_not_enough": "無權使用網站同步", + "code_error.team_error.website_sync_not_enough": "免費版無法使用Web站點同步~", "code_error.token_error_code.403": "登入狀態無效,請重新登入", "code_error.user_error.balance_not_enough": "帳戶餘額不足", "code_error.user_error.bin_visitor_guest": "您目前身份為訪客,無權操作", diff --git a/projects/app/public/docs/versionIntro.md b/projects/app/public/docs/versionIntro.md index 396b88876b0e..078daa220216 100644 --- a/projects/app/public/docs/versionIntro.md +++ b/projects/app/public/docs/versionIntro.md @@ -1,21 +1,12 @@ -### FastGPT V4.8.16 更新说明 - -1. 新增 - SearXNG 搜索插件[点击查看教程](https://doc.fastgpt.cn//docs/guide/plugins/searxng_plugin_guide/) -2. 新增 - 商业版支持 API 知识库和链接集合定时同步。 -3. 新增 - 猜你想问支持选择模型和自定义提示词。 -4. 新增 - 钉钉和企微机器人 webhook 插件。 -5. 新增 - 商业版支持钉钉 SSO 登录配置。[点击查看教程](https://doc.fastgpt.cn//docs/guide/admin/sso_dingtalk/) -6. 新增 - 商业版支持飞书和语雀知识库导入。[点击查看教程](https://doc.fastgpt.cn//docs/guide/knowledge_base/lark_dataset/) -7. 新增 - sandbox 新增 createHmac 加密全局方法。 -8. 新增 - 工作流右键支持全部折叠。 -9. 优化 - 工作流/简易模式变量初始化代码,去除监听初始化,避免因渲染顺序不一致导致的失败。 -10. 优化 - 工作流获取数据类型不一致数据时,增加类型转化,避免 undefined。 -11. 修复 - 无法自动切换默认语言。增加分享链接,强制执行一次切换默认语言。 -12. 修复 - 数组选择器自动兼容 4.8.13 以前的数据。 -13. 修复 - 站点同步知识库,链接同步时未使用选择器。 -14. 修复 - 简易模式转工作流,没有把系统配置项转化。 -15. 修复 - 插件独立运行,变量初始值未赋上。 -16. 修复 - 工作流使用弹窗组件时,关闭弹窗后,有时候会出现页面偏移。 -17. 修复 - 插件调试时,日志未保存插件输入参数。 +### FastGPT V4.8.20 更新说明 +1. 新增 - 使用记录导出和仪表盘。 +2. 新增 - markdown 语法扩展,支持音视频(代码块 audio 和 video)。 +3. 新增 - 飞书/语雀知识库。 +4. 新增 - 工作流知识库检索支持按知识库权限进行过滤。 +5. 新增 - 流程等待插件,可以等待 n 毫秒后继续执行流程。 +6. 新增 - 飞书机器人接入,支持配置私有化飞书地址。 +7. 新增 - 支持通过 JSON 配置直接创建应用。 +8. 新增 - 支持通过 CURL 脚本快速创建 HTTP 插件。 +9. 新增 - 支持部门架构权限模式。 diff --git a/projects/app/src/components/support/wallet/NotSufficientModal/index.tsx b/projects/app/src/components/support/wallet/NotSufficientModal/index.tsx index 551bc43af28c..9b82c0a45241 100644 --- a/projects/app/src/components/support/wallet/NotSufficientModal/index.tsx +++ b/projects/app/src/components/support/wallet/NotSufficientModal/index.tsx @@ -29,7 +29,10 @@ const NotSufficientModal = ({ type }: { type: NotSufficientModalType }) => { [TeamErrEnum.datasetSizeNotEnough]: t('common:support.wallet.Dataset_not_sufficient'), [TeamErrEnum.datasetAmountNotEnough]: t('common:support.wallet.Dataset_amount_not_sufficient'), [TeamErrEnum.teamMemberOverSize]: t('common:support.wallet.Team_member_over_size'), - [TeamErrEnum.appAmountNotEnough]: t('common:support.wallet.App_amount_not_sufficient') + [TeamErrEnum.appAmountNotEnough]: t('common:support.wallet.App_amount_not_sufficient'), + [TeamErrEnum.pluginAmountNotEnough]: t('common:support.wallet.App_amount_not_sufficient'), + [TeamErrEnum.websiteSyncNotEnough]: t('common:code_error.team_error.website_sync_not_enough'), + [TeamErrEnum.reRankNotEnough]: t('common:code_error.team_error.re_rank_not_enough') }; return ( diff --git a/projects/app/src/components/support/wallet/QRCodePayModal.tsx b/projects/app/src/components/support/wallet/QRCodePayModal.tsx index c2db2fd8e461..306ab1a3481b 100644 --- a/projects/app/src/components/support/wallet/QRCodePayModal.tsx +++ b/projects/app/src/components/support/wallet/QRCodePayModal.tsx @@ -4,9 +4,9 @@ import { useTranslation } from 'next-i18next'; import { Box, ModalBody } from '@chakra-ui/react'; import { checkBalancePayResult } from '@/web/support/wallet/bill/api'; import { useToast } from '@fastgpt/web/hooks/useToast'; -import { getErrText } from '@fastgpt/global/common/error/utils'; import LightTip from '@fastgpt/web/components/common/LightTip'; import QRCode from 'qrcode'; +import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; export type QRPayProps = { readPrice: number; @@ -54,35 +54,16 @@ const QRCodePayModal = ({ drawCode(); }, [drawCode]); - useEffect(() => { - let timer: NodeJS.Timeout; - const check = async () => { - try { - const res = await checkBalancePayResult(billId); - if (res) { - try { - await onSuccess?.(); - toast({ - title: res, - status: 'success' - }); - return clearTimeout(timer); - } catch (error) { - toast({ - title: getErrText(error), - status: 'error' - }); - } - } - } catch (error) {} - clearTimeout(timer); - timer = setTimeout(check, 2000); - }; - - check(); - - return () => clearTimeout(timer); - }, [billId, drawCode, onSuccess, toast]); + useRequest2(() => checkBalancePayResult(billId), { + manual: false, + pollingInterval: 2000, + onSuccess: (res) => { + if (res) { + onSuccess?.(); + } + }, + errorToast: '' + }); return ( diff --git a/projects/app/src/service/events/generateQA.ts b/projects/app/src/service/events/generateQA.ts index 0824e317e974..fc213f83f815 100644 --- a/projects/app/src/service/events/generateQA.ts +++ b/projects/app/src/service/events/generateQA.ts @@ -18,7 +18,7 @@ import { } from '@fastgpt/service/common/string/tiktoken/index'; import { pushDataListToTrainingQueueByCollectionId } from '@fastgpt/service/core/dataset/training/controller'; import { loadRequestMessages } from '@fastgpt/service/core/chat/utils'; -import { llmCompletionsBodyFormat } from '@fastgpt/service/core/ai/utils'; +import { llmCompletionsBodyFormat, llmStreamResponseToText } from '@fastgpt/service/core/ai/utils'; const reduceQueue = () => { global.qaQueueLen = global.qaQueueLen > 0 ? global.qaQueueLen - 1 : 0; @@ -44,7 +44,7 @@ export async function generateQA(): Promise { { mode: TrainingModeEnum.qa, retryCount: { $gte: 0 }, - lockTime: { $lte: addMinutes(new Date(), -6) } + lockTime: { $lte: addMinutes(new Date(), -10) } }, { lockTime: new Date(), @@ -120,12 +120,12 @@ ${replaceVariable(Prompt_AgentQA.fixedText, { text })}`; model: modelData.model, temperature: 0.3, messages: await loadRequestMessages({ messages, useVision: false }), - stream: false + stream: true }, modelData ) }); - const answer = chatResponse.choices?.[0].message?.content || ''; + const answer = await llmStreamResponseToText(chatResponse); const qaArr = formatSplitText(answer, text); // 格式化后的QA对 diff --git a/projects/app/src/service/events/generateVector.ts b/projects/app/src/service/events/generateVector.ts index a9d72ed13147..92ea0451c82f 100644 --- a/projects/app/src/service/events/generateVector.ts +++ b/projects/app/src/service/events/generateVector.ts @@ -40,7 +40,7 @@ export async function generateVector(): Promise { { mode: TrainingModeEnum.chunk, retryCount: { $gte: 0 }, - lockTime: { $lte: addMinutes(new Date(), -6) } + lockTime: { $lte: addMinutes(new Date(), -3) } }, { lockTime: new Date(), diff --git a/projects/app/src/web/common/api/request.ts b/projects/app/src/web/common/api/request.ts index 009dd5c45066..20bbe2010fb2 100644 --- a/projects/app/src/web/common/api/request.ts +++ b/projects/app/src/web/common/api/request.ts @@ -101,6 +101,7 @@ function checkRes(data: ResponseDataType) { */ function responseError(err: any) { console.log('error->', '请求错误', err); + const data = err?.response?.data || err; if (!err) { return Promise.reject({ message: '未知错误' }); @@ -108,8 +109,12 @@ function responseError(err: any) { if (typeof err === 'string') { return Promise.reject({ message: err }); } + if (typeof data === 'string') { + return Promise.reject(data); + } + // 有报错响应 - if (err?.code in TOKEN_ERROR_CODE || err?.response?.data?.code in TOKEN_ERROR_CODE) { + if (data?.code in TOKEN_ERROR_CODE) { if (!['/chat/share', '/chat/team', '/login'].includes(window.location.pathname)) { clearToken(); window.location.replace( @@ -120,18 +125,18 @@ function responseError(err: any) { return Promise.reject({ message: i18nT('common:unauth_token') }); } if ( - err?.statusText === TeamErrEnum.aiPointsNotEnough || - err?.statusText === TeamErrEnum.datasetSizeNotEnough || - err?.statusText === TeamErrEnum.datasetAmountNotEnough || - err?.statusText === TeamErrEnum.appAmountNotEnough + data?.statusText === TeamErrEnum.aiPointsNotEnough || + data?.statusText === TeamErrEnum.datasetSizeNotEnough || + data?.statusText === TeamErrEnum.datasetAmountNotEnough || + data?.statusText === TeamErrEnum.appAmountNotEnough || + data?.statusText === TeamErrEnum.pluginAmountNotEnough || + data?.statusText === TeamErrEnum.websiteSyncNotEnough || + data?.statusText === TeamErrEnum.reRankNotEnough ) { - useSystemStore.getState().setNotSufficientModalType(err.statusText); - return Promise.reject(err); - } - if (err?.response?.data) { - return Promise.reject(err?.response?.data); + useSystemStore.getState().setNotSufficientModalType(data.statusText); + return Promise.reject(data); } - return Promise.reject(err); + return Promise.reject(data); } /* 创建请求实例 */ diff --git a/projects/app/src/web/context/useInitApp.ts b/projects/app/src/web/context/useInitApp.ts index a705e36459d8..4b32a7c88b16 100644 --- a/projects/app/src/web/context/useInitApp.ts +++ b/projects/app/src/web/context/useInitApp.ts @@ -63,7 +63,7 @@ export const useInitApp = () => { useRequest2(initFetch, { manual: false, - pollingInterval: 300000 + pollingInterval: 300000 // 5 minutes refresh }); useEffect(() => {