From 7fa823447fac328ce3871741d12e9d4faec09e30 Mon Sep 17 00:00:00 2001 From: code-october <148516338+code-october@users.noreply.github.com> Date: Thu, 3 Oct 2024 02:16:49 +0000 Subject: [PATCH 1/6] add more criteria for detecting invalid messages --- app/store/chat.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/store/chat.ts b/app/store/chat.ts index 968d8cb6422..7ea0d2d611a 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -693,6 +693,17 @@ export const useChatStore = createPersistStore( } function isValidMessage(message: any): boolean { + if (message.startsWith("```") && message.endsWith("```")) { + const jsonString = message.slice(3, -3).trim(); + try { + const jsonObject = JSON.parse(jsonString); + if (jsonObject.error) { + return false; + } + } catch (e) { + console.log("Invalid JSON format."); + } + } return typeof message === "string" && !message.startsWith("```json"); } }, From a039690f7723609801194c7c28542736569b0d5d Mon Sep 17 00:00:00 2001 From: code-october <148516338+code-october@users.noreply.github.com> Date: Thu, 3 Oct 2024 02:20:32 +0000 Subject: [PATCH 2/6] add response judgment conditions for summarizing messages request --- app/store/chat.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/app/store/chat.ts b/app/store/chat.ts index 7ea0d2d611a..60558932cf5 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -681,6 +681,7 @@ export const useChatStore = createPersistStore( }, onFinish(message) { console.log("[Memory] ", message); + if (!isValidMessage(message)) return; get().updateCurrentSession((session) => { session.lastSummarizeIndex = lastSummarizeIndex; session.memoryPrompt = message; // Update the memory prompt for stored it in local storage From 4bb52b2a19f1b8248a525736f52e5a309a912d11 Mon Sep 17 00:00:00 2001 From: code-october <148516338+code-october@users.noreply.github.com> Date: Fri, 11 Oct 2024 14:38:03 +0000 Subject: [PATCH 3/6] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E8=A7=84=E5=88=99=E3=80=81=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/store/chat.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/app/store/chat.ts b/app/store/chat.ts index 60558932cf5..8ee86d38909 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -694,18 +694,26 @@ export const useChatStore = createPersistStore( } function isValidMessage(message: any): boolean { + if (typeof message !== "string") { + return false; + } if (message.startsWith("```") && message.endsWith("```")) { - const jsonString = message.slice(3, -3).trim(); + const codeBlockContent = message.slice(3, -3).trim(); + const jsonString = codeBlockContent.replace(/^json\s*/i, '').trim(); try { + // 返回 json 格式消息,含 error.message 字段,判定为错误回复,否则为正常回复 const jsonObject = JSON.parse(jsonString); - if (jsonObject.error) { + if (jsonObject?.error?.message) { return false; } + return true; } catch (e) { console.log("Invalid JSON format."); + // 非 json 格式,大概率是正常回复 + return true; } } - return typeof message === "string" && !message.startsWith("```json"); + return true; } }, From dd793e0833ed49458212cd41b48a9bd89303b55b Mon Sep 17 00:00:00 2001 From: code-october <148516338+code-october@users.noreply.github.com> Date: Sat, 12 Oct 2024 06:19:11 +0000 Subject: [PATCH 4/6] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=E6=B7=BB=E5=8A=A0jest=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E6=A0=B7=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/store/chat.ts | 6 +-- test/isValidMessage.test.ts | 96 +++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 test/isValidMessage.test.ts diff --git a/app/store/chat.ts b/app/store/chat.ts index f01dd7b41b3..1970258533e 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -743,15 +743,15 @@ export const useChatStore = createPersistStore( const codeBlockContent = message.slice(3, -3).trim(); const jsonString = codeBlockContent.replace(/^json\s*/i, '').trim(); try { - // 返回 json 格式消息,含 error.message 字段,判定为错误回复,否则为正常回复 + // 返回 json 格式消息,error 字段为 true 或者包含 error.message 字段,判定为错误回复,否则为正常回复 const jsonObject = JSON.parse(jsonString); - if (jsonObject?.error?.message) { + if (jsonObject?.error == true || jsonObject?.error?.message) { return false; } return true; } catch (e) { console.log("Invalid JSON format."); - // 非 json 格式,大概率是正常回复 + // 非 json 格式,通常可认为是正常回复 return true; } } diff --git a/test/isValidMessage.test.ts b/test/isValidMessage.test.ts new file mode 100644 index 00000000000..edea222f931 --- /dev/null +++ b/test/isValidMessage.test.ts @@ -0,0 +1,96 @@ +function isValidMessage(message: any): boolean { + if (typeof message !== "string") { + return false; + } + if (message.startsWith("```") && message.endsWith("```")) { + const codeBlockContent = message.slice(3, -3).trim(); + const jsonString = codeBlockContent.replace(/^json\s*/i, '').trim(); + try { + // 返回 json 格式消息,含 error.message 字段,判定为错误回复,否则为正常回复 + const jsonObject = JSON.parse(jsonString); + if (jsonObject?.error == true || jsonObject?.error?.message) { + return false; + } + return true; + } catch (e) { + console.log("Invalid JSON format."); + // 非 json 格式,大概率是正常回复 + return true; + } + } + return true; +} + +describe("is valid message module", () => { + test("error msg no.0", () => { + const message = "Hello! How can I assist you today?"; + expect(isValidMessage(message)).toBe(true); + }); + test("error msg no.1", () => { + const message = ` + \`\`\`json + { + "error": true, + "msg": "金额不足" + } + \`\`\` + `; + expect(isValidMessage(message)).toBe(false); + }); + test("error msg no.2", () => { + const message = ` + \`\`\` + { + "error": { + "message": "You didn't provide an API key. You need to provide your API key in an Authorization header using Bearer auth (i.e. Authorization: Bearer YOUR_KEY), or as the password field (with blank username) if you're accessing the API from your browser and are prompted for a username and password. You can obtain an API key from https://platform.openai.com/account/api-keys.", + "type": "invalid_request_error", + "param": null, + "code": null + } + } + \`\`\` + `; + expect(isValidMessage(message)).toBe(false); + }); + test("error msg no.3", () => { + const message = ` + \`\`\` + { + "error": { + "message": "Incorrect API key provided: 123456. You can find your API key at https://platform.openai.com/account/api-keys.", + "type": "invalid_request_error", + "param": null, + "code": "invalid_api_key" + } + } + \`\`\` + `; + expect(isValidMessage(message)).toBe(false); + }); + test("error msg no.4", () => { + const message = ` + \`\`\` + { + "error": { + "message": "当前分组 default 下对于模型 gpt-4 无可用渠道 (request id: 2024101214105418395279367750613)", + "type": "one_api_error" + } + } + \`\`\` + `; + expect(isValidMessage(message)).toBe(false); + }); + test("error msg no.5", () => { + const message = ` + \`\`\` + { + "error": { + "message": "该令牌状态不可用 (request id: 2024101214105418395279367750613)", + "type": "one_api_error" + } + } + \`\`\` + `; + expect(isValidMessage(message)).toBe(false); + }); +}); \ No newline at end of file From fe9c31c3b761d4c5388698f84444bb094f24266a Mon Sep 17 00:00:00 2001 From: code-october <148516338+code-october@users.noreply.github.com> Date: Sat, 12 Oct 2024 06:28:14 +0000 Subject: [PATCH 5/6] fix isValidMessage.test.ts --- test/isValidMessage.test.ts | 84 ++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/test/isValidMessage.test.ts b/test/isValidMessage.test.ts index edea222f931..c9eac65bc5e 100644 --- a/test/isValidMessage.test.ts +++ b/test/isValidMessage.test.ts @@ -28,68 +28,68 @@ describe("is valid message module", () => { }); test("error msg no.1", () => { const message = ` - \`\`\`json - { - "error": true, - "msg": "金额不足" - } - \`\`\` +\`\`\`json +{ + "error": true, + "msg": "金额不足" +} +\`\`\` `; expect(isValidMessage(message)).toBe(false); }); test("error msg no.2", () => { const message = ` - \`\`\` - { - "error": { - "message": "You didn't provide an API key. You need to provide your API key in an Authorization header using Bearer auth (i.e. Authorization: Bearer YOUR_KEY), or as the password field (with blank username) if you're accessing the API from your browser and are prompted for a username and password. You can obtain an API key from https://platform.openai.com/account/api-keys.", - "type": "invalid_request_error", - "param": null, - "code": null - } - } - \`\`\` +\`\`\` +{ + "error": { + "message": "You didn't provide an API key. You need to provide your API key in an Authorization header using Bearer auth (i.e. Authorization: Bearer YOUR_KEY), or as the password field (with blank username) if you're accessing the API from your browser and are prompted for a username and password. You can obtain an API key from https://platform.openai.com/account/api-keys.", + "type": "invalid_request_error", + "param": null, + "code": null + } +} +\`\`\` `; expect(isValidMessage(message)).toBe(false); }); test("error msg no.3", () => { const message = ` - \`\`\` - { - "error": { - "message": "Incorrect API key provided: 123456. You can find your API key at https://platform.openai.com/account/api-keys.", - "type": "invalid_request_error", - "param": null, - "code": "invalid_api_key" - } - } - \`\`\` +\`\`\` +{ + "error": { + "message": "Incorrect API key provided: 123456. You can find your API key at https://platform.openai.com/account/api-keys.", + "type": "invalid_request_error", + "param": null, + "code": "invalid_api_key" + } +} +\`\`\` `; expect(isValidMessage(message)).toBe(false); }); test("error msg no.4", () => { const message = ` - \`\`\` - { - "error": { - "message": "当前分组 default 下对于模型 gpt-4 无可用渠道 (request id: 2024101214105418395279367750613)", - "type": "one_api_error" - } - } - \`\`\` +\`\`\` +{ + "error": { + "message": "当前分组 default 下对于模型 gpt-4 无可用渠道 (request id: 2024101214105418395279367750613)", + "type": "one_api_error" + } +} +\`\`\` `; expect(isValidMessage(message)).toBe(false); }); test("error msg no.5", () => { const message = ` - \`\`\` - { - "error": { - "message": "该令牌状态不可用 (request id: 2024101214105418395279367750613)", - "type": "one_api_error" - } - } - \`\`\` +\`\`\` +{ + "error": { + "message": "该令牌状态不可用 (request id: 2024101214105418395279367750613)", + "type": "one_api_error" + } +} +\`\`\` `; expect(isValidMessage(message)).toBe(false); }); From b0236f7b19c27b9e7242f751eea6579545890ba1 Mon Sep 17 00:00:00 2001 From: code-october <148516338+code-october@users.noreply.github.com> Date: Sat, 12 Oct 2024 06:41:08 +0000 Subject: [PATCH 6/6] fix jest error --- app/store/chat.ts | 1 + test/isValidMessage.test.ts | 71 +++++++++++++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/app/store/chat.ts b/app/store/chat.ts index 1970258533e..72f84635ac3 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -739,6 +739,7 @@ export const useChatStore = createPersistStore( if (typeof message !== "string") { return false; } + message = message.trim(); if (message.startsWith("```") && message.endsWith("```")) { const codeBlockContent = message.slice(3, -3).trim(); const jsonString = codeBlockContent.replace(/^json\s*/i, '').trim(); diff --git a/test/isValidMessage.test.ts b/test/isValidMessage.test.ts index c9eac65bc5e..6e6a8bd78d6 100644 --- a/test/isValidMessage.test.ts +++ b/test/isValidMessage.test.ts @@ -2,11 +2,12 @@ function isValidMessage(message: any): boolean { if (typeof message !== "string") { return false; } + message = message.trim(); if (message.startsWith("```") && message.endsWith("```")) { const codeBlockContent = message.slice(3, -3).trim(); const jsonString = codeBlockContent.replace(/^json\s*/i, '').trim(); try { - // 返回 json 格式消息,含 error.message 字段,判定为错误回复,否则为正常回复 + // 返回 json 格式消息,error 字段为 true 或者包含 error.message 字段,判定为错误回复,否则为正常回复 const jsonObject = JSON.parse(jsonString); if (jsonObject?.error == true || jsonObject?.error?.message) { return false; @@ -14,7 +15,7 @@ function isValidMessage(message: any): boolean { return true; } catch (e) { console.log("Invalid JSON format."); - // 非 json 格式,大概率是正常回复 + // 非 json 格式,通常可认为是正常回复 return true; } } @@ -22,10 +23,12 @@ function isValidMessage(message: any): boolean { } describe("is valid message module", () => { - test("error msg no.0", () => { + // 0. 正常的 string 文本 + test("string msg", () => { const message = "Hello! How can I assist you today?"; expect(isValidMessage(message)).toBe(true); }); + // 1. 一些可能的错误消息 test("error msg no.1", () => { const message = ` \`\`\`json @@ -93,4 +96,66 @@ describe("is valid message module", () => { `; expect(isValidMessage(message)).toBe(false); }); + + // 2. 仅包含 ``` 的字符串 + test("only code block markers", () => { + const message = "``` ```"; + expect(isValidMessage(message)).toBe(true); // 空代码块,视为正常回复 + }); + test("only opening code block marker", () => { + const message = "```json\n{ \"key\": \"value\" }"; + expect(isValidMessage(message)).toBe(true); // 不完整的代码块 + }); + test("only closing code block marker", () => { + const message = "{ \"key\": \"value\" } ```"; + expect(isValidMessage(message)).toBe(true); // 不完整的代码块 + }); + // 3. 非 JSON 格式的代码块 + test("code block with non-JSON content - plain text", () => { + const message = ` +\`\`\`json +This is not a JSON string. +\`\`\` + `; + expect(isValidMessage(message)).toBe(true); // 解析失败,视为正常回复 + }); + test("code block with non-JSON content - JavaScript", () => { + const message = ` +\`\`\`js +function hello() { + console.log("Hello, world!"); +} +\`\`\` + `.trim(); + expect(isValidMessage(message)).toBe(true); // 解析失败,视为正常回复 + }); + + // 4. JSON 格式但不包含 'error' 字段 + test("JSON without error field", () => { + const message = ` +\`\`\`json +{ + "message": "Operation successful", + "data": { + "id": 1, + "name": "Test" + } +} +\`\`\` + `; + expect(isValidMessage(message)).toBe(true); // 无 error 字段,视为正常回复 + }); + + // 5. JSON 格式,'error' 字段为 false + test("JSON with 'error': false", () => { + const message = ` +\`\`\`json +{ + "error": false, + "message": "Everything is fine." +} +\`\`\` + `; + expect(isValidMessage(message)).toBe(true); // error 为 false,视为正常回复 + }); }); \ No newline at end of file