GEPA: Genetic-Pareto optimizer for text-based system components.
Basic Example
trainset = [%{input: "What is 2+2?", answer: "4"}, ...]
valset = [%{input: "What is 5+5?", answer: "10"}]
{:ok, result} = GEPA.optimize(
seed_candidate: %{"instruction" => "You are a helpful assistant."},
trainset: trainset,
valset: valset,
adapter: GEPA.Adapters.Basic.new(),
max_metric_calls: 100
)
IO.puts("Best score: #{GEPA.Result.best_score(result)}")
IO.inspect(GEPA.Result.best_candidate(result))With LLM-based Reflection
llm = GEPA.LLM.req_llm(:openai, model: "gpt-5.4-mini")
{:ok, result} = GEPA.optimize(
seed_candidate: %{"instruction" => "You are a helpful assistant."},
trainset: trainset,
valset: valset,
adapter: GEPA.Adapters.Basic.new(),
max_metric_calls: 100,
reflection_llm: llm
)This uses the LLM to propose improved instructions based on execution feedback, rather than using a simple placeholder improvement.
Summary
Functions
Build the official-style default adapter.
Run GEPA optimization.
Optimize an arbitrary candidate/evaluator pair.
Functions
@spec default_adapter(keyword()) :: GEPA.Adapters.Default.t()
Build the official-style default adapter.
This is a top-level convenience for callers coming from the upstream Python
surface. It delegates to GEPA.Adapters.Default.new/1.
@spec optimize(Keyword.t()) :: {:ok, GEPA.Result.t()}
Run GEPA optimization.
Options
Required
:seed_candidate- Initial program as map of component -> text:trainset- Training data (list or DataLoader):adapter- Adapter module/struct implementing GEPA.Adapter
If :adapter is omitted, provide :task_lm or :model and GEPA will build
the default adapter. If :valset is omitted, GEPA reuses :trainset.
At least one stopping path is required: :max_metric_calls,
:max_reflection_cost, :max_candidate_proposals, :stop_conditions,
:stop_callbacks, or :run_dir (which adds a gepa.stop file stopper).
Optional
:valset- Validation data (list or DataLoader, default::trainset):candidate_selection_strategy/:candidate_selector-:pareto,:current_best,:epsilon_greedy,:top_k_pareto, or a custom selector (default::pareto):batch_sampler- Batch sampler or:epoch_shuffled(default::epoch_shuffled):module_selector-:round_robin,:all, or a custom component selector (default::round_robin):val_evaluation_policy-:full_evalor a custom evaluation policy (default::full_eval):reflection_minibatch_size- Minibatch size (default: 3):perfect_score- Perfect score value (default: 1.0):skip_perfect_score- Skip if perfect (default: true):seed- Random seed (default: 0):run_dir- Directory for state persistence (default: nil):reflection_llm- LLM for generating improved instructions (default: nil):custom_candidate_proposer- Function used when no reflection LLM or adapter proposer is available:proposal_template- Custom template for instruction proposal (default: built-in):structured_output- Use tool_use / function calling for instruction proposals (default: false):acceptance_criterion- Candidate acceptance criterion (default::strict_improvement):cache_evaluation- Build an evaluation cache automatically (default:false):raise_on_exception- Propagate proposer/evaluator exceptions (default:true):use_merge- Enable merge proposer construction (default:false):max_merge_invocations- Maximum merge attempts when merge is enabled (default: 5):merge_val_overlap_floor- Minimum shared validation IDs for merge subsamples (default: 5):callbacks- Synchronous observational callbacks (default:[]):track_best_outputs- Track best validation outputs in state/result (default:false):frontier_type- Pareto frontier mode::instance,:objective,:hybrid, or:cartesian(default::instance):progress- Enable progress display (default: false). Can betrueor a keyword list with options:[width: 60, color: true]
Returns
{:ok, result} where result is a GEPA.Result struct
LLM-based Reflection
When :reflection_llm is provided, GEPA uses the LLM to propose improved
instruction texts based on feedback from execution traces. This is the
recommended mode for production use.
Without :reflection_llm, the adapter must implement propose_new_texts/4
or /3, or you must pass :custom_candidate_proposer. GEPA does not use a
placeholder production mutation path.
Custom Templates
When using :reflection_llm, you can customize the prompt template with
:proposal_template. The template must include these placeholders:
<curr_param>- Current instruction text<side_info>- Formatted examples with feedback
Legacy {component_name}, {current_instruction}, and
{reflective_dataset} templates are still accepted for existing Elixir
callers.
Example:
custom_template = """
Improve this instruction:
Current: <curr_param>
Examples: <side_info>
New instruction:
"""
GEPA.optimize(..., reflection_llm: llm, proposal_template: custom_template)
@spec optimize_anything(keyword() | map() | GEPA.OptimizeAnything.Config.t()) :: {:ok, GEPA.Result.t()} | {:error, term()}
Optimize an arbitrary candidate/evaluator pair.
This top-level entrypoint mirrors upstream gepa.optimize_anything while the
implementation lives in GEPA.OptimizeAnything.optimize_anything/1.