Skip to content

optimize_anything

gepa.optimize_anything.optimize_anything(seed_candidate: str | Candidate | None = None, *, evaluator: Callable[..., Any] | None = None, batch_evaluator: Callable[..., Any] | None = None, dataset: list[Any] | None = None, valset: list[Any] | None = None, objective: str | None = None, background: str | None = None, test_set: list[Any] | None = None, config: OptimizeAnythingConfig | None = None) -> GEPAResult

Optimize a text candidate (prompt, code, instructions, ...) against a score.

The signature mirrors :func:gepa.gepa_launcher.optimize_anything (seed_candidate / evaluator / batch_evaluator / dataset / valset / objective / background) so the two entry points share one shape; the new API swaps config for an :class:OptimizeAnythingConfig and adds test_set.

Parameters:

Name Type Description Default
seed_candidate str | Candidate | None

The seed to evolve from — either a single text string or, for multi-component optimization, a {component: text} dict (:data:Candidate) whose components are co-optimized. Dict seeds are supported by the gepa engine; the other engines treat the seed as a single text. None for seedless mode, where the engine bootstraps the first candidate from objective / background.

None
evaluator Callable[..., Any] | None

Scoring function returning (score, info) — a bare score is also accepted, with info defaulting to {}. Use (candidate) -> (score, info) for a single task, or (candidate, example) -> (score, info) when dataset/val/test examples are provided. score is a float (higher is better) and info is a free-form dict surfaced to the engine as feedback. Optional when batch_evaluator is provided (at least one is required).

None
batch_evaluator Callable[..., Any] | None

Grouped scoring hook (launcher parity): receives ALL (candidate, example) pairs of an evaluation stage in ONE call — e.g. to submit a provider batch job or fan out over your own infrastructure — and returns one result per pair (score or (score, info)). Multi-pair evaluations (minibatch, valset, and held-out test passes) prefer it; single-pair evaluations use evaluator, or route through the batch function as singleton batches when evaluator is omitted. If its signature accepts an opt_states keyword, the gepa engine forwards the aligned per-pair optimization states.

None
dataset list[Any] | None

Optional training examples used during optimization. Items are opaque — any object evaluator understands. Pairs the dataset-shaped (candidate, example) signature with evaluator.

None
valset list[Any] | None

Optional validation examples used for candidate selection.

None
objective str | None

Short goal statement (e.g. "Maximize sum of circle radii"). Surfaced verbatim by every engine as the optimization goal.

None
background str | None

Long-form context — problem statement, evaluation rules, domain notes. Surfaced verbatim by every engine.

None
test_set list[Any] | None

Optional held-out test examples. When provided, the seed and optimized candidates are each scored on it outside the budget — the test set never enters the eval server, so engines and agents cannot see it. When omitted, test scoring is skipped entirely. Reported under result.metadata["test_score(s)"] (optimized) and result.metadata["baseline_test_score(s)"] (seed).

None
config OptimizeAnythingConfig | None

Engine selection, run name, budgets, output directory, and engine-specific options. Defaults to OptimizeAnythingConfig(); at least one of config.max_evals or config.max_token_cost must be set. When config.name is omitted, a name is generated from the engine, a short uuid, and a timestamp. A legacy :class:GEPAConfig is also accepted and converted to run the gepa engine.

None

Returns:

Type Description
GEPAResult

A single :class:~gepa.core.result.GEPAResult for every run. The

GEPAResult

universal core is always populated — best_candidate, best_score,

GEPAResult

total_evals, eval_log, metadata (the lean accessors), plus

GEPAResult

the candidates / best_idx / val_aggregate_scores /

GEPAResult

to_dict() pool surface. The gepa engine fills the full candidate

GEPAResult

pool and Pareto data; other engines return a single-candidate snapshot

GEPAResult

with the gepa-only fields (per_val_instance_best_candidates,

GEPAResult

val_aggregate_subscores, ...) left None/empty. Held-out

GEPAResult

test_set scores land in metadata on any engine.

GEPAResult

total_evals is the eval-server call count (budget.used), not

GEPAResult

total_metric_calls. The candidate pool lives on the result

GEPAResult

(candidates, best_idx, ...); metadata no longer nests a

GEPAResult

gepa_result object. to_dict() still serializes only the pool

GEPAResult

and GEPA-core fields.

Source code in gepa/optimize_anything.py
def optimize_anything(
    seed_candidate: str | Candidate | None = None,
    *,
    evaluator: Callable[..., Any] | None = None,
    batch_evaluator: Callable[..., Any] | None = None,
    dataset: list[Any] | None = None,
    valset: list[Any] | None = None,
    objective: str | None = None,
    background: str | None = None,
    test_set: list[Any] | None = None,
    config: OptimizeAnythingConfig | None = None,
) -> GEPAResult:
    """Optimize a text candidate (prompt, code, instructions, ...) against a score.

    The signature mirrors :func:`gepa.gepa_launcher.optimize_anything`
    (``seed_candidate`` / ``evaluator`` / ``batch_evaluator`` / ``dataset`` /
    ``valset`` / ``objective`` / ``background``) so the two entry points share
    one shape; the new API swaps ``config`` for an
    :class:`OptimizeAnythingConfig` and adds ``test_set``.

    Args:
        seed_candidate: The seed to evolve from — either a single text string
            or, for multi-component optimization, a ``{component: text}`` dict
            (:data:`Candidate`) whose components are co-optimized. Dict seeds
            are supported by the ``gepa`` engine; the other engines treat the
            seed as a single text. ``None`` for seedless mode, where the engine
            bootstraps the first candidate from ``objective`` / ``background``.
        evaluator: Scoring function returning ``(score, info)`` — a bare
            ``score`` is also accepted, with ``info`` defaulting to ``{}``. Use
            ``(candidate) -> (score, info)`` for a single task, or
            ``(candidate, example) -> (score, info)`` when dataset/val/test
            examples are provided. ``score`` is a float (higher is better) and
            ``info`` is a free-form dict surfaced to the engine as feedback.
            Optional when ``batch_evaluator`` is provided (at least one is
            required).
        batch_evaluator: Grouped scoring hook (launcher parity): receives ALL
            ``(candidate, example)`` pairs of an evaluation stage in ONE call —
            e.g. to submit a provider batch job or fan out over your own
            infrastructure — and returns one result per pair (``score`` or
            ``(score, info)``). Multi-pair evaluations (minibatch, valset, and
            held-out test passes) prefer it; single-pair evaluations use
            ``evaluator``, or route through the batch function as singleton
            batches when ``evaluator`` is omitted. If its signature accepts an
            ``opt_states`` keyword, the gepa engine forwards the aligned
            per-pair optimization states.
        dataset: Optional training examples used during optimization. Items
            are opaque — any object ``evaluator`` understands. Pairs the
            dataset-shaped ``(candidate, example)`` signature with ``evaluator``.
        valset: Optional validation examples used for candidate selection.
        objective: Short goal statement (e.g. "Maximize sum of circle radii").
            Surfaced verbatim by every engine as the optimization goal.
        background: Long-form context — problem statement, evaluation rules,
            domain notes. Surfaced verbatim by every engine.
        test_set: Optional held-out test examples. When provided, the seed and
            optimized candidates are each scored on it outside the budget — the
            test set never enters the eval server, so engines and agents cannot
            see it. When omitted, test scoring is skipped entirely. Reported
            under ``result.metadata["test_score(s)"]`` (optimized) and
            ``result.metadata["baseline_test_score(s)"]`` (seed).
        config: Engine selection, run ``name``, budgets, output directory, and
            engine-specific options. Defaults to ``OptimizeAnythingConfig()``;
            at least one of ``config.max_evals`` or ``config.max_token_cost``
            must be set. When ``config.name`` is omitted, a name is generated
            from the engine, a short uuid, and a timestamp. A legacy
            :class:`GEPAConfig` is also accepted and converted to run the gepa
            engine.

    Returns:
        A single :class:`~gepa.core.result.GEPAResult` for every run. The
        universal core is always populated — ``best_candidate``, ``best_score``,
        ``total_evals``, ``eval_log``, ``metadata`` (the lean accessors), plus
        the ``candidates`` / ``best_idx`` / ``val_aggregate_scores`` /
        ``to_dict()`` pool surface. The gepa engine fills the full candidate
        pool and Pareto data; other engines return a single-candidate snapshot
        with the gepa-only fields (``per_val_instance_best_candidates``,
        ``val_aggregate_subscores``, ...) left ``None``/empty. Held-out
        ``test_set`` scores land in ``metadata`` on any engine.

        ``total_evals`` is the eval-server call count (``budget.used``), not
        ``total_metric_calls``. The candidate pool lives on the result
        (``candidates``, ``best_idx``, ...); ``metadata`` no longer nests a
        ``gepa_result`` object. ``to_dict()`` still serializes only the pool
        and GEPA-core fields.
    """
    if config is None:
        config = OptimizeAnythingConfig()
    elif not isinstance(config, OptimizeAnythingConfig):
        config = _from_legacy_config(config)
    if evaluator is None and batch_evaluator is None:
        raise ValueError("Provide evaluator=, batch_evaluator=, or both.")
    if config.max_evals is None and config.max_token_cost is None:
        warnings.warn(
            "Neither config.max_evals nor config.max_token_cost is set; the run is unbounded "
            "and will stop only on the engine's own stop conditions.",
            stacklevel=2,
        )

    result = _optimize_to_result(
        seed_candidate,
        evaluator=evaluator,
        batch_evaluator=batch_evaluator,
        dataset=dataset,
        valset=valset,
        objective=objective,
        background=background,
        test_set=test_set,
        config=config,
    )
    return _to_gepa_result(result, seed_candidate)