ガイド
進捗と並行処理
稼働中のモデルに対するスイートには数分かかり、その大半はモデルを待つ時間です。このページでは、Oloproof が同時に処理する呼び出しの数、呼び出しの実行中に表示されるもの、そして判断できなかったルールに決着をつけるにはあとどれだけ実行すればよいかを知る方法を扱います。
並行処理
oloproof.yaml の concurrency: は、同時に処理する呼び出しの数を制限します。
concurrency:
system: 4
judge: 4system はテスト対象のシステムへの呼び出しを制限し、デフォルトは 8 です。judge は LLM ジャッジへの呼び出しを制限し、デフォルトは 4 です。この 2 つは通常、異なるレート制限の背後にあるため、別々になっています。
1 回の呼び出しに 0.1 秒かかるシステムに対する 120 ケース:
| system: | 経過時間 |
|---|---|
| 1 | 13.4s |
| 16 | 1.7s |
| 変更なし、再実行 | 0.4s |
最後の行は並行処理ではなくキャッシュによるもので、すべての実行結果が再利用されました。並行処理はシステムの同一性の一部ではないので、変更しても保存済みのものが無効になることはありません。
各ケースはそれぞれ個別の呼び出しです。Oloproof はケースをプロバイダーのバッチ API にまとめないので、プロバイダーのバッチ割引は Oloproof 経由では利用できません。実行を速くするのは並行処理とキャッシュです。
再試行
ジャッジのプロバイダーや HTTP のシステムが 429 または 5xx を返した場合、タイムアウトした場合、あるいは接続が切断された場合は、バックオフを挟んで最大 4 回まで再試行されます。Retry-After ヘッダーが求めるより早く再試行することはありません。呼び出し可能なシステムは、oloproof の TransientError を 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 のデフォルトは False です。これがないと、エラーはケースに記録され、そのケースは再試行されずに欠測になります。30 ケースそれぞれで、最初の呼び出しではそのように例外を送出し、2 回目で応答したシステムの場合:
│ exact_label │ 100.0% │ [88.4%, 100.0%] │ 30 / 30 observed · 0 missing · 0 excluded │同じシステムから retryable=True を取り除いた場合:
│ exact_label │ │ [0.0%, 100.0%] │ 0 / 0 observed · 30 missing · 0 excluded │実行中に表示されるもの
ターミナルでは、oloproof run は標準エラー出力にライブビューを再描画します。完了したケース数、キャッシュヒット、エラー、そして各二値メトリクスの暫定推定値です。その 1 フレーム:
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.このキャプションがルールです。暫定区間は、完了したものに対する Wilson 区間です。見ておくと役に立つものですが、判断の根拠にするものではありません。ケースが到着するたびに再計算され、良く見えるまで繰り返し確認された区間は、もはや 95% 区間ではないからです。これにもとづいて実行が早期に停止することはありません。判断は、完了したエビデンスに対して、ポリシーが指定する手法で 1 回だけ行われます。
CI などターミナルの外では、ライブビューは描画されず、表は最後に 1 回だけ出力されます。
イベントストリーム
--json は、同じ進捗を 1 行に 1 つの JSON オブジェクトとして標準出力に書き出し、表は標準エラー出力に出力します。
oloproof run --json120 ケースの実行を run.ndjson に保存し、jq -r '.type' run.ndjson | sort | uniq -c で数えると、次のイベントが出力されています。
120 case_executed
120 case_judged
11 provisional_metrics
1 run_finished
2 run_phase_changed
1 run_startedそれぞれに実行 ID とタイムスタンプが含まれます。
{"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 には、各二値メトリクスについて、実行中の Wilson 区間が含まれます。
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]パイプを途中で閉じないでください。head のように最初の数行で読むのをやめるリーダーは、実行が最後のケースを保存する前にその実行を終わらせてしまい、実行は RUN_ERROR/PARTIAL として記録されます。
あとどれだけで判断できるか
INSUFFICIENT_EVIDENCE になったルールは、不合格になったわけではありません。スイートが小さすぎて、結果をしきい値と区別できなかったのです。oloproof plan は、スイートがあとどれだけ大きくなる必要があるかを、実行がすでに費やした量をもとに見積もって示します。18 ケースの examples/support_bot/ の場合:
oloproof plan RUN_ID --runRun 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実行ルールのサイズ見積もりが認められているのは、合格/不合格の比率だけです。平均の場合、プランは推測する代わりにそう伝えます。
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代わりに比較 ID を渡すと、比較のルールについて見積もり、フラグは不要です。
次に読むページ
- システムが行ったことを記録する では、これらの見積もりの元になるレイテンシとトークンの数値を扱います。
- CI での実行 では、スクリプトからイベントストリームを読む方法を扱います。