Tolerate malformed LLM JSON escapes
This commit is contained in:
@@ -372,6 +372,28 @@ function extractJsonObject(text: string): string {
|
|||||||
return trimmed;
|
return trimmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function escapeInvalidJsonBackslashes(text: string): string {
|
||||||
|
return text.replace(/\\(?:u(?![0-9a-fA-F]{4})|(?!["\\/bfnrtu]))/g, "\\\\");
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseLlmJson<T>(content: string, context: string): T {
|
||||||
|
const json = extractJsonObject(content);
|
||||||
|
try {
|
||||||
|
return JSON.parse(json) as T;
|
||||||
|
} catch (error) {
|
||||||
|
const repaired = escapeInvalidJsonBackslashes(json);
|
||||||
|
if (repaired !== json) {
|
||||||
|
try {
|
||||||
|
return JSON.parse(repaired) as T;
|
||||||
|
} catch {
|
||||||
|
// Fall through to the contextual error below.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
|
throw new SyntaxError(`${context}: ${message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function summarizeSegmentierungsQualitaet(fragen: FrageMitAntwort[] | undefined): SegmentierungsQualitaet | undefined {
|
function summarizeSegmentierungsQualitaet(fragen: FrageMitAntwort[] | undefined): SegmentierungsQualitaet | undefined {
|
||||||
const items = fragen ?? [];
|
const items = fragen ?? [];
|
||||||
if (!items.length) return undefined;
|
if (!items.length) return undefined;
|
||||||
@@ -961,9 +983,9 @@ ${JSON.stringify(data, null, 2)}`,
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsed = JSON.parse(extractJsonObject(content)) as Partial<LlmScoringAssessment> & {
|
const parsed = parseLlmJson<Partial<LlmScoringAssessment> & {
|
||||||
begruendung?: string;
|
begruendung?: string;
|
||||||
};
|
}>(content, "Could not parse traffic light assessment JSON");
|
||||||
const ausschlussgruende = Array.isArray(parsed.ausschlussgruende)
|
const ausschlussgruende = Array.isArray(parsed.ausschlussgruende)
|
||||||
? parsed.ausschlussgruende.map((flag) => String(flag).trim()).filter(Boolean)
|
? parsed.ausschlussgruende.map((flag) => String(flag).trim()).filter(Boolean)
|
||||||
: [];
|
: [];
|
||||||
@@ -1065,7 +1087,10 @@ Vorgaben:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsed = JSON.parse(extractJsonObject(content)) as { fragen?: Array<Partial<FrageMitAntwort>> };
|
const parsed = parseLlmJson<{ fragen?: Array<Partial<FrageMitAntwort>> }>(
|
||||||
|
content,
|
||||||
|
`Could not parse answer segmentation JSON for ${fallbackLabel}`,
|
||||||
|
);
|
||||||
const byId = new Map((parsed.fragen ?? []).map((frage) => [String(frage.id ?? ""), frage]));
|
const byId = new Map((parsed.fragen ?? []).map((frage) => [String(frage.id ?? ""), frage]));
|
||||||
|
|
||||||
return fragen.map((frage) => {
|
return fragen.map((frage) => {
|
||||||
@@ -1149,7 +1174,7 @@ ${JSON.stringify(data, null, 2)}`,
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsed = JSON.parse(extractJsonObject(content)) as Partial<SWOTAnalyse>;
|
const parsed = parseLlmJson<Partial<SWOTAnalyse>>(content, "Could not parse SWOT analysis JSON");
|
||||||
const toStringArray = (value: unknown): string[] =>
|
const toStringArray = (value: unknown): string[] =>
|
||||||
Array.isArray(value) ? value.map((item) => String(item).trim()).filter(Boolean) : [];
|
Array.isArray(value) ? value.map((item) => String(item).trim()).filter(Boolean) : [];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user