Use cases
This page shows, from problem to code, three common situations solved with jangada. Less theory, more "paste it, swap the key and run". Each case links to the matching capability page.
1. Structured document extraction (invoice vision)
Problem. You receive invoices as PDF/image and need the fields (supplier, total, items) typed and validated — not loose text you later regex over.
Solution. Define a Pydantic schema and use parse(...) with files=.
Jangada sends the document to the provider and returns the response already
validated into your model.
from pydantic import BaseModel
from jangada_ai import LLM
class Item(BaseModel):
description: str
amount: float
class Invoice(BaseModel):
supplier: str
tax_id: str
total: float
items: list[Item]
llm = LLM("openai", "gpt-4o")
resp = llm.parse(
"Extract the data from this invoice.",
schema=Invoice,
files=["invoice.pdf"], # pdf, image, docx, csv, xlsx…
)
invoice = resp.parsed # validated Invoice object
print(invoice.supplier, invoice.total, len(invoice.items))It works the same by switching to LLM("gemini", "gemini-2.5-flash") or
LLM("anthropic", "claude-sonnet-4-5"). See
Structured output, Vision and
Documents.
2. Error-based fallback across providers
Problem. The primary provider hits a rate limit, times out or goes down (5xx). You don't want the app to go down with it, nor to rewrite the call.
Solution. Chain a fallback list. When the error is recoverable, jangada tries the next provider without changing the rest of your code.
from jangada_ai import LLM
llm = LLM("anthropic", "claude-sonnet-4-5").with_fallback(
LLM("openai", "gpt-5"),
LLM("groq", "llama-4-scout"),
)
# primary failed? automatic failover
resp = llm.complete("Explain rafts in one sentence.")
print(resp.text)The chain respects the normalized error classification (rate limit, timeout, 5xx, 404…). See Errors and Retry and fallback.
3. Support RAG (retrieve before answering)
Problem. The model must answer from your knowledge base (docs, tickets), not from what it "remembers".
Solution. Index the documents once (chunk + embed + vector store) and, for each question, retrieve the relevant chunks and inject them into the prompt.
from jangada_ai import LLM, RAG
rag = RAG(
embedder=LLM("openai", "text-embedding-3-small"),
store="postgresql://localhost/jangada", # pgvector
)
# 1) index (once)
rag.add(files=["manual.pdf", "faq.md"])
# 2) answer using the retrieved context
context = rag.search("How do I get a second copy?", k=4)
llm = LLM("anthropic", "claude-sonnet-4-5")
resp = llm.complete(
"Answer using only the context:\n{{ context }}\n\nQuestion: {{ q }}",
context="\n\n".join(context),
q="How do I get a second copy?",
)
print(resp.text)See RAG and Step-back prompting to retrieve background context.
Next steps
- Full structured extraction tutorial.
- End-to-end RAG tutorial.
- Why Jangada — an honest comparison with other libs.
Per-provider capability matrix
What each provider supports in jangada. The public API features are the same (complete, parse, stream, transcribe, ...); what changes is what each provider can do under...
Why Jangada
An honest comparison of jangada with LiteLLM, LangChain and instructor — what each does best and when to pick each. Jangada is a thin PT-BR layer with native observability, not an orchestration framework.