本文へスキップ

ガイド

チュートリアル: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.jsonl15 ケース:13 ケースは関連性ラベルとゴールドパッセージを持ち、2 ケースはどちらも持ちません
oloproof.yamlスイート:データセット、システム、評価器、スライス
oloproof.http.yamlHTTP サーバーに対する同じスイート
release.yaml1 回の実行に対するリリースポリシー
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/v1query、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_budgetcitation_validity、groundedness_judge、citation_support_judge
citations/v1ids。それぞれが doc_id または doc_id#chunk_idcitation_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.citations

server.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: 0

min ルールは、区間全体が下限を上回るときにのみ合格し、区間全体が下限より下にあるときに不合格となり、それ以外は INSUFFICIENT_EVIDENCE です。observed_count ルールは、区間なしで、実際に実行したケースに基づいて判断します:「このスイートに無効な引用はない」。CI のゲート を参照してください。

実行する

oloproof run
Run 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 --failures
4 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: failed

oloproof 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_reviewhit_rate_at_2 は合格しましたが、回答は別のパッセージから来ましたcontext/v1 を調べます。関連するパッセージは予算のために落とされたのでしょうか
seat_count正しいパッセージが取得され、残され、引用されました。回答は「five」と言い、ケースは「5」を期待しています検索ではなく、期待値か回答の形式を直します

この表は、記録に対するあなたの読みです。失敗とステージの間の関連であって、証明された原因ではありません。ステージを変えてケースを再実行したものは何もないからです。

ブラックボックスに対して diagnose が行うこと

oloproof diagnose RUN_ID --intervention gold-context --criterion answer_correct
Selected: 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.yamlsystem.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 run
Gate: 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 miss

Stages の行は、ステージ化されたシステム自身のキャッシュです。終了コード 3:何も FAIL していませんが、2 つのルールには PASS するだけのエビデンスがありません。

対照群と並べて、ゴールドコンテキストで診断する

oloproof diagnose RUN_ID --intervention gold-context --criterion answer_correct
Selected: 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_ID
money_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_LOSStop-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_correct
Recovered 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_correct
Recovered 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.yaml
Stages: retrieve 13 hit/0 miss; generate 7 hit/6 miss

top_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 systemcallable または 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、ブラウザのどこで何が動作するかは 現在動作するもの にあります。