DSPy:斯坦福声明式提示编程框架安装与使用指南
| 项目名称 | stanfordnlp/dspy (DSPy) |
| 仓库地址 | https://github.com/stanfordnlp/dspy |
| 官方网站 | https://dspy.ai/ |
| 官方文档 | https://dspy.ai/docs/ |
| 最新更新时间 | 2026-10-25(持续活跃更新) |
| 项目定位 | 斯坦福提出的"编程而非提示"框架,用签名+优化器自动生成 Prompt |
| 开源协议 | MIT |
一、项目背景
过去两年,"写 Prompt"成了程序员的新日常。一个 RAG 应用里,你要手写检索 Prompt、回答 Prompt、重排 Prompt、 hallucination 检测 Prompt;换个模型,Prompt 就得重写;业务改个需求,Prompt 又得重新调。这种"手工 Prompt 工程"在原型阶段很爽,但当系统有几十个模块、上百条 Prompt 时,维护成本会指数级爆炸——没人记得每个 Prompt 为什么这么写,也没人敢改。
DSPy 由斯坦福 NLP 组(Omar Khattab 等人)开源,主张"Program, don't prompt"——你不再手写 Prompt 字符串,而是像写函数签名一样声明"输入是什么、输出是什么、任务要什么风格",DSPy 内部的"优化器(Optimizer)"会自动给不同的 LLM 生成最合适的 Prompt,并用小样本数据集做梯度式调优。
这个思路从根本上改变了 LLM 应用的开发范式:Prompt 从"艺术品"变成"可编译产物",可以像代码一样版本管理、单元测试、A/B 对比。DeepMind、OpenAI、苏黎世联邦理工等机构的论文都基于 DSPy 做实验,它已经成为学术圈做 LLM 系统研究的事实标准框架。
二、核心特性
- 声明式签名(Signatures):用 Python 类声明输入输出字段与任务描述,无需手写 Prompt 模板。
- 模块化模块(Modules):Predict、ChainOfThought、ReAct、Retrieve 等可像搭积木一样组合。
- 自动优化器:BootstrapFewShot、MIPROv2、COPRO、SignatureOptimizer 等,自动搜出最优 Prompt 与 few-shot 样本。
- 多 LLM 后端:一行切换 OpenAI、Anthropic、Gemini、本地 Ollama、vLLM、HuggingFace 模型。
- RAG 原生集成:内置 ColBERTv2 检索器,支持把向量库接入模块链。
- 评估体系:内置 Evaluate 类,支持多指标、并发、批量打分。
- 可序列化:优化后的 Prompt/模块可保存为 JSON,部署时直接加载,无需再跑优化。
- 学术研究友好:论文级抽象,方便复现实验、做 ablation。
三、环境要求
- Python:3.10 及以上。
- 操作系统:Linux / macOS / WSL2。
- LLM API Key:至少一个 OpenAI / Anthropic / DeepSeek 等兼容接口的 Key。
- 磁盘:几 MB 即可,模型由远端 API 提供。
- 网络:能访问你选择的 LLM API。
- (可选)GPU:如果跑本地小模型做优化器推理,需要 GPU。
四、详细部署步骤
方式一:pip 安装(推荐)
python3 -m venv .venv
source .venv/bin/activate
# 稳定版
pip install -U dspy
# 如果要用到 OpenAI
pip install -U "dspy[openai]"
# Anthropic / Gemini / Azure 等按需
pip install -U "dspy[anthropic]"
pip install -U "dspy[google]"方式二:从源码安装最新开发版
git clone https://github.com/stanfordnlp/dspy
cd dspy
pip install -e .配置 LLM 后端
使用 OpenAI:
import os
os.environ["OPENAI_API_KEY"] = "sk-xxxx"
import dspy
lm = dspy.LM("openai/gpt-4o-mini")
dspy.configure(lm=lm)使用 DeepSeek(OpenAI 兼容接口):
lm = dspy.LM(
model="deepseek/deepseek-chat",
api_key=os.environ["DEEPSEEK_API_KEY"],
api_base="https://api.deepseek.com/v1",
)
dspy.configure(lm=lm)使用本地 Ollama:
lm = dspy.LM("ollama_chat/qwen2.5:7b", api_base="http://localhost:11434")
dspy.configure(lm=lm)第一个 DSPy 程序:写一个问答器
import dspy
# 1) 定义签名:输入 question,输出 answer
class QuestionAnswer(dspy.Signature):
"""Answer questions with short factoid answers."""
question: str = dspy.InputField()
answer: str = dspy.OutputField(desc="often between 1 and 5 words")
# 2) 组合模块:带 CoT 的 Predict
qa = dspy.ChainOfThought(QuestionAnswer)
# 3) 调用
result = qa(question="谁提出了相对论?")
print("推理过程:", result.reasoning)
print("答案:", result.answer)注意你没有手写任何 Prompt——DSPy 会根据 Signature 的 docstring 与字段描述自动组装 Prompt。
用优化器自动调 Prompt
# 准备少量标注数据(几十条即可)
trainset = [
dspy.Example(question="水的化学式?", answer="H2O").with_inputs("question"),
dspy.Example(question="法国首都?", answer="巴黎").with_inputs("question"),
# ... 再加 20-50 条
]
# 定义评分函数
def metric(example, pred, trace=None):
return example.answer.lower() == pred.answer.lower()
# 用 MIPROv2 优化器自动搜 Prompt
from dspy.teleprompt import MIPROv2
optimizer = MIPROv2(metric=metric, num_candidates=10)
optimized_qa = optimizer.compile(
student=qa,
trainset=trainset,
num_trials=30,
)
# 保存优化结果
optimized_qa.save("optimized_qa.json")
# 部署时直接加载,无需再调
prod_qa = dspy.ChainOfThought(QuestionAnswer).load("optimized_qa.json")构建一个 RAG 程序
from dspy.retrieve.chromadb_rm import ChromadbRM
# 准备向量库(这里用本地 Chroma)
retriever = ChromadbRM(
collection_name="my_docs",
persist_directory="./chroma_store",
)
class RAG(dspy.Signature):
"""根据给定上下文回答问题。"""
context: str = dspy.InputField()
question: str = dspy.InputField()
answer: str = dspy.OutputField()
class RAGPipeline(dspy.Module):
def __init__(self):
super().__init__()
self.retrieve = retriever
self.generate = dspy.ChainOfThought(RAG)
def forward(self, question):
context = self.retrieve(question)
return self.generate(context=str(context), question=question)
rag = RAGPipeline()
print(rag("DSPy 是哪家机构开发的?").answer)五、进阶用法与生产建议
5.1 把 DSPy 模块包成 FastAPI 服务
from fastapi import FastAPI
app = FastAPI()
# 启动时加载优化好的模块
qa = dspy.ChainOfThought(QuestionAnswer).load("optimized_qa.json")
@app.post("/ask")
def ask(q: str):
return {"answer": qa(question=q).answer}5.2 评估与回归
DSPy 的核心价值是可优化。上线后建议:
- 持续收集 bad case 加入 trainset;
- 每次改 Prompt/换模型前跑 Evaluate 对比;
- 把 metric 数值记录下来,形成回归曲线。
5.3 常见 Signature 模式
- Predict:单步输入输出;
- ChainOfThought:自动加推理过程;
- ReAct:带工具调用;
- ProgramOfThought:让 LLM 写程序再执行。
六、使用方法示例
评估一个模块:
from dspy.evaluate import Evaluate
devset = [dspy.Example(question="...", answer="...").with_inputs("question")]
evaluator = Evaluate(devset=devset, metric=metric, num_threads=4, display_progress=True)
print("准确率:", evaluator(rag))查看 LLM 历史调用(debug Prompt 时非常有用):
lm.inspect_history(n=3) # 打印最近 3 次实际发给模型的完整 Prompt典型任务示例:
- 客服 FAQ:用户问题 → 检索知识库 → 生成答案。
- 论文摘要:输入长文 → 输出 200 字中文摘要。
- 代码审查:输入 diff → 输出风险点与建议。
默认账号密码:DSPy 是纯 Python 库,没有 Web 服务、不需要登录。它通过你配置的 LLM API Key 调用远端模型,账单走对应服务商。
七、常见问题(FAQ)
Q1:DSPy 和 LangChain 是什么关系?
两者都能编排 LLM 应用,但哲学不同:LangChain 是"胶水库",你手写 Prompt、它帮你串链;DSPy 是"编译器",你声明任务、它自动生成并优化 Prompt。复杂、需要反复迭代效果的系统,DSPy 的可维护性更强;快速原型 LangChain 更快。
Q2:优化一次要花多少钱?
MIPROv2 默认会让 LLM 跑几十到几百次试验,用 gpt-4o-mini 通常一次优化几毛到几块人民币;用 gpt-4o 可能几十元。建议先用小模型做优化,再把优化后的 Prompt 套到大模型上。
Q3:必须要有标注数据才能用吗?
不是。没有标注时可以用 BootstrapFewShotWithRandomSearch 这种"自举"优化器,让强模型给弱模型生成 few-shot 示例;纯零样本也能直接跑 Predict,只是效果没优化过的好。
Q4:支持国产模型吗?
支持任何 OpenAI 兼容接口,包括 DeepSeek、Qwen-Max、Moonshot、智谱 GLM。只要设置 api_base 即可。
Q5:优化后的模块怎么部署?
调用 module.save("prod.json") 把 Prompt/权重序列化,线上服务启动时 Module.load("prod.json") 即可。整个模块是纯 Python 对象,可以放进 FastAPI 接口。
Q6:DSPy 学习曲线陡吗?
比手写 Prompt 稍陡,因为要理解 Signature/Module/Optimizer 三个抽象。官方有完整 Colab 教程,2 小时可上手。
Q7:能和 RAG 向量库搭配吗?
原生支持。用 dspy.Retrieve 接 ColBERTv2,或自己包一个 retriever 作为 Module,嵌入到流水线里。