基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
  • 知识卡片碎片时间过考点
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
    • AI 热点每日 AI 资讯与动向
AI 工作台
简历
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-11-05 12:02

用 DSPy 将提示词调优变成可评测流程

dev.to · AI#提示词优化#模型评测#开源
Editor brief · 编辑速览

DSPy 通过类型化输入输出定义任务,用模块选择直接调用、推理或工具执行策略,再依据样例与评分函数优化提示词。文章介绍三类核心组件,帮助将人工试改提示词转为可测试的代码流程。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

改一版提示词,挑几条输出看看,感觉不错就上线。等模型更新、边界案例出现,再重新调。DSPy 想把这套循环变成可评估的程序:开发者定义任务、运行策略和评分标准,优化器负责寻找更合适的指令与示例。

这篇文章值得读的地方,是把「提示词改得好不好」变成了工程问题。不过,文中的代码是入门示例,模型迁移流程也不是基准测试。真正需要学走的,是如何组织任务、评估和发布门槛。

不手写长提示词,任务要怎么表达

DSPy 是 Stanford NLP 的开源 Python 框架,采用 MIT 许可证。按原文提供的信息,DSPy 3.4.1 于 2026 年 10 月发布,需要 Python 3.10 或更新版本,安装命令是 pip install dspy。

它把 LLM 程序拆成三部分。

Signature 声明输入和输出,相当于给模型任务写接口契约。它支持 Literal、Optional、列表,甚至 dspy.Image。Module 决定执行策略:dspy.Predict 直接调用,dspy.ChainOfThought 增加逐步推理,dspy.ReAct 加入工具与推理循环。Optimizer 则根据样本和评分函数,调整指令或少样本示例。

下面的工单分类器,展示了任务契约如何落到代码里:

from typing import Literal
import dspy

class TriageTicket(dspy.Signature):
    """Classify a customer support ticket for routing."""

    ticket: str = dspy.InputField()
    category: Literal["billing", "bug", "account", "feature_request"] = dspy.OutputField()
    urgency: Literal["low", "medium", "high"] = dspy.OutputField()

triage = dspy.ChainOfThought(TriageTicket)

pred = triage(ticket="I was charged twice for my subscription this month.")
print(pred.category, pred.urgency)   # 例如 billing high
print(pred.reasoning)                # ChainOfThought 增加 reasoning 字段

要留意 Literal 那两行:类别和紧急程度都有明确候选值,模型与解析器据此处理输出。但字段声明不能保证业务判断正确,仍然需要评估。

所谓「没有提示词」,也不能理解成指令消失了。类的 docstring 会成为指令,字段名和类型会参与输出格式定义。快速实验还可以写 dspy.Predict("question -> answer")。运行 dspy.inspect_history(n=1),就能看到完整消息和原始响应。

模型通过 provider/model 标识,例如 openai/gpt-5-nano。原文列出的路由包括 Anthropic 的 anthropic/...、Google AI Studio 的 gemini/...、Azure OpenAI、Vertex AI,以及本地 Ollama 的 ollama_chat/llama3.2:1b。OpenAI-compatible 服务可以通过 api_base 和 api_key 接入。

dspy.configure(lm=lm) 设置进程默认模型;局部切换使用 with dspy.context(lm=other_lm):。任务定义与模型选择分开,后续才容易比较不同模型。

优化器能调提示词,但谁来定义「更好」

评分函数才是优化器真正执行的需求。

原文建议从历史工单取 50-200 条标注数据。用 dspy.Example(...).with_inputs("ticket") 指定输入字段,category 和 urgency 留作评分标签。

示例评分很直接:类别、紧急程度各占一半,两项都对得 1.0,只对一项得 0.5。生成示范时,如果 trace is not None,则只接受两项都正确的结果。dspy.Evaluate 使用 num_threads=4、display_progress=True 执行评估,返回的 .score 是百分数。

文中的 50.0 只是示意输出,没有证据表明它是作者实测的基线。

BootstrapFewShot 会运行训练样本,保留评分通过的执行轨迹,再把它们放进提示词作为示范。示例设置 max_bootstrapped_demos=4、max_labeled_demos=4。包内还提供 MIPROv2 和 GEPA。

GEPA 更进一步:评分函数不仅返回分数,还能说明错在哪里,让反思模型据此改写指令。下面这段代码展示了这条反馈链:

def triage_feedback(example, pred, trace=None, pred_name=None, pred_trace=None):
    problems = []
    if example.category != pred.category:
        problems.append(f"category should be {example.category}, got {pred.category}")
    if example.urgency != pred.urgency:
        problems.append(f"urgency should be {example.urgency}, got {pred.urgency}")
    score = 1.0 - len(problems) / 2
    return dspy.Prediction(score=score, feedback="; ".join(problems) or None)

gepa = dspy.GEPA(
    metric=triage_feedback,
    reflection_lm=dspy.LM("openai/gpt-5.4"),  # 用更强的模型编写指令
    auto="light",                              # 预算可选 "light"、"medium"、"heavy"
    num_threads=2,
)
optimized = gepa.compile(triage, trainset=trainset, valset=devset)

要注意最后一行:trainset 为反思更新提供材料,valset 用于选择最终候选程序。两者之外,还要保留独立测试集。

这里也有业务前提。类别与紧急程度各占一半,是示例作者的选择。假如漏掉高紧急度工单的代价远高于普通分类错误,这个评分就没有完整表达需求。优化器可能提高平均分,却仍然放过最昂贵的错误。

换便宜模型之前,先把发布条件写下来

原文给出的迁移流程很实用:固定 TriageTicket,导出 200 条已解决工单,按最终类别和紧急程度标注,再拆成训练、验证和独立测试集。

先测大模型与小模型的基线,再让小模型执行任务、大模型担任 reflection_lm,通过 GEPA 优化。只有小模型最终测试分数至少达到大模型基线,才发布 triage_small_v1.json。

作者明确说了,这是示例工作流,不是基准测试。

文中引用 DSPy 文档的生产案例:Shopify 把单提示词 GPT-5 任务迁移到经 GEPA 优化的小型 Qwen 模型,报告成本约降至原来的 1/75,可靠性约为原来的 2 倍;Dropbox 则报告通过优化器迁移到更小模型,并让程序准确率翻倍。原文没有交代完整数据集、指标口径和对照配置,不能据此推算普通团队的收益。

优化结果通过 optimized.save("triage_v1.json") 保存,服务端重新创建模块,再用 triage.load("triage_v1.json") 加载。JSON 包含指令、示范以及保存时的 DSPy、Python 版本,适合随代码提交并审查差异。

运行细节同样会影响判断。DSPy 默认启用内存和磁盘缓存,重复输入可能直接拿到旧答案。测试采样时,可以用 dspy.LM(..., cache=False),或调用 dspy.configure_cache(enable_disk_cache=False, enable_memory_cache=False)。

优化过程会多次调用模型,建议从 auto="light" 开始,让 num_threads 适配服务商限流,并通过 dspy.configure(lm=lm, track_usage=True) 查看每次预测的 token 用量。编译后还应运行 dspy.inspect_history(),或打开 JSON 检查指令是否夹带数据、编码了不希望出现的偏差。

原文列出 3.3.0、3.4.0、3.4.1 分别在 2026 年 8、9、10 月发布,提醒生产环境固定 dspy== 的具体版本,升级前查看迁移说明。

我的判断

我认可它把注意力从措辞转向评估。对工单分类这类输入、输出和标签比较明确的任务,这比挑几条结果凭感觉判断更容易复查,也更方便比较模型。

但原文没有给出作者自己的完整实验,也没有证明 DSPy 一定优于「手写提示词加评估脚本」。如果任务简单、示例少、提示词很短,后者可能已经够用。DSPy 的吸引力在于把任务声明、执行策略、优化和状态保存组织成一套流程,代价是引入框架与优化调用成本。

数据划分也不能只做表面功夫。入门代码直接按顺序切半,没有讨论重复工单、时间分布和类别不均衡。评估集如果不能代表真实流量,分数再精确也可能误导决策。

还有一个容易忽略的细节:示例流程先用测试集比较两个模型,再做最终验收。如果团队反复根据测试结果修改方案,这个测试集也会逐渐参与决策。应给最终验收保留边界,避免把同一批样本磨成另一套训练材料。

能拿来做什么

  • 给已有的工单分类功能补一份人工确认的评估集,先明确类别错误和紧急程度错误各自的代价,再决定评分方式。
  • 在 Node API 或前端管理后台接入分类能力时,可以把 DSPy 放在 Python 服务中负责分类,接口只返回业务所需字段;先验证接入收益,再增加部署复杂度。
  • 准备更换模型时,固定任务和发布门槛,分别记录测试分数、调用成本与延迟。优化器运行成功,不等于新模型已经满足上线条件。
  • 把优化后的 JSON 纳入版本管理,审查指令和示范的变化,同时固定 DSPy 版本;重新评估模型时,检查缓存是否影响了观察结果。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
MCP 工具调用需要逐次授权
下一篇
排查 Claude Code 不遵守项目指令

资讯速览

dev.to · AI · 2026-11-05 12:02

AI 评分 8.0 / 10

相关标签

#提示词优化#模型评测#开源

继续阅读

  • Claude Code 默认自动审批如何配置
  • MCP 工具调用需要逐次授权
  • 排查 Claude Code 不遵守项目指令
  • Postman被指静默植入编程助手插件
  • OpenAI 披露内核漏洞自动发现与修补流程