mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-21 03:35:36 +00:00
feat: chat error msg (#4826)
* perf: i18n * feat: chat error msg * feat: doc
This commit is contained in:
BIN
docSite/assets/imgs/official_account_faq.png
Normal file
BIN
docSite/assets/imgs/official_account_faq.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 386 KiB |
@@ -12,6 +12,7 @@ weight: 791
|
||||
|
||||
1. 切换 SessionId 来替代 JWT 实现登录鉴权,可控制最大登录客户端数量。
|
||||
2. 新的商业版 License 管理模式。
|
||||
3. 公众号调用,显示记录 chat 对话错误,方便排查。
|
||||
|
||||
## ⚙️ 优化
|
||||
|
||||
|
@@ -132,7 +132,9 @@ weight: 506
|
||||
### 公众号没响应
|
||||
|
||||
检查应用对话日志,如果有对话日志,但是微信公众号无响应,则是白名单 IP未成功。
|
||||
添加白名单IP 后,通常需要等待几分钟微信更新。
|
||||
添加白名单IP 后,通常需要等待几分钟微信更新。可以在对话日志中,找点错误日志。
|
||||
|
||||

|
||||
|
||||
### 如何新开一个聊天记录
|
||||
|
||||
|
2
packages/global/core/chat/type.d.ts
vendored
2
packages/global/core/chat/type.d.ts
vendored
@@ -112,6 +112,7 @@ export type ChatItemSchema = (UserChatItemType | SystemChatItemType | AIChatItem
|
||||
appId: string;
|
||||
time: Date;
|
||||
durationSeconds?: number;
|
||||
errorMsg?: string;
|
||||
};
|
||||
|
||||
export type AdminFbkType = {
|
||||
@@ -143,6 +144,7 @@ export type ChatSiteItemType = (UserChatItemType | SystemChatItemType | AIChatIt
|
||||
responseData?: ChatHistoryItemResType[];
|
||||
time?: Date;
|
||||
durationSeconds?: number;
|
||||
errorMsg?: string;
|
||||
} & ChatBoxInputType &
|
||||
ResponseTagItemType;
|
||||
|
||||
|
@@ -57,14 +57,19 @@ export const addLog = {
|
||||
|
||||
level === LogLevelEnum.error && console.error(obj);
|
||||
|
||||
// store
|
||||
if (level >= STORE_LOG_LEVEL && connectionMongo.connection.readyState === 1) {
|
||||
// store log
|
||||
getMongoLog().create({
|
||||
if (level >= STORE_LOG_LEVEL && connectionMongo.connection.readyState === 1) {
|
||||
(async () => {
|
||||
try {
|
||||
await getMongoLog().create({
|
||||
text: msg,
|
||||
level,
|
||||
metadata: obj
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('store log error', error);
|
||||
}
|
||||
})();
|
||||
}
|
||||
},
|
||||
debug(msg: string, obj?: Record<string, any>) {
|
||||
|
@@ -61,6 +61,7 @@ const ChatItemSchema = new Schema({
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
errorMsg: String,
|
||||
userGoodFeedback: {
|
||||
type: String
|
||||
},
|
||||
|
@@ -32,6 +32,7 @@ type Props = {
|
||||
content: [UserChatItemType & { dataId?: string }, AIChatItemType & { dataId?: string }];
|
||||
metadata?: Record<string, any>;
|
||||
durationSeconds: number; //s
|
||||
errorMsg?: string;
|
||||
};
|
||||
|
||||
export async function saveChat({
|
||||
@@ -50,6 +51,7 @@ export async function saveChat({
|
||||
outLinkUid,
|
||||
content,
|
||||
durationSeconds,
|
||||
errorMsg,
|
||||
metadata = {}
|
||||
}: Props) {
|
||||
if (!chatId || chatId === 'NO_RECORD_HISTORIES') return;
|
||||
@@ -104,7 +106,8 @@ export async function saveChat({
|
||||
return {
|
||||
...item,
|
||||
[DispatchNodeResponseKeyEnum.nodeResponse]: nodeResponse,
|
||||
durationSeconds
|
||||
durationSeconds,
|
||||
errorMsg
|
||||
};
|
||||
}
|
||||
return item;
|
||||
|
@@ -35,6 +35,7 @@
|
||||
"delete_all_input_guide_confirm": "Are you sure you want to clear the input guide lexicon?",
|
||||
"download_chunks": "Download data",
|
||||
"empty_directory": "This directory is empty~",
|
||||
"error_message": "error message",
|
||||
"file_amount_over": "Exceeded maximum file quantity {{max}}",
|
||||
"file_input": "File input",
|
||||
"file_input_tip": "You can obtain the link to the corresponding file through the \"File Link\" of the [Plug-in Start] node",
|
||||
|
@@ -1134,7 +1134,7 @@
|
||||
"support.wallet.subscription.AI points usage tip": "Each time the AI model is called, a certain amount of AI points will be consumed. For specific calculation standards, please refer to the 'Pricing' above.",
|
||||
"support.wallet.subscription.Ai points": "AI Points Calculation Standards",
|
||||
"support.wallet.subscription.Current plan": "Current Package",
|
||||
"support.wallet.subscription.Extra ai points": "Extra AI Points",
|
||||
"support.wallet.subscription.Extra ai points": "AI points",
|
||||
"support.wallet.subscription.Extra dataset size": "Extra Dataset Capacity",
|
||||
"support.wallet.subscription.Extra plan": "Extra Resource Pack",
|
||||
"support.wallet.subscription.Extra plan tip": "When the standard package is not enough, you can purchase extra resource packs to continue using",
|
||||
@@ -1147,7 +1147,7 @@
|
||||
"support.wallet.subscription.Team plan and usage": "Package and Usage",
|
||||
"support.wallet.subscription.Training weight": "Training Priority: {{weight}}",
|
||||
"support.wallet.subscription.Update extra ai points": "Extra AI Points",
|
||||
"support.wallet.subscription.Update extra dataset size": "Extra Storage",
|
||||
"support.wallet.subscription.Update extra dataset size": "Storage",
|
||||
"support.wallet.subscription.Upgrade plan": "Upgrade Package",
|
||||
"support.wallet.subscription.ai_model": "AI Language Model",
|
||||
"support.wallet.subscription.function.History store": "{{amount}} Days of Chat History Retention",
|
||||
@@ -1156,9 +1156,9 @@
|
||||
"support.wallet.subscription.function.Max dataset size": "{{amount}} Dataset Indexes",
|
||||
"support.wallet.subscription.function.Max members": "{{amount}} Team Members",
|
||||
"support.wallet.subscription.function.Points": "{{amount}} AI Points",
|
||||
"support.wallet.subscription.mode.Month": "Monthly",
|
||||
"support.wallet.subscription.mode.Month": "Month",
|
||||
"support.wallet.subscription.mode.Period": "Subscription Period",
|
||||
"support.wallet.subscription.mode.Year": "Yearly",
|
||||
"support.wallet.subscription.mode.Year": "Year",
|
||||
"support.wallet.subscription.mode.Year sale": "Two Months Free",
|
||||
"support.wallet.subscription.point": "Points",
|
||||
"support.wallet.subscription.standardSubLevel.custom": "Custom",
|
||||
@@ -1167,7 +1167,7 @@
|
||||
"support.wallet.subscription.standardSubLevel.experience": "Experience",
|
||||
"support.wallet.subscription.standardSubLevel.experience_desc": "Unlock the full functionality of FastGPT",
|
||||
"support.wallet.subscription.standardSubLevel.free": "Free",
|
||||
"support.wallet.subscription.standardSubLevel.free desc": "Basic functions can be used for free every month. If the system is not logged in for 30 consecutive days, the Dataset will be automatically cleared.",
|
||||
"support.wallet.subscription.standardSubLevel.free desc": "Free trial of core features. \nIf you haven't logged in for 30 days, the knowledge base will be cleared.",
|
||||
"support.wallet.subscription.standardSubLevel.team": "Team",
|
||||
"support.wallet.subscription.standardSubLevel.team_desc": "Suitable for small teams to build Dataset applications and provide external services",
|
||||
"support.wallet.subscription.status.active": "Active",
|
||||
|
@@ -35,6 +35,7 @@
|
||||
"delete_all_input_guide_confirm": "确定要清空输入引导词库吗?",
|
||||
"download_chunks": "下载数据",
|
||||
"empty_directory": "这个目录已经没东西可选了~",
|
||||
"error_message": "错误信息",
|
||||
"file_amount_over": "超出最大文件数量 {{max}}",
|
||||
"file_input": "系统文件",
|
||||
"file_input_tip": "可通过【插件开始】节点的“文件链接”获取对应文件的链接",
|
||||
|
@@ -1166,7 +1166,7 @@
|
||||
"support.wallet.subscription.standardSubLevel.experience": "体验版",
|
||||
"support.wallet.subscription.standardSubLevel.experience_desc": "可解锁 FastGPT 完整功能",
|
||||
"support.wallet.subscription.standardSubLevel.free": "免费版",
|
||||
"support.wallet.subscription.standardSubLevel.free desc": "每月均可免费使用基础功能,连续 30 天未登录系统,将会自动清除知识库",
|
||||
"support.wallet.subscription.standardSubLevel.free desc": "核心功能免费试用。30 天未登录,将会清空知识库。",
|
||||
"support.wallet.subscription.standardSubLevel.team": "团队版",
|
||||
"support.wallet.subscription.standardSubLevel.team_desc": "适合小团队构建知识库应用并提供对外服务",
|
||||
"support.wallet.subscription.status.active": "生效中",
|
||||
|
@@ -33,6 +33,7 @@
|
||||
"delete_all_input_guide_confirm": "確定要清除輸入導引詞彙庫嗎?",
|
||||
"download_chunks": "下載資料",
|
||||
"empty_directory": "此目錄中已無項目可選~",
|
||||
"error_message": "錯誤訊息",
|
||||
"file_amount_over": "超出檔案數量上限 {{max}}",
|
||||
"file_input": "檔案輸入",
|
||||
"file_input_tip": "可透過「外掛程式啟動」節點的「檔案連結」取得對應檔案的連結",
|
||||
|
@@ -1166,7 +1166,7 @@
|
||||
"support.wallet.subscription.standardSubLevel.experience": "體驗版",
|
||||
"support.wallet.subscription.standardSubLevel.experience_desc": "可解鎖 FastGPT 完整功能",
|
||||
"support.wallet.subscription.standardSubLevel.free": "免費版",
|
||||
"support.wallet.subscription.standardSubLevel.free desc": "每月可免費使用基本功能。若連續 30 天未登入系統,系統將自動清除知識庫",
|
||||
"support.wallet.subscription.standardSubLevel.free desc": "核心功能免費試用。 \n30 天未登錄,將會清空知識庫。",
|
||||
"support.wallet.subscription.standardSubLevel.team": "團隊版",
|
||||
"support.wallet.subscription.standardSubLevel.team_desc": "適合小團隊建構知識庫應用並提供對外服務",
|
||||
"support.wallet.subscription.status.active": "使用中",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "app",
|
||||
"version": "4.9.8",
|
||||
"version": "4.9.9",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
@@ -35,6 +35,7 @@ import {
|
||||
import { addStatisticalDataToHistoryItem } from '@/global/core/chat/utils';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
import ChatBoxDivider from '../../../Divider';
|
||||
|
||||
const ResponseTags = dynamic(() => import('./ResponseTags'));
|
||||
|
||||
@@ -371,7 +372,20 @@ const ChatItem = (props: Props) => {
|
||||
</>
|
||||
)}
|
||||
{/* Example: Response tags. A set of dialogs only needs to be displayed once*/}
|
||||
{i === splitAiResponseResults.length - 1 && <>{children}</>}
|
||||
{i === splitAiResponseResults.length - 1 && (
|
||||
<>
|
||||
{/* error message */}
|
||||
{!!chat.errorMsg && (
|
||||
<Box mt={2}>
|
||||
<ChatBoxDivider icon={'common/errorFill'} text={t('chat:error_message')} />
|
||||
<Box fontSize={'xs'} color={'myGray.500'}>
|
||||
{chat.errorMsg}
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
{children}
|
||||
</>
|
||||
)}
|
||||
{/* 对话框底部的复制按钮 */}
|
||||
{type == ChatRoleEnum.AI &&
|
||||
value[0]?.type !== 'interactive' &&
|
||||
|
@@ -160,7 +160,7 @@ const Standard = ({
|
||||
<Box fontSize={['32px', '42px']} fontWeight={'bold'} color={'myGray.900'}>
|
||||
¥{item.price}
|
||||
</Box>
|
||||
<Box color={'myGray.500'} h={'40px'} fontSize={'xs'}>
|
||||
<Box color={'myGray.500'} minH={'40px'} fontSize={'xs'}>
|
||||
{t(item.desc as any, { title: feConfigs?.systemTitle })}
|
||||
</Box>
|
||||
|
||||
@@ -183,17 +183,6 @@ const Standard = ({
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
// feature:
|
||||
// if (
|
||||
// item.level === myStandardPlan?.nextSubLevel &&
|
||||
// selectSubMode === myStandardPlan?.nextMode
|
||||
// ) {
|
||||
// return (
|
||||
// <Button mt={4} mb={6} w={'100%'} variant={'whiteBase'} isDisabled>
|
||||
// {t('common:support.wallet.subscription.Next plan')}
|
||||
// </Button>
|
||||
// );
|
||||
// }
|
||||
if (isCurrentPlan) {
|
||||
return (
|
||||
<Button
|
||||
@@ -312,7 +301,7 @@ const RowTabs = ({
|
||||
px={'12px'}
|
||||
py={'7px'}
|
||||
userSelect={'none'}
|
||||
w={['150px', '170px']}
|
||||
w={['150px', '190px']}
|
||||
{...(value === item.value
|
||||
? {
|
||||
color: 'white',
|
||||
|
@@ -55,12 +55,14 @@ async function handler(
|
||||
const isPlugin = app.type === AppTypeEnum.plugin;
|
||||
const isOutLink = authType === GetChatTypeEnum.outLink;
|
||||
|
||||
const commonField =
|
||||
'dataId obj value adminFeedback userGoodFeedback userBadFeedback time hideInUI durationSeconds errorMsg';
|
||||
const fieldMap = {
|
||||
[GetChatTypeEnum.normal]: `dataId obj value adminFeedback userBadFeedback userGoodFeedback time hideInUI durationSeconds ${
|
||||
[GetChatTypeEnum.normal]: `${commonField} ${
|
||||
DispatchNodeResponseKeyEnum.nodeResponse
|
||||
} ${loadCustomFeedbacks ? 'customFeedbacks' : ''}`,
|
||||
[GetChatTypeEnum.outLink]: `dataId obj value userGoodFeedback userBadFeedback adminFeedback time hideInUI durationSeconds ${DispatchNodeResponseKeyEnum.nodeResponse}`,
|
||||
[GetChatTypeEnum.team]: `dataId obj value userGoodFeedback userBadFeedback adminFeedback time hideInUI durationSeconds ${DispatchNodeResponseKeyEnum.nodeResponse}`
|
||||
[GetChatTypeEnum.outLink]: `${commonField} ${DispatchNodeResponseKeyEnum.nodeResponse}`,
|
||||
[GetChatTypeEnum.team]: `${commonField} ${DispatchNodeResponseKeyEnum.nodeResponse}`
|
||||
};
|
||||
|
||||
const { total, histories } = await getChatItems({
|
||||
|
@@ -109,6 +109,12 @@ function checkRes(data: ResponseDataType) {
|
||||
*/
|
||||
function responseError(err: any) {
|
||||
console.log('error->', '请求错误', err);
|
||||
const isOutlinkPage = {
|
||||
'/chat/share': true,
|
||||
'/chat/team': true,
|
||||
'/login': true
|
||||
}[window.location.pathname];
|
||||
|
||||
const data = err?.response?.data || err;
|
||||
|
||||
if (!err) {
|
||||
@@ -123,7 +129,7 @@ function responseError(err: any) {
|
||||
|
||||
// 有报错响应
|
||||
if (data?.code in TOKEN_ERROR_CODE) {
|
||||
if (!['/chat/share', '/chat/team', '/login'].includes(window.location.pathname)) {
|
||||
if (!isOutlinkPage) {
|
||||
clearToken();
|
||||
window.location.replace(
|
||||
getWebReqUrl(`/login?lastRoute=${encodeURIComponent(location.pathname + location.search)}`)
|
||||
@@ -133,13 +139,17 @@ function responseError(err: any) {
|
||||
return Promise.reject({ message: i18nT('common:unauth_token') });
|
||||
}
|
||||
if (
|
||||
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
|
||||
data?.statusText &&
|
||||
[
|
||||
TeamErrEnum.aiPointsNotEnough,
|
||||
TeamErrEnum.datasetSizeNotEnough,
|
||||
TeamErrEnum.datasetAmountNotEnough,
|
||||
TeamErrEnum.appAmountNotEnough,
|
||||
TeamErrEnum.pluginAmountNotEnough,
|
||||
TeamErrEnum.websiteSyncNotEnough,
|
||||
TeamErrEnum.reRankNotEnough
|
||||
].includes(data?.statusText) &&
|
||||
!isOutlinkPage
|
||||
) {
|
||||
useSystemStore.getState().setNotSufficientModalType(data.statusText);
|
||||
return Promise.reject(data);
|
||||
|
Reference in New Issue
Block a user