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)   # 2

The 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: bool

Structured 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] = None

Wrap 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

  1. Define a Pydantic class for a movie review with title, rating from one to five, and a short summary.
  2. Extract data from five messy sentences and print each field.
  3. Add a Literal field with three allowed moods and observe how the model stays inside the list.
  4. 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.