Setting the target score
The score threshold tells reflex when to stop — “make my model at least this good.” Rather than picking an arbitrary number, you should set the target from a real benchmark. There are three ways to set the target, in priority order:- From verdict results (recommended)
- Live benchmark
- Explicit threshold
If you’ve already run Python API:
aevyra-verdict to compare models, pass the results
file and reflex uses the best model’s score:OptimizerConfig
All configuration goes throughOptimizerConfig:
Train/test split
By default, reflex splits your dataset 80/20 before running. The 80% train portion is used during the optimization loop — failing samples are drawn from here and all iteration scores are computed on these examples. The 20% test set is held out completely, and the baseline and final scores you see in the results summary are computed on that held-out set only. This matters because without a split, the same examples that drive rewrites also determine whether the prompt “improved.” That inflates the reported improvement, especially on small datasets where a handful of examples have an outsized effect on the mean score.With small datasets (fewer than ~20 examples), the test set may be too small
for stable scores. In that case, use
--train-split 1.0 to disable splitting
and rely on the score trajectory to judge improvement instead.Validation split and early stopping
Reflex supports a 3-way train / val / test split to detect overfitting mid-run. Without a validation set, a prompt can score well on training examples simply by overfitting to their specific patterns — the optimization loop has no way to notice. With a validation set, reflex evaluates each candidate prompt on the val examples after every iteration. If the train score climbs but val plateaus or declines, that’s a sign the prompt is fitting the training examples specifically rather than generalizing. Early stopping on val plateau saves you compute and returns the least-overfit prompt.The validation set adds one extra eval call per optimization iteration.
With
val_ratio=0.1 on 100 examples you’re evaluating 10 extra samples
per iteration — usually inexpensive compared to the reasoning step.Mini-batch mode
By default every optimization iteration evaluates the full training set. For large datasets this can be slow — each iteration costsn_train LLM calls.
Mini-batch mode samples a random subset each round:
batch_seed + i, so the
optimizer sees different examples each round. The stochasticity can also
help escape local optima by smoothing out noise from individual examples.
Baseline and final verification evals always use the full test set —
batch_size only affects the per-iteration training evals used by the
optimization strategy.
Periodic full-eval checkpoints
Mini-batch scores are noisy — a single good or bad batch can skew the trajectory. Use--full-eval-steps to periodically score the full
training set for an accurate checkpoint:
Statistical significance
Reflex reports whether the improvement from baseline to final is statistically significant using a paired test on per-sample scores. This compares how each individual sample scored under the original prompt vs the optimized one. The result appears inresult.summary():
--eval-runs to
average multiple passes before computing the test:
mean ± std in the results summary:
--eval-runs only affects the baseline and final verification evals — not
the optimization iterations, which always use a single pass for speed.
--eval-runs 3 triples the cost of those two checkpoints.Strategy-specific parameters
Pass strategy-specific parameters viaextra_kwargs:
- Auto
- PDO
- Few-shot
- Structural
Parallel execution
Strategies like structural and PDO evaluate multiple prompt variants per iteration. These variants are evaluated in parallel using threads. For cloud APIs (OpenAI, OpenRouter, Together), parallelism works out of the box:If reflex detects Ollama without
OLLAMA_NUM_PARALLEL set, it automatically
falls back to 1 worker and logs a warning with setup instructions.OLLAMA_NUM_PARALLEL uses more VRAM. Guidelines:
Choosing a reasoning model
Reflex is an agent — it observes eval results, diagnoses failures, and iteratively rewrites your prompt. To do this reasoning, it calls an LLM. By default that’s Claude Sonnet, but you can swap in any model: a local Ollama model, an OpenAI-compatible endpoint, or another cloud provider. The reasoning model is separate from the model being optimized (-m).
A more capable reasoning model produces better prompt rewrites.
- Ollama (local)
- OpenAI
- Gemini
- OpenRouter / Together / etc.
- Self-hosted endpoint
The reasoning model needs strong analytical abilities. Local models work
well for simpler strategies (iterative), but the auto strategy benefits
from a more capable model since it makes multi-step decisions about which
optimization axes to apply.
Automatic language detection. Reflex samples up to 20 user messages
from your training set and detects the dominant script family using Unicode
heuristics (no external dependencies). The reasoning model is then
instructed to write all revised prompts and diagnostic explanations in that
language. This prevents multilingual models such as Qwen3 from silently
switching languages mid-run when optimizing non-English datasets. No
configuration is required — the detection is automatic.
Run persistence and checkpointing
Reflex automatically saves every run to a.reflex/ directory. Each
iteration is checkpointed so that if a run crashes or is interrupted, you
can resume exactly where it left off.
Directory structure
001, 002, …) and a timestamped
directory. The config, dataset path, and initial prompt are captured at
the start so every run is fully reproducible.
Resuming interrupted runs
If a run is interrupted (Ctrl-C, crash, network timeout), use--resume
to pick up where it left off:
Listing runs
-v for config details (reasoning model, target models).
Custom run directory
By default, runs are stored in.reflex/ in the current working
directory. Use --run-dir to change this:
Python API
Metrics
By default, reflex uses ROUGE. You can switch to a different metric or use an LLM judge:--metric and --judge are mutually exclusive. If neither is specified,
ROUGE is used as the default.
--judge-criteria only applies when --judge is set. It accepts a path to a
plain text file describing your scoring rubric (1–5 scale). Use this when the
default accuracy/helpfulness/clarity/completeness criteria don’t match your
task — for example, when you need to enforce a strict output format, check
domain-specific correctness, or evaluate against a proprietary style guide.
rubric.md (example)