Skip to main content
COPRO (Collaborative Prompt Optimization) iteratively refines instructions through generation and evaluation cycles.

How it works

COPRO runs a generate-and-evaluate loop:
  1. Generate candidates: Create breadth candidate instructions per predictor
  2. Evaluate: Test each candidate on your training data
  3. Refine: Use the best candidate as the seed for the next round
  4. Repeat: Continue for depth rounds
The base instruction always competes in every round, so COPRO never installs a candidate that is worse than what you started with.

Configuration

Other fields: prompt_model (separate LM for generating candidate instructions), eval_concurrency (concurrent LM calls during evaluation, default 16), track_stats, and init_temperature (currently unused, reserved for candidate diversity control). The full field table is in the optimizers reference.

Usage example

The trainset here is a slice of (QAInput, QAOutput) tuples, the zero-boilerplate row form. Any row type that implements ToInput<QAInput> works, including #[derive(Example)] structs carrying gold labels and metric-only fields; see Data. The predictors! line names the module’s optimizable leaves — without it the module does not satisfy the Predictors bound compile_module requires.

Typed data loading

Use the shared data ingress reference: DataLoader.

When to use COPRO

Best for:
  • Quick iteration cycles
  • Simple tasks
  • Limited compute budget
  • Short turnaround requirements
Avoid when:
  • You need best possible quality (use MIPROv2 or GEPA)
  • Task has complex failure modes (use GEPA)
  • You want to leverage prompting best practices (use MIPROv2)

Comparison with other optimizers

GEPA is the only optimizer that requires textual feedback from the metric (Eval::with_feedback). The others use numerical scores alone. Full configuration tables for all six live in the optimizers reference.

Configuration details

Breadth

Number of candidate instructions generated at each round, per predictor. Higher breadth means more exploration but proportionally more LM calls. Must be greater than 1; compile errors otherwise. Recommended: 5-15

Depth

Number of refinement rounds. Each round builds on the best candidate from the previous one, with diminishing returns beyond about 5. Recommended: 2-5

Prompt model

An optional separate LM used to generate candidate instructions. Falls back to the global LM set with configure when unset.

Track stats

A per-round statistics flag. COPRO’s compile_module returns (), so nothing is returned either way; leave it at the default.

Implementation notes

COPRO is a thin strategy over the shared evaluation engine: each candidate instruction is a name-keyed Candidate injected ambiently per rollout through a cached, bounded-concurrency fan-out — the module is never mutated during evaluation — and the final winner is installed once through OptimizeTarget::install. Repeated candidates are deduplicated by content hash and served from the rollout cache, so re-evaluating an instruction it has already seen costs nothing. See the optimizer engine reference for the machinery. Cost is approximately breadth × depth × num_predictors × trainset_size LM calls, minus cache hits.

Examples

COPRO Examples

See examples 02-module-iteration-and-updation.rs and 04-optimize-hotpotqa.rs