Skip to main content
GEPA (Genetic-Pareto) is a reflective prompt optimizer: it evolves instructions using the textual feedback your metric returns alongside each score, and it keeps a Pareto frontier of candidates that win on different examples instead of a single best candidate.
Reference: “GEPA: Reflective Prompt Evolution Can Outperform Reinforcement Learning” (Agrawal et al., 2025, arxiv:2507.19457)

Overview

GEPA adaptively evolves the textual components of your module (its instructions). In addition to the scalar score, your metric returns text feedback explaining why the score is what it is. That feedback gives GEPA visibility into the failure, and a reflection LM uses it to propose a better instruction. Because each rollout carries an explanation rather than just a number, GEPA can find high-performing prompts in comparatively few rollouts.

What GEPA adds

Compared to COPRO and MIPROv2, GEPA changes four things:

Rich textual feedback

Instead of just scalar scores (0.8, 0.9), GEPA uses detailed explanations:

Pareto-based selection

GEPA maintains a diverse set of candidates that excel on different examples, preventing premature convergence:
  • Candidate A: Best on examples 1, 3, 5
  • Candidate B: Best on examples 2, 4, 6
  • Both stay in the population (complementary strengths)

LLM-driven reflection

A reflection LM (prompt_model) reads the current instruction, the per-example feedback, and the mutated component’s execution trace, then proposes a targeted rewrite:
Without a prompt_model, mutation degrades to deterministic feedback concatenation, so setting one is strongly recommended. GEPA can optimize at test time, not just training time (see Inference-time search).

Quick start

1. Implement a typed metric with feedback

The third parameter is the rollout’s execution Trace; metrics that inspect intermediate steps can slice it with trace.for_component("predictor").

2. Configure and run GEPA

Configuration options

num_trials and temperature also exist on the builder but are currently unused (reserved for multi-child evolution and mutation diversity control). The full field table is in the optimizers reference. Pass validation data at compile time:
With Some(valset), initial evaluation and child scoring use the validation set while parent re-evaluation uses trainset minibatches; with None, the trainset serves both roles (this is what compile_module does).

Understanding GEPA results

Architecture

Core components

Eval The metric result type: one score, optional textual feedback. GEPA errors if any Eval has feedback: None.
Execution traces Every rollout runs under trace capture, recording one span per Predict invocation. GEPA feeds the mutated component’s spans (trace.for_component(name)) to the reflection LM alongside the feedback. See Traces. Pareto bookkeeping GEPA uses the engine’s score matrix directly: ParetoView (see Optimizer engine) tracks which validation columns each candidate wins on, parent sampling is proportional to that coverage, and candidates with zero wins are dominated. GEPACandidate

Evolutionary algorithm

  1. Initialize the candidate pool with the unoptimized program
  2. Iterate:
    • Sample a candidate from the Pareto frontier (proportional to coverage)
    • Sample a minibatch from the training set
    • Collect execution traces with feedback
    • Select a module component for targeted improvement
    • LLM Reflection: Propose a new instruction using reflective meta-prompting
    • Roll out the new candidate; if improved, evaluate on the validation columns
    • Update the Pareto frontier
  3. Continue until budget is exhausted
  4. Return best candidate by average score

Implementing feedback metrics

A well-designed metric is central to GEPA’s sample efficiency. The DSRs implementation expects the metric to return an Eval; for GEPA that means Eval::with_feedback(score, feedback) on every example.

Practical recipe for GEPA-friendly feedback

  • Leverage existing artifacts: Use logs, unit tests, evaluation scripts, profiler outputs
  • Decompose outcomes: Break scores into per-objective components
  • Expose trajectories: Label pipeline stages with pass/fail and errors
  • Ground in checks: Use validators or an LLM judge for subjective tasks
  • Prioritize clarity: Focus on error coverage and decision points

Feedback examples by domain

Document retrieval: List correctly retrieved, incorrect, or missed documents Multi-objective tasks: Decompose aggregate scores to reveal contributions from each objective Stacked pipelines: Expose stage-specific failures (parse, compile, run, test)

Best practices

Design feedback for actionability

Leverage domain knowledge

  • Code generation: Show stage-specific failures
  • Retrieval: List specific documents missed
  • QA: Explain reasoning errors

Balance feedback detail

  • Too brief: Not actionable
  • Too verbose: Drowns out signal
  • Aim for 2 to 5 lines per issue

Set realistic budgets

Using an LLM judge for feedback

For tasks where feedback rules are hard to codify, a second LLM can generate the feedback: it reads the task output and writes the evaluation text that becomes the metric’s feedback string.
A judge fits these situations:
  • Subjective quality assessment (writing style, helpfulness, clarity)
  • Complex reasoning evaluation (soundness of the logic)
  • Tasks where rules are hard to codify
  • Analyzing reasoning quality beyond answer correctness
Prefer deterministic checks over a judge when they exist:
  • Unit tests or schema validation cover the failure modes
  • Correctness is verifiable (code compilation, exact matches)
  • Evaluation must be fast and cheap
  • The outcome is a simple binary pass/fail

Task signature with reasoning

Judge signature

Optimized module

TypedMetric with judge

GEPA itself does not own a special feedback_metric hook. The feedback function lives in your TypedMetric implementation, and GEPA enforces that every evaluation returns Eval::with_feedback(...). That keeps the optimizer generic while preserving full judge-driven behavior.

What a judge catches

  • Lucky guesses: a correct answer reached through unsound reasoning is penalized instead of scoring 1.0.
  • Partial progress: a wrong answer with a correct approach (an arithmetic slip in the final step) earns partial credit instead of 0.
  • Systematic issues: the judge surfaces recurring patterns such as skipped intermediate steps, confused concepts (area versus perimeter), or missing unit checks, and GEPA’s reflection turns them into explicit instructions.
In the worked example, the baseline instruction “Solve the math word problem step by step” produced solutions that skipped steps, which the judge flagged as incomplete reasoning. After optimization the instruction requires all intermediate calculations to be shown and each step to be labeled. The judge’s analysis is the signal that drives the rewrite.

Cost considerations

LLM judges double your evaluation cost since every prediction requires both a task LM call and a judge LM call.
Budget accordingly:
Ways to contain cost:
  • Use a cheaper model for judging (gpt-4o-mini vs gpt-4)
  • Judge only failed examples (not ones that passed)
  • Cache judge evaluations for identical outputs
  • Use parallel evaluation to reduce wall-clock time

Hybrid metrics

Combining explicit checks with LLM judging often gives the best results:

Running the judge example

The run shows baseline performance, judge evaluations during optimization, the prompt evolving from feedback, and a final test with judge analysis.

Full Working Example

See the complete implementation with step-by-step comments

Examples

Sentiment Analysis

Basic GEPA usage with explicit feedback for sentiment classification

LLM-as-Judge

Using an LLM judge to generate feedback

Comparison with other optimizers

GEPA is the only optimizer that requires textual feedback from the metric (Eval::with_feedback). The others use numerical scores alone. Full configuration tables for all six live in the optimizers reference.

When to use GEPA

  • Complex tasks with subtle failure modes
  • When you can provide rich feedback
  • Multi-objective optimization
  • Need for diverse solutions
  • Inference-time search

When to use alternatives

  • COPRO: Simple tasks, quick iteration
  • MIPROv2: Best prompting practices, single objective

Troubleshooting

Issue: GEPA errors because an Eval has no feedback

GEPA requires feedback for every evaluated example.

Issue: Slow convergence

Issue: Running out of budget

Inference-time search

GEPA can act as a test-time/inference search mechanism. By setting your valset to your evaluation batch and enabling track_best_outputs(true), GEPA produces for each batch element the highest-scoring outputs found during the evolutionary search.

Additional resources