桃子桃子快讯
返回首页
工具

DSPy 新增 Flex 模块:让优化器重写代码而非仅改提示

DSPy 推出 Flex 模块,允许 GEPA 等优化器直接重写模块的 Python 代码,在地址消歧任务上将准确率从…

2026.08.25 · 周二5 分钟阅读

DSPy 近日发布新模块 Flex,把「模型写代码」这一能力正式引入到自动优化流程中。与传统 DSPy 优化器只改写提示词不同,Flex 会在保留原有接口的前提下,把模块内部的 Python 代码一并暴露给优化器(如 GEPA),由更强的「反射模型」直接对程序逻辑进行重构、拆分辅助函数、改写路由与提示,目标是让最终程序在用户给定的 metric 上跑出更高分。

核心机制:把代码也变成可优化对象

在 DSPy 中,一个常见的程序写法是:

  • dspy.Predict(my_signature) 定义一个简单的「输入 -> 输出」模块;
  • 通过 GEPA、MIPROv2 等优化器,针对训练集和验证集自动挑选 few-shot 示例或改写指令;
  • 最终得到一个针对特定任务调优过的程序。

Flex 在此基础上做了两件事:

  • 把模块对应的源代码作为可优化对象,连同指令一起交给 GEPA。这意味着反射模型可以新增函数、改写分支逻辑,而不仅限于调整自然语言提示。
  • 在执行层面把生成的代码丢进沙箱解释器运行,避免「模型写的不可信代码」直接落到用户进程里;只有显式声明的 predictor 调用和工具调用能桥接回主进程,并通过 max_predictor_calls 限制单次前向传播的最大调用次数。

优化完成后,程序可以序列化保存为 JSON 文件,可读、可 diff、可版本管理。

基准测试:地址消歧任务

文章以「两个地点描述是否为同一物理地址」的地理空间消歧任务为例,给出一组可直接比较的数字。数据集共 1029 条标注样本,240 条作为留出测试集(类平衡,随机基线 50%),全程关闭缓存以反映真实生产开销。

  • 基线(dspy.Predict,每条记录 1 次模型调用):准确率 90.4%,单千条成本 0.98 美元。
  • 仅优化提示词(GEPA,无 Flex):准确率提升到 92.5%,但提示被显著拉长,每千条成本涨到 2.88 美元,约为基线的 2.9 倍,延迟增加约 48%。
  • Flex + GEPA(提示词和代码同时优化):准确率 95.0%,单千条成本 0.70 美元,相比基线便宜 28%、快 40%;LLM 调用次数减少 75%。

文章给出的解释是:很多「明显是同一地点」或「明显不是」的样本,其实只用规则化代码就能判定,反射模型于是写出了对应的路由逻辑,把这些易例用纯 Python 消化掉,只把真正模糊的样本留给 LLM。

用 metric 引导「少调模型」

Flex 还允许 GEPA 的 metric 看到「这条样本上程序调用了几次 LLM」,并把这个数字写进反馈信号:

  • 作者在 metric 中加入形如 score = max(0, correct − λ × n_llm_calls) 的惩罚项;
  • λ 为 0 时等价于「调用免费」,优化器只追准确率;
  • λ 越大,每次模型调用都需要「赚回」更多准确率才能被接受,优化器被推向用代码消解样本;
  • λ ≥ 1 时单次调用永远无法覆盖自身成本,等价于「永远不调用模型」。

实验在 λ ∈ {0, 0.05, 0.1, 0.2, 0.4} 上做了扫描:推理侧使用 Claude Haiku 4.5(目前最便宜、最弱的 Claude 系列),反射模型使用更强的 Claude Opus 5。结果显示 Flex 路径在不同 λ 下都能在「准确率」和「成本 / 调用次数」之间取得比纯提示优化更好的折中。

实际意义与局限

Flex 的卖点是把代码变成一等公民的可优化对象,从而把 prompt engineering 进一步推向「program engineering」。对于已经使用 DSPy 写 RAG、ReAct 或 RLM 管线的团队而言,这意味着优化器有机会在不改动业务接口的前提下,端到端地压缩延迟与成本。

需要注意的是:

  • 优化阶段仍需调用一个较强的反射模型(示例中为 Opus 5)来写代码,编译成本不低,但只发生一次,可被分摊到推理流量上。
  • 生成的代码默认跑在沙箱中,功能受解释器能力限制,且会被 max_predictor_calls 限流,并非「任意 Python 都能执行」。
  • 优化结果强依赖 metric 的设计,λ 的选择会显著影响「代码消解 / 模型调用」的边界。
信源