跳到主要内容

DSPy 编程框架

DSPy(Declarative Self-improving Python)是斯坦福大学 NLP 组开发的 LLM 编程框架,代表了一种与 LangChain、LlamaIndex 截然不同的设计哲学:将逻辑与提示分离,通过自动优化取代手动提示工程。

DSPy 的核心理念

传统 LLM 开发的痛点:

  • 提示(Prompt)脆弱,换一个模型或版本就需要重新调整
  • 手动提示工程耗时且不可复现
  • 提示优化依赖直觉,缺乏系统性

DSPy 的解决思路类比神经网络:就像神经网络通过反向传播自动调整权重,DSPy 通过优化器(Teleprompter)自动调整提示和少样本示例,使模型行为满足定义的评估指标。

核心原则:

  • 声明式:描述"做什么",而不是"怎么做"(写什么提示)
  • 模块化:将复杂程序拆解为可组合的模块
  • 自动优化:基于评估数据自动找到最优提示和示例

核心组件

Signature(签名)

Signature 定义模块的输入输出类型和含义,类似函数签名:

import dspy

# 简洁语法:输入 -> 输出
class Classify(dspy.Signature):
"""将用户评论分类为正面、负面或中性"""
comment: str = dspy.InputField()
sentiment: Literal["positive", "negative", "neutral"] = dspy.OutputField()

# 也可以用字符串语法(快速原型)
classify = dspy.Predict("comment -> sentiment")

Module(模块)

模块是 DSPy 程序的基础构建块,封装了 LLM 调用逻辑:

class RAGPipeline(dspy.Module):
def __init__(self, num_passages=3):
super().__init__()
self.retrieve = dspy.Retrieve(k=num_passages)
self.generate = dspy.ChainOfThought("context, question -> answer")

def forward(self, question):
context = self.retrieve(question).passages
answer = self.generate(context=context, question=question)
return answer

# 使用
rag = RAGPipeline(num_passages=5)
result = rag(question="Python 中的 asyncio 是如何工作的?")
print(result.answer)

Teleprompter(优化器)

Teleprompter 是 DSPy 的"训练器",通过少量标注数据自动优化程序:

from dspy.teleprompt import BootstrapFewShot

# 定义评估指标
def validate_answer(example, pred, trace=None):
return example.answer.lower() in pred.answer.lower()

# 准备少量训练样本(10-50 条即可)
trainset = [
dspy.Example(question="Python 列表和元组的区别?", answer="列表可变,元组不可变").with_inputs("question"),
# ... 更多示例
]

# 自动优化
optimizer = BootstrapFewShot(metric=validate_answer, max_bootstrapped_demos=4)
optimized_rag = optimizer.compile(RAGPipeline(), trainset=trainset)

# 保存优化后的程序
optimized_rag.save("optimized_rag.json")

内置模块

Predict(基础预测)

最简单的模块,直接按 Signature 调用 LLM:

predict = dspy.Predict(Classify)
result = predict(comment="这个产品真的很好用!")
print(result.sentiment) # "positive"

ChainOfThought(思维链)

自动添加推理步骤,提高复杂问题的准确率:

cot = dspy.ChainOfThought("question -> answer")
result = cot(question="如果苹果比橘子贵,橘子比香蕉贵,那么苹果和香蕉哪个更贵?")
print(result.reasoning) # 推理过程
print(result.answer) # 最终答案

ReAct(推理+行动)

ReAct 模块实现 Reasoning + Acting 循环,支持工具调用:

def search_web(query: str) -> str:
"""搜索互联网获取信息"""
# 实际实现
return "搜索结果..."

react = dspy.ReAct("question -> answer", tools=[search_web])
result = react(question="2024 年的诺贝尔物理学奖得主是谁?")

Retrieve(检索)

与向量数据库集成的检索模块:

# 配置检索后端(如 ColBERT、Weaviate 等)
dspy.settings.configure(rm=MyRetriever())

retrieve = dspy.Retrieve(k=5)
passages = retrieve("Python 异步编程").passages

优化器

BootstrapFewShot

最基础的优化器,从训练集中自动选择最优的少样本示例:

  • 运行程序生成预测,保留满足评估指标的示例
  • 将这些示例作为 Few-shot 嵌入提示
  • 适合小数据集(10-50 条)

MIPROv2

多阶段优化器,同时优化提示指令和少样本示例:

from dspy.teleprompt import MIPROv2

optimizer = MIPROv2(
metric=validate_answer,
auto="medium", # light/medium/heavy,控制搜索力度
)
optimized = optimizer.compile(
program,
trainset=trainset,
num_trials=30 # 优化迭代次数
)

MIPROv2 适合需要高质量优化且有足够算力预算的场景。

与 LangChain 的根本差异

维度DSPyLangChain
提示管理自动优化(不写提示)手动编写提示模板
核心抽象Signature + ModuleChain + Prompt
学习曲线较陡(需理解新范式)中等
集成生态较少非常丰富
适合阶段需要系统优化时快速集成原型
可解释性高(程序结构清晰)中等

适用场景

DSPy 特别适合以下场景:

  • 信息提取:从文档中提取结构化数据,需要高精度
  • 分类任务:文本分类、意图识别,有评估数据集可用
  • 问答系统:有标准答案可评估的 RAG 系统
  • 学术研究:需要可复现的 NLP 实验
  • 跨模型迁移:同一程序在不同 LLM 上自动重新优化

不适合的场景:

  • 需要快速集成大量第三方服务(用 LangChain)
  • 没有任何评估数据(优化器无法工作)
  • 以创意生成为主(优化目标不明确)

代码示例:完整 QA 系统

import dspy
from dspy.teleprompt import BootstrapFewShot

# 1. 配置 LLM
lm = dspy.LM("openai/gpt-4o", api_key="...")
dspy.configure(lm=lm)

# 2. 定义程序
class QAWithSources(dspy.Module):
def __init__(self):
self.generate_query = dspy.ChainOfThought("question -> search_query")
self.retrieve = dspy.Retrieve(k=3)
self.generate_answer = dspy.ChainOfThought(
"context, question -> answer, confidence"
)

def forward(self, question):
query = self.generate_query(question=question).search_query
context = self.retrieve(query).passages
result = self.generate_answer(
context="\n".join(context), question=question
)
return dspy.Prediction(
answer=result.answer,
confidence=result.confidence
)

# 3. 优化
qa = QAWithSources()
optimizer = BootstrapFewShot(metric=lambda ex, pred, trace: ex.answer in pred.answer)
optimized_qa = optimizer.compile(qa, trainset=trainset)

# 4. 使用
result = optimized_qa(question="深度学习的反向传播算法是如何工作的?")
print(f"回答:{result.answer}")
print(f"置信度:{result.confidence}")