Skip to content

fix(aux): downgrade json_schema response_format to json_object for DeepSeek - #88953

Closed
gerryqi wants to merge 1 commit into
NousResearch:mainfrom
gerryqi:fix/deepseek-json-schema-downgrade
Closed

gerryqi wants to merge 1 commit into
NousResearch:mainfrom
gerryqi:fix/deepseek-json-schema-downgrade

Conversation

@gerryqi

@gerryqi gerryqi commented Aug 18, 2026

Copy link
Copy Markdown

Bug Description

Auxiliary title generation fails on DeepSeek with HTTP 400:

Auxiliary title generation failed: HTTP 400: This response_format type is unavailable now

Sessions get no model-generated title (only the instant derived title); the error is logged on every title attempt.

Root Cause

agent/title_generator.py sends response_format: {"type": "json_schema", ...} via extra_body (line 412). The DeepSeek API (api.deepseek.com) only supports response_format of type json_object — json_schema is rejected with a hard 400 "This response_format type is unavailable now". Reproduced directly against the API:

  • response_format: {"type": "json_schema", ...} → 400 This response_format type is unavailable now
  • response_format: {"type": "json_object"} → 200

_build_call_kwargs in agent/auxiliary_client.py passes the caller's extra_body through untouched, so the unsupported type reaches the wire for every DeepSeek-based aux setup (auxiliary.*.provider: deepseek, the default for title_generation).

Fix

In agent/auxiliary_client.py::_build_call_kwargs, at the extra_body merge point, downgrade response_format from json_schema to json_object when the provider is DeepSeek (provider name deepseek/aliases, or base_url host api.deepseek.com). Other providers keep json_schema untouched.

The title extractor already tolerates json_object output (it parses the JSON object and falls back through a loose scan), so no title-quality regression on DeepSeek.

How to Verify

  1. Configure auxiliary.title_generation.provider: deepseek (default).
  2. Start a session; send a message; observe the session title is generated (previously: HTTP 400: This response_format type is unavailable now in agent.log).

Test Plan

  • Added regression tests: tests/agent/test_auxiliary_client.py::TestDeepSeekJsonSchemaDowngrade (provider-name downgrade, base_url downgrade, other providers unaffected)
  • Full tests/agent/test_auxiliary_client.py passes (185 tests)
  • Manual verification: real DeepSeek title-generation call returns a title (e.g. 分析磁盘流量日志目的IP和端口分布)

Risk Assessment

Low — the change only rewrites response_format.type from json_schema to json_object when the request targets DeepSeek (by provider name or api.deepseek.com host). OpenAI/Anthropic/OpenRouter/etc. requests are byte-identical to before. DeepSeek json_object still guarantees valid JSON output, which the title parser handles.

…epSeek

DeepSeek's OpenAI-compatible API only supports response_format
json_object; title generation sends json_schema and 400s with
'This response_format type is unavailable now'. Downgrade the
response_format in the auxiliary kwargs merge point when the
provider or base_url is DeepSeek, so aux tasks keep working
without pinning a non-DeepSeek model.
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint provider/deepseek DeepSeek API labels Aug 18, 2026
@Enough1122

Copy link
Copy Markdown

AI code review — automated review for reference; please use your judgment.

Right compatibility shim, correctly scoped: provider-name OR api.deepseek.com host matching (so custom providers pointed at DeepSeek are covered), strict equality on the json_schema type so other response formats pass untouched, and a three-case test matrix including the negative. Points:

  1. agent/auxiliary_client.py:~8566 — downgrading drops the JSON Schema entirely, but json_object mode on DeepSeek only encourages valid JSON — it doesn't enforce the shape that json_schema guaranteed. Aux consumers like title generation presumably parse specific fields; if the model emits valid-but-different JSON (or prose), those callers may now throw where they used to get a guaranteed shape. Consider appending a condensed form of the schema ("Respond as JSON with keys: ...") to the system/user message when downgrading, or verify each affected aux task tolerates loose JSON.
  2. The provider set {"deepseek", "deepseek-chat", "deepseek-reasoner"} duplicates names that likely exist in a registry/alias table; deriving from the same source as other DeepSeek special-cases would keep them in sync. (nit)
  3. Host match uses base_url_host_matches(effective_base, "api.deepseek.com") — confirm it also covers subdomain forms the API documents, or that exact-host is intentional. (nit)

No blocking issues found beyond confirming item 1's downstream parsers.

@teknium1

Copy link
Copy Markdown
Collaborator

Thanks @gerryqi. The problem this PR targets landed on main via #113966 (5cc8177), which handles the whole class (primary and fallback auxiliary paths, provider capability up front, per-route memo) in one change. Closing as superseded by the landed fix; the issue is closed with the same reference.

@teknium1 teknium1 closed this Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P3 Low — cosmetic, nice to have provider/deepseek DeepSeek API type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants