Fix AI output showing UTF-8 bytes as hex escapes instead of Chinese.
Decode <0xE5><0xA7><0xA4> style model output to proper characters; add prompt rule to use normal Chinese text. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,4 +1,9 @@
|
|||||||
import type { AiRequestBody } from "@/lib/ai/types";
|
import type { AiRequestBody } from "@/lib/ai/types";
|
||||||
|
import { decodeHexByteEscapes } from "@/lib/ai/decode-text";
|
||||||
|
|
||||||
|
function emitText(text: string, onUpdate: (text: string) => void) {
|
||||||
|
onUpdate(decodeHexByteEscapes(text));
|
||||||
|
}
|
||||||
|
|
||||||
function parseApiError(text: string, status: number): string {
|
function parseApiError(text: string, status: number): string {
|
||||||
const trimmed = text.trim();
|
const trimmed = text.trim();
|
||||||
@@ -41,11 +46,11 @@ export async function streamAiCompletion(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
text += decoder.decode(value, { stream: true });
|
text += decoder.decode(value, { stream: true });
|
||||||
onUpdate(text);
|
emitText(text, onUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
text += decoder.decode();
|
text += decoder.decode();
|
||||||
onUpdate(text);
|
emitText(text, onUpdate);
|
||||||
|
|
||||||
if (!text.trim()) {
|
if (!text.trim()) {
|
||||||
throw new Error("AI 返回内容为空,请检查模型配置或稍后重试");
|
throw new Error("AI 返回内容为空,请检查模型配置或稍后重试");
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* 部分模型会把 UTF-8 汉字输出成 <0xE5><0xA7><0xA4> 形式,还原为正常文字。
|
||||||
|
* 例:<0xE5><0xA7><0xA4> → 姤
|
||||||
|
*/
|
||||||
|
export function decodeHexByteEscapes(text: string): string {
|
||||||
|
return text.replace(/(?:<0x[0-9A-Fa-f]{2}>)+/gi, (match) => {
|
||||||
|
const parts = match.match(/<0x([0-9A-Fa-f]{2})>/gi);
|
||||||
|
if (!parts?.length) {
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
const bytes = Uint8Array.from(
|
||||||
|
parts.map((part) => parseInt(part.slice(3, 5), 16)),
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
||||||
|
} catch {
|
||||||
|
return new TextDecoder("utf-8", { fatal: false }).decode(bytes);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -3,7 +3,9 @@ export const LIUYAO_SYSTEM_PROMPT = `你是一位精通《周易》六爻的 AI
|
|||||||
任务要求:逻辑清晰,语气得当
|
任务要求:逻辑清晰,语气得当
|
||||||
1. 结合起卦时辰(节气、日柱、时辰)与地域,分析天时地利对卦象的影响
|
1. 结合起卦时辰(节气、日柱、时辰)与地域,分析天时地利对卦象的影响
|
||||||
2. 解读主卦、变爻及变卦,说明整体趋势和吉凶
|
2. 解读主卦、变爻及变卦,说明整体趋势和吉凶
|
||||||
3. 针对用户问事,结合卦象给出具体分析和可行建议`;
|
3. 针对用户问事,结合卦象给出具体分析和可行建议
|
||||||
|
|
||||||
|
输出规范:必须使用正常中文汉字与标点(如「姤卦」「乾为天」),禁止使用 <0xXX> 或十六进制字节形式表示文字。`;
|
||||||
|
|
||||||
export const BAZI_SYSTEM_PROMPT = `你是一位精通子平八字的命理分析师,根据用户提供的排盘信息和问题,给出专业、清晰的命理解读。
|
export const BAZI_SYSTEM_PROMPT = `你是一位精通子平八字的命理分析师,根据用户提供的排盘信息和问题,给出专业、清晰的命理解读。
|
||||||
|
|
||||||
@@ -13,7 +15,9 @@ export const BAZI_SYSTEM_PROMPT = `你是一位精通子平八字的命理分析
|
|||||||
3. 结合大运流年分析趋势
|
3. 结合大运流年分析趋势
|
||||||
4. 提示相关神煞吉凶
|
4. 提示相关神煞吉凶
|
||||||
5. 针对用户具体问题给出切实可行的建议
|
5. 针对用户具体问题给出切实可行的建议
|
||||||
语气得当,逻辑清晰,避免绝对化断言。`;
|
语气得当,逻辑清晰,避免绝对化断言。
|
||||||
|
|
||||||
|
输出规范:必须使用正常中文汉字与标点,禁止使用 <0xXX> 或十六进制字节形式表示文字。`;
|
||||||
|
|
||||||
export const COMBINED_SYSTEM_PROMPT = `你是一位融合天时、地利、人和的综合命理顾问,精通子平八字与周易六爻。
|
export const COMBINED_SYSTEM_PROMPT = `你是一位融合天时、地利、人和的综合命理顾问,精通子平八字与周易六爻。
|
||||||
|
|
||||||
@@ -21,4 +25,6 @@ export const COMBINED_SYSTEM_PROMPT = `你是一位融合天时、地利、人
|
|||||||
1. 综合天时(节气、日柱时辰)、地利(地域经度方位)、人和(八字命局)进行分析
|
1. 综合天时(节气、日柱时辰)、地利(地域经度方位)、人和(八字命局)进行分析
|
||||||
2. 若用户提供卦象,结合卦辞与变爻补充解读
|
2. 若用户提供卦象,结合卦辞与变爻补充解读
|
||||||
3. 针对用户问事给出具体、可操作的指引
|
3. 针对用户问事给出具体、可操作的指引
|
||||||
语气得当,逻辑清晰,各维度分析要有机融合而非简单罗列。`;
|
语气得当,逻辑清晰,各维度分析要有机融合而非简单罗列。
|
||||||
|
|
||||||
|
输出规范:必须使用正常中文汉字与标点,禁止使用 <0xXX> 或十六进制字节形式表示文字。`;
|
||||||
|
|||||||
Reference in New Issue
Block a user