Structured output (Pydantic)
A single parse() call returns a validated Pydantic instance, regardless of
how each provider implements it under the hood.
from pydantic import BaseModel
from jangada_ai import LLM
class Person(BaseModel):
name: str
age: int
llm = LLM("openai", "gpt-4o-mini")
comp = llm.parse("Extract: João is 30 years old.", Person)
print(comp.parsed.name, comp.parsed.age) # João 30comp.parsed→ the Pydantic instance. Reliable: if some SDK returnsparsed=Nonewith valid JSON in.text, jangada validates the text against the schema automatically (no manualmodel_validate_jsonneeded).comp.text→ the raw JSON returned.comp.usage/comp.cost→ tokens and estimated cost.
🔁 JSON off-schema → failover. Output that doesn't match the model raises
errors.OutputValidationErrorand tries the next model inwith_fallback(it won't retry the same one). Fallback covers API errors and malformed output.
max_tokens has a high default of 8192 since v1.4.5. Extractions that
exceed this limit may still truncate JSON. In that case jangada raises
errors.TruncatedError (message: "raise max_tokens") before attempting to
validate — you don't get a confusing cut-off-JSON error from Pydantic. The fix is
to pass a higher max_tokens — see Generation parameters.
Async
comp = await llm.aparse("Extract: ...", Person)How each provider resolves it
| Provider | Mechanism |
|---|---|
| OpenAI | chat.completions.parse(response_format=Model) |
| Groq | json_schema when the model supports it; otherwise JSON Object mode |
| Gemini | config.response_schema=Model → resp.parsed |
| Anthropic | tool-forcing (pinned tool_choice) → validates tool_use |
You don't need to know which is which — parse()/aparse() take care of it. Use
Pydantic v2 (model_json_schema(), model_validate).
Groq — works on any model. Only some Groq models accept
json_schema(e.g.,openai/gpt-oss-*,llama-4-scout). For the rest (e.g.,llama-3.3-70b-versatile), jangada automatically falls back to JSON Object mode: it injects the schema into the instruction, asks for a JSON object, and validates with Pydantic. You callparse()the same way — without knowing what the model supports.
It works together with Vision and Documents: pass
images= or files= in the same parse() call.
Example
examples/structured_example.py — runnable script.
Vertex AI
Provider vertex. The Gemini models served by Google Cloud Vertex AI, through jangada's normalized API, authenticating with your project/region + Application Default Credentials.
Tools (function calling)
The model can request that tools (functions) be called. The API is low-level: complete() returns the requested calls in Completion.tool_calls, you run them and send the...