LangChain Structured Output
Free text delights humans and frustrates programs. A program cannot reliably read "The meeting is on Friday at three in the afternoon" and extract a date field. Structured output solves the problem. The model returns data that matches a shape you define, such as an object with named fields and correct types.
Why Structure Matters
Imagine a paper form with labeled boxes. A clerk fills every box in the same order, so the next person finds every detail quickly. Structured output turns the model into that clerk.
Messy text Structured result
"Priya booked 2 seats → name: Priya
to Goa on 12 March" seats: 2
city: Goa
date: 12 March
Defining the Shape with Pydantic
Pydantic is a Python library that describes data shapes with classes. Each field has a name, a type, and an optional description. The descriptions guide the model.
from pydantic import BaseModel, Field
class Booking(BaseModel):
name: str = Field(description="Full name of the traveler")
seats: int = Field(description="Number of seats booked")
city: str = Field(description="Destination city")
date: str = Field(description="Travel date as written")Asking the Model for That Shape
The method with_structured_output wraps a chat model so every reply arrives as an object of your class.
from langchain.chat_models import init_chat_model
model = init_chat_model("gpt-4o-mini", model_provider="openai", temperature=0)
extractor = model.with_structured_output(Booking)
result = extractor.invoke("Priya booked 2 seats to Goa on 12 March.")
print(result.name) # Priya
print(result.seats) # 2The result is a real Python object. You read fields with dot notation and trust the types.
How It Works Behind the Scenes
Your Booking class
|
v
Converted to a JSON schema
|
v
Sent to the model with your text
|
v
Model fills the schema
|
v
LangChain validates the data → Booking object
Many providers support this natively through tool calling or JSON mode. LangChain hides the provider differences, so the same code runs on different models.
Nested and List Fields
Real data often contains lists. Define a smaller class and place it inside a bigger one.
from typing import List
class Item(BaseModel):
product: str
quantity: int
class Order(BaseModel):
customer: str
items: List[Item]
order_extractor = model.with_structured_output(Order)
order = order_extractor.invoke("Ravi wants 3 notebooks and 2 pens.")
for item in order.items:
print(item.product, item.quantity)Limiting Choices with Literals
Use a Literal type when only a few answers are valid. The model must pick from your list.
from typing import Literal
class Ticket(BaseModel):
category: Literal["billing", "technical", "general"]
urgent: boolStructured Output vs Output Parsers
Output parsers read plain text after the model finishes and try to find structure inside it. Structured output asks the model to produce the structure from the start, which reduces broken replies. Choose structured output for new projects. Keep parsers for models without structured support.
Handling Failures
Validation can still fail when the input lacks the data. Make optional fields explicit so the model can leave them empty.
from typing import Optional
class Contact(BaseModel):
name: str
phone: Optional[str] = NoneWrap the call in try and except blocks for production code. Log failed inputs and review them later.
Real-World Scenario
A clinic receptionist receives appointment requests by email in many writing styles. A structured extractor reads each email and fills a form with patient name, preferred day, and reason for the visit. The scheduling software receives clean data and books slots automatically. Emails that lack a day produce an empty optional field, and the software asks the patient a follow-up question. Staff stop retyping details, and errors drop sharply because the types are checked on every reply.
Practice Tasks
- Define a Pydantic class for a movie review with title, rating from one to five, and a short summary.
- Extract data from five messy sentences and print each field.
- Add a Literal field with three allowed moods and observe how the model stays inside the list.
- Remove a description from one field and compare accuracy against the described version.
Key Points
- Structured output returns typed objects instead of loose text.
- Pydantic classes define the fields and descriptions.
- with_structured_output attaches the shape to any supported chat model.
- Nested classes, lists, literals, and optional fields cover real data.
- Field descriptions raise accuracy at no extra cost.
