fix: implement json_schema fallback for OpenAI-compatible providers (#1343)
When json_schema response_format is sent to models that do not natively
support Structured Output (e.g. DeepSeek/Ollama/local LLMs via
openai-compatible-* providers), they often return empty or malformed
content.
Detect response_format.type === "json_schema", inject the schema into the
system prompt, and downgrade response_format to json_object so Structured
Output works transparently across openai-compatible providers.
Gated to provider.startsWith("openai-compatible-") so providers with
native Structured Output support are not downgraded.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -12,7 +12,28 @@ export class DefaultExecutor extends BaseExecutor {
|
||||
}
|
||||
|
||||
transformRequest(model, body) {
|
||||
return injectReasoningContent({ provider: this.provider, model, body });
|
||||
const transformed = this.applyJsonSchemaFallback(body);
|
||||
return injectReasoningContent({ provider: this.provider, model, body: transformed });
|
||||
}
|
||||
|
||||
// Fallback json_schema → json_object for openai-compatible providers without native Structured Output.
|
||||
applyJsonSchemaFallback(body) {
|
||||
if (!this.provider?.startsWith?.("openai-compatible-")) return body;
|
||||
const rf = body?.response_format;
|
||||
if (rf?.type !== "json_schema" || !rf.json_schema?.schema) return body;
|
||||
|
||||
const schemaJson = JSON.stringify(rf.json_schema.schema, null, 2);
|
||||
const prompt = `You must respond with valid JSON that strictly follows this JSON schema:\n\`\`\`json\n${schemaJson}\n\`\`\`\nRespond ONLY with the JSON object, no other text.`;
|
||||
|
||||
const messages = Array.isArray(body.messages) ? body.messages.map(m => ({ ...m })) : [];
|
||||
const sys = messages.find(m => m.role === "system");
|
||||
if (sys) {
|
||||
if (typeof sys.content === "string") sys.content = `${sys.content}\n\n${prompt}`;
|
||||
else if (Array.isArray(sys.content)) sys.content.push({ type: "text", text: `\n\n${prompt}` });
|
||||
} else {
|
||||
messages.unshift({ role: "system", content: prompt });
|
||||
}
|
||||
return { ...body, messages, response_format: { type: "json_object" } };
|
||||
}
|
||||
|
||||
buildUrl(model, stream, urlIndex = 0, credentials = null) {
|
||||
|
||||
Reference in New Issue
Block a user