DSPy
Auto-instrument DSPy for declarative prompting.
Risicare automatically instruments DSPy for declarative prompt programming.
Installation
pip install risicare[dspy]
# or
pip install risicare dspyVersion Compatibility
Requires dspy >= 2.5.0.
Auto-Instrumentation
import risicare
import dspy
risicare.init()
lm = dspy.LM("openai/gpt-4o")
dspy.configure(lm=lm)
class BasicQA(dspy.Signature):
question = dspy.InputField()
answer = dspy.OutputField()
qa = dspy.Predict(BasicQA)
# Automatically traced
result = qa(question="What is DSPy?")What's Captured
| Feature | Description |
|---|---|
| Module Calls | Predict, ChainOfThought, ReAct, etc. |
| Signatures | Input/output field definitions |
| Demonstrations | Few-shot examples |
| LLM Calls | Underlying provider calls (deduplicated) |
| Optimizers | Compilation and optimization runs |
Span Hierarchy
dspy.module/{type} (INTERNAL kind)
├── dspy.lm/{model} (LLM_CALL kind)
└── dspy.tool/{name} (TOOL_CALL kind, if applicable)
Provider Deduplication
When using DSPy, underlying LLM provider spans are automatically suppressed to avoid duplicate traces. You don't need to disable provider instrumentation manually.
Modules
All DSPy modules are traced:
Predict
predict = dspy.Predict(BasicQA)
result = predict(question="What is AI?")ChainOfThought
cot = dspy.ChainOfThought(BasicQA)
result = cot(question="Explain quantum computing")
# reasoning field is capturedReAct
def search(query: str) -> str:
return f"Results for {query}"
react = dspy.ReAct(BasicQA, tools=[search])
result = react(question="Search for AI news")
# Tool calls and iterations capturedProgramOfThought
pot = dspy.ProgramOfThought(MathProblem)
result = pot(problem="What is 2+2?")
# Generated code is capturedCompilers/Optimizers
Optimization runs are traced:
from dspy.teleprompt import BootstrapFewShot
optimizer = BootstrapFewShot(metric=my_metric)
compiled = optimizer.compile(qa, trainset=trainset)Note
Optimizers and Assertions do not create distinct spans. Their activity is captured within the parent module span.