Select a candidate from the Pareto frontier to evolve from:
# From candidate_selector.pyclass ParetoCandidateSelector: def select_candidate_idx(self, state: GEPAState) -> int: # Get all candidates on the Pareto front pareto_programs = state.get_pareto_front_programs() # Randomly select one return self.rng.choice(list(pareto_programs))
Strategy options:
pareto (default): Randomly select from Pareto front for diverse exploration
current_best: Always select the single best-scoring candidate (greedy)
epsilon_greedy: Select best with probability (1-ε), random from front otherwise
Trace capture is more expensive than scoring alone. GEPA only captures traces for the minibatch during reflection, not during full validation evaluation.
The reflection LM generates an improved candidate:
# From instruction_proposal.pydef propose_new_texts( candidate: dict[str, str], reflective_dataset: dict[str, list[dict]], components_to_update: list[str]) -> dict[str, str]: new_texts = {} for component_name in components_to_update: # Build prompt with current text + reflective dataset prompt = build_reflection_prompt( current_text=candidate[component_name], examples=reflective_dataset[component_name] ) # LLM proposes improvement new_text = reflection_lm(prompt) new_texts[component_name] = new_text return new_texts
The default reflection prompt template (from optimize_anything.py):
I am optimizing a parameter in my system. The current parameter value is:
curr_param
Below is evaluation data showing how this parameter performed:
side_info
Your task is to propose a new, improved parameter value.Carefully analyze all evaluation data. Look for patterns:- Performance metrics and correlations- Recurring issues or failure patterns- Successful behaviors to preserve- Domain-specific constraintsBased on your analysis, propose a new parameter value that addressesthe identified issues while maintaining what works well.Provide the new parameter value within ``` blocks.
You can customize the reflection prompt template via ReflectionConfig.reflection_prompt_template. Use <curr_param> and <side_info> as placeholders.
config = GEPAConfig( reflection=ReflectionConfig( reflection_prompt_template={ "system_prompt": """ You are optimizing a system prompt for math reasoning. Current prompt: <curr_param> Performance data: <side_info> Propose an improved prompt that fixes arithmetic errors while preserving chain-of-thought reasoning. """, "few_shot_examples": """ You are curating few-shot examples. Current examples: <curr_param> Performance data: <side_info> Propose better examples that cover edge cases. """ } ))
GEPA can bootstrap the initial candidate from your objective:
result = optimize_anything( seed_candidate=None, # No starting point evaluator=evaluate, objective="Generate a Python function that reverses a string", background="Use only built-in Python, no imports. Handle Unicode correctly.", dataset=test_cases)
The reflection LM generates the first candidate, then GEPA iterates normally. Useful for: