fix(gateway): keep reasoning trace split compatible
This commit is contained in:
parent
60529d7752
commit
496975ed94
@ -1,18 +1,66 @@
|
|||||||
export interface ReasoningTraceSplit {
|
export interface ReasoningTraceSplit {
|
||||||
visible: string;
|
visible: string;
|
||||||
trace: string | null;
|
finalAnswer: string;
|
||||||
|
trace: {
|
||||||
|
marker: 'thinking_tag' | 'think_tag' | 'markdown_header' | 'json_field';
|
||||||
|
content: string;
|
||||||
|
estimatedTokens: number;
|
||||||
|
} | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function splitReasoningTrace(output: string): ReasoningTraceSplit {
|
function estimateTokens(text: string): number {
|
||||||
const match = output.match(/<think>([\s\S]*?)<\/think>/i);
|
return Math.max(1, Math.ceil(text.length / 4));
|
||||||
if (!match) return { visible: output, trace: null };
|
}
|
||||||
|
|
||||||
|
function splitWithTrace(
|
||||||
|
output: string,
|
||||||
|
marker: NonNullable<ReasoningTraceSplit['trace']>['marker'],
|
||||||
|
traceContent: string,
|
||||||
|
finalAnswer: string
|
||||||
|
): ReasoningTraceSplit {
|
||||||
|
const visible = finalAnswer.trim();
|
||||||
return {
|
return {
|
||||||
visible: output.replace(match[0], '').trim(),
|
visible,
|
||||||
trace: match[1]?.trim() ?? null,
|
finalAnswer: visible,
|
||||||
|
trace: {
|
||||||
|
marker,
|
||||||
|
content: traceContent.trim(),
|
||||||
|
estimatedTokens: estimateTokens(traceContent),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function storeReasoningTrace(_callId: string, _trace: string | null): Promise<void> {
|
export function splitReasoningTrace(output: string): ReasoningTraceSplit {
|
||||||
|
const trimmed = output.trim();
|
||||||
|
|
||||||
|
const thinkingMatch = trimmed.match(/<thinking>([\s\S]*?)<\/thinking>/i);
|
||||||
|
if (thinkingMatch) {
|
||||||
|
return splitWithTrace(trimmed, 'thinking_tag', thinkingMatch[1] ?? '', trimmed.replace(thinkingMatch[0], ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
const thinkMatch = trimmed.match(/<think>([\s\S]*?)<\/think>/i);
|
||||||
|
if (thinkMatch) {
|
||||||
|
return splitWithTrace(trimmed, 'think_tag', thinkMatch[1] ?? '', trimmed.replace(thinkMatch[0], ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
const markdownMatch = trimmed.match(/\*\*Reasoning:\*\*([\s\S]*?)\*\*Answer:\*\*([\s\S]*)/i);
|
||||||
|
if (markdownMatch) {
|
||||||
|
return splitWithTrace(trimmed, 'markdown_header', markdownMatch[1] ?? '', markdownMatch[2] ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(trimmed) as { reasoning?: unknown; answer?: unknown };
|
||||||
|
if (typeof parsed.reasoning === 'string' && typeof parsed.answer === 'string') {
|
||||||
|
return splitWithTrace(trimmed, 'json_field', parsed.reasoning, parsed.answer);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Plain model output, not a reasoning envelope.
|
||||||
|
}
|
||||||
|
|
||||||
|
return { visible: trimmed, finalAnswer: trimmed, trace: null };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function storeReasoningTrace(_callId: string, _trace: ReasoningTraceSplit['trace']): Promise<void> {
|
||||||
// Reasoning trace persistence is optional. Keep the public route usable when
|
// Reasoning trace persistence is optional. Keep the public route usable when
|
||||||
// the storage table has not been deployed yet.
|
// the storage table has not been deployed yet.
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user