DSPy Stanford 9 min read

DSPy Guide 2025: Program LLMs with Stanford's Framework

DSPy lets you build reliable LLM pipelines by declaring what you want rather than wrestling with prompts. This guide covers Signatures, Modules, Optimizers, and a working QA pipeline quickstart.

What Is DSPy?

DSPy (Declarative Self-improving Python) is a Stanford research framework that treats LLM pipelines as programs, not prompt templates. The core insight: instead of hand-crafting prompts and manually adjusting them when the LLM changes, you write a pipeline in Python, define a quality metric, and let DSPy's Optimizer automatically figure out the best prompts and few-shot examples.

This makes your pipeline modular and LLM-agnostic. Swap GPT-4 for Claude Sonnet, recompile with the optimizer, and your pipeline adapts without a manual prompt rewrite.

pip install dspy-ai

Key Concepts: Signatures, Modules, Optimizers

DSPy has three core abstractions:

  • Signature — declares the input and output fields of an LLM call. Think of it as a typed function signature. No prompt text needed.
  • Module — a reusable LLM call strategy: Predict (direct), ChainOfThought (adds reasoning), ReAct (tool use), MultiChainComparison (self-consistency).
  • Optimizer — automatically generates few-shot examples and/or instructions to maximize your metric on a trainset.

signatures_example.py

import dspy

# A Signature is just a class with docstring + typed fields
class QuestionAnswer(dspy.Signature):
    """Answer questions with short factual responses."""
    question: str = dspy.InputField()
    answer: str = dspy.OutputField(desc="1-2 sentence answer")

class SentimentAnalysis(dspy.Signature):
    """Classify the sentiment of a review."""
    review: str = dspy.InputField()
    sentiment: str = dspy.OutputField(desc="positive, negative, or neutral")

Built-in Modules

Module What it does When to use
dspy.Predict Single LLM call Simple extraction, classification
dspy.ChainOfThought Adds reasoning field before output Multi-step reasoning, math
dspy.ReAct Interleaves Thought/Act/Observe Tool use, search, agents
dspy.MultiChainComparison Generates N chains, picks best Self-consistency, high accuracy

QA Pipeline Quickstart

A complete working example: configure a language model, build a ChainOfThought QA module, and compile it with BootstrapFewShot:

qa_pipeline.py

import dspy
from dspy.teleprompt import BootstrapFewShot

# 1. Configure the language model
lm = dspy.LM('openai/gpt-4o-mini', api_key='sk-...')
# Or use Claude: dspy.LM('anthropic/claude-sonnet-4-5', api_key='sk-ant-...')
# Or local Ollama: dspy.LM('ollama/llama3', base_url='http://localhost:11434')
dspy.configure(lm=lm)

# 2. Define Signature and Module
class QASignature(dspy.Signature):
    """Answer questions accurately and concisely."""
    question: str = dspy.InputField()
    answer: str = dspy.OutputField()

class RAGPipeline(dspy.Module):
    def __init__(self):
        self.qa = dspy.ChainOfThought(QASignature)

    def forward(self, question: str):
        return self.qa(question=question)

# 3. Define metric
def exact_match(example, pred, trace=None):
    return example.answer.lower() == pred.answer.lower()

# 4. Compile with BootstrapFewShot
trainset = [
    dspy.Example(question="What year was Python created?", answer="1991").with_inputs("question"),
    dspy.Example(question="Who created Linux?", answer="Linus Torvalds").with_inputs("question"),
    # ... more examples
]
optimizer = BootstrapFewShot(metric=exact_match)
compiled_pipeline = optimizer.compile(RAGPipeline(), trainset=trainset)

# 5. Use the compiled pipeline
result = compiled_pipeline(question="What is the capital of France?")
print(result.answer)  # Paris

Optimizers: BootstrapFewShot vs MIPRO

DSPy 2.x ships several optimizers. The two most important:

from dspy.teleprompt import BootstrapFewShot, MIPROv2

# BootstrapFewShot — fast, generates few-shot examples only
optimizer = BootstrapFewShot(metric=my_metric, max_bootstrapped_demos=4)
compiled = optimizer.compile(program, trainset=trainset)

# MIPROv2 — slower, optimizes both instructions AND few-shot examples
# Requires a larger trainset (50+ examples recommended)
optimizer = MIPROv2(metric=my_metric, auto="medium")
compiled = optimizer.compile(program, trainset=trainset, num_trials=25)

Start with BootstrapFewShot — it's fast and requires fewer training examples. Upgrade to MIPROv2 once you have a solid trainset and want to squeeze out more accuracy.

DSPy vs LangChain vs LlamaIndex vs Direct Prompting

Approach Prompt control Auto-optimization Best for
DSPy Declarative Yes (Optimizers) Reliable, repeatable pipelines
LangChain Manual templates No Rapid prototyping, tool chains
LlamaIndex Manual templates Partial RAG, document Q&A
Direct prompting Full manual No Simple one-off calls

Also see: LangChain guide · LlamaIndex guide · Ollama guide

Monitor the LLMs Your Pipeline Uses

DSPy pipelines call OpenAI, Anthropic, or other LLM APIs. Prismix monitors live API status and alerts you when your LLM backend goes down.

Check LLM API Status →