fix: harden prompt optimizer json parsing
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-02-20 17:46:06 +08:00
parent cf0b6c72e2
commit 40a1b429ea

View File

@ -299,6 +299,30 @@ const IMAGE_GEN_OPTIMIZER_SYSTEM_PROMPT = `你是一个专业的图片生成提
- 细节:一句话补充风格/材质/光线/构图
`;
function parseOptimizerJsonCandidate(raw: string): {
optimizedPrompt?: string;
negativePrompt?: string;
suggestedParams?: {
aspectRatio?: string;
imageSize?: string;
imageCount?: number;
promptExtend?: boolean;
};
} | null {
const normalized = raw
.trim()
.replace(/\uFEFF/g, "")
.replace(/[“”]/g, "\"")
.replace(/[‘’]/g, "'")
.replace(/,\s*([}\]])/g, "$1");
if (!normalized) return null;
try {
return JSON.parse(normalized);
} catch {
return null;
}
}
function parseOptimizerJson(responseText: string): {
optimizedPrompt?: string;
negativePrompt?: string;
@ -309,13 +333,40 @@ function parseOptimizerJson(responseText: string): {
promptExtend?: boolean;
};
} | null {
const jsonMatch = responseText.match(/\{[\s\S]*\}/);
if (!jsonMatch) return null;
try {
return JSON.parse(jsonMatch[0]);
} catch (error) {
return null;
if (!responseText || typeof responseText !== "string") return null;
const fencedBlocks = Array.from(
responseText.matchAll(/```(?:json)?\s*([\s\S]*?)```/gi)
).map((match) => match[1]?.trim() || "");
for (const block of fencedBlocks) {
const parsed = parseOptimizerJsonCandidate(block);
if (parsed) return parsed;
}
const text = responseText.trim();
const starts: number[] = [];
for (let i = 0; i < text.length; i++) {
if (text[i] === "{") starts.push(i);
}
for (const start of starts) {
let depth = 0;
for (let end = start; end < text.length; end++) {
if (text[end] === "{") depth += 1;
if (text[end] === "}") {
depth -= 1;
if (depth === 0) {
const candidate = text.slice(start, end + 1);
const parsed = parseOptimizerJsonCandidate(candidate);
if (parsed) return parsed;
break;
}
}
}
}
return null;
}
function sanitizeSuggestedParams(input?: {
@ -590,7 +641,10 @@ export async function optimizePromptWithLLM(params: {
}
// 解析失败,回退到模板优化
console.log("[Prompt Optimizer LLM] Parse failed, falling back to template");
console.log(
"[Prompt Optimizer LLM] Parse failed, falling back to template. raw=",
responseText.slice(0, 320)
);
return optimizePrompt({ originalPrompt, intent, subIntent });
} catch (error) {