dspy.GEPA: 反射式提示优化器
GEPA (Genetic-Pareto) 是一种反射式优化器,在《GEPA: Reflective Prompt Evolution Can Outperform Reinforcement Learning》(Agrawal等人, 2025, arxiv:2507.19457)中被提出,它能自适应地进化任意系统的文本组件(例如提示)。除了指标返回的标量分数外,用户还可以向GEPA提供文本反馈以指导优化过程。这种文本反馈使GEPA更清楚地了解系统获得该分数的原因,然后GEPA可以通过自省来识别如何提高分数。这使得GEPA能够在极少的尝试中提出高性能的提示。
dspy.GEPA(metric: GEPAFeedbackMetric, *, auto: Literal['light', 'medium', 'heavy'] | None = None, max_full_evals: int | None = None, max_metric_calls: int | None = None, reflection_minibatch_size: int = 3, candidate_selection_strategy: Literal['pareto', 'current_best'] = 'pareto', reflection_lm: LM | None = None, skip_perfect_score: bool = True, add_format_failure_as_feedback: bool = False, use_merge: bool = True, max_merge_invocations: int | None = 5, num_threads: int | None = None, failure_score: float = 0.0, perfect_score: float = 1.0, log_dir: str = None, track_stats: bool = False, use_wandb: bool = False, wandb_api_key: str | None = None, wandb_init_kwargs: dict[str, Any] | None = None, track_best_outputs: bool = False, seed: int | None = 0)
基类: Teleprompter
GEPA是一种进化优化器,它使用反思来进化复杂系统的文本组件。GEPA在论文GEPA: Reflective Prompt Evolution Can Outperform Reinforcement Learning中被提出。
GEPA优化引擎由gepa包提供,可从https://github.com/gepa-ai/gepa获取。
GEPA捕获DSPy模块执行的完整轨迹,识别轨迹中与特定预测器对应的部分,并反思预测器的行为,为预测器提出新的指令。GEPA允许用户向优化器提供文本反馈,用于指导预测器的演化。文本反馈可以在单个预测器的粒度上提供,也可以在系统整体执行的层面上提供。
为向GEPA优化器提供反馈,按如下方式实现一个度量函数:
def metric(
gold: Example,
pred: Prediction,
trace: Optional[DSPyTrace] = None,
pred_name: Optional[str] = None,
pred_trace: Optional[DSPyTrace] = None,
) -> float | ScoreWithFeedback:
"""
此函数被调用时包含以下参数:
- gold: 黄金示例。
- pred: 预测输出。
- trace: 可选。程序执行的追踪记录。
- pred_name: 可选。当前正在由GEPA优化的目标预测器名称,针对该预测器请求反馈。
- pred_trace: 可选。GEPA寻求反馈的目标预测器执行追踪记录。
注意`pred_name`和`pred_trace`参数。在优化过程中,GEPA将调用此度量函数以获取
正在优化的各个预测器的反馈。GEPA在`pred_name`中提供预测器名称,
并在`pred_trace`中提供与预测器对应的(追踪记录的)子追踪。
如果在预测器级别可用,度量函数应返回与预测器对应的{'score': float, 'feedback': str}。
如果在预测器级别不可用,度量函数也可以在程序级别返回文本反馈
(仅使用gold、pred和trace)。
如果未返回反馈,GEPA将使用仅包含分数的简单文本反馈:
f"该轨迹获得分数{score}。"
"""
...
GEPA 也可以用作批量推理时搜索策略,通过传递 valset=trainset, track_stats=True, track_best_outputs=True,并使用优化程序的 detailed_results 属性(由 compile 返回)来获取批次的帕累托前沿。optimized_program.detailed_results.best_outputs_valset 将包含批次中每个任务的最佳输出。
示例:
gepa = GEPA(metric=metric, track_stats=True)
batch_of_tasks = [dspy.Example(...) for task in tasks]
new_prog = gepa.compile(student, trainset=trainset, valset=batch_of_tasks)
pareto_frontier = new_prog.detailed_results.val_aggregate_scores
# pareto_frontier 是一个分数列表,每个任务对应一个分数。
参数:
| 名称 | 类型 | 描述 | 默认值 |
|---|---|---|---|
metric
|
GEPAFeedbackMetric
|
用于反馈和评估的指标函数。 |
必填 |
auto
|
Literal['light', 'medium', 'heavy'] | None
|
运行使用的自动预算。选项:"light", "medium", "heavy"。 |
None
|
max_full_evals
|
int | None
|
执行完整评估的最大次数。 |
None
|
max_metric_calls
|
int | None
|
执行的最大指标调用次数。 |
None
|
reflection_minibatch_size
|
int
|
在单个GEPA步骤中用于反思的示例数量。默认为3。 |
3
|
candidate_selection_strategy
|
Literal['pareto', 'current_best']
|
用于候选选择的策略。默认为"pareto",即从所有验证分数的帕累托前沿中随机选择候选。选项:"pareto", "current_best"。 |
'pareto'
|
reflection_lm
|
LM | None
|
用于反思的语言模型。必需参数。GEPA 受益于强大的反思模型。考虑使用 |
None
|
skip_perfect_score
|
bool
|
是否在反思过程中跳过得分完美的示例。默认为True。 |
True
|
add_format_failure_as_feedback
|
bool
|
是否将格式失败添加为反馈。默认为False。 |
False
|
use_merge
|
bool
|
是否使用基于合并的优化。默认值为 True。 |
True
|
max_merge_invocations
|
int | None
|
最大合并调用次数。默认值为5。 |
5
|
num_threads
|
int | None
|
用于使用 |
None
|
failure_score
|
float
|
分配给失败示例的分数。默认值为0.0。 |
0.0
|
perfect_score
|
float
|
该指标可达到的最高分数。默认值为1.0。被GEPA用于判断小批次中的所有示例是否完美。 |
1.0
|
log_dir
|
str
|
保存日志的目录。GEPA会将详细的日志以及所有候选程序保存在此目录中。使用相同的 |
None
|
track_stats
|
bool
|
是否在优化程序的 |
False
|
use_wandb
|
bool
|
是否使用wandb进行日志记录。默认为False。 |
False
|
wandb_api_key
|
str | None
|
用于wandb的API密钥。如果未提供,wandb将使用环境变量 |
None
|
wandb_init_kwargs
|
dict[str, Any] | None
|
传递给 |
None
|
track_best_outputs
|
bool
|
是否在验证集上追踪最佳输出。如果track_best_outputs为True,则track_stats必须为True。优化后的程序的 |
False
|
seed
|
int | None
|
用于复现的随机种子。默认值为0。 |
0
|
注意
预算配置:必须提供auto、max_full_evals或max_metric_calls中的其中一个。
auto参数提供预设配置:"light"用于快速实验,"medium"用于平衡优化,"heavy"用于全面优化。
反射配置:reflection_lm参数是必需的,并且应该是一个强大的语言模型。
GEPA在使用如dspy.LM(model='gpt-5', temperature=1.0, max_tokens=32000)等模型时表现最佳。
反射过程会分析失败的示例,以生成用于程序改进的反馈。
合并配置:GEPA 可以使用 use_merge=True 合并成功的程序变体。
max_merge_invocations 参数控制在优化过程中进行多少次合并尝试。
评估配置:使用 num_threads 并行化评估。failure_score 和
perfect_score 参数帮助GEPA理解你的指标范围并相应优化。
日志配置:设置 log_dir 以保存详细日志并启用检查点恢复。
使用 track_stats=True 通过 detailed_results 属性访问详细优化结果。
启用 use_wandb=True 进行实验跟踪和可视化。
可重现性:设置 seed 以确保在相同配置下多次运行获得一致结果。
Source code in dspy/teleprompt/gepa/gepa.py
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 | |
函数
compile(student: Module, *, trainset: list[Example, teacher: Module | None = None, valset: list[Example] | None = None) -> Module
GEPA 使用训练集对提示进行反射性更新,但使用验证集来跟踪帕累托分数。 如果未提供验证集,GEPA 将同时使用训练集。
参数: - student: 要优化的学生模块。 - trainset: 用于反射更新的训练集。 - valset: 用于追踪帕累托分数的验证集。如果未提供,GEPA将使用训练集同时用于两者。
Source code in dspy/teleprompt/gepa/gepa.py
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 | |
:::
GEPA 背后的关键洞察之一是它能够利用领域特定的文本反馈。用户应提供一个反馈函数作为 GEPA 指标,该函数具有以下调用签名:
dspy.teleprompt.gepa.gepa.GEPAFeedbackMetric
基类: Protocol
函数
__call__(gold: Example, pred: Prediction, trace: Optional[DSPyTrace], pred_name: str | None, pred_trace: Optional[DSPyTrace]) -> Union[float, ScoreWithFeedback]
该函数调用时使用以下参数: - gold: 黄金示例。 - pred: 预测输出。 - trace: 可选。程序执行的追踪记录。 - pred_name: 可选。当前由GEPA优化的目标预测器名称,正为其请求反馈。 - pred_trace: 可选。GEPA寻求反馈的目标预测器执行追踪记录。
注意pred_name和pred_trace参数。在优化过程中,GEPA会调用评估指标来获取正在优化的各个预测器的反馈。GEPA在pred_name中提供预测器的名称,并在pred_trace中提供与该预测器对应的(追踪记录的)子追踪记录。
如果在预测器级别可用,评估指标应返回与预测器对应的dspy.Prediction(score: float, feedback: str)。
如果在预测器级别不可用,评估指标也可以在程序级别返回文本反馈(仅使用gold、pred和trace)。
如果没有返回反馈,GEPA将使用一个简单的文本反馈,仅包含分数:f"该轨迹获得了{score}分。"
Source code in dspy/teleprompt/gepa/gepa.py
:::
当 track_stats=True 时,GEPA 会返回所有候选方案的详细结果,以及优化运行的元数据。这些结果可在 GEPA 返回的优化程序的 detailed_results 属性中找到,并具有以下类型:
dspy.teleprompt.gepa.gepa.DspyGEPAResult(candidates: list[Module], parents: list[list[int | None]], val_aggregate_scores: list[float], val_subscores: list[list[float]], per_val_instance_best_candidates: list[set[int]], discovery_eval_counts: list[int], best_outputs_valset: list[list[tuple[int, list[Prediction]]]] | None = None, total_metric_calls: int | None = None, num_full_val_evals: int | None = None, log_dir: str | None = None, seed: int | None = None)
dataclass
与GEPA运行相关的附加数据。
字段: - candidates: 提议候选者列表 (组件名称 -> 组件文本) - parents: 谱系信息; 对于每个候选者i, parents[i] 是父索引列表或None - val_aggregate_scores: 验证集上每个候选者的聚合分数 (越高越好) - val_subscores: 验证集上每个候选者每个实例的分数 (长度 == 验证实例数量) - per_val_instance_best_candidates: 对于每个验证实例t, 在t上获得最佳分数的候选者索引集合 - discovery_eval_counts: 预算 (指标调用/rollout次数) 消耗至发现每个候选者
- total_metric_calls: 运行过程中进行的指标调用总次数
- num_full_val_evals: 执行的完整验证评估次数
- log_dir: 写入产物的目录(如果有)
-
seed: 用于重现性的随机数生成器种子(如果已知)
-
best_idx: 具有最高 val_aggregate_scores 的候选索引
- best_candidate: 最佳索引对应的程序文本映射
属性
candidates: list[Module]
instance-attribute
parents: list[list[int | None]]
instance-attribute
val_aggregate_scores: list[float]
instance-attribute
val_subscores: list[list[float]]
instance-attribute
per_val_instance_best_candidates: list[set[int]]
instance-attribute
discovery_eval_counts: list[int]
instance-attribute
best_outputs_valset: list[list[tuple[int, list[Prediction]]]] | None = None
class-attribute
instance-attribute
total_metric_calls: int | None = None
class-attribute
instance-attribute
num_full_val_evals: int | None = None
class-attribute
instance-attribute
log_dir: str | None = None
class-attribute
instance-attribute
seed: int | None = None
class-attribute
instance-attribute
best_idx: int
property
best_candidate: dict[str, str]
property
highest_score_achieved_per_val_task: list[float]
property
函数
to_dict() -> dict[str, Any]
Source code in dspy/teleprompt/gepa/gepa.py
from_gepa_result(gepa_result: GEPAResult, adapter: DspyAdapter) -> DspyGEPAResult
staticmethod
Source code in dspy/teleprompt/gepa/gepa.py
:::
使用示例
查看GEPA教程中的GEPA使用教程。
推理时间搜索
GEPA 可以作为测试时/推理搜索机制。通过将你的 valset 设置为你的评估批次并使用 track_best_outputs=True,GEPA 为每个批次元素生成进化搜索期间发现的最高分输出。
gepa = dspy.GEPA(metric=metric, track_stats=True, ...)
new_prog = gepa.compile(student, trainset=my_tasks, valset=my_tasks)
highest_score_achieved_per_task = new_prog.detailed_results.highest_score_achieved_per_val_task
best_outputs = new_prog.detailed_results.best_outputs_valset
GEPA 如何工作?
1. 反思式提示变异
GEPA 使用 LLM 对结构化执行轨迹(输入、输出、失败、反馈)进行反思,针对选定模块,并根据实际观察到的失败和丰富的文本/环境反馈提出新的指令/程序文本。
2. 将富文本反馈作为优化信号
GEPA可以利用任何可用的文本反馈——不仅仅是标量奖励。这包括评估日志、代码跟踪、解析失败、约束违反、错误消息字符串,甚至是孤立的子模块特定反馈。这使得可以进行可操作的、领域感知的优化。
3. 基于帕累托的候选选择
不同于仅演化最佳全局候选方案(这会导致局部最优或停滞),GEPA维护一个帕累托前沿:即在至少一个评估实例上达到最高分的候选方案集合。在每次迭代中,下一个待变异的候选方案会从这个前沿中采样(概率与覆盖度成正比),确保既能探索又能稳健保留互补策略。
算法概述
- 初始化候选池,使用未优化的程序。
- 迭代:
- 从帕累托前沿中抽取候选样本。
- 从训练集中采样一个小批次
- 收集执行轨迹 + 反馈 用于在小批次上推出模块。
- 选择一个模块 用于针对性改进候选对象。
- LLM 反思: 使用反思性元提示和收集到的反馈,为目标模块提出新的指令/提示。
- 在新候选集上推出;如果有所改进,则在帕累托验证集上进行评估。
- 更新候选池/帕累托前沿。
- [可选] 系统感知合并/交叉: 合并不同谱系中表现最佳的模块。
- 继续直到耗尽 rollout 或指标预算。
- 返回在验证集上综合表现最佳的候选方案。
实现反馈指标
设计良好的指标对于GEPA的样本效率和学习信号丰富性至关重要。GEPA期望该指标返回一个dspy.Prediction(score=..., feedback=...)。GEPA利用基于LLM工作流程的自然语言轨迹进行优化,以纯文本形式保留中间轨迹和错误,而不是将它们简化为数值奖励。这反映了人类诊断过程,能够更清晰地识别系统行为和瓶颈。
GEPA友好反馈的实用指南:
- 利用现有工件: 使用日志、单元测试、评估脚本和分析器输出;展示这些通常就足够了。
- 分解结果: 将分数拆分为每个目标的组成部分(例如:正确性、延迟、成本、安全性),并将错误归因于步骤。
- 暴露轨迹: 标记流水线阶段,报告通过/失败情况并附带显著错误(例如,在代码生成流水线中)。
- 基础检查: 对于可验证任务使用自动验证器(单元测试、模式、模拟器),对于不可验证任务(如PUPA中所示)使用LLM作为评判者。
- 优先确保清晰度: 重点关注错误覆盖率和决策点,而非技术复杂性。
示例
- 文档检索 (例如,HotpotQA): 除了Recall/F1分数外,还需列出正确检索到的、错误的或遗漏的文档。
- 多目标任务 (例如,PUPA): 将综合评分分解以揭示每个目标的贡献,突出权衡(例如,质量与隐私)。
- 堆叠式流水线 (例如,代码生成:解析 → 编译 → 运行 → 分析 → 评估):暴露阶段特定的故障;自然语言追踪通常足以让LLM进行自我修正。
更多阅读
- GEPA Paper: arxiv:2507.19457
- GEPA Github - 该仓库提供了由
dspy.GEPA优化器使用的核心GEPA进化流程。 - DSPy 教程