Skip to content

feat(llm): setting to skip json_object on OpenAI-compatible providers (#4935) - #5261

Merged
nicoloboschi merged 2 commits into
mainfrom
fix/llm-json-object-mode
Oct 5, 2026
Merged

nicoloboschi merged 2 commits into
mainfrom
fix/llm-json-object-mode

Conversation

@nicoloboschi

Copy link
Copy Markdown
Collaborator

Closes #4935.

Problem

On the soft (non-strict) structured-output path, the OpenAI-compatible provider decides whether to send response_format={"type": "json_object"} from a hardcoded provider-name list: lmstudio, ollama and volcano skip it, llamacpp follows HINDSIGHT_API_LLAMACPP_NO_GRAMMAR, and every other provider sends it.

provider=openai with a custom base_url pointing at a local server is a common setup, and it had no way to opt out. The reporter's local server can't constrain output, so it rewrites the prompt with its own "respond with valid JSON only" line instead. A thinking model loops on that line until the LLM timeout. The same request without json_object returned valid JSON in 77 s.

Change

  • New tri-state setting HINDSIGHT_API_LLM_OPENAI_COMPATIBLE_JSON_MODE, following the HINDSIGHT_API_LLM_VISION pattern:
    • unset: the provider decides, same as today
    • false: never send json_object; the schema goes in the prompt only
    • true: always send json_object
  • The provider-name list moves into one helper, OpenAICompatibleLLM._supports_json_mode().
  • It is a server-level setting, not per bank, like the other structured-output flags (LLM_SUPPORTS_MAX_ITEMS, LLM_STRUCTURED_OUTPUT_FORCED_TOOL).

This doesn't make a weak model write JSON. It only drops a request that some servers mishandle.

Tests

tests/test_llm_strict_schema.py now covers the provider defaults (openai sends json_object, lmstudio doesn't), both overrides, and reading the setting from the environment. The docs, .env.example and the hindsight-embed copy of the template are updated.

…_object per deployment

Whether the OpenAI-compatible provider sends response_format=json_object on the
soft structured-output path was keyed off a hardcoded provider-name list
(lmstudio/ollama/volcano skip it, llamacpp follows LLAMACPP_NO_GRAMMAR). A
provider=openai pointed at a local server that can't constrain output had no
way to opt out, and such a server can rewrite the prompt in ways a thinking
model loops on until the LLM timeout (#4935).

The new tri-state setting overrides that default in both directions; unset
keeps today's behaviour.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provider selection: retain still sends response_format to local OpenAI-compatible servers that cannot honor it, burning a full LLM timeout per attempt

1 participant