DSPy (Declarative Self-improving Python) is a framework from Stanford NLP that replaces:
Prompting → with Programming
String manipulation → with Typed signatures
Manual tuning → with Automatic optimization
Copy
Traditional Prompting DSPy Approach━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"You are an expert..." class MyModule(dspy.Module):"Step 1: First..." def forward(self, question):"Example: ..." return self.predictor(question=question)Manual prompt engineering Automatic optimizationFragile to model changes Model-agnostic
import dspy# Simple signature (inline)qa = dspy.Predict("question -> answer")result = qa(question="What is the capital of France?")print(result.answer) # Paris# Class-based signature for more controlclass QuestionAnswer(dspy.Signature): """Answer questions with concise, accurate responses.""" question: str = dspy.InputField(desc="The question to answer") answer: str = dspy.OutputField(desc="A concise answer")qa = dspy.Predict(QuestionAnswer)result = qa(question="What is machine learning?")print(result.answer)
class MathProblem(dspy.Signature): """Solve math word problems step by step.""" problem: str = dspy.InputField() answer: float = dspy.OutputField()# Use ChainOfThought for better reasoningsolver = dspy.ChainOfThought(MathProblem)result = solver(problem=""" A store has 45 apples. They sell 12 in the morning and receive a shipment of 30 more. How many apples do they have now?""")print(f"Answer: {result.answer}")print(f"Reasoning: {result.reasoning}") # Shows step-by-step work
class SearchAndAnswer(dspy.Signature): """Answer questions using search when needed.""" question: str = dspy.InputField() answer: str = dspy.OutputField()# Define toolsdef search(query: str) -> str: """Search the web for information.""" # Implement actual search return f"Search results for: {query}"def calculate(expression: str) -> str: """Evaluate a mathematical expression.""" return str(eval(expression))# Create ReAct agentreact = dspy.ReAct( SearchAndAnswer, tools=[search, calculate], max_iters=5)result = react(question="What is the population of Tokyo and what's 10% of that?")print(result.answer)
DSPy can automatically optimize your prompts using training examples:
Copy
# Define training examplestrainset = [ Example(question="What is 2+2?", answer="4").with_inputs("question"), Example(question="What is the capital of Japan?", answer="Tokyo").with_inputs("question"), Example(question="Who wrote Hamlet?", answer="William Shakespeare").with_inputs("question"),]# Create moduleqa = dspy.Predict("question -> answer")# Optimize with MIPROv2from dspy.teleprompt import MIPROv2optimizer = MIPROv2( metric=lambda example, pred, trace: pred.answer.lower() == example.answer.lower(), num_candidates=10, init_temperature=1.0)optimized_qa = optimizer.compile(qa, trainset=trainset)# The optimized module has better promptsresult = optimized_qa(question="What is the speed of light?")
import dspy# Enable cachingdspy.configure( lm=dspy.LM("openai/gpt-4o-mini"), experimental=True # Enables caching)# Or use explicit cachefrom dspy.utils import DummyLM# For testing without API callsdspy.configure(lm=DummyLM([ {"answer": "Paris"}, {"answer": "Tokyo"}]))