Skip to content

Handleidingen

Voortgang en gelijktijdigheid

Een suite tegen een live model duurt minuten, en de meeste daarvan gaan op aan wachten op het model. Deze pagina behandelt hoeveel aanroepen Oloproof tegelijk onderweg houdt, wat het je laat zien terwijl ze lopen, en hoe je uitzoekt hoeveel meer draaien een regel zou beslechten die niet besliste.

Gelijktijdigheid

concurrency: in oloproof.yaml begrenst hoeveel aanroepen tegelijk onderweg zijn:

concurrency:
  system: 4
  judge: 4

system begrenst aanroepen naar het geteste systeem en staat standaard op 8. judge begrenst aanroepen naar LLM-judges en staat standaard op 4. Ze zijn gescheiden omdat de twee meestal achter verschillende rate limits zitten.

Honderdtwintig cases tegen een systeem dat een tiende seconde per aanroep nodig heeft:

system:Kloktijd
113.4s
161.7s
ongewijzigd, opnieuw gedraaid0.4s

De laatste rij is de cache, niet gelijktijdigheid: elke uitvoering werd hergebruikt. Gelijktijdigheid maakt geen deel uit van de identiteit van een systeem, dus die wijzigen maakt nooit ongeldig wat is opgeslagen.

Elke case is zijn eigen aanroep. Oloproof groepeert cases niet in de batch-API van een provider, dus de batchkorting van een provider is er niet via beschikbaar; gelijktijdigheid en de cache zijn wat een run sneller maakt.

Nieuwe pogingen

Een judge-provider of een HTTP-systeem dat 429 of een 5xx antwoordt, een time-out geeft of de verbinding verbreekt, wordt opnieuw geprobeerd met backoff, tot vier pogingen, en nooit eerder dan een Retry-After-header vraagt. Een aanroepbaar systeem doet mee door TransientError uit oloproof te werpen met retryable=True:

from oloproof import TransientError, system


@system(name="example-support-bot", version="1")
def answer(case):
    ...
    raise TransientError("provider timed out", retryable=True)

retryable staat standaard op False. Zonder die vlag wordt de fout op de case vastgelegd, die dan ontbreekt in plaats van opnieuw geprobeerd te worden. Een systeem dat bij de eerste aanroep voor elk van dertig cases zo een exceptie wierp, en bij de tweede antwoordde:

│ exact_label │ 100.0%   │ [88.4%, 100.0%] │ 30 / 30 observed · 0 missing · 0 excluded │

Hetzelfde systeem met retryable=True verwijderd:

│ exact_label │          │ [0.0%, 100.0%] │ 0 / 0 observed · 30 missing · 0 excluded │

Wat een run laat zien terwijl hij draait

In een terminal tekent oloproof run een live weergave op standaardfout: afgeronde cases, cachetreffers, fouten en een voorlopige schatting voor elke binaire metriek. Eén frame:

                    56/120 cases · 0 cached · 0 errors
┏━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Metric      ┃ Estimate ┃ Provisional interval ┃ Cases                   ┃
┡━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ exact_label │ 89.8%    │ [78.2%, 95.6%]       │ 49 observed · 0 missing │
└─────────────┴──────────┴──────────────────────┴─────────────────────────┘
     Provisional Wilson estimates over finished cases; not a decision.

Het onderschrift is de regel. Een voorlopig interval is een Wilson-interval over wat er ook maar klaar is, wat nuttig is om naar te kijken en niet iets om op te beslissen: het wordt herberekend naarmate cases binnenkomen, en een interval dat herhaaldelijk wordt gecontroleerd totdat het er goed uitziet, is geen 95%-interval meer. Niets stopt een run er vroegtijdig op. De beslissing wordt één keer genomen, op het voltooide bewijs, met de methode die de policy noemt.

Buiten een terminal, zoals in CI, wordt de live weergave niet getekend en worden de tabellen één keer afgedrukt, aan het eind.

De eventstream

--json schrijft dezelfde voortgang als één JSON-object per regel op standaardoutput, en de tabellen op standaardfout:

oloproof run --json

Een run van 120 cases, opgeslagen in run.ndjson en geteld met jq -r '.type' run.ndjson | sort | uniq -c, levert:

 120 case_executed
 120 case_judged
  11 provisional_metrics
   1 run_finished
   2 run_phase_changed
   1 run_started

Elk event draagt de id van de run en een tijdstempel:

{"run_id":"run_01M3C3ZNXPVQJCDF31DJSBXBHC","timestamp":"2026-09-25T11:07:37.782628Z","type":"run_started","suite_digest":"sha256:c6ae32f25d38ddac175f688c15c40991c1e0ec5348f32bfabd9c493a3f688c28","cases":120}
{"run_id":"run_01M3C3ZNXPVQJCDF31DJSBXBHC","timestamp":"2026-09-25T11:07:37.885640Z","type":"case_executed","scenario_id":"q000","status":"OK","from_cache":false,"latency_ms":102.11420899941004}
{"run_id":"run_01M3C3ZNXPVQJCDF31DJSBXBHC","timestamp":"2026-09-25T11:07:37.885667Z","type":"case_judged","scenario_id":"q000","criterion":"exact_label","status":"OK","passed":true,"score":null,"from_cache":false}
{"run_id":"run_01M3C3ZNXPVQJCDF31DJSBXBHC","timestamp":"2026-09-25T11:07:41.362779Z","type":"run_finished","status":"DECIDED","completeness":"COMPLETE","exit_code":0}

provisional_metrics draagt het lopende Wilson-interval voor elke binaire metriek:

jq -c 'select(.type == "provisional_metrics") | [.cases_done, .metrics[0].estimate, .metrics[0].wilson_lower, .metrics[0].wilson_upper]' run.ndjson
[1,1.0,0.20654931411298355,1.0]
[13,0.8461538461538461,0.5776536895684791,0.9567418216820717]
[25,0.88,0.7004420606159933,0.9583318285288502]
[37,0.8918918918918919,0.7529146844205937,0.9571481006263428]

Sluit de pipe niet te vroeg. Een lezer die na de eerste paar regels stopt, zoals head, beëindigt de run voordat die zijn laatste cases opslaat, en de run wordt vastgelegd als RUN_ERROR/PARTIAL.

Hoeveel meer het zou beslissen

Een regel die INSUFFICIENT_EVIDENCE leest, is niet mislukt; de suite was te klein om het resultaat van de drempel te onderscheiden. oloproof plan zegt hoeveel groter hij zou moeten zijn, geprijsd op basis van wat de run al uitgaf. Voor de examples/support_bot/ met achttien cases:

oloproof plan RUN_ID --run
Run run_01M3C3WS0SBTFAG55M7ECM1EZ4
  observed  18 cases

exact-label-floor: about 1614 more cases would decide it, if the observed rate holds (1632 in total)
  time      <1s – 27s
  tokens    none reported by this run's providers
  assuming  the cases to come resemble the 18 already run
            cases run one after another; concurrency divides the time and not the cost

Het dimensioneren van een run-regel is alleen toegelaten voor slagingspercentages. Bij een gemiddelde zegt het plan dat, in plaats van te gokken:

Run run_01M3C3W5YWJY65X9YM6N02F3W4: no sample size can be computed for a rule that did not decide.
  error-budget: sizing a run rule is admitted for binary rates only, and days_error is a MEAN metric: a run stores its summary, not the per-case values sizing one would need

Met een vergelijkings-id in plaats daarvan plant het de regels van de vergelijking, en is er geen vlag nodig.

Verder lezen

deze schattingen zijn geprijsd.

  • Draaien in CI behandelt het lezen van de eventstream vanuit een script.