Skip to content

feat: LLM-native structured output via JSON schema enforcement#1037

Merged
cybermaggedon merged 1 commit into
release/v2.7from
feature/llm-native-structured-output
Jul 10, 2026
Merged

feat: LLM-native structured output via JSON schema enforcement#1037
cybermaggedon merged 1 commit into
release/v2.7from
feature/llm-native-structured-output

Conversation

@cybermaggedon

@cybermaggedon cybermaggedon commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Thread existing JSON schemas from prompt definitions through to LLM backends' native structured output APIs, enabling constrained decoding at the token level for guaranteed schema-valid output
  • Add runtime schema compatibility checker (is_strict_mode_compatible) that performs per-prompt eligibility decisions — compliant schemas use structured output, non-compliant schemas fall back to free-text + post-hoc validation
  • Implement structured output across all LLM backends: OpenAI (with variant-aware top-level array handling + new vllm variant), vLLM, Ollama, Claude (tool-use trick), Mistral, Llamafile, LM Studio, Azure OpenAI, Azure serverless, TGI, VertexAI Gemini, VertexAI Claude, Google AI Studio. Bedrock and Cohere accept the new signature but don't use it yet.

Changes

  • Wire format: response_format and schema fields added to TextCompletionRequest, translator, client, and service layers
  • Schema checker: New schema_compatibility.py validates strict-mode constraints (additionalProperties, required, no unsupported keywords)
  • Prompt manager: Checks schema eligibility at invocation time, passes through when compliant
  • 13 LLM backends updated with provider-specific structured output integration
  • Tech spec: docs/tech-specs/structured-output.md with phased rollout plan
  • Post-hoc jsonschema.validate() retained as defence-in-depth

Test plan

  • Unit tests for is_strict_mode_compatible (30 cases covering all paths)
  • Integration tests updated for new kwargs in streaming mocks
  • End-to-end tested with vLLM via OpenAI adapter — structured output produces schema-valid JSON
  • Test with other backends (Gemini, Claude, Ollama) in staging

Thread existing JSON schemas from prompt definitions through the
text-completion service to LLM backends' native structured output
APIs. When a prompt has response-type "json" and a strict-mode
compatible schema, the LLM constrains token selection at the logit
level to guarantee schema-valid output.

Wire-level changes:
- Add response_format and schema fields to TextCompletionRequest
- Update translator to encode/decode new fields
- Pass new fields through LlmService, TextCompletionClient, and
  PromptManager

Runtime schema compatibility checker:
- New is_strict_mode_compatible() utility validates schemas against
  LLM provider constraints (additionalProperties, required fields,
  no unsupported constraints, no open-ended objects)
- Per-prompt eligibility decision: compliant schemas use structured
  output, non-compliant schemas fall back to free-text + post-hoc
  validation

LLM backend implementations:
- OpenAI: response_format with json_schema, variant-aware top-level
  array rejection (openai variant blocks, llama/vllm variants allow)
- New vllm variant for the OpenAI backend
- vLLM (dedicated): response_format in raw HTTP body
- Ollama: format=<schema> parameter
- Claude: tool-use trick (forced tool call with schema as input_schema)
- Mistral: native json_schema response_format
- Llamafile, LM Studio: OpenAI SDK response_format
- Azure OpenAI: AzureOpenAI SDK response_format
- Azure serverless: response_format in raw HTTP body
- TGI: response_format in raw HTTP body
- VertexAI Gemini: response_mime_type + response_schema
- VertexAI Claude: tool-use trick
- Google AI Studio: response_mime_type + response_schema
- Bedrock, Cohere: signature-only (no structured output yet)

Post-hoc jsonschema.validate() retained as defence-in-depth.

Tech spec added: docs/tech-specs/structured-output.md

Update tests
@github-actions

Copy link
Copy Markdown

Contributor License Agreement ✅

All contributors have signed the CLA. Thank you!

@cybermaggedon
cybermaggedon changed the base branch from master to release/v2.7 July 10, 2026 14:28
@cybermaggedon
cybermaggedon merged commit 9136526 into release/v2.7 Jul 10, 2026
3 checks passed
@cybermaggedon
cybermaggedon deleted the feature/llm-native-structured-output branch July 10, 2026 14:29
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.

1 participant