Loading...

文章背景图

DSPy:斯坦福声明式提示编程框架安装与使用指南

2026-10-25
0
- 字
- 分钟
|

DSPy

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,嵌入到流水线里。

八、跳转链接

评论交流

文章目录