Skip to content

Evolution Overview

ChainEvolver runs a genetic search over variants of a chain: it mutates a base chain, scores each variant on your dataset, keeps the fittest, and repeats for a few generations.

from mmar_carl import ChainEvolver
evolver = ChainEvolver(
base_chain=chain,
dataset=dataset,
metric=AccuracyMetric(),
population_size=6,
generations=3,
elitism=2,
checkpoint_path="evolution.json", # atomic resume on crash
)
result = await evolver.evolve(
context_factory=lambda case: ReasoningContext(outer_context=case.input, api=client),
)
print(result.best_score, "@ generation", result.best_generation)
best = ReasoningChain.from_dict(result.best_chain_spec) # rehydrate the winner
ParameterTypeDefaultPurpose
base_chainReasoningChain—The chain to evolve.
datasetAbstractDataset—Cases each variant is scored on.
metricMetricBase | list[MetricBase]—One metric, or several (multi-objective).
fitness_fnCallable[[dict], float] | Nonemean of metricsComposes per-metric scores into one fitness.
mutatorChainMutator | NoneNoneWhat mutations to try — see mutation.
population_sizeint6Variants per generation.
generationsint3Number of generations.
elitismint2Top variants carried over unchanged.
smoke_checkboolTrueValidate the base chain before evolving.
max_concurrent_individualsint1Evaluate this many variants at once.
checkpoint_pathstr | NoneNoneAtomic checkpoint file for crash-safe resume.

evolve(context_factory) is async and returns an EvolutionResult.

Pass a list of metrics plus a fitness_fn that weights them:

evolver = ChainEvolver(
base_chain=chain,
dataset=dataset,
metric=[AccuracyMetric(), BrevityMetric()],
fitness_fn=lambda s: 0.7 * s["accuracy"] + 0.3 * s["brevity"],
population_size=4, generations=3, elitism=1,
)

Metric names must be unique. With no fitness_fn, fitness is the mean of all metric scores.

Project the spend before running:

estimate = evolver.estimate_cost(
context_factory,
pricing={"qwen/qwen3-8b": (0.00002, 0.00006)},
)
print(estimate.format_summary()) # smoke + population × generations × cases

The same projection drives the budget preview in the TUI: the Evolution dashboard in MAESTRO CARE shows this estimate and a live cost meter before and during a run.