Structured output (Pydantic)
Uma só chamada parse() devolve uma instância Pydantic validada, independente
de como cada provider implementa isso por baixo.
from pydantic import BaseModel
from jangada_ai import LLM
class Pessoa(BaseModel):
nome: str
idade: int
llm = LLM("openai", "gpt-4o-mini")
comp = llm.parse("Extraia: João tem 30 anos.", Pessoa)
print(comp.parsed.nome, comp.parsed.idade) # João 30comp.parsed→ a instância Pydantic. Confiável: se algum SDK devolverparsed=Nonecom JSON válido em.text, a jangada valida o texto pelo schema automaticamente (sem precisar demodel_validate_jsonmanual).comp.text→ o JSON bruto retornado.comp.usage/comp.cost→ tokens e custo estimado.
🔁 JSON fora do schema → failover. Saída que não casa com o modelo levanta
errors.OutputValidationErrore tenta o próximo modelo dowith_fallback(não repete o mesmo). O fallback cobre erro de API e resposta malformada.
max_tokens tem default alto de 8192 desde a v1.4.5. Extrações que excedam
esse limite ainda podem truncar o JSON. Nesse caso a jangada levanta
errors.TruncatedError (com mensagem "aumente max_tokens") antes de tentar
validar — você não recebe um erro confuso de JSON cortado do Pydantic. A correção
é passar max_tokens maior — veja Parâmetros de geração.
Async
comp = await llm.aparse("Extraia: ...", Pessoa)Como cada provider resolve
| Provider | Mecanismo |
|---|---|
| OpenAI | chat.completions.parse(response_format=Modelo) |
| Groq | json_schema quando o modelo suporta; senão JSON Object mode |
| Gemini | config.response_schema=Modelo → resp.parsed |
| Anthropic | tool-forcing (tool_choice fixo) → valida tool_use |
Você não precisa saber qual é qual — parse()/aparse() cuidam disso. Use
Pydantic v2 (model_json_schema(), model_validate).
Groq — funciona em qualquer modelo. Só alguns modelos do Groq aceitam
json_schema(ex.:openai/gpt-oss-*,llama-4-scout). Para os demais (ex.:llama-3.3-70b-versatile), a jangada cai automaticamente para JSON Object mode: injeta o schema na instrução, pede um objeto JSON e valida com Pydantic. Você chamaparse()igual — sem saber o que o modelo suporta.
Funciona junto com Vision e Documentos: passe
images= ou files= na mesma chamada parse().
Exemplo
examples/structured_example.py — script executável.