DSPy 教程:用评估驱动提示词优化,读懂签名、模块与优化器
DSPy 值不值得用,关键在于任务能否评估。本文梳理签名、模块与优化器,给出可直接运行的 Python 示例,并用工单分流说明训练、验证和最终测试如何划分、调用次数与模型费用如何估算。读懂 DSPy 提示词优化的边界,比较手写提示词与微调,再判断团队是否具备样例、评分规则和维护能力,适合从哪里开始试验。
发布于

如果一项 AI 任务需要反复执行,结果可以评分,而手工调整提示词已经成了持续的维护负担,就值得试试 DSPy。它把这项工作转成 Python 程序和优化循环。下文设计的小规模首次实验,预算最多为 100 次单步骤程序执行,重试另计。如果业务团队还无法就什么是正确答案达成共识,应先解决这个问题,再引入 DSPy。
本文于 2026 年 10 月 15 日 依据 DSPy 当前文档、PyPI 和 Google 模型价格核验。PyPI 列出的版本为 DSPy 3.4.1,发布于 2026 年 10 月 12 日,要求 Python 不低于 3.10、低于 3.16。安装包名为 dspy。PyPI 包元数据。
DSPy 是什么?compile 到底在做什么?
DSPy 是一个开源 Python 框架,用于把语言模型任务定义成程序,再优化程序中的提示词;使用特定优化器时,也可以调整模型权重。它真正有价值的地方,是围绕你定义的成功标准,建立可重复的改进流程。它并不保证第一次生成的提示词就能胜过精心编写的版本。DSPy 概览。
可以把这个过程想成排练:签名交代任务要求,模块决定如何表演,评估指标则是评分规则。优化器尝试改动,观察结果,再保留有效的调整。如果没有评分规则,即使换着方式排练,也无法判断是否真的有所进步。
签名:把任务说清楚
签名(signature) 声明输入、输出和任务指令。"ticket -> category" 表示输入一条工单,输出一个类别。用类定义签名时,还可以为字段指定类型,并通过文档字符串说明任务。不过,字段如何设计仍然关键:如果业务对“紧急”的定义含糊不清,优化器也无能为力。签名文档。
DSPy 模块:决定任务怎么执行
模块(module) 实现完成任务的具体策略。dspy.Predict 是基础预测组件;dspy.ChainOfThought 在答案前增加一个推理字段;dspy.ReAct 支持推理与工具调用的循环。如果单次模型调用无法完成任务,可以在 Python 中组合多个模块。模块文档。
做客服工单分流时,先从 Predict 开始。只是给一条短消息分类,就加入工具调用循环,会在需求尚未得到验证之前增加系统复杂度。
编译:实际执行的是优化流程
优化器(optimizer) 借助样例和评估指标,调整程序中的指定部分。用于提示词优化时,.compile() 返回的程序包含修改后的指令或示范样例,也就是放进提示词里的例子。它不会把应用变成本地可执行文件,也不会让后续模型调用消失。若要训练模型权重,需要另选相应的优化器。优化器选择指南。
DSPy 教程:从当前文档的最小示例入手
当前入门程序的任务是生成一首俳句。这个小例子足以展示接口的用法,不涉及数据库、工具或优化搜索。
在 Python 环境中安装已核验的版本:
python -m pip install 'dspy[litellm]==3.4.1'在环境变量 GEMINI_API_KEY 中设置有效的 Google Gemini API 密钥。将以下代码保存为 first_dspy.py,再运行 python first_dspy.py:
import os
import dspy
lm = dspy.LM(
"gemini/gemini-2.5-flash-lite",
api_key=os.environ["GEMINI_API_KEY"],
engine="litellm",
)
dspy.configure(lm=lm)
haiku_signature = "subject -> haiku"
haiku_generator = dspy.Predict(haiku_signature)
result = haiku_generator(subject="computer science")
print(result.haiku)最后四行来自当前文档的首个程序。初始化部分遵循 DSPy 的模型配置方式,但将模型换成了 Google Gemini 2.5 Flash-Lite,让下文实验统一使用一个成本较低的模型。模型提供方字符串采用 LiteLLM 的 Gemini 接入格式;DSPy LM API 支持在这里显式指定后端。
DSPy 根据签名构建提示词,将其发送给已配置的模型,再解析返回的 haiku 字段。这只是推理示例,并未运行优化流程,也不承诺会生成某首特定的诗,或带来质量提升。
用 DSPy 做提示词优化,先定义评估指标
没有评估指标,就谈不上有意义的优化。 评估指标是把预测结果转成分数的函数。对于工单分流,可以将预测类别与人工确认的标签比较;对于生成式回答,判断正确性可能需要评分标准或可执行的检查逻辑。DSPy 的评估指标接口接收你提供的评分函数,但不会替业务决定应该奖励什么结果。评估指标与评测。
这也是为什么需要一套规模不大、但有标注的评测集。如果你已经厌倦了把“简洁一点”改成“简短作答”,不如收集真实的失败案例:退款申请被分到了技术支持,登录问题被误判成账单问题,或一条消息同时提出了两个请求。在查看新提示词的输出之前,先标注好预期结果。
首次试点可以使用 60 个不同的样例,明确拆成 训练集 20 个、验证集 20 个、最终测试集 20 个样例。这只是本文建议的实验规模,既不是 DSPy 的要求,也不能据此证明系统已经具备生产环境所需的可靠性。
- 训练样例 为优化器提供可学习的材料。
- 验证样例 用于比较版本,并辅助开发决策。
- 最终测试样例 在候选程序和评测规则确定之前保持封存。
同一客户或同一事件的相关工单应归入同一个数据子集。否则,近乎重复的样例可能让优化后的提示词显得比实际更有泛化能力。也要纳入那些少见却重要的失败案例,别让每个子集都只剩下简单题。

“没有指标就无法优化”也需要说得更准确一些。未优化的 DSPy 程序可以不带评估指标运行,LabeledFewShot 也能直接附加样例,无须为其评分。但这只是配置变化,不能证明任务效果有所改善。每项任务也不一定都要有人工编写的参考答案:可执行的正确性检查同样能提供优化信号。对于业务分类任务,经过确认的标签通常是最清晰的起点。少样本基线。
DSPy 优化器怎么选?先认清当前文档中的名称
从能解决已知问题的最简单优化器开始。只有评估指标能区分候选程序的好坏,扩大搜索范围才有意义。
当前的优化器 API 索引列出了以下条目:BetterTogether、BootstrapFewShot、BootstrapFewShotWithRandomSearch、BootstrapFinetune、BootstrapRS、COPRO、Ensemble、GEPA、InferRules、KNN、KNNFewShot、LabeledFewShot、MIPROv2 和 SIMBA。
这些条目并不全是独立的搜索算法。BootstrapRS 是 BootstrapFewShotWithRandomSearch 的别名;KNN 则是 KNNFewShot 使用的检索辅助组件。当前选择指南还介绍了适用于智能体类程序的 AvatarOptimizer,但它并未出现在该 API 索引中。优化器家族详解、选择指南。
MIPROv2 提出候选指令,再用贝叶斯优化探索指令与示范样例的组合;这种搜索方法会参考先前获得的分数。SIMBA 则按小批次处理样例,并提出规则或示范样例。它们采用的是不同方法,并非给 BootstrapFewShot 换了个名字。MIPROv2 API、SIMBA API。
GEPA 使用反思模型读取执行反馈,并提出指令修改方案。比起只有一个失败分数,分数再加上具体解释更有价值,例如:“退款申请即使提到了功能故障,也应归入账单类。”详细文档允许只返回数值的评估指标,但也说明这样会失去更丰富的反馈。GEPA 工作机制。
首次优化实验,先把规模限定好
与开放式指令搜索相比,小规模 BootstrapFewShot 实验更容易核算开销。下面的方案只使用一个 Predict 模块,以确定性的标签匹配作为评估指标,并让同一个模型承担教师和预测角色。
DSPy BootstrapFewShot:从小规模实验开始
准备 train.jsonl、validation.jsonl 和 test.jsonl,每个文件包含 20 条不同的、经过人工标注的工单。每行都是一个 JSON 对象,包含 text 和 label 字段;标签只能是 billing、technical、account 和 other。例如,要求更改发票地址的工单可以标为 billing。这里必须使用你自己的样例,不能拿前面的俳句输出充数。
将下面这个独立脚本保存为 optimize_tickets.py,设置好同一个 API 密钥后运行:
import json
import os
from typing import Literal
import dspy
lm = dspy.LM(
"gemini/gemini-2.5-flash-lite",
api_key=os.environ["GEMINI_API_KEY"],
engine="litellm",
cache=False,
)
dspy.configure(lm=lm)
class RouteTicket(dspy.Signature):
"""Choose the support queue responsible for the ticket's main request."""
text: str = dspy.InputField()
label: Literal["billing", "technical", "account", "other"] = (
dspy.OutputField()
)
def load_examples(path):
with open(path, encoding="utf-8") as source:
rows = [json.loads(line) for line in source if line.strip()]
assert len(rows) == 20
return [dspy.Example(**row).with_inputs("text") for row in rows]
train = load_examples("train.jsonl")
validation = load_examples("validation.jsonl")
test = load_examples("test.jsonl")
assert len({e.text for e in train + validation + test}) == 60
def correct_label(example, prediction, trace=None):
return prediction.label == example.label
program = dspy.Predict(RouteTicket)
evaluate = dspy.Evaluate(
devset=validation, metric=correct_label, num_threads=1
)
print("Baseline validation:", evaluate(program).score)
optimizer = dspy.BootstrapFewShot(
metric=correct_label,
max_bootstrapped_demos=4,
max_labeled_demos=0,
max_rounds=1,
)
optimized = optimizer.compile(program, trainset=train)
print("Optimized validation:", evaluate(optimized).score)
# Freeze this candidate before opening the final test results.
final_test = dspy.Evaluate(
devset=test, metric=correct_label, num_threads=1
)
print("Baseline final test:", final_test(program).score)
print("Optimized final test:", final_test(optimized).score)
optimized.save("candidate_ticket_router.json")这段代码依据文档中的 BootstrapFewShot 构造函数和评测接口改编,不代表任何实测基准结果。它最多收集四个成功的示范样例,每个训练样例允许进行一次自举尝试,并且不直接添加原始标注样例作为示范。保存的文件只是待审核的候选程序,不会自动进入生产环境。
这个方案的执行次数如下:
- 在验证集上评测基线:20 次程序执行。
- 对训练集进行自举:最多 20 次教师程序执行;如果提前收集到足够的合格示范样例,次数还会更少。
- 在验证集上评测优化后的程序:20 次程序执行。
- 在最终测试集上评测两个版本:40 次程序执行。
合计 最多 100 次单步骤执行,其中包含评测;单独编译最多占 20 次。如果每次程序执行只发出一次成功的模型请求,没有重试,也没有解析失败后的回退调用,那么最多就是 100 次任务模型调用。前面的俳句运行检查另计。引入 LLM 裁判、智能体循环、重试,或再做一轮优化,都会改变总量。

按 Google 对 Gemini 2.5 Flash-Lite 的 Standard 付费文本公开标价计算,输入为每百万 token $0.10,输出为每百万 token $0.40。假设 100 次调用平均每次使用 1,000 个输入 token 和 100 个输出 token,费用为 $0.014:100,000 ÷ 1,000,000 × $0.10 + 10,000 ÷ 1,000,000 × $0.40。 Google 价格页。
这只是模型费用的算术估算,既不是实测账单,也不是支出上限。输入量假设必须包含 DSPy 的格式化内容和附加的示范样例;工单更长、输出更多,或产生计费的思考 token,都会增加费用。估算没有计入批处理或缓存折扣。最终应以模型服务商记录的实际用量为准。
DSPy 框架、手写提示词和微调,该怎么选?
如果需要用可重复的方法改进一个可衡量的程序,可以使用 DSPy。如果手写提示词已经满足任务要求,就继续使用。如果已有证据表明调整提示词不够用,并且模型训练符合部署约束,再考虑微调。
这些方法可以配合使用。DSPy 提供 BootstrapFinetune,BetterTogether 则能组合提示词优化与权重优化。实际区别在于需要改动和维护什么,而不在于哪个名称听起来更先进。提示词与权重优化。
何时值得切换,取决于日常维护负担:如果每次更换模型或出现新的失败案例,工程师都得回头手工修改好几个提示词,带评分的优化循环就有了吸引力。如果一个简短提示词已经通过验收标准,就还没有证据表明换成框架会带来收益。
谁适合马上尝试,谁应该等待或跳过?
对于工程师,适合动手的前提是:有重复执行的任务、可运行的基线,以及有代表性的失败案例。 工单分流和结构化信息提取都是合适的起点,因为预期输出便于检查。先优化一个小组件,再扩展系统。DSPy 的能力边界在于目标定义的质量:即便评估指标奖励的是错误行为,它仍然可能据此选出分数更高的候选程序。
业务运营人员应负责标签定义和错误优先级。 客服主管可能认为,把账户无法登录的事件分错队列,远比误分一条普通账单咨询严重。如果评分对两种错误一视同仁,优化方向就可能偏离主管的优先级。先明确这项业务规则,再让工程师提高分数。
采购决策者应要求提供未见样例上的证据。 要问清楚:比较的是哪个基线,哪些案例退步了,当前上线运行的程序包含哪些环节,以及流程是否仍满足延迟要求。优化器的名称本身不能作为验收依据。如果团队正在组织评测工作,可以延伸阅读本站的 Promptfoo 评测。
如果只是偶尔写文案、做一次性研究,或流程变化太快、来不及积累样例,业务团队就不必使用 DSPy。 如果无人维护 Python 代码,或无法就评分规则达成共识,也应跳过。一个好用的提示词、一份检查清单,再配合人工审核,可能才是投入与需求更匹配的方案。如果真正缺的是源数据,或业务流程尚未定义清楚,就先等等;优化措辞无法补上这两者。
DSPy 有哪些被夸大的说法?
“用编程代替提示词”并不意味着提示词消失了。DSPy 负责生成和管理提示词,人仍然要定义任务、分析失败,并决定结果是否可接受。
“编译”不意味着模型永久学会了什么。对于提示词优化器,学到并保存下来的内容是指令或示范样例。推理时仍然要调用模型,示范样例也会占用提示词空间。学习得到的状态可以保存为 JSON,再加载到一个新程序中。保存与加载。
“自动优化”也不意味着效果必然更好。真正有意义的比较,是在未见过的输入上与现有方案对照。开发阶段分数更高,可能只是过拟合、裁判标准太宽松,或数据集漏掉了代价高昂的失败场景。
还要注意,评估指标调用次数不等于模型服务商 API 调用次数。GEPA 的 max_metric_calls 限制的是评分函数调用次数;反思过程也会调用模型,而一次被评分的程序执行本身就可能发起多次请求。它的 auto 设置并不对应一个通用的账单金额。GEPA 预算控制。
工程师常问的 DSPy 问题
DSPy 的工作原理是什么?
先用签名声明输入和输出,选择或组合模块,再配置语言模型。适配器负责构建消息并解析结果。在此基础上,优化器可以结合样例和评估指标,改进程序中的指定部分。
DSPy 可以用于生产环境吗?
是否具备生产可用性,要看你自己的程序。固定包版本和模型配置,保留基线,测试有代表性的失败案例,并明确回滚条件。有一个当前发布版本,并不等于你的工作流已经通过验证。
现在还有必要使用 DSPy 吗?
有,前提是语言模型任务需要反复执行、效果可以衡量,而且提示词存在持续维护需求。如果简单提示词已能满足需要,或任务缺乏稳定的评测规则,DSPy 的价值就会小得多。
LangChain 和 DSPy 的主要区别是什么?
LangChain 是构建智能体的框架,提供模型和工具集成。DSPy 的侧重点是声明模型任务,再围绕评估指标优化程序。选择取决于要解决的问题:是把智能体的各个组件连接起来,还是系统性地改进一个可评分的任务。LangChain 概览。
DSPy 能用来优化提示词吗?
能。根据所选优化器,它可以筛选示范样例、修改指令,或同时搜索两者的组合。提示词优化不会改变底层模型权重;微调是另一条路径。
DSPy 是谁开发的?
DSPy 由 Omar Khattab 及其合作者开发。代码仓库归属 Stanford NLP 并在其名下维护;软件包的研究文献引用中列出了参与作者。项目与作者。
DSPy 的 GEPA 如何工作?
GEPA 把程序执行反馈交给反思模型,由它提出指令修改方案,再评估候选程序并返回选中的版本。具体的失败反馈能为搜索提供比单独分数更充分的依据,但这并不保证质量一定提升。
DSPy 框架的全称是什么?
根据官方软件包说明,DSPy 是 Declarative Self-improving Python 的缩写。
下一步怎么做?
周一,选一个反复出现的工单分流或信息提取错误,请流程负责人标注有代表性的样例。固定基线,定义评分规则,再运行一轮规模受控的实验。批准候选程序前,先检查哪些答案发生了变化。如果还无法定义分数,眼下最有价值的工作就是先把业务规则谈清楚。
- 发布日期
- 分类
- Build
- 语言








