Instructor: Structured LLM Outputs for Reliable Data Extraction

Jul 7, 2025

Introduction

Getting reliable, structured data from Large Language Models (LLMs) is a persistent challenge for developers building production AI applications. While LLMs are exceptional at generating natural language, they often struggle to consistently return valid JSON or follow a strict schema, leading to fragile parsing logic and runtime errors. Instructor solves this by providing a type-safe, validated layer over LLM clients, with over 10k GitHub stars and 3 million monthly downloads, making it the industry standard for structured extraction.

What Is Instructor?

Instructor is a multi-language library that enables developers to extract structured, validated data from any LLM using type-safe schemas. Built primarily on top of Pydantic in Python, it allows you to define the desired output structure as a class and ensures the LLM’s response matches that structure exactly. If the response is invalid, Instructor can automatically retry the request with the validation error provided back to the model for self-correction.

The project is maintained as an open-source tool under the MIT License and is available in Python, TypeScript, Go, Ruby, Elixir, and Rust, providing a consistent API across different programming environments.

Why Instructor Matters

Before Instructor, developers had to rely on complex prompt engineering, manual JSON parsing, and fragile regex patterns to force LLMs into returning structured data. This “prompt-and-pray” approach often failed in production, as a single missing comma or an unexpected explanatory sentence from the LLM could crash an entire data pipeline.

Instructor transforms the LLM from a text generator into a validated function. By leveraging Pydantic’s powerful validation engine, it guarantees that the data entering your application logic is typed and correct. This shift allows developers to treat LLM calls as typed API calls rather than unpredictable text streams, significantly reducing the amount of boilerplate code required for error handling and data cleaning.

With adoption by teams at OpenAI, Google, Microsoft, and AWS, Instructor has become essential for any project requiring high-reliability data extraction, such as automating document processing or building complex AI agents that require precise communication between decoupled components.

Key Features

  • Type-Safe Extraction: Define your output structure using Pydantic models (or Zod in TypeScript), ensuring that the data you receive is always validated against a strict schema.
  • Automatic Retries: When a validation error occurs, Instructor automatically re-prompts the LLM with the error message, allowing the model to correct its own mistakes in real-time.
  • Multi-Provider Support: A unified interface works across 15+ providers, including OpenAI, Anthropic, Google Gemini, Mistral, Cohere, and local models via Ollama or vLLM.
  • Streaming Support: Stream partial objects as they are generated, allowing for a more responsive user interface and real-time processing of large datasets.
  • Nested Object Support: 쉽게 extract complex, hierarchical data structures by nesting Pydantic models within one another.
  • Multimodal Capabilities: Consistent API for loading and extracting data from images, PDFs, and audio files across different AI providers.
  • Validation Hooks: Define custom validation logic within your schemas to enforce business rules that go beyond simple type checking.
  • Provider Agnostic: Patch existing LLM clients without replacing them, maintaining all original functionality while adding structured output capabilities.

How Instructor Compares

Feature Instructor Raw JSON Mode LangChain / LlamaIndex
Automatic Validation Yes (Pydantic/Zod) No Partial
Self-Correction Retries Yes No No
Provider Agnostic Yes (15+ providers) Provider Specific Yes
Overhead / Complexity Low (Lightweight wrapper) Minimal High (Heavy framework)
IDE Support Full (Type Inference) None (Dict/JSON) Partial

Instructor is designed as a minimalist wrapper rather than a full-blown agent framework. Unlike LangChain or LlamaIndex, which provide vast ecosystems of tools and abstractions, Instructor focuses on a single, critical problem: getting typed data out of an LLM. This makes it significantly easier to debug, faster to implement, and lighter on dependencies.

Compared to using raw JSON mode provided by LLM providers, Instructor adds a critical layer of validation. While JSON mode ensures the output is valid JSON, it does not ensure the JSON contains the required fields or that the values are of the correct type. Instructor bridges this gap by validating the JSON against a Pydantic model and automatically retrying the request if the model is not satisfied.

Getting Started: Installation

Instructor can be installed via pip, uv, or poetry. Depending on your LLM provider, you may need to install optional dependencies.

Using pip

pip install instructor

Using uv

uv add instructor

Using Poetry

poetry add instructor

Provider-Specific Installations

To use providers other than OpenAI, install the corresponding extras:

# For Anthropic
pip install "instructor[anthropic]"

# For Google Gemini
pip install "instructor[google-genai]"

# For Cohere
pip install "instructor[cohere]"

# For Mistral
pip install "instructor[mistralai]"

How to Use Instructor

The core workflow of Instructor involves three simple steps: defining a Pydantic model for your desired output, patching an LLM client, and making a request with the response_model parameter.

First, you define a class that inherits from BaseModel. This class describes the fields, types, and descriptions you want the LLM to extract. These descriptions are passed to the LLM as part of the prompt, guiding the model toward higher accuracy.

Next, you use instructor.from_provider() or instructor.from_openai() to wrap your existing LLM client. This “patches” the client, adding the response_model capability to the chat.completions.create method without removing any of the original client’s functionality.

Code Examples

Basic Extraction

This example demonstrates how to extract a simple user profile from a piece of natural language text.

from pydantic import BaseModel
import instructor
from openai import OpenAI

class User(BaseModel):
    name: str
    age: int

# Patch the OpenAI client
client = instructor.from_openai(OpenAI())

user = client.chat.completions.create(
    model="gpt-4o",
    response_model=User,
    messages=[
        {"role": "user", "content": "Extract: Jason is 25 years old"}
    ]
)

print(user.name) # Jason
print(user.age)  # 25

Advanced Extraction with Retries

This example shows how to use max_retries to handle cases where the LLM might fail validation initially.

from pydantic import BaseModel, Field
import instructor
from openai import OpenAI

class User(BaseModel):
    name: str
    age: int = Field(description="The user's age in years")

client = instructor.from_openai(OpenAI())

user = client.chat.completions.create(
    model="gpt-4o",
    response_model=User,
    messages=[
        {"role": "user", "content": "Extract: Jason is 25 years old"}
    ],
    max_retries=3
)

print(user)

Nested Objects and Lists

This example demonstrates extracting a complex, nested data structure containing a list of addresses.

from typing import List
from pydantic import BaseModel
import instructor
from openai import OpenAI

class Address(BaseModel):
    street: str
    city: str
    country: str

class User(BaseModel):
    name: str
    age: int
    addresses: List[Address]

client = instructor.from_openai(OpenAI())

user = client.chat.completions.create(
    model="gpt-4o",
    response_model=User,
    messages=[
    {"role": "user", "content": "Jason lives at 123 Main St, New York, USA and 456 Oak Ave, London, UK"}
    ]
)

print(user.addresses[0].city) # New York

Real-World Use Cases

Instructor is particularly effective in scenarios where the cost of a validation error is high and the data must be consumed by downstream systems.

  • Automated Document Processing: A legal firm can use Instructor to extract key dates, parties, and clauses from thousands of PDFs, ensuring that the extracted data is perfectly formatted for a database.
  • Customer Support Ticket Routing: An enterprise can extract the sentiment, priority, and product category from support tickets, using a strict Enum for categories to ensure tickets are routed to the correct department.
  • AI Agents for API Integration: When building agents that must call external APIs, Instructor ensures the agent generates the exact JSON payload required by the API, preventing 400 Bad Request errors.
  • Structured Data Mining: Researchers can extract specific entities and relationships from academic papers, using nested models to capture complex associations between authors, citations, and findings.

Contributing to Instructor

The Instructor project is community-driven and welcomes contributions from developers of all experience levels. You can contribute by reporting bugs via GitHub issues, submitting pull requests for new features, or improving the documentation.

The project encourages the use of AI-powered editors like Cursor to streamline the project’s specific contribution rules. If you are submitting a new feature, it is recommended to start by opening an issue to discuss the design before submitting a PR.

Community and Support

Instructor has a massive ecosystem of examples and tutorials. The primary hub for community interaction is the official Discord server, where developers share recipes and discuss implementation patterns.

For technical documentation, the project provides a comprehensive guides site at python.useinstructor.com. You can also follow the project’s progress on GitHub Discussions and Twitter/X.

Conclusion

Instructor is the definitive tool for developers who need to bridge the gap between the probabilistic nature of LLMs and the deterministic requirements of production software. By turning LLM responses into validated Pydantic models, it eliminates the majority of the boilerplate code associated with AI data extraction.

If your project requires high-reliability structured outputs, Instructor is the right choice. While it is a lightweight wrapper, it is a critical piece of infrastructure that ensures your AI applications are stable and stable. Star the repo, try the quickstart, and join the community to start building reliable AI applications.

What is Instructor and what problem does it solve?

Instructor is a library that enables structured data extraction from LLMs using type-safe schemas. It solves the problem of unpredictable LLM outputs by validating responses against a Pydantic model and automatically retrying requests when validation fails.

How do I install Instructor?

You can install Instructor using pip with the command pip install instructor. For other providers like Anthropic or Google, you can install specific extras such as pip install "instructor[anthropic]".

How does Instructor compare to LangChain's output parsers?

Instructor is a lightweight wrapper that focuses specifically on structured extraction. Unlike LangChain, it provides native automatic retries with validation error feedback to the LLM, which is a more robust way to ensure correct outputs.

Can I use Instructor for local LLMs?

Yes, Instructor supports local LLMs through providers like Ollama, llama-cpp-python, and vLLM, allowing you to extract structured data while keeping your data on your own hardware.

Does Instructor support multiple languages?

Yes, Instructor is available in Python, TypeScript, Go, Ruby, Elixir, and Rust, providing a consistent API for structured extraction across different stacks.

What is the benefit of Pydantic models in Instructor?

Pydantic models provide type safety, IDE autocompletion, and a powerful validation engine. By using them, you can ensure that the LLM’s response matches your exact requirements before the data ever reaches your application logic.

Is Instructor free to use?

Yes, Instructor is an open-source project licensed under the MIT License, making it free for commercial use in any project.