provider-comparison.md

reference

← Back to skill

Content hash: 7c1f276b92271796a1d3c094350b3fe51b246fe16c635e3bdf11b1cf36fc9474
## Structured Output Reference

### Provider comparison

| Provider | Method | Notes |
|----------|--------|-------|
| OpenAI | `response_format={"type": "json_schema", ...}` | Strong guarantee, native |
| Anthropic | Tool use / `structured messages` | Constrains output format |
| vLLM | `--guided-decoding-backend outlines` | Grammar-constrained, open models |
| Ollama | `format: json` | Simplified, no schema enforcement |
| llama.cpp | `--grammar-file` (GBNF) | Full grammar control |

### OpenAI example
```python
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Analyze this article: ..."}],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "article_summary",
            "schema": ArticleSummary.model_json_schema(),
            "strict": True,
        }
    },
)
```

### llama.cpp grammar (GBNF)
```
root ::= object
object ::= "{" ws "\"title\":" ws string "," ws "\"sentiment\":" ws string "}"
string ::= "\"" [a-zA-Z0-9 ]+ "\""
ws ::= [ \t\n]*
```

### Common failures + fixes

| Failure | Fix |
|---------|-----|
| Markdown fences (```json) | Strip with regex before parsing |
| Trailing commas | Use `strict=False` in json.loads or regex-strip |
| NaN/Infinity | Replace with null or 0 (not valid JSON) |
| Missing required fields | Repair prompt: "You are missing X. Add it." |
| Wrong enum value | Include all allowed values in schema AND prompt |

### Retry loop pattern
```python
for attempt in range(1 + MAX_RETRIES):
    raw = llm_call(prompt)
    try:
        return schema.model_validate_json(extract_json(raw))
    except ValidationError as e:
        prompt = repair_prompt(raw, str(e))  # feed error back to LLM
raise OutputValidationError("Structured output failed after retries")
```

### Validation rules
- `additionalProperties: false` -- reject extra fields
- `required` -- list all mandatory fields
- `minLength`/`maxLength` -- constrain string sizes
- `minimum`/`maximum` -- constrain numbers
- `enum` -- constrain to allowed values