ガイド
チュートリアル:RAG アプリケーションを評価する
検索拡張アプリケーションのための、実際に動かせるウォークスルーです。道筋は 2 つあります。1 つは既存のブラックボックスのアプリケーションで、その検索、コンテキスト、引用を外側から記録します。もう 1 つはステージ化されたアプリケーションで、Oloproof がステージごとに実行するため、oloproof diagnose が失敗したケースを制御された変更のもとで再実行できます。どちらもプロバイダーの認証情報なしにローカルで動作します。
各ステップの背後にある概念(ステージ、関連性ラベル、ゴールドコンテキスト、4 つの失敗ラベル)は RAG の評価 ページに、ケース、評価器、メトリクス、区間、ゲートといった用語は 基本概念 にあります。このページは、それらを実際に手を動かしてたどる道筋です。
どちらの道筋か
| あなたのアプリケーション | 道筋 | 得られるもの | 得られないもの |
|---|---|---|---|
| 1 回の呼び出しで 1 つの回答(サービス、HTTP エンドポイント、分割したくないフレームワークのチェーン) | A、ブラックボックス | 検索メトリクス、引用チェック、根拠性ジャッジ、ゲート、比較 | 制御された介入:diagnose は何も再実行しません |
| 検索と生成を別々に呼び出せる | B、ステージ化 | A のすべて、ステージごとのキャッシュ、そして対照群と並べたゴールドコンテキスト、top-k、リランカーによる diagnose | その 3 つ以外の介入 |
迷ったら A から始めてください。アプリケーションに変更は不要で、後で B に移ってもデータセット、評価器、ポリシーはそのまま使えます。
前提条件
- Python 3.11 以降と、インストールした Oloproof(pip install oloproof)。
- パッケージに同梱されているサンプルプロジェクト:道筋 A には blackbox_rag、道筋 B には support_rag。どちらかを新しいディレクトリにコピーし、そこで作業します:
oloproof init --example blackbox_rag my-rag
cd my-rag以下のすべてのコマンドは、コピーしたディレクトリの中で実行します。実行、判定、診断はそこの .oloproof/ に保存されます。
道筋 A:既存のアプリケーションをブラックボックスとして扱う
ファイル
| ファイル | 内容 |
|---|---|
| app.py | あなたのアプリケーションの代わりとなる support_api(question) と、アダプターである run(case) |
| server.py | 同じアプリケーションを HTTP で提供するもの。下の HTTP 版で使います |
| data/corpus.jsonl | アプリケーションが検索する、14 パッセージのナレッジベース |
| data/support.jsonl | 15 ケース:13 ケースは関連性ラベルとゴールドパッセージを持ち、2 ケースはどちらも持ちません |
| oloproof.yaml | スイート:データセット、システム、評価器、スライス |
| oloproof.http.yaml | HTTP サーバーに対する同じスイート |
| release.yaml | 1 回の実行に対するリリースポリシー |
| compare.yaml | 候補の実行をベースラインと比較するためのポリシー |
アプリケーションが返すもの
support_api は、あなたがすでに持っているアプリケーションのように振る舞います。検索し、語数の予算に収まる最良のソースからプロンプトを組み立て、回答し、引用します。その応答には、行ったことがすでに含まれています:
{
"answer": "Team plans include five seats.",
"cited": ["kb-03"],
"sources": [{"id": "kb-03", "score": 3.0, "text": "Team plans include five seats. ..."}],
"prompt_sources": [{"id": "kb-03", "score": 3.0, "text": "...", "rank": 1, "tokens": 17}],
"skipped": [{"id": "kb-05", "rank": 3, "why": "top_k"}]
}あなたのアプリケーションのフィールド名は異なるでしょう。重要なのは、質問ごとに、取得した順位付きのソース、モデルに届いたソース、引用したソースを伝えられることです。それができないなら、まずそれらを応答かログに追加してください。Oloproof は記録されたものを測定し、回答から検索を推測することは決してありません。
アダプター
run はアプリケーションを変更せずに呼び出し、応答を 3 つの型付きアーティファクトに対応付けます。これは検索評価器と引用評価器が読むレコードです:
@system(
name="support-rag-blackbox",
version="tutorial",
records=("retrieval/v1", "context/v1", "citations/v1"),
)
def run(case):
response = support_api(str(case["question"]))
recorder = current_case()
recorder.retrieval(
Retrieval(
query=case["question"],
depth=SEARCH_DEPTH,
candidates=tuple(
Passage(doc_id=s["id"], score=s["score"], text=s["text"])
for s in response["sources"]
),
)
)
recorder.context(
Context(
items=tuple(
ContextItem(doc_id=i["id"], position=i["rank"], tokens=i["tokens"], text=i["text"])
for i in response["prompt_sources"]
),
dropped=tuple(
DroppedItem(doc_id=i["id"], position=i["rank"], reason=i["why"])
for i in response["skipped"]
),
token_budget=PROMPT_WORD_BUDGET,
)
)
recorder.citations(response["cited"])
return {"answer": response["answer"], "citations": response["cited"]}| アーティファクト | 形 | 読むもの |
|---|---|---|
| retrieval/v1 | query、depth、そしてリトリーバーが返した順の candidates。それぞれが Passage(doc_id, chunk_id, score, text) | hit_rate、recall、mrr、ndcg |
| context/v1 | モデルに届いた items(doc_id、position、tokens、text)、top_k または token_budget の reason を持つ dropped の項目、そして token_budget | citation_validity、groundedness_judge、citation_support_judge |
| citations/v1 | ids。それぞれが doc_id または doc_id#chunk_id | citation_validity、citation_support_judge |
Oloproof は与えられた位置をそのまま記録し、並べ替え直すことは決してありません。不正な形のアーティファクトは保存されず、実行は終了コード 2 で停止します。case はケースの input オブジェクトなので、case["question"] はデータセットにある質問です。
自分のアプリケーションを使うには、support_api の本体をその呼び出し(SDK の呼び出し、HTTP リクエスト)に置き換え、run は残します。oloproof.yaml の system.callable を module:function としてそれに向けてください。
HTTP 版
HTTP システムはレコーダーを呼び出せないため、代わりに応答がエビデンスを、すでに上の 3 つの形で運び、設定がその場所を指定します:
system:
name: support-rag-http
version: tutorial
http:
url: http://127.0.0.1:8766/answer
output_path: result
artifacts:
retrieval/v1: evidence.retrieval
context/v1: evidence.context
citations/v1: evidence.citationsserver.py はまさにそれを提供します。起動してから、それに対して実行します:
python server.py 8766
oloproof run --config oloproof.http.yamlケースの入力は JSON ボディとして送信されます。output_path は応答から出力を取り出し、artifacts の各エントリはドット区切りのパスをその種類として記録します。フィールドが欠けているか不正な形の場合、実行は終了コード 2 で停止します。結果は下の callable の道筋と同一です。自分のサービスでは、エビデンスのオブジェクトは通常、評価用のトラフィックで有効にするデバッグ用フィールドです。
ケースが宣言するもの
{"id":"seat_count","input":{"question":"How many seats does a team plan include?"},"expected":{"answer":"5 seats","relevant":[{"doc_id":"kb-03"}],"gold_context":[{"doc_id":"kb-03","text":"Team plans include five seats. ..."}]},"metadata":{"topic":"billing"}}
{"id":"office_hours","input":{"question":"What are the support office hours?"},"expected":{"answer":"09:00"},"metadata":{"topic":"account"}}- expected.relevant は、質問に答えるパッセージを列挙します。検索メトリクスはこれを読みます。office_hours のようにこれを持たないケースは no_relevance_labels で除外されます。合格や失敗として数えられるのではなく、分母から外れます。
- expected.gold_context はパッセージのテキストそのものです。道筋 A はこれを使いません。道筋 B は診断の際に、取得したコンテキストの代わりにこれを用います。
関連性のラベル付けには手間がかかるので、ラベルのないケースは実際にはよくあります。それでも回答チェックと引用チェックには数えられます。
評価器を選ぶ
evaluators:
- {type: contains, criterion: answer_correct, field: answer, expected_field: answer}
- {type: hit_rate, k: 2}
- {type: recall, k: 2}
- {type: citation_validity, require_citations: true}
slices: [metadata.topic]
min_slice_support: 4- contains は、回答が期待されるテキストを含むかを確認します。これはタスクのチェック、つまりユーザーが正しい回答を得たかどうかです。言い回しが変わる場合は、完全一致やルーブリックジャッジを代わりに使ってください。
- k: 2 の hit_rate と recall は、アプリケーションが実際にプロンプトに入れる深さで検索を測定します。モデルが決して見ない深さでの検索メトリクスは、アプリケーションではなくインデックスを記述するものです。
- citation_validity は、引用されたすべての ID がモデルに届いたパッセージを指していることを確認します。require_citations: true は、何も引用しない回答も失敗にします。
- groundedness_judge と citation_support_judge(任意)は、回答がコンテキストに裏付けられているかをモデルに尋ねます。プロバイダー、モデル、環境変数にある認証情報が必要で、ケースごとに費用がかかります。ジャッジがゲートに使えるようになる前に満たすべきことは ジャッジ を参照してください。
relevant_position と context_truncated のスライスはここでは使えません。それらは位置をアプリケーションの top-k と比較しますが、top-k を宣言するのはステージ化されたシステムだけです。それらを求めると、実行は slice 'relevant_position' compares relevant positions with top_k, so it needs a staged system で停止します。
リリースポリシー
version: 1
confidence_level: 0.95
block_on: [FAIL, INSUFFICIENT_EVIDENCE, MANUAL_REVIEW]
rules:
- id: answer-floor
metric: answer_correct
min: 0.70
- id: retrieval-floor
metric: hit_rate_at_2
min: 0.80
- id: citations-valid
metric: citations_valid
kind: observed_count
max_failures: 0min ルールは、区間全体が下限を上回るときにのみ合格し、区間全体が下限より下にあるときに不合格となり、それ以外は INSUFFICIENT_EVIDENCE です。observed_count ルールは、区間なしで、実際に実行したケースに基づいて判断します:「このスイートに無効な引用はない」。CI のゲート を参照してください。
実行する
oloproof runRun run_01M4FCBPE0G550CKCVGXCNEM2P [DECIDED/COMPLETE]
Gate: BLOCK (exit 1)
│ answer-floor │ answer_correct │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold │
│ retrieval-floor │ hit_rate_at_2 │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold │
│ citations-valid │ citations_valid │ FAIL │ observed_failures_exceed_limit │
│ answer_correct │ 73.3% │ [44.8%, 92.3%] │ 11 / 15 observed · 0 missing · 0 excluded │
│ hit_rate_at_2 │ 92.3% │ [63.9%, 99.9%] │ 12 / 13 observed · 0 missing · 2 excluded │
│ recall_at_2 │ 92.3% │ [63.9%, 99.9%] │ 12 / 13 observed · 0 missing · 2 excluded │
│ citations_valid │ 93.3% │ [68.0%, 99.9%] │ 14 / 15 observed · 0 missing · 0 excluded │
Cache: execution 0 hit/15 miss; judgment 0 hit/56 miss読み方:
- Gate: BLOCK (exit 1):ルールが FAIL しました。終了コード 1 は FAIL を意味し、終了コード 3 は FAIL なしでゲートがブロックしたことを意味し(ここでは INSUFFICIENT_EVIDENCE がそれに当たります)、終了コード 0 はポリシーがブロックするものが何もないことを意味します。[DECIDED/COMPLETE] は実行状態で、すべてのケースが実行されたことを示します。
- citations-valid は FAIL します。1 つの回答が何も引用しておらず、require_citations はそれを無効として数えます。
- answer-floor は、73.3% が 70% を上回っているにもかかわらず、PASS ではなく INSUFFICIENT_EVIDENCE です。15 ケースでは区間が 44.8% まで下がるため、エビデンスは下限が満たされていることを示せません。
- hit_rate_at_2 は 2 excluded を示します。これはラベルのない 2 ケースです。分母は 15 ではなく 13 です。
- 続く Slices の表は探索的なもので、ゲートには決して使われません。min_slice_support に満たないスライスには区間が表示されません。
失敗を調べる
実行 ID は、実行の出力の最初の行にあります。
oloproof inspect RUN_ID --failures4 of 15 cases failed, errored or did not finish
refund_review
output: {"answer": "Every refund request on an annual plan is logged in the audit trail, and the same request is listed again on the day it was reviewed and approved."…
answer_correct: failed
money_back
output: {"answer": "I could not find that in the knowledge base.", "citations": []}
answer_correct: failed
hit_rate_at_2: failed
recall_at_2: failed
citations_valid: failed
security_review
output: {"answer": "Security reviews during Enterprise onboarding include an access review and a written summary for the customer, and every review is scheduled with t…
answer_correct: failed
seat_count
output: {"answer": "Team plans include five seats.", "citations": ["kb-03"]}
answer_correct: failedoloproof inspect RUN_ID --case refund_review は、1 ケースの入力、期待値、出力、そしてすべての判定を表示します。記録されたアーティファクトはエクスポートしたバンドルにあります:
oloproof export RUN_ID.oloproof/bundles/RUN_ID/cases.jsonl の各行が 1 ケースのレコードで、その artifacts フィールドに記録された内容が入っています。money_back では、そのフィールドは次のとおりです:
{"retrieval/v1": [{"candidates": [], "depth": 6, "query": "Where do I claim money back on a yearly subscription?"}], "context/v1": [{"dropped": [], "items": [], "source": "retrieval", "token_budget": 40}], "citations/v1": [{"ids": []}]}記録されたエビデンスだけから 4 つの失敗を読むと:
| ケース | 記録が示すもの | 意味のある次の行動 |
|---|---|---|
| money_back | 検索は何も返しませんでした。質問は返金のパッセージと 1 語も共有していません | クエリの書き換えや同義語。hit_rate_at_2 で測定します |
| refund_review、security_review | hit_rate_at_2 は合格しましたが、回答は別のパッセージから来ました | context/v1 を調べます。関連するパッセージは予算のために落とされたのでしょうか |
| seat_count | 正しいパッセージが取得され、残され、引用されました。回答は「five」と言い、ケースは「5」を期待しています | 検索ではなく、期待値か回答の形式を直します |
この表は、記録に対するあなたの読みです。失敗とステージの間の関連であって、証明された原因ではありません。ステージを変えてケースを再実行したものは何もないからです。
ブラックボックスに対して diagnose が行うこと
oloproof diagnose RUN_ID --intervention gold-context --criterion answer_correctSelected: 4 failed cases with gold context (observed; no population claim)
UNRESOLVED: 4 of 4, the system is not staged, so no case was re-executed
Diagnosis sha256:8809e100ab2ec1dad8ffeacc136cd510300081a0edf01ec11f881c543ed104bc
Cases: oloproof inspect sha256:8809e100ab2ec1dad8ffeacc136cd510300081a0edf01ec11f881c543ed104bcすべてのケースは理由 intervention_unsupported で UNRESOLVED になります。Oloproof はブラックボックスに、その検索結果の代わりにゴールドパッセージを渡すことができないので、渡したふりもしません。制御された介入には道筋 B が必要です。
候補の変更を行って比較する
記録によれば、money_back は検索で失敗しました。候補の変更は、検索の前に質問を同義語で拡張します。app.py で:
EXPAND_QUERY = Trueコードを変更すると、実行に記録されるシステムのバージョンが変わります。もう一度実行し、候補をベースラインと比較します:
oloproof run
oloproof compare CANDIDATE_RUN_ID BASELINE_RUN_ID --policy compare.yaml候補の実行単体では、citations-valid が PASS するようになり、hit_rate_at_2 は 100.0% [75.2%, 100.0%] を示しますが、answer-floor と retrieval-floor が INSUFFICIENT_EVIDENCE のままなので、ゲートは依然として終了コード 3 でブロックします。比較:
Comparison sha256:2feb024c… of run_01M4FCCJYCVVYA8NB4XZDV6YMB against run_01M4FCCHVBG9WHDP7G5HFX7RDT · 15 paired cases
answer_correct: +6.7 points [-26.5, +40.8] · 15 paired · 0 missing · 0 excluded
hit_rate_at_2: +7.7 points [-29.8, +45.5] · 13 paired · 0 missing · 2 excluded
excluded 2: no_relevance_labels
recall_at_2: +7.7 points [-29.8, +45.5] · 13 paired · 0 missing · 2 excluded
excluded 2: no_relevance_labels
citations_valid: +6.7 points [-26.5, +40.8] · 15 paired · 0 missing · 0 excluded
20 exploratory slice differences not shown; add --slices to list them
Decisions
answers-not-worse answer_correct non-inferiority, margin 5.0 points INSUFFICIENT_EVIDENCE interval_overlaps_margin
about 38 more paired cases would decide it, if the difference holds (53 in total at 7% discordance)
citations-not-worse citations_valid non-inferiority, margin 2.0 points INSUFFICIENT_EVIDENCE interval_overlaps_margin
about 68 more paired cases would decide it, if the difference holds (83 in total at 7% discordance)
Gate: BLOCK (exit 3)変更は狙ったケースを直しました(回答が 1 つ増え、15 個の対応のあるケースで +6.7 ポイント)。それでも比較は、候補がベースラインよりマージンを超えて悪くはないことを立証できません。15 個の対応のあるケースでは、区間の幅はおよそ 67 ポイントあります。計画の行は、差が保たれるなら、あと何件の対応のあるケースで判断できるかを示しています。次の行動は、マージンを変えることではなく、スイートを大きくすることです。候補をベースラインと比較する と 比較ルール を参照してください。
道筋 B:診断付きのステージ化されたアプリケーション
ステージ化のファイル
道筋 B では、RAG の評価 ページで説明している support_rag の例を実行します。コピーします:
oloproof init --example support_rag my-staged-rag
cd my-staged-rag| ファイル | 内容 |
|---|---|
| app.py | @rag_system でデコレートしたクラス SupportRag:retrieve(input, depth)、generate(input, context)、count_tokens(passage) |
| data/corpus.jsonl、data/support.jsonl | ナレッジベースと、それぞれ relevant と gold_context を持つ 13 ケース |
| oloproof.yaml | system.rag がクラスを指し、depth、top_k、token_budget、index_version を設定します |
| release.yaml、compare.yaml | 道筋 A と同じポリシー |
道筋 A との違いは、誰がコンテキストを組み立てるかです。ここでは Oloproof が retrieve を呼び出し、先頭の top_k 個の候補を残し、token_budget を超えたパッセージを落とし、残りを generate に渡します。ステージを分けて保持しているので、それぞれを別々にキャッシュし、異なるコンテキストで生成を再実行できます。自分のアプリケーションに合わせるには、retrieve(インデックスを呼び出し、リトリーバーの順序で Retrieval(candidates=[Passage(...)]) を返す)と generate(与えられたパッセージでモデルを呼び出す)の本体を置き換えてください。index_version は、インデックスが変わると変わる値に設定してください。これは検索の同一性の一部であり、古い値のままだと、もうそれらを返さないインデックスに対してキャッシュされた検索結果が再利用されます。
同じ設定では、relevant_position と context_truncated のスライス、そして検索の深さ全体に対する ndcg 評価器も使えます。
ステージ化されたスイートを実行する
oloproof runGate: BLOCK (exit 3)
│ answer-floor │ answer_correct │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold │
│ retrieval-floor │ hit_rate_at_2 │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold │
│ citations-valid │ citations_valid │ PASS │ observed_failures_within_limit │
│ answer_correct │ 69.2% │ [38.5%, 91.0%] │ 9 / 13 observed · 0 missing · 0 excluded │
│ hit_rate_at_2 │ 92.3% │ [63.9%, 99.9%] │ 12 / 13 observed · 0 missing · 0 excluded │
│ recall_at_2 │ 92.3% │ [63.9%, 99.9%] │ 12 / 13 observed · 0 missing · 0 excluded │
│ ndcg_at_6 │ 0.866 │ [0.506, 0.990] │ mean of 13 observed · 0 missing · 0 excluded │
│ citations_valid │ 100.0% │ [75.2%, 100.0%] │ 13 / 13 observed · 0 missing · 0 excluded │
Cache: execution 0 hit/13 miss; judgment 0 hit/65 miss
Stages: retrieve 0 hit/13 miss; generate 0 hit/13 missStages の行は、ステージ化されたシステム自身のキャッシュです。終了コード 3:何も FAIL していませんが、2 つのルールには PASS するだけのエビデンスがありません。
対照群と並べて、ゴールドコンテキストで診断する
oloproof diagnose RUN_ID --intervention gold-context --criterion answer_correctSelected: 4 failed cases with gold context (observed; no population claim)
Control: 0 of 4 passed when re-executed without the intervention
Recovered under gold context: 3 of 4
RETRIEVAL_MISS: 1 of 4, recovered; no relevant evidence was retrieved
CONTEXT_ASSEMBLY_LOSS: 2 of 4, recovered; relevant evidence within top-k was left out of the context
GENERATION_FAILURE: 1 of 4, still failed with the gold context
Implicated: context budget, in 2 of the 3 recovered failures.
Candidate experiment: a larger token budget. This is a hypothesis to test, not an established cause.
Candidate experiment: smaller chunks. This is a hypothesis to test, not an established cause.
Diagnosis sha256:50a6124f…
Child runs: gold context run_…, control run_…
Cases: oloproof inspect sha256:50a6124f…失敗したケースから 2 つの子実行が作られます。1 つは取得したコンテキストの代わりにケースの gold_context を使うもので、もう 1 つは何も変えずに再実行する対照群です。読みを安全にするのは対照群です。単純な再実行で合格するケースは不安定だったのであって、診断されたのではありません。diagnose は何を見つけても終了コード 0 で終了します。リリースについては何も判断しません。
oloproof inspect DIAGNOSIS_IDmoney_back: RETRIEVAL_MISS, relevant_not_retrieved, strength intervention_recovery, best relevant position none
refund_review: CONTEXT_ASSEMBLY_LOSS, relevant_dropped_from_context, strength intervention_recovery, best relevant position 2
seat_count: GENERATION_FAILURE, fails_with_gold_context, strength intervention_non_recovery, best relevant position 1
security_review: CONTEXT_ASSEMBLY_LOSS, relevant_dropped_from_context, strength intervention_recovery, best relevant position 2ラベルを読む
| ラベル | 観測されたこと | 立証しないこと |
|---|---|---|
| RETRIEVAL_MISS | 関連するパッセージが取得されず、ゴールドパッセージがあればケースは合格した | 検索だけが問題であること、あるいは特定の検索の変更でそれが直ること |
| RANKED_OUT | 関連するパッセージが top_k より下で取得され、ゴールドパッセージがあればケースは合格した | top-k を広げれば他のケースにも役立つこと |
| CONTEXT_ASSEMBLY_LOSS | top-k 内の関連するパッセージがコンテキストから落とされ、ゴールドパッセージがあればケースは合格した | どの予算なら十分か |
| GENERATION_FAILURE | ゴールドパッセージを手にしていてもケースは失敗した | プロンプトや期待値ではなく、モデルに責任があること |
| UNRESOLVED | 何も結論できなかった:システムがステージ化されていない(intervention_unsupported)、ケースが対照群で回復した(unstable_under_control)、関連性ラベルがない(no_relevance_labels)、またはエビデンスが欠けている | そのケースについてのあらゆること |
どのラベルも、これらのケースに対する 1 つの介入のもとでの、失敗とステージの間の関連です。証明された原因ではありません。出力が使う最も強い言葉は「Implicated」と「Candidate experiment」であり、件数は選ばれたケースだけを記述します(「no population claim」)。seat_count はよい教訓です。ナレッジベースは「five」と言い、ケースは「5」を期待しているため、正しいパッセージがあっても失敗します。これはどんな検索の変更でも直せません。
ゴールドパッセージのあるケースとないケース
再実行できるのは、expected.gold_context を宣言している失敗ケースだけです。seat_count と money_back からゴールドパッセージを(そして money_back から関連性ラベルを)取り除くと、同じコマンドは次のように報告します:
Selected: 2 failed cases with gold context (observed; no population claim)
Excluded: 2 failed cases, no_gold_context - declare the passages that would have answered the case in its `expected.gold_context`, as a list of `{doc_id, text}` objects; an intervention needs them to tell a retrieval failure from a generation one
Control: 0 of 2 passed when re-executed without the intervention
Recovered under gold context: 2 of 2
CONTEXT_ASSEMBLY_LOSS: 2 of 2, recovered; relevant evidence within top-k was left out of the context除外されたケースは黙って落とされるのではなく、列挙されます。関連性ラベルを取り除くことが実行そのものに何をもたらすかにも注意してください。hit_rate_at_2 は 100.0%(12 / 12 observed、1 excluded)に上がりました。検索が取りこぼした 1 ケースがもう測定されないからです。ラベルのないケースは分母から外れます。合格としては数えられず、より少ないケースに対するメトリクスはアプリケーションの実力より良く見えることがあります。難しいケースから先にラベルを付けてください。
修正を加える前に試す:top-k とリランカー
さらに 2 つの介入は、記録された検索結果を異なる設定で再生するので、リトリーバーは再び呼び出されません:
oloproof diagnose RUN_ID --intervention top-k --top-k 4 --criterion answer_correctRecovered under top-k 4: 0 of 4
Confirmed under top-k 4: 0 of 0 RANKED_OUT cases also recovered
Labels from gold context (diagnosis sha256:50a6124f…): 3 of 4 recoveredリランカーは、あなたが書く (input, candidates) -> candidates という関数です。app.py の隣に rerank.py として保存します:
"""A candidate reranker: shorter passages first, so more of them fit the token budget."""
from oloproof import Passage
def shortest_first(input: dict, candidates: list[Passage]) -> list[Passage]:
return sorted(candidates, key=lambda passage: len((passage.text or "").split()))oloproof diagnose RUN_ID --intervention reranker --reranker rerank:shortest_first --criterion answer_correctRecovered under reranker rerank:shortest_first: 0 of 4
Confirmed under reranker rerank:shortest_first: 0 of 0 RANKED_OUT cases also recoveredどちらも何も回復させません。これはゴールドコンテキストのラベルが予測したとおりです。ここでの失敗に、カットのすぐ下に順位付けされたパッセージによるものはありませんでした。各再生はゴールドコンテキストのラベルを引き継ぐので、診断は合わせて読めます。
診断が挙げた実験を実行し、比較する
oloproof.yaml で token_budget を 120 に上げてから:
oloproof run
oloproof compare CANDIDATE_RUN_ID BASELINE_RUN_ID --policy compare.yamlStages: retrieve 13 hit/0 miss; generate 7 hit/6 misstop_k と予算は検索の同一性の外にあるので、すべての検索結果が再利用されました。コンテキストが変わった 6 ケースだけが再び生成されました。
answer_correct: +0.0 points [-33.6, +33.6] · 13 paired · 0 missing · 0 excluded
Decisions
answers-not-worse answer_correct non-inferiority, margin 5.0 points INSUFFICIENT_EVIDENCE interval_overlaps_margin
citations-not-worse citations_valid non-inferiority, margin 2.0 points INSUFFICIENT_EVIDENCE interval_overlaps_margin
Gate: BLOCK (exit 3)実験は役に立ちませんでした。判定が変わったケースは 1 つもなく、診断が示した仮説はこれらのケースについては支持されません。これは有用な結果です。次の実験はより小さなチャンク、あるいはコンテキスト組み立ての 2 ケースのプロンプトです。seat_count は期待値を直す必要があります。
トラブルシューティング
| 症状 | 原因 | 対処 |
|---|---|---|
| Configuration error: slice 'relevant_position' ... needs a staged system | callable または HTTP のシステムに位置のスライスを指定した | スライスを外すか、道筋 B に移ります |
| 実行が終了コード 2 と malformed retrieval/v1 artifact で停止する | スキーマが許さないフィールド、または depth を超える候補 | 文書化されたフィールドだけを対応付けます。depth を返される数以上に設定します |
| citations_valid が 0 / 0 observed · 15 missing を示し、そのルールが no_observations で INSUFFICIENT_EVIDENCE になる | アダプターが citations/v1(または context/v1)を記録しませんでした。そのような各ケースは合格ではなく欠損です | 「回答なし」を含め、アダプターのすべての経路で両方を記録します。oloproof inspect RUN_ID --failures でケースごとのエラーがわかります |
| 検索メトリクスに多くの excluded が表示される | expected.relevant のないケース | ラベルを付けるか、小さい分母を承知のうえで受け入れます |
| diagnose が UNRESOLVED ... not staged と言う | 道筋 A | 想定どおりです。介入には道筋 B を使います |
| diagnose が an intervention must re-execute the same system で拒否する | 実行以降にコードか設定が変わった | 現在のバージョンの実行を診断するか、実行したバージョンに戻します |
| 診断が、失敗した数より少ないケースを選ぶ | expected.gold_context のない失敗ケース | ゴールドパッセージを追加します。除外されたケースは出力に名前が示されます |
| インデックスが変わった後も検索結果が再利用される | index_version が変わっていない | インデックスが変わったら index_version を変更します |
制限事項
- Oloproof はあなたのアプリケーションを呼び出しますが、ホストも、サンドボックス化も、リセットもしません。そのインデックス、キャッシュ、保持する状態はあなたのものです。
- ブラックボックスでは介入は使えません。diagnose はすべてのケースを UNRESOLVED とし、何も再実行しません。
- 介入はゴールドコンテキスト、top-k、リランカーです。チャンク分割、埋め込み、プロンプトの介入はありません。
- 診断ラベルは、対照群と並べた 1 つの介入のもとで、選ばれた失敗ケースを記述します。失敗とステージを関連付けますが、原因を証明するものではなく、選ばれなかったケースについては何も主張しません。
- 検索メトリクスには関連性ラベルが、診断にはゴールドパッセージが必要です。Oloproof はどちらも作成しません。
- 決定的な例は、実際のリトリーバーとモデルの代わりです。generate 内の実際のモデルやジャッジ評価器はプロバイダーを呼び出し、認証情報が必要で、ケースごとに費用がかかります。
- SDK、YAML、ブラウザのどこで何が動作するかは 現在動作するもの にあります。