Skip to content

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 受益于强大的反思模型。考虑使用 dspy.LM(model='gpt-5', temperature=1.0, max_tokens=32000) 以获得最佳性能。

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

用于使用Evaluate进行评估的线程数。可选。

None
failure_score float

分配给失败示例的分数。默认值为0.0。

0.0
perfect_score float

该指标可达到的最高分数。默认值为1.0。被GEPA用于判断小批次中的所有示例是否完美。

1.0
log_dir str

保存日志的目录。GEPA会将详细的日志以及所有候选程序保存在此目录中。使用相同的log_dir运行GEPA将从最后一个检查点恢复运行。

None
track_stats bool

是否在优化程序的detailed_results属性中返回详细结果和所有提议的程序。默认值为False。

False
use_wandb bool

是否使用wandb进行日志记录。默认为False。

False
wandb_api_key str | None

用于wandb的API密钥。如果未提供,wandb将使用环境变量WANDB_API_KEY中的API密钥。

None
wandb_init_kwargs dict[str, Any] | None

传递给 wandb.init 的额外关键字参数。

None
track_best_outputs bool

是否在验证集上追踪最佳输出。如果track_best_outputs为True,则track_stats必须为True。优化后的程序的detailed_results.best_outputs_valset将包含验证集中每个任务的最佳输出。

False
seed int | None

用于复现的随机种子。默认值为0。

0
注意

预算配置:必须提供automax_full_evalsmax_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_scoreperfect_score 参数帮助GEPA理解你的指标范围并相应优化。

日志配置:设置 log_dir 以保存详细日志并启用检查点恢复。 使用 track_stats=True 通过 detailed_results 属性访问详细优化结果。 启用 use_wandb=True 进行实验跟踪和可视化。

可重现性:设置 seed 以确保在相同配置下多次运行获得一致结果。

Source code in dspy/teleprompt/gepa/gepa.py
def __init__(
    self,
    metric: GEPAFeedbackMetric,
    *,
    # Budget configuration
    auto: Literal["light", "medium", "heavy"] | None = None,
    max_full_evals: int | None = None,
    max_metric_calls: int | None = None,
    # Reflection based configuration
    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,
    # Merge-based configuration
    use_merge: bool = True,
    max_merge_invocations: int | None = 5,
    # Evaluation configuration
    num_threads: int | None = None,
    failure_score: float = 0.0,
    perfect_score: float = 1.0,
    # Logging
    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,
    # Reproducibility
    seed: int | None = 0,
):
    try:
        inspect.signature(metric).bind(None, None, None, None, None)
    except TypeError as e:
        raise TypeError(
            "GEPA metric must accept five arguments: (gold, pred, trace, pred_name, pred_trace). "
            "See https://dspy.ai/api/optimizers/GEPA for details."
        ) from e

    self.metric_fn = metric

    # Budget configuration
    assert (
        (max_metric_calls is not None) +
        (max_full_evals is not None) +
        (auto is not None)
        == 1
    ), (
        "Exactly one of max_metric_calls, max_full_evals, auto must be set. "
        f"You set max_metric_calls={max_metric_calls}, "
        f"max_full_evals={max_full_evals}, "
        f"auto={auto}."
    )
    self.auto = auto
    self.max_full_evals = max_full_evals
    self.max_metric_calls = max_metric_calls

    # Reflection based configuration
    self.reflection_minibatch_size = reflection_minibatch_size
    self.candidate_selection_strategy = candidate_selection_strategy
    # self.reflection_lm = reflection_lm
    assert reflection_lm is not None, "GEPA requires a reflection language model to be provided. Typically, you can use `dspy.LM(model='gpt-5', temperature=1.0, max_tokens=32000)` to get a good reflection model. Reflection LM is used by GEPA to reflect on the behavior of the program and propose new instructions, and will benefit from a strong model."
    self.reflection_lm = lambda x: reflection_lm(x)[0]
    self.skip_perfect_score = skip_perfect_score
    self.add_format_failure_as_feedback = add_format_failure_as_feedback

    # Merge-based configuration
    self.use_merge = use_merge
    self.max_merge_invocations = max_merge_invocations

    # Evaluation Configuration
    self.num_threads = num_threads
    self.failure_score = failure_score
    self.perfect_score = perfect_score

    # Logging configuration
    self.log_dir = log_dir
    self.track_stats = track_stats
    self.use_wandb = use_wandb
    self.wandb_api_key = wandb_api_key
    self.wandb_init_kwargs = wandb_init_kwargs

    if track_best_outputs:
        assert track_stats, "track_stats must be True if track_best_outputs is True."
    self.track_best_outputs = track_best_outputs

    # Reproducibility
    self.seed = seed

函数

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
def compile(
    self,
    student: Module,
    *,
    trainset: list[Example],
    teacher: Module | None = None,
    valset: list[Example] | None = None,
) -> Module:
    """
    GEPA uses the trainset to perform reflective updates to the prompt, but uses the valset for tracking Pareto scores.
    If no valset is provided, GEPA will use the trainset for both.

    Parameters:
    - student: The student module to optimize.
    - trainset: The training set to use for reflective updates.
    - valset: The validation set to use for tracking Pareto scores. If not provided, GEPA will use the trainset for both.
    """
    from gepa import GEPAResult, optimize

    from dspy.teleprompt.gepa.gepa_utils import DspyAdapter, LoggerAdapter

    assert trainset is not None and len(trainset) > 0, "Trainset must be provided and non-empty"
    assert teacher is None, "Teacher is not supported in DspyGEPA yet."

    if self.auto is not None:
        self.max_metric_calls = self.auto_budget(
            num_preds=len(student.predictors()),
            num_candidates=AUTO_RUN_SETTINGS[self.auto]["n"],
            valset_size=len(valset) if valset is not None else len(trainset),
        )
    elif self.max_full_evals is not None:
        self.max_metric_calls = self.max_full_evals * (len(trainset) + (len(valset) if valset is not None else 0))
    else:
        assert self.max_metric_calls is not None, "Either auto, max_full_evals, or max_metric_calls must be set."

    logger.info(f"Running GEPA for approx {self.max_metric_calls} metric calls of the program. This amounts to {self.max_metric_calls / len(trainset) if valset is None else self.max_metric_calls / (len(trainset) + len(valset)):.2f} full evals on the {'train' if valset is None else 'train+val'} set.")

    valset = valset or trainset
    logger.info(f"Using {len(valset)} examples for tracking Pareto scores. You can consider using a smaller sample of the valset to allow GEPA to explore more diverse solutions within the same budget.")

    rng = random.Random(self.seed)

    def feedback_fn_creator(pred_name: str, predictor) -> "PredictorFeedbackFn":
        def feedback_fn(
            predictor_output: dict[str, Any],
            predictor_inputs: dict[str, Any],
            module_inputs: Example,
            module_outputs: Prediction,
            captured_trace: "DSPyTrace",
        ) -> "ScoreWithFeedback":
            trace_for_pred = [(predictor, predictor_inputs, predictor_output)]
            o = self.metric_fn(
                module_inputs,
                module_outputs,
                captured_trace,
                pred_name,
                trace_for_pred,
            )
            if hasattr(o, "feedback"):
                if o["feedback"] is None:
                    o["feedback"] = f"This trajectory got a score of {o['score']}."
                return o
            else:
                return dict(score=o, feedback=f"This trajectory got a score of {o}.")
        return feedback_fn

    feedback_map = {
        k: feedback_fn_creator(k, v)
        for k, v in student.named_predictors()
    }

    # Build the DSPy adapter that encapsulates evaluation, trace capture, feedback extraction, and instruction proposal
    adapter = DspyAdapter(
        student_module=student,
        metric_fn=self.metric_fn,
        feedback_map=feedback_map,
        failure_score=self.failure_score,
        num_threads=self.num_threads,
        add_format_failure_as_feedback=self.add_format_failure_as_feedback,
        rng=rng,
    )

    reflection_lm = self.reflection_lm

    # Instantiate GEPA with the simpler adapter-based API
    base_program = {name: pred.signature.instructions for name, pred in student.named_predictors()}
    gepa_result: GEPAResult = optimize(
        seed_candidate=base_program,
        trainset=trainset,
        valset=valset,
        adapter=adapter,

        # Reflection-based configuration
        reflection_lm=reflection_lm,
        candidate_selection_strategy=self.candidate_selection_strategy,
        skip_perfect_score=self.skip_perfect_score,
        reflection_minibatch_size=self.reflection_minibatch_size,

        perfect_score=self.perfect_score,

        # Merge-based configuration
        use_merge=self.use_merge,
        max_merge_invocations=self.max_merge_invocations,

        # Budget
        max_metric_calls=self.max_metric_calls,

        # Logging
        logger=LoggerAdapter(logger),
        run_dir=self.log_dir,
        use_wandb=self.use_wandb,
        wandb_api_key=self.wandb_api_key,
        wandb_init_kwargs=self.wandb_init_kwargs,
        track_best_outputs=self.track_best_outputs,
        display_progress_bar=True,
        raise_on_exception=True,

        # Reproducibility
        seed=self.seed,
    )

    new_prog = adapter.build_program(gepa_result.best_candidate)

    if self.track_stats:
        dspy_gepa_result = DspyGEPAResult.from_gepa_result(gepa_result, adapter)
        new_prog.detailed_results = dspy_gepa_result

    return new_prog

:::

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_namepred_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
def __call__(
    gold: Example,
    pred: Prediction,
    trace: Optional["DSPyTrace"],
    pred_name: str | None,
    pred_trace: Optional["DSPyTrace"],
) -> Union[float, "ScoreWithFeedback"]:
    """
    This function is called with the following arguments:
    - gold: The gold example.
    - pred: The predicted output.
    - trace: Optional. The trace of the program's execution.
    - pred_name: Optional. The name of the target predictor currently being optimized by GEPA, for which 
        the feedback is being requested.
    - pred_trace: Optional. The trace of the target predictor's execution GEPA is seeking feedback for.

    Note the `pred_name` and `pred_trace` arguments. During optimization, GEPA will call the metric to obtain
    feedback for individual predictors being optimized. GEPA provides the name of the predictor in `pred_name`
    and the sub-trace (of the trace) corresponding to the predictor in `pred_trace`.
    If available at the predictor level, the metric should return dspy.Prediction(score: float, feedback: str) corresponding 
    to the predictor.
    If not available at the predictor level, the metric can also return a text feedback at the program level
    (using just the gold, pred and trace).
    If no feedback is returned, GEPA will use a simple text feedback consisting of just the score: 
    f"This trajectory got a score of {score}."
    """
    ...

:::

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
def to_dict(self) -> dict[str, Any]:
    cands = [
        {k: v for k, v in cand.items()}
        for cand in self.candidates
    ]

    return dict(
        candidates=cands,
        parents=self.parents,
        val_aggregate_scores=self.val_aggregate_scores,
        best_outputs_valset=self.best_outputs_valset,
        val_subscores=self.val_subscores,
        per_val_instance_best_candidates=[list(s) for s in self.per_val_instance_best_candidates],
        discovery_eval_counts=self.discovery_eval_counts,
        total_metric_calls=self.total_metric_calls,
        num_full_val_evals=self.num_full_val_evals,
        log_dir=self.log_dir,
        seed=self.seed,
        best_idx=self.best_idx,
    )

from_gepa_result(gepa_result: GEPAResult, adapter: DspyAdapter) -> DspyGEPAResult staticmethod

Source code in dspy/teleprompt/gepa/gepa.py
@staticmethod
def from_gepa_result(gepa_result: "GEPAResult", adapter: "DspyAdapter") -> "DspyGEPAResult":
    return DspyGEPAResult(
        candidates=[adapter.build_program(c) for c in gepa_result.candidates],
        parents=gepa_result.parents,
        val_aggregate_scores=gepa_result.val_aggregate_scores,
        best_outputs_valset=gepa_result.best_outputs_valset,
        val_subscores=gepa_result.val_subscores,
        per_val_instance_best_candidates=gepa_result.per_val_instance_best_candidates,
        discovery_eval_counts=gepa_result.discovery_eval_counts,
        total_metric_calls=gepa_result.total_metric_calls,
        num_full_val_evals=gepa_result.num_full_val_evals,
        log_dir=gepa_result.run_dir,
        seed=gepa_result.seed,
    )

:::

使用示例

查看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维护一个帕累托前沿:即在至少一个评估实例上达到最高分的候选方案集合。在每次迭代中,下一个待变异的候选方案会从这个前沿中采样(概率与覆盖度成正比),确保既能探索又能稳健保留互补策略。

算法概述

  1. 初始化候选池,使用未优化的程序。
  2. 迭代:
  3. 从帕累托前沿中抽取候选样本
  4. 从训练集中采样一个小批次
  5. 收集执行轨迹 + 反馈 用于在小批次上推出模块。
  6. 选择一个模块 用于针对性改进候选对象。
  7. LLM 反思: 使用反思性元提示和收集到的反馈,为目标模块提出新的指令/提示。
  8. 在新候选集上推出如果有所改进,则在帕累托验证集上进行评估
  9. 更新候选池/帕累托前沿。
  10. [可选] 系统感知合并/交叉: 合并不同谱系中表现最佳的模块。
  11. 继续直到耗尽 rollout 或指标预算。
  12. 返回在验证集上综合表现最佳的候选方案。

实现反馈指标

设计良好的指标对于GEPA的样本效率和学习信号丰富性至关重要。GEPA期望该指标返回一个dspy.Prediction(score=..., feedback=...)。GEPA利用基于LLM工作流程的自然语言轨迹进行优化,以纯文本形式保留中间轨迹和错误,而不是将它们简化为数值奖励。这反映了人类诊断过程,能够更清晰地识别系统行为和瓶颈。

GEPA友好反馈的实用指南:

  • 利用现有工件: 使用日志、单元测试、评估脚本和分析器输出;展示这些通常就足够了。
  • 分解结果: 将分数拆分为每个目标的组成部分(例如:正确性、延迟、成本、安全性),并将错误归因于步骤。
  • 暴露轨迹: 标记流水线阶段,报告通过/失败情况并附带显著错误(例如,在代码生成流水线中)。
  • 基础检查: 对于可验证任务使用自动验证器(单元测试、模式、模拟器),对于不可验证任务(如PUPA中所示)使用LLM作为评判者。
  • 优先确保清晰度: 重点关注错误覆盖率和决策点,而非技术复杂性。

示例

  • 文档检索 (例如,HotpotQA): 除了Recall/F1分数外,还需列出正确检索到的、错误的或遗漏的文档。
  • 多目标任务 (例如,PUPA): 将综合评分分解以揭示每个目标的贡献,突出权衡(例如,质量与隐私)。
  • 堆叠式流水线 (例如,代码生成:解析 → 编译 → 运行 → 分析 → 评估):暴露阶段特定的故障;自然语言追踪通常足以让LLM进行自我修正。

更多阅读