mcpField
D
dspy-gepa-optimizer

dspy-gepa-optimizer

github.com/intertwineAgent 工作流278100 次安装7 周前更新
代码仓库

关于 dspy-gepa-optimizer

这是一份面向 DSPy 3.2.x 开发者的 GEPA 程序优化指南,适用于能提供文本反馈指标及独立训练集、验证集的场景,并介绍预算、检查点和结果检查。

主要功能

  1. 01反思式指令与少样本优化
  2. 02帕累托候选选择
  3. 03自动或显式评估预算
  4. 04检查点与运行恢复
  5. 05跟踪候选程序的最佳输出

适用场景

  1. 01用定向反馈改进多预测器程序
  2. 02以轻量预算试运行优化器
  3. 03恢复中断的优化任务
  4. 04检查候选项和最佳验证输出

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/intertwine/dspy-agent-skills --skill dspy-gepa-optimizer

安装后在 Claude Code 中输入/dspy-gepa-optimizer确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

example_bettertogether.py
example_gepa.py
reference.md

详细介绍

DSPy GEPA 优化器(3.2.x)

GEPA(Genetic-Pareto)是一种反思式优化器:它使用能够读取指标文本反馈并提出改进建议的大模型,来变异程序的指令和少样本示例。它会在多个验证任务上维护帕累托前沿,并且是 2026 年复杂 DSPy 工作负载的默认推荐方案。

一些 AI 生成的摘要中出现的扩展名称“Genetic-Evolutionary Prompt Adaptation”是大模型幻觉生成的逆向缩写。论文将 GEPA 定义为 Genetic-Pareto;其中的“Pareto”至关重要(GEPA 会保留候选项前沿,而不是将其收敛为单个候选项)。

前置条件——先完成这些,否则 GEPA 会浪费 rollout

  1. 一个能够端到端运行的 dspy.Module(参见 dspy-fundamentals)。
  2. 一个返回 dspy.Prediction(score=float, feedback=str) 的丰富反馈指标(参见 dspy-evaluation-harness)。有信息量的反馈有助于反思;应在任务上评估优化器的收益,而不要想当然地认为它更优。在 DSPy 3.2.1 中,即使字典包含相同字段,dspy.Evaluate 仍会因此崩溃——请使用 dspy.Prediction。
  3. trainset 和一个单独的 valset。对于 GEPA,应尽可能增加训练示例,并确保验证集规模足以代表下游分布;不要让训练集和验证集复用相同示例。
  4. 一个 reflection_lm——用于生成创意提案的强大大模型(通常与任务大模型相同或更强),并设置为 temperature=1.0。当前 DSPy 文档使用 GPT-5 级别的反思模型,并为其配置较大的输出预算。

标准调用

import dspy

dspy.configure(lm=dspy.LM("openai/gpt-5-mini"))
reflection_lm = dspy.LM("openai/gpt-5", temperature=1.0, max_tokens=32000)

optimizer = dspy.GEPA(
    metric=rich_metric,
    auto="medium",                       # "light" / "medium" / "heavy"
    reflection_lm=reflection_lm,
    reflection_minibatch_size=3,
    candidate_selection_strategy="pareto",  # or "current_best"
    skip_perfect_score=True,
    use_merge=True,
    num_threads=8,
    track_stats=True,
    track_best_outputs=True,             # enables inference-time best-of selection
    log_dir="./gepa_logs",               # resume/checkpoint
    seed=0,
)

optimized = optimizer.compile(
    student=program,
    trainset=trainset,
    valset=valset,
)

# Pareto inspection
pareto = optimized.detailed_results.val_aggregate_scores
print("Pareto frontier:", sorted(pareto, reverse=True)[:5])

optimized.save("optimized_program.json", save_program=False)

导入路径

两种方式均可;新代码请使用顶层导入:

import dspy
dspy.GEPA(...)                              # preferred
# equivalently:
from dspy.teleprompt import GEPA

指标约定(精确说明)

import dspy

def rich_metric(gold, pred, trace=None, pred_name=None, pred_trace=None):
    score = ...      # 0.0..1.0
    feedback = ...   # detailed natural-language critique
    return dspy.Prediction(score=score, feedback=feedback)

请返回 dspy.Prediction,而不是字典。 一些上游 GEPA 文档将 score/feedback 描述为类似字典的结构,但 DSPy 3.2.1 中的 dspy.Evaluate 在指标返回字面字典时仍会崩溃(TypeError: unsupported operand type(s) for +: 'int' and 'dict')。GEPA 在内部使用 dspy.Evaluate 对候选项评分,因此字典返回值也可能导致 GEPA 内部出错,而不仅仅是在你显式调用 Evaluate(...) 时出错。

  • pred_name / pred_trace 会在反思某个模块中的特定预测器时设置——尽可能编写针对单个预测器的反馈(归因)。如果无法定位反馈,请返回程序级反馈,而不是含糊地只给出分数的批评。
  • 反馈质量至关重要:反思大模型会根据具体说明的失败原因以及理想效果采取行动。

预算选项

使用 auto=... 或显式预算,不要同时使用两者。

模式大致 rollout 数适用场景
auto="light"~20–40 次完整评估检查 GEPA 是否能基于你的指标正常工作
auto="medium"~80–150 次完整评估日常优化
auto="heavy"~300–600 次完整评估发布前的最终运行
max_full_evals=N显式指定确定性预算
max_metric_calls=N显式指定对指标调用次数设定硬上限(成本更可预测)

每次“完整评估”约等于 len(valset) 次指标调用。请据此安排成本预算。

构造函数参数(全部参数,DSPy 3.2.x)

dspy.GEPA(
    metric,                                  # required
    auto=None,                               # Literal["light","medium","heavy"] | None
    max_full_evals=None,
    max_metric_calls=None,
    reflection_minibatch_size=3,
    candidate_selection_strategy="pareto",   # or "current_best"
    reflection_lm=None,                      # required in practice
    skip_perfect_score=True,
    add_format_failure_as_feedback=False,
    instruction_proposer=None,               # custom ProposalFn
    component_selector="round_robin",        # or a callable
    use_merge=True,
    max_merge_invocations=5,
    num_threads=None,
    failure_score=0.0,
    perfect_score=1.0,
    log_dir=None,
    track_stats=False,
    use_wandb=False,
    wandb_api_key=None,                      # overrides WANDB_API_KEY env var
    wandb_init_kwargs=None,                  # dict forwarded to wandb.init(...)
    track_best_outputs=False,
    warn_on_score_mismatch=True,
    use_mlflow=False,
    seed=0,
    gepa_kwargs=None,                        # e.g. {"use_cloudpickle": True} for dynamic signatures
)

.compile(student, *, trainset, valset=None, teacher=None)——目前未使用 teacher。

数据集划分建议

DSPy 的通用提示词优化器文档通常建议采用偏重验证集的划分,例如 20% 训练 / 80% 验证,因为小型提示词优化器可能会对很小的训练集过拟合。GEPA 则有所不同:应尽可能扩大训练集,只预留足以代表下游行为的验证示例。帕累托前沿仍需要真正的验证集,但 GEPA 会基于训练示例的轨迹和文本反馈进行学习,因此训练集过小会造成不利影响。

DSPy 3.2.x 中的 BetterTogether

如果你想要多阶段优化器循环,DSPy 3.2.0 的 BetterTogether 现在支持任意命名的优化器,不再局限于旧版固定的 prompt_optimizer / weight_optimizer 组合:

optimizer = dspy.BetterTogether(
    metric=rich_metric,
    bootstrap=dspy.BootstrapFewShotWithRandomSearch(metric=rich_metric),
    gepa=dspy.GEPA(metric=rich_metric, auto="light", reflection_lm=reflection_lm),
)

optimized = optimizer.compile(
    student=program,
    trainset=trainset,
    valset=valset,
    strategy="bootstrap -> gepa",
)

使用 bootstrap=... 和 gepa=... 等命名阶段时,请显式传入 strategy=。DSPy 3.2.0 的默认策略仍是 "p -> w -> p",只有当优化器键恰好是 p 和 w 时才适用。

将纯 GEPA 作为默认的首轮优化器。只有在有特定理由需要串联优化器,并且希望由验证集选出最佳中间程序时,才使用 BetterTogether。

何时 GEPA 优于 MIPROv2

  • 你的指标能够提供具体且有助于改进的批评反馈(这是 GEPA 的强项)。
  • 程序包含多个需要针对性改进的预测器(GEPA 会提供每个预测器的反馈;MIPRO 不会)。
  • 展开预算较小(凭借丰富的反馈,GEPA 收敛更快)。

何时 MIPROv2 优于 GEPA

  • 指标仅返回标量(没有可供反思的信号)——使用 dspy.MIPROv2。
  • 你只想进行纯少样本自举,不修改指令。
  • 训练集非常大(500+),此时对示例进行贝叶斯搜索更有价值。

何时值得尝试 SIMBA

dspy.SIMBA 是一种更轻量的反思式优化器。如果你想要比 GEPA 成本更低的反思式优化,程序比较简单,或者需要在进行完整 GEPA 运行前快速探索,可以试试它。对于重视每个预测器反馈和帕累托候选选择的多预测器程序,仍将 GEPA 作为默认选择。

恢复与检查点

log_dir 会按轮次写入候选程序及其分数。若要恢复中断的运行,将 log_dir 指向同一目录即可——GEPA 会从最近的检查点继续。查看 <log_dir>/candidates/,即可看到所有提议过的程序。

推理时的最佳结果选择:track_best_outputs

设置 track_best_outputs=True 后,GEPA 会针对每项任务,记录所有候选项中表现最佳的预测结果。在留出数据上的推理阶段,你可以集成或从排名靠前的帕累托程序中选择,以提高稳健性。通过 optimized.detailed_results.best_outputs_valset 访问。

反模式

  • 指标只返回浮点数(“分数是 0.7”),不提供反馈——GEPA 会退化为随机搜索。
  • 训练集和验证集相同——帕累托选择会导致过拟合。
  • reflection_lm 使用小模型——它无法提供批评反馈;此角色应使用你能负担得起的最强 LM。
  • 在未经测试的指标上运行 auto="heavy"——结果可能花了钱才发现指标有 bug。先运行 auto="light"。
  • 忽略 log_dir——因连接中断而丢失 4 小时的运行结果,会非常痛苦。

注意:reflection_lm 必须在构造时提供,而非编译时

dspy.GEPA(...) 会在初始化时断言 reflection_lm is not None(或存在自定义的 instruction_proposer)——你不能将其延后到 .compile() 时再提供。如果你看到

AssertionError: GEPA requires a reflection language model...

请在构造函数中添加 reflection_lm=dspy.LM("openai/gpt-5", temperature=1.0, max_tokens=32000),或替换为你的服务提供商所提供的最强指令遵循模型。dspy.LM(...) 是一个轻量的存根,只有实际调用时才会运行,因此创建实例不会访问网络。

后续步骤

评论

支持 Markdown