SKILL.md
SKILL.mdBrowse 4 files
3,737 tokens
15,220 bytes
Token encoding: o200k_base
Snapshot 24fd22b
1---2name: dspy3description: "DSPy: declarative LM programs, auto-optimize prompts, RAG."4version: 1.0.05author: Orchestra Research6license: MIT7dependencies: [dspy, openai, anthropic]8platforms: [linux, macos, windows]9metadata:10 hermes:11 tags: [Prompt Engineering, DSPy, Declarative Programming, RAG, Agents, Prompt Optimization, LM Programming, Stanford NLP, Automatic Optimization, Modular AI]12 13---14 15# DSPy: Declarative Language Model Programming16 17## When to Use This Skill18 19Use DSPy when you need to:20- **Build complex AI systems** with multiple components and workflows21- **Program LMs declaratively** instead of manual prompt engineering22- **Optimize prompts automatically** using data-driven methods23- **Create modular AI pipelines** that are maintainable and portable24- **Improve model outputs systematically** with optimizers25- **Build RAG systems, agents, or classifiers** with better reliability26 27**GitHub Stars**: 22,000+ | **Created By**: Stanford NLP28 29## Installation30 31```bash32# Stable release33pip install dspy34 35# Latest development version36pip install git+https://github.com/stanfordnlp/dspy.git37 38# With specific LM providers39pip install dspy[openai] # OpenAI40pip install dspy[anthropic] # Anthropic Claude41pip install dspy[all] # All providers42```43 44## Quick Start45 46### Basic Example: Question Answering47 48```python49import dspy50 51# Configure your language model52lm = dspy.Claude(model="claude-sonnet-4-5-20250929")53dspy.settings.configure(lm=lm)54 55# Define a signature (input → output)56class QA(dspy.Signature):57 """Answer questions with short factual answers."""58 question = dspy.InputField()59 answer = dspy.OutputField(desc="often between 1 and 5 words")60 61# Create a module62qa = dspy.Predict(QA)63 64# Use it65response = qa(question="What is the capital of France?")66print(response.answer) # "Paris"67```68 69### Chain of Thought Reasoning70 71```python72import dspy73 74lm = dspy.Claude(model="claude-sonnet-4-5-20250929")75dspy.settings.configure(lm=lm)76 77# Use ChainOfThought for better reasoning78class MathProblem(dspy.Signature):79 """Solve math word problems."""80 problem = dspy.InputField()81 answer = dspy.OutputField(desc="numerical answer")82 83# ChainOfThought generates reasoning steps automatically84cot = dspy.ChainOfThought(MathProblem)85 86response = cot(problem="If John has 5 apples and gives 2 to Mary, how many does he have?")87print(response.rationale) # Shows reasoning steps88print(response.answer) # "3"89```90 91## Core Concepts92 93### 1. Signatures94 95Signatures define the structure of your AI task (inputs → outputs):96 97```python98# Inline signature (simple)99qa = dspy.Predict("question -> answer")100 101# Class signature (detailed)102class Summarize(dspy.Signature):103 """Summarize text into key points."""104 text = dspy.InputField()105 summary = dspy.OutputField(desc="bullet points, 3-5 items")106 107summarizer = dspy.ChainOfThought(Summarize)108```109 110**When to use each:**111- **Inline**: Quick prototyping, simple tasks112- **Class**: Complex tasks, type hints, better documentation113 114### 2. Modules115 116Modules are reusable components that transform inputs to outputs:117 118#### dspy.Predict119Basic prediction module:120 121```python122predictor = dspy.Predict("context, question -> answer")123result = predictor(context="Paris is the capital of France",124 question="What is the capital?")125```126 127#### dspy.ChainOfThought128Generates reasoning steps before answering:129 130```python131cot = dspy.ChainOfThought("question -> answer")132result = cot(question="Why is the sky blue?")133print(result.rationale) # Reasoning steps134print(result.answer) # Final answer135```136 137#### dspy.ReAct138Agent-like reasoning with tools:139 140```python141from dspy.predict import ReAct142 143class SearchQA(dspy.Signature):144 """Answer questions using search."""145 question = dspy.InputField()146 answer = dspy.OutputField()147 148def search_tool(query: str) -> str:149 """Search Wikipedia."""150 # Your search implementation151 return results152 153react = ReAct(SearchQA, tools=[search_tool])154result = react(question="When was Python created?")155```156 157#### dspy.ProgramOfThought158Generates and executes code for reasoning:159 160```python161pot = dspy.ProgramOfThought("question -> answer")162result = pot(question="What is 15% of 240?")163# Generates: answer = 240 * 0.15164```165 166### 3. Optimizers167 168Optimizers improve your modules automatically using training data:169 170#### BootstrapFewShot171Learns from examples:172 173```python174from dspy.teleprompt import BootstrapFewShot175 176# Training data177trainset = [178 dspy.Example(question="What is 2+2?", answer="4").with_inputs("question"),179 dspy.Example(question="What is 3+5?", answer="8").with_inputs("question"),180]181 182# Define metric183def validate_answer(example, pred, trace=None):184 return example.answer == pred.answer185 186# Optimize187optimizer = BootstrapFewShot(metric=validate_answer, max_bootstrapped_demos=3)188optimized_qa = optimizer.compile(qa, trainset=trainset)189 190# Now optimized_qa performs better!191```192 193#### MIPRO (Most Important Prompt Optimization)194Iteratively improves prompts:195 196```python197from dspy.teleprompt import MIPRO198 199optimizer = MIPRO(200 metric=validate_answer,201 num_candidates=10,202 init_temperature=1.0203)204 205optimized_cot = optimizer.compile(206 cot,207 trainset=trainset,208 num_trials=100209)210```211 212#### BootstrapFinetune213Creates datasets for model fine-tuning:214 215```python216from dspy.teleprompt import BootstrapFinetune217 218optimizer = BootstrapFinetune(metric=validate_answer)219optimized_module = optimizer.compile(qa, trainset=trainset)220 221# Exports training data for fine-tuning222```223 224### 4. Building Complex Systems225 226#### Multi-Stage Pipeline227 228```python229import dspy230 231class MultiHopQA(dspy.Module):232 def __init__(self):233 super().__init__()234 self.retrieve = dspy.Retrieve(k=3)235 self.generate_query = dspy.ChainOfThought("question -> search_query")236 self.generate_answer = dspy.ChainOfThought("context, question -> answer")237 238 def forward(self, question):239 # Stage 1: Generate search query240 search_query = self.generate_query(question=question).search_query241 242 # Stage 2: Retrieve context243 passages = self.retrieve(search_query).passages244 context = "\n".join(passages)245 246 # Stage 3: Generate answer247 answer = self.generate_answer(context=context, question=question).answer248 return dspy.Prediction(answer=answer, context=context)249 250# Use the pipeline251qa_system = MultiHopQA()252result = qa_system(question="Who wrote the book that inspired the movie Blade Runner?")253```254 255#### RAG System with Optimization256 257```python258import dspy259from dspy.retrieve.chromadb_rm import ChromadbRM260 261# Configure retriever262retriever = ChromadbRM(263 collection_name="documents",264 persist_directory="./chroma_db"265)266 267class RAG(dspy.Module):268 def __init__(self, num_passages=3):269 super().__init__()270 self.retrieve = dspy.Retrieve(k=num_passages)271 self.generate = dspy.ChainOfThought("context, question -> answer")272 273 def forward(self, question):274 context = self.retrieve(question).passages275 return self.generate(context=context, question=question)276 277# Create and optimize278rag = RAG()279 280# Optimize with training data281from dspy.teleprompt import BootstrapFewShot282 283optimizer = BootstrapFewShot(metric=validate_answer)284optimized_rag = optimizer.compile(rag, trainset=trainset)285```286 287## LM Provider Configuration288 289### Anthropic Claude290 291```python292import dspy293 294lm = dspy.Claude(295 model="claude-sonnet-4-5-20250929",296 api_key="your-api-key", # Or set ANTHROPIC_API_KEY env var297 max_tokens=1000,298 temperature=0.7299)300dspy.settings.configure(lm=lm)301```302 303### OpenAI304 305```python306lm = dspy.OpenAI(307 model="gpt-4",308 api_key="your-api-key",309 max_tokens=1000310)311dspy.settings.configure(lm=lm)312```313 314### Local Models (Ollama)315 316```python317lm = dspy.OllamaLocal(318 model="llama3.1",319 base_url="http://localhost:11434"320)321dspy.settings.configure(lm=lm)322```323 324### Multiple Models325 326```python327# Different models for different tasks328cheap_lm = dspy.OpenAI(model="gpt-3.5-turbo")329strong_lm = dspy.Claude(model="claude-sonnet-4-5-20250929")330 331# Use cheap model for retrieval, strong model for reasoning332with dspy.settings.context(lm=cheap_lm):333 context = retriever(question)334 335with dspy.settings.context(lm=strong_lm):336 answer = generator(context=context, question=question)337```338 339## Common Patterns340 341### Pattern 1: Structured Output342 343```python344from pydantic import BaseModel, Field345 346class PersonInfo(BaseModel):347 name: str = Field(description="Full name")348 age: int = Field(description="Age in years")349 occupation: str = Field(description="Current job")350 351class ExtractPerson(dspy.Signature):352 """Extract person information from text."""353 text = dspy.InputField()354 person: PersonInfo = dspy.OutputField()355 356extractor = dspy.TypedPredictor(ExtractPerson)357result = extractor(text="John Doe is a 35-year-old software engineer.")358print(result.person.name) # "John Doe"359print(result.person.age) # 35360```361 362### Pattern 2: Assertion-Driven Optimization363 364```python365import dspy366from dspy.primitives.assertions import assert_transform_module, backtrack_handler367 368class MathQA(dspy.Module):369 def __init__(self):370 super().__init__()371 self.solve = dspy.ChainOfThought("problem -> solution: float")372 373 def forward(self, problem):374 solution = self.solve(problem=problem).solution375 376 # Assert solution is numeric377 dspy.Assert(378 isinstance(float(solution), float),379 "Solution must be a number",380 backtrack=backtrack_handler381 )382 383 return dspy.Prediction(solution=solution)384```385 386### Pattern 3: Self-Consistency387 388```python389import dspy390from collections import Counter391 392class ConsistentQA(dspy.Module):393 def __init__(self, num_samples=5):394 super().__init__()395 self.qa = dspy.ChainOfThought("question -> answer")396 self.num_samples = num_samples397 398 def forward(self, question):399 # Generate multiple answers400 answers = []401 for _ in range(self.num_samples):402 result = self.qa(question=question)403 answers.append(result.answer)404 405 # Return most common answer406 most_common = Counter(answers).most_common(1)[0][0]407 return dspy.Prediction(answer=most_common)408```409 410### Pattern 4: Retrieval with Reranking411 412```python413class RerankedRAG(dspy.Module):414 def __init__(self):415 super().__init__()416 self.retrieve = dspy.Retrieve(k=10)417 self.rerank = dspy.Predict("question, passage -> relevance_score: float")418 self.answer = dspy.ChainOfThought("context, question -> answer")419 420 def forward(self, question):421 # Retrieve candidates422 passages = self.retrieve(question).passages423 424 # Rerank passages425 scored = []426 for passage in passages:427 score = float(self.rerank(question=question, passage=passage).relevance_score)428 scored.append((score, passage))429 430 # Take top 3431 top_passages = [p for _, p in sorted(scored, reverse=True)[:3]]432 context = "\n\n".join(top_passages)433 434 # Generate answer435 return self.answer(context=context, question=question)436```437 438## Evaluation and Metrics439 440### Custom Metrics441 442```python443def exact_match(example, pred, trace=None):444 """Exact match metric."""445 return example.answer.lower() == pred.answer.lower()446 447def f1_score(example, pred, trace=None):448 """F1 score for text overlap."""449 pred_tokens = set(pred.answer.lower().split())450 gold_tokens = set(example.answer.lower().split())451 452 if not pred_tokens:453 return 0.0454 455 precision = len(pred_tokens & gold_tokens) / len(pred_tokens)456 recall = len(pred_tokens & gold_tokens) / len(gold_tokens)457 458 if precision + recall == 0:459 return 0.0460 461 return 2 * (precision * recall) / (precision + recall)462```463 464### Evaluation465 466```python467from dspy.evaluate import Evaluate468 469# Create evaluator470evaluator = Evaluate(471 devset=testset,472 metric=exact_match,473 num_threads=4,474 display_progress=True475)476 477# Evaluate model478score = evaluator(qa_system)479print(f"Accuracy: {score}")480 481# Compare optimized vs unoptimized482score_before = evaluator(qa)483score_after = evaluator(optimized_qa)484print(f"Improvement: {score_after - score_before:.2%}")485```486 487## Best Practices488 489### 1. Start Simple, Iterate490 491```python492# Start with Predict493qa = dspy.Predict("question -> answer")494 495# Add reasoning if needed496qa = dspy.ChainOfThought("question -> answer")497 498# Add optimization when you have data499optimized_qa = optimizer.compile(qa, trainset=data)500```501 502### 2. Use Descriptive Signatures503 504```python505# ❌ Bad: Vague506class Task(dspy.Signature):507 input = dspy.InputField()508 output = dspy.OutputField()509 510# ✅ Good: Descriptive511class SummarizeArticle(dspy.Signature):512 """Summarize news articles into 3-5 key points."""513 article = dspy.InputField(desc="full article text")514 summary = dspy.OutputField(desc="bullet points, 3-5 items")515```516 517### 3. Optimize with Representative Data518 519```python520# Create diverse training examples521trainset = [522 dspy.Example(question="factual", answer="...).with_inputs("question"),523 dspy.Example(question="reasoning", answer="...").with_inputs("question"),524 dspy.Example(question="calculation", answer="...").with_inputs("question"),525]526 527# Use validation set for metric528def metric(example, pred, trace=None):529 return example.answer in pred.answer530```531 532### 4. Save and Load Optimized Models533 534```python535# Save536optimized_qa.save("models/qa_v1.json")537 538# Load539loaded_qa = dspy.ChainOfThought("question -> answer")540loaded_qa.load("models/qa_v1.json")541```542 543### 5. Monitor and Debug544 545```python546# Enable tracing547dspy.settings.configure(lm=lm, trace=[])548 549# Run prediction550result = qa(question="...")551 552# Inspect trace553for call in dspy.settings.trace:554 print(f"Prompt: {call['prompt']}")555 print(f"Response: {call['response']}")556```557 558## Comparison to Other Approaches559 560| Feature | Manual Prompting | LangChain | DSPy |561|---------|-----------------|-----------|------|562| Prompt Engineering | Manual | Manual | Automatic |563| Optimization | Trial & error | None | Data-driven |564| Modularity | Low | Medium | High |565| Type Safety | No | Limited | Yes (Signatures) |566| Portability | Low | Medium | High |567| Learning Curve | Low | Medium | Medium-High |568 569**When to choose DSPy:**570- You have training data or can generate it571- You need systematic prompt improvement572- You're building complex multi-stage systems573- You want to optimize across different LMs574 575**When to choose alternatives:**576- Quick prototypes (manual prompting)577- Simple chains with existing tools (LangChain)578- Custom optimization logic needed579 580## Resources581 582- **Documentation**: https://dspy.ai583- **GitHub**: https://github.com/stanfordnlp/dspy (22k+ stars)584- **Discord**: https://discord.gg/XCGy2WDCQB585- **Twitter**: @DSPyOSS586- **Paper**: "DSPy: Compiling Declarative Language Model Calls into Self-Improving Pipelines"587 588## See Also589 590- `references/modules.md` - Detailed module guide (Predict, ChainOfThought, ReAct, ProgramOfThought)591- `references/optimizers.md` - Optimization algorithms (BootstrapFewShot, MIPRO, BootstrapFinetune)592- `references/examples.md` - Real-world examples (RAG, agents, classifiers)593 594 595 Discovery context
Discovered by repository scan. No exact path reference found in the snapshot’s root AGENTS.md.