Module: The Execution Engine
A Module in DSPy is an executable component that takes a signature and adds behaviorβlike making LM calls, adding reasoning steps, or using tools.
π‘ Think of It Like a Function
If a signature is like a function declaration, a module is like the implementation:
# In regular Python:
def calculate_tax(income: float, rate: float) -> float: # Declaration
return income * rate # Implementation
# In DSPy:
class TaxCalculation(dspy.Signature): # Declaration
"""Calculate the estimated tax."""
income: float = dspy.InputField()
tax_rate: float = dspy.InputField()
tax_amount: float = dspy.OutputField()
calculator = dspy.Predict(TaxCalculation) # Implementation
The module wraps the signature and provides the execution logicβhow to actually call the LM and handle the response.
π§ What Modules Actually Do
When you call a module, several things happen behind the scenes:
Construct the Prompt
The module uses the signature to build a prompt from the docstring, field names, and descriptions.
Add Module-Specific Behavior
Depending on the module type, it may add reasoning steps, tool calls, or multiple attempts.
Call the Language Model
The complete prompt is sent to the configured LM (GPT-4, Claude, Llama, etc.).
Parse and Return Results
The LM's response is parsed according to the output fields and returned as a structured object.
π Basic Example
Here's the simplest possible module usage:
import dspy
# 1. Configure LM
lm = dspy.LM("openai/gpt-4o-mini")
dspy.configure(lm=lm)
# 2. Define a signature
class Summarize(dspy.Signature):
"""Create a brief summary of the text."""
text: str = dspy.InputField()
summary: str = dspy.OutputField()
# 3. Create a module from the signature
summarizer = dspy.Predict(Summarize)
# 4. Call the module
result = summarizer(text="DSPy is a framework for programming language models...")
# 5. Access the output
print(result.summary)
Key insight: The module is callable! Just pass the input fields as keyword arguments and access outputs as attributes.
ποΈ Types of Modules
DSPy provides several built-in modules, each adding different behavior:
| Module | Behavior | Best For |
|---|---|---|
dspy.Predict |
Direct LM call, no additional steps | Simple tasks, fast responses |
dspy.ChainOfThought |
Adds reasoning before answering | Complex reasoning, math, analysis |
dspy.ProgramOfThought |
Generates and executes code | Computational tasks, calculations |
dspy.ReAct |
Uses tools with observation loops | Tool use, external APIs, search |
dspy.Module |
Base class for custom modules | Complex pipelines, custom logic |
π Same Signature, Different Modules
One powerful aspect of DSPy is that you can use the same signature with different modules to get different behaviors:
class MathProblem(dspy.Signature):
"""Solve the math problem."""
problem: str = dspy.InputField()
answer: str = dspy.OutputField()
# Same signature, different modules:
# Quick answer (might make mistakes)
quick_solver = dspy.Predict(MathProblem)
# With reasoning (more accurate)
reasoning_solver = dspy.ChainOfThought(MathProblem)
# With code execution (precise calculations)
code_solver = dspy.ProgramOfThought(MathProblem)
Comparing the Results
problem = "What is 847 * 293?"
# Quick answer
result1 = quick_solver(problem=problem)
print(f"Predict: {result1.answer}")
# With reasoning
result2 = reasoning_solver(problem=problem)
print(f"Reasoning: {result2.rationale}") # Shows work
print(f"Answer: {result2.answer}")
# With code
result3 = code_solver(problem=problem)
print(f"Code: {result3.answer}") # 248,171 (exact)
ποΈ The Module Hierarchy
All DSPy modules inherit from dspy.Module:
dspy.Module
βββ dspy.Predict # Basic prediction
βββ dspy.ChainOfThought # Adds reasoning
βββ dspy.ChainOfThoughtWithHint # CoT with hints
βββ dspy.ProgramOfThought # Code generation
βββ dspy.ReAct # Tool use
βββ dspy.MultiChainComparison # Multiple reasoning chains
βββ YourCustomModule # Your own modules!
Because they all share the same base class, they can:
Be Composed Together
Use multiple modules in sequence within a custom module.
Track Parameters
DSPy automatically tracks all sub-modules for optimization.
Be Optimized
Optimizers can improve prompts across all modules uniformly.