DSPy 声明式编程
DSPy:声明式 LM 程序、自动优化提示词、RAG 流水线
DSPy 声明式语言模型编程
使用场景
需要以下场景时使用 DSPy:
- 构建具有多个组件和工作流的复杂 AI 系统
- 以声明式方式编程 LLM,而非手动设计提示词
- 使用数据驱动方法自动优化提示词
- 创建可维护、可移植的模块化 AI 流水线
- 使用优化器系统性地改进模型输出
- 构建更可靠的 RAG 系统、智能体或分类器
GitHub Stars: 22,000+ | 创建方: Stanford NLP
安装
# 稳定版
pip install dspy
# 最新开发版
pip install git+https://github.com/stanfordnlp/dspy.git
# 带特定 LM 提供商
pip install dspy[openai] # OpenAI
pip install dspy[anthropic] # Anthropic Claude
pip install dspy[all] # 所有提供商
快速入门
基础示例:问答
import dspy
# 配置语言模型
lm = dspy.Claude(model="claude-sonnet-4-5-20250929")
dspy.settings.configure(lm=lm)
# 定义签名(输入 → 输出)
class QA(dspy.Signature):
"""用简短的实事答案回答问题。"""
question = dspy.InputField()
answer = dspy.OutputField(desc="通常在 1-5 个词之间")
# 创建模块
qa = dspy.Predict(QA)
# 使用
response = qa(question="法国的首都是哪里?")
print(response.answer) # "巴黎"
思维链推理
import dspy
lm = dspy.Claude(model="claude-sonnet-4-5-20250929")
dspy.settings.configure(lm=lm)
# 使用 ChainOfThought 以获得更好的推理
class MathProblem(dspy.Signature):
"""解数学应用题。"""
problem = dspy.InputField()
answer = dspy.OutputField(desc="数字答案")
# ChainOfThought 自动生成推理步骤
cot = dspy.ChainOfThought(MathProblem)
response = cot(problem="如果约翰有 5 个苹果,给了玛丽 2 个,他还剩多少?")
print(response.rationale) # 显示推理步骤
print(response.answer) # "3"
核心概念
签名(Signatures)
签名定义模块的输入和输出字段,类似于函数的类型注解:
class RAG(dspy.Signature):
"""根据给定上下文回答问题。"""
context = dspy.InputField(desc="可能包含答案的上下文")
question = dspy.InputField()
answer = dspy.OutputField(desc="1-2 句话的答案")
模块(Modules)
DSPy 提供多种内置模块:
- Predict:基础模块,在给定签名下执行 LM 调用
- ChainOfThought:生成中间推理步骤再得出答案
- ChainOfThoughtWithHint:带提示的思维链
- ReAct:结合推理和操作(如搜索)
- ProgramOfThought:将推理作为代码执行
- MultiChainComparison:比较多个思维链结果
# 选择不同的模块
cot = dspy.ChainOfThought(MathProblem)
react = dspy.ReAct(RAG)
Teleprompter(提示词优化器)
Teleprompter 使用数据驱动方式自动优化提示词和推理策略:
- Bootstrap FewShot:从少量示例生成候选提示词
- LabeledFewShot:使用手动标注的示例
- Ensemble:组合多个模块
- Majority Voting:多数投票(适用于多个样本)
from dspy.teleprompt import BootstrapFewShot
# 使用 FewShot 优化器
teleprompter = BootstrapFewShot(metric=my_metric)
compiled = teleprompter.compile(student=dspy.RAG(), trainset=trainset)
多阶段流水线
DSPy 支持组合多个模块构建复杂流水线:
class RAGModule(dspy.Module):
def __init__(self):
super().__init__()
self.retriever = dspy.Retrieve(top_k=3)
self.rag = dspy.Predict(RAG)
def forward(self, question):
context = self.retriever(query=question).passages
return self.rag(context=context, question=question)
评估
from dspy.evaluate import Evaluate
evaluate = Evaluate(
devset=devset,
metric=my_metric,
num_threads=4,
display=True
)
results = evaluate(compiled_rag)
print(f"Accuracy: {results}")
提示词编译器内部机制
DSPy 提示词编译器通过以下步骤工作:
- 演示收集:运行模块,收集成功案例作为示例
- 提示生成:基于演示和签名构建提示词
- 候选评分:用评估指标对候选提示词评分
- 选择:选择得分最高的提示词
对于复杂流水线,每个阶段可以使用不同签名和模块。
提示词示例
RAG 系统
import dspy
# 配置
lm = dspy.Claude(model="claude-sonnet-4-5-20250929")
dspy.settings.configure(lm=lm, rm=colbertv2)
# 签名
class GenerateAnswer(dspy.Signature):
"""给定上下文,回答问题。"""
context = dspy.InputField(desc="可能包含答案的相关段落")
question = dspy.InputField()
answer = dspy.OutputField(desc="1-2 句话的答案")
# RAG 模块
class RAG(dspy.Module):
def __init__(self, num_passages=3):
super().__init__()
self.retrieve = dspy.Retrieve(top_k=num_passages)
self.generate = dspy.Predict(GenerateAnswer)
def forward(self, question):
context = self.retrieve(query=question).passages
prediction = self.generate(context=context, question=question)
return dspy.Prediction(context=context, answer=prediction.answer)
完整示例
import dspy
from dspy.retrieve import ChromaRM
# 设置 Chroma 作为检索模型
rm = ChromaRM(collection_name="my_collection")
dspy.settings.configure(rm=rm)
# 定义签名
class QA(dspy.Signature):
question = dspy.InputField()
answer = dspy.OutputField()
# 创建流水线
qa_pipeline = dspy.ChainOfThought(QA)
# 运行
response = qa_pipeline(question="巴黎是哪国的首都?")
print(response.answer)
提示词最佳实践
- 简洁的签名描述:描述字段帮助 LM 理解期望的输出格式
- 从简单开始:先用 Predict,再用 ChainOfThought 提升质量
- 评估驱动优化:使用真实评估指标指导提示词优化
- 分阶段流水线:将复杂任务分解为多个签名/模块
- 迭代改进:优化是迭代过程,多次编译通常能提升质量
安装指南
复制下方命令,在终端运行即可安装:
# 安装到当前项目
npx skills add dspy
# 全局安装 — 所有项目可用
npx skills add dspy -g
使用指南
安装完成后,在对话框中直接使用此技能。