LangChain Structured Output
LangChain structured output means asking a model to return data that matches a schema you define, and getting back a validated Python object instead of free text. It is the most reliable way to do extraction, classification and form filling with LLMs.
Define a Schema with Pydantic
Describe the shape you want with a Pydantic model. Field descriptions are sent to the model, so write them clearly.
from pydantic import BaseModel, Field
class Contact(BaseModel):
name: str = Field(description="Full name of the person")
email: str | None = Field(default=None, description="Email address if present")
company: str | None = Field(default=None, description="Company name")(no output: this only defines the schema)
Using with_structured_output
from langchain_ollama import ChatOllama
llm = ChatOllama(model="llama3.2", temperature=0)
extractor = llm.with_structured_output(Contact)
text = "Hi, I'm Ali Raza from Bright Labs. Reach me at ali@brightlabs.io."
contact = extractor.invoke(text)
print(contact)
print(contact.email)Sample output: name='Ali Raza' email='ali@brightlabs.io' company='Bright Labs' ali@brightlabs.io
with_structured_output returns a new Runnable. ChatOllama uses Ollama's native JSON schema support by default, and the result is validated into a Contact instance. Hosted providers such as OpenAI and Anthropic use their own native structured output or tool calling the same way.
Lists and Enums
Schemas can nest. Here the model classifies support tickets into fixed categories using Literal:
from typing import Literal
class Ticket(BaseModel):
category: Literal["billing", "bug", "feature_request", "other"]
urgent: bool
summary: str = Field(description="One short sentence")
class TicketBatch(BaseModel):
tickets: list[Ticket]
classifier = llm.with_structured_output(TicketBatch)
result = classifier.invoke(
"1) I was charged twice this month!! 2) Please add dark mode."
)
for t in result.tickets:
print(t.category, t.urgent, "-", t.summary)Sample output: billing True - Customer was charged twice this month. feature_request False - Customer requests a dark mode.
Combining with a Prompt
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "Extract contact details. Use null for missing fields."),
("human", "{email_body}"),
])
chain = prompt | extractor
print(chain.invoke({"email_body": "Regards, Maria Lopez (Sales)"}))Sample output: name='Maria Lopez' email=None company=None
Structured Output Tips
- Pass include_raw=True to also get the raw message and any parsing error.
- Keep schemas small and flat for small local models.
- Use clear field descriptions; they act as instructions.
- Agents can return structured output too, via create_agent(response_format=YourModel).
Frequently asked questions
Does Ollama support structured output in LangChain?
Yes. ChatOllama.with_structured_output uses Ollama's JSON schema support by default, and can also use tool calling with method="function_calling".
Can I use a TypedDict or JSON schema instead of Pydantic?
Yes. with_structured_output accepts Pydantic models, TypedDicts and JSON schema dictionaries. Non-Pydantic schemas return plain dictionaries.
What happens if the model output does not match the schema?
A validation error is raised. Use include_raw=True to inspect the failure, simplify the schema, or retry with with_retry().