Skip to content

Commit 9d5f1b1

Browse files
committed
improv: improve error dialog
#150
1 parent 72ad066 commit 9d5f1b1

File tree

7 files changed

+90
-52
lines changed

7 files changed

+90
-52
lines changed

backend/api/exceptions.py

+14-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ def __init__(self, reason: Any = None, message: str = "", code: int = -1) -> Non
88
self.code = code # 错误码:负数为自定义错误;正数为 http 错误码
99

1010
def __str__(self):
11-
return f"{self.__class__.__name__}: {self.code} {self.message}"
11+
return f"{self.__class__.__name__}: [{self.code}] {self.reason} {self.message}"
1212

1313

1414
class AuthorityDenyException(SelfDefinedException):
@@ -51,7 +51,16 @@ def __init__(self, message: str = ""):
5151
super().__init__(reason="errors.config", message=message)
5252

5353

54-
class OpenaiWebException(SelfDefinedException):
55-
def __init__(self, message: str = "", status_code: int = -1):
56-
super().__init__(reason="errors.openaiWeb", message=message)
57-
self.status_code = status_code
54+
class OpenaiException(SelfDefinedException):
55+
def __init__(self, reason: str, message: str = "", code: int = -1):
56+
super().__init__(reason=reason, message=message, code=code)
57+
58+
59+
class OpenaiWebException(OpenaiException):
60+
def __init__(self, message: str = "", code: int = -1):
61+
super().__init__(reason="errors.openaiWeb", message=message, code=code)
62+
63+
64+
class OpenaiApiException(OpenaiException):
65+
def __init__(self, message: str = "", code: int = -1):
66+
super().__init__(reason="errors.openaiWeb", message=message, code=code)

backend/api/routers/chat.py

+17-17
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from api.conf import Config
1919
from api.database import get_async_session_context
2020
from api.enums import OpenaiWebChatStatus, ChatSourceTypes, OpenaiWebChatModels, OpenaiApiChatModels
21-
from api.exceptions import InternalException, InvalidParamsException
21+
from api.exceptions import InternalException, InvalidParamsException, OpenaiException
2222
from api.models.db import OpenaiWebConversation, User, BaseConversation
2323
from api.models.doc import OpenaiWebChatMessage, OpenaiApiChatMessage, OpenaiWebConversationHistoryDocument, \
2424
OpenaiApiConversationHistoryDocument, OpenaiApiChatMessageTextContent, AskLogDocument, OpenaiWebAskLogMeta, \
@@ -27,7 +27,7 @@
2727
from api.schemas import OpenaiWebConversationSchema, AskRequest, AskResponse, AskResponseType, UserReadAdmin, \
2828
BaseConversationSchema
2929
from api.schemas.openai_schemas import OpenaiChatPlugin, OpenaiChatPluginUserSettings
30-
from api.sources import OpenaiWebChatManager, convert_revchatgpt_message, OpenaiApiChatManager, OpenAIChatException
30+
from api.sources import OpenaiWebChatManager, convert_revchatgpt_message, OpenaiApiChatManager, OpenaiApiException
3131
from api.users import websocket_auth, current_active_user, current_super_user
3232
from utils.logger import get_logger
3333

@@ -326,24 +326,25 @@ async def reply(response: AskResponse):
326326
))
327327
websocket_code = 1001
328328
websocket_reason = "errors.timout"
329-
except revChatGPTError as e:
329+
except OpenaiException as e:
330330
logger.error(str(e))
331-
content = check_message(f"{e.source} {e.code}: {e.message}")
331+
error_detail_map = {
332+
401: "errors.openai.401",
333+
403: "errors.openai.403",
334+
404: "errors.openai.404",
335+
429: "errors.openai.429",
336+
}
337+
if e.code in error_detail_map:
338+
tip = error_detail_map[e.code]
339+
else:
340+
tip = "errors.openai.unknown"
332341
await reply(AskResponse(
333342
type=AskResponseType.error,
334-
tip="errors.chatgptResponseError",
335-
error_detail=content
343+
tip=tip,
344+
error_detail=check_message(str(e))
336345
))
337346
websocket_code = 1001
338-
websocket_reason = "errors.chatgptResponseError"
339-
except OpenAIChatException as e:
340-
logger.error(str(e))
341-
content = check_message(str(e))
342-
await reply(AskResponse(
343-
type=AskResponseType.error,
344-
tip="errors.openaiResponseError",
345-
error_detail=str(e)
346-
))
347+
websocket_reason = "errors.openaiResponseUnknownError"
347348
except HTTPError as e:
348349
logger.error(str(e))
349350
content = check_message(str(e))
@@ -356,11 +357,10 @@ async def reply(response: AskResponse):
356357
websocket_reason = "errors.httpError"
357358
except Exception as e:
358359
logger.error(str(e))
359-
content = check_message(str(e))
360360
await reply(AskResponse(
361361
type=AskResponseType.error,
362362
tip="errors.unknownError",
363-
error_detail=content
363+
error_detail=check_message(str(e))
364364
))
365365
websocket_code = 1011
366366
websocket_reason = "errors.unknownError"

backend/api/sources/openai_api.py

+2-12
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from api.conf import Config, Credentials
1010
from api.enums import OpenaiApiChatModels, ChatSourceTypes
11+
from api.exceptions import OpenaiApiException
1112
from api.models.doc import OpenaiApiChatMessage, OpenaiApiConversationHistoryDocument, OpenaiApiChatMessageMetadata, \
1213
OpenaiApiChatMessageTextContent
1314
from api.schemas.openai_schemas import OpenaiChatResponse
@@ -22,24 +23,13 @@
2223
MAX_CONTEXT_MESSAGE_COUNT = 1000
2324

2425

25-
class OpenAIChatException(Exception):
26-
def __init__(self, source: str, message: str, code: int = None):
27-
self.source = source
28-
self.message = message
29-
self.code = code
30-
31-
def __str__(self):
32-
return f"{self.source} {self.code} error: {self.message}"
33-
34-
3526
async def _check_response(response: httpx.Response) -> None:
3627
# 改成自带的错误处理
3728
try:
3829
response.raise_for_status()
3930
except httpx.HTTPStatusError as ex:
4031
await response.aread()
41-
error = OpenAIChatException(
42-
source="OpenAI",
32+
error = OpenaiApiException(
4333
message=response.text,
4434
code=response.status_code,
4535
)

backend/api/sources/openai_web.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ async def _check_response(response: httpx.Response) -> None:
121121
await response.aread()
122122
error = OpenaiWebException(
123123
message=response.text,
124-
status_code=response.status_code,
124+
code=response.status_code,
125125
)
126126
raise error from ex
127127

frontend/src/locales/en-US.json

+31-6
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@
141141
"quoteContent": "Quote Content",
142142
"click": "Click",
143143
"error": "Error",
144-
"browsingActions": "Browsing History",
145144
"browsingHistory": "Browsing History",
146145
"shouldRenderMarkdown": "Whether Render Content As Markdown",
147146
"showRawMessage": "Show raw messages",
@@ -155,7 +154,19 @@
155154
"minutes": "minute",
156155
"times": "Second-rate",
157156
"scrolling_down": "Scrolling down",
158-
"detail": "details"
157+
"detail": "details",
158+
"openaiSettings": "OpenAI Settings",
159+
"all": "all",
160+
"disable": "disabled",
161+
"enable": "enable",
162+
"enabled": "activated",
163+
"install": "Install",
164+
"installed": "Installed",
165+
"most_popular": "most popular",
166+
"newly_added": "Add",
167+
"noPluginsAvailable": "Failed to get the plugin list, please check whether the item \"openai_web.is_plus_account\" is set to true",
168+
"pluginSettings": "OpenAI Web Plugin Settings",
169+
"uninstall": "uninstall"
159170
},
160171
"errors": {
161172
"403": "403 error: access denied",
@@ -188,7 +199,15 @@
188199
"invalidParams": "Invalid Params",
189200
"noAvailableTotalAskCount": "The total number of conversations that are not available for this type of conversation",
190201
"userChatTypeExpired": "The validity period of this conversation type has expired, please contact the administrator to increase the duration",
191-
"userNotAllowToAskAtThisTime": "Questions are not allowed in the current time period"
202+
"userNotAllowToAskAtThisTime": "Questions are not allowed in the current time period",
203+
"openai": {
204+
"401": "OpenAI authorization failed (401 error), please contact the administrator",
205+
"403": "OpenAI authorization failed (403 error), please contact the administrator",
206+
"404": "The OpenAI interface does not exist (404 error), please contact the administrator",
207+
"429": "The OpenAI interface request is too frequent (429 error), it may be that the model usage limit has been exceeded, please try again later",
208+
"unkown": "OpenAI unknown error, please contact the administrator"
209+
},
210+
"unknown": "unknown mistake"
192211
},
193212
"tips": {
194213
"loginExpired": "Login expired. Do you want to go to the login page?",
@@ -240,7 +259,10 @@
240259
"pleaseCheckInput": "Please check the input",
241260
"registerSuccess": "registration success",
242261
"seperate_settings": "The following will set options for using revChatGPT and API respectively",
243-
"updateSuccess": "update completed"
262+
"updateSuccess": "update completed",
263+
"disablePluginSuccess": "Disable plugin successfully",
264+
"enablePluginSuccess": "Enable plugin successfully",
265+
"installSuccess": "Successful installation"
244266
},
245267
"labels": {
246268
"nickname": "Nickname",
@@ -283,7 +305,9 @@
283305
"type": "type",
284306
"username": "username",
285307
"valid_until": "validity period",
286-
"source": "source"
308+
"source": "source",
309+
"gpt4_count_in_3_hours": "GPT-4 dosage / 3h",
310+
"plugins": "plug-in"
287311
},
288312
"models": {
289313
"gpt_3_5": "GPT-3.5",
@@ -303,6 +327,7 @@
303327
},
304328
"desc": {
305329
"daily_available_time_slots": "It is only allowed to be used during these time periods of the day, if it is empty, it means unlimited.",
306-
"rate_limits": "Define the maximum number of conversations a user can initiate within a certain time interval, and the priority is calculated from small to large time intervals."
330+
"rate_limits": "Define the maximum number of conversations a user can initiate within a certain time interval, and the priority is calculated from small to large time intervals.",
331+
"openai_web_installed_plugins": "Note: Only the plugins enabled here can be selected when using GPT-4 Plugin!"
307332
}
308333
}

frontend/src/locales/zh-CN.json

+11-2
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@
165165
"enable": "启用",
166166
"enabled": "已启用",
167167
"scrolling_down": "向下浏览",
168-
"detail": "详情"
168+
"detail": "详情",
169+
"openaiSettings": "OpenAI 设置"
169170
},
170171
"errors": {
171172
"403": "403 错误:无访问权限",
@@ -198,7 +199,15 @@
198199
"internal": "内部错误",
199200
"noAvailableTotalAskCount": "该类型对话方式无可用总对话次数",
200201
"userChatTypeExpired": "该对话类型有效期已到期,请联系管理员增加时长",
201-
"userNotAllowToAskAtThisTime": "当前时间段不允许提问"
202+
"userNotAllowToAskAtThisTime": "当前时间段不允许提问",
203+
"openai": {
204+
"401": "OpenAI 授权失败 (401 错误),请联系管理员处理",
205+
"403": "OpenAI 授权失败 (403 错误),请联系管理员处理",
206+
"404": "OpenAI 接口不存在 (404 错误),请联系管理员处理",
207+
"429": "OpenAI 接口请求过于频繁 (429 错误),可能是超过模型使用限制,请稍后再试",
208+
"unkown": "OpenAI 未知错误,请联系管理员处理"
209+
},
210+
"unknown": "未知错误"
202211
},
203212
"tips": {
204213
"loginExpired": "登录已过期。是否跳转到登录页面?",

frontend/src/views/conversation/index.vue

+14-9
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ const sendMsg = async () => {
280280
currentRecvMessages.value = [buildTemporaryMessage('assistant', '...', currentSendMessage.value.id, currentConversation.value!.current_model!)];
281281
const wsUrl = getAskWebsocketApiUrl();
282282
let hasError = false;
283-
let wsErrorMessage: string | null = null;
283+
let wsErrorMessage: AskResponse | null = null;
284284
console.log('Connecting to', wsUrl, askRequest);
285285
const webSocket = new WebSocket(wsUrl);
286286
@@ -321,9 +321,7 @@ const sendMsg = async () => {
321321
} else if (response.type === 'error') {
322322
hasError = true;
323323
console.error('websocket received error message', response);
324-
if (response.error_detail) {
325-
wsErrorMessage = response.error_detail;
326-
}
324+
wsErrorMessage = response;
327325
}
328326
if (autoScrolling.value) scrollToBottom();
329327
};
@@ -332,7 +330,7 @@ const sendMsg = async () => {
332330
aborter = null;
333331
canAbort.value = false;
334332
console.log('WebSocket connection is closed', event, isAborted.value);
335-
if ((isAborted.value || event.code === 1000) && !hasError) {
333+
if (!hasError && (event.code == 1000 || isAborted.value)) {
336334
// 正常关闭
337335
if (hasGotReply) {
338336
const allNewMessages = [currentSendMessage.value] as BaseChatMessage[];
@@ -367,12 +365,19 @@ const sendMsg = async () => {
367365
console.log('done', allNewMessages, currentConversationId.value);
368366
}
369367
} else {
368+
let content = '';
369+
if (wsErrorMessage != null) {
370+
if (wsErrorMessage.tip) {
371+
content = t(wsErrorMessage.tip);
372+
} else {
373+
content = wsErrorMessage.error_detail || t('errors.unknown');
374+
}
375+
} else {
376+
content = `WebSocket ${event.code}: ${t(event.reason || 'errors.unknown')}`;
377+
}
370378
Dialog.error({
371379
title: t('errors.askError'),
372-
content:
373-
wsErrorMessage != null
374-
? `${t(event.reason)}: ${wsErrorMessage}`
375-
: `${t(event.reason)}`,
380+
content,
376381
positiveText: t('commons.withdrawMessage'),
377382
negativeText: t('commons.cancel'),
378383
onPositiveClick: () => {

0 commit comments

Comments
 (0)