본문으로 건너뛰기

가이드

튜토리얼: RAG 애플리케이션 평가하기

검색 증강 애플리케이션을 위한 실행 가능한 안내로, 두 경로가 있습니다. 하나는 검색, 컨텍스트, 인용을 바깥에서 기록하는 기존 블랙박스 애플리케이션이고, 다른 하나는 Oloproof가 단계별로 실행하여 oloproof diagnose가 실패한 케이스를 통제된 변경 아래에서 다시 실행할 수 있는 단계형 애플리케이션입니다. 둘 다 제공자 자격 증명 없이 로컬에서 실행됩니다.

각 단계의 배경 개념(단계, 관련성 레이블, 정답 컨텍스트, 네 가지 실패 레이블)은 RAG 평가 페이지에 있고, 케이스, 평가기, 지표, 구간, 게이트 같은 용어는 핵심 개념에 있습니다. 이 페이지는 그것들을 직접 따라가는 실습 경로입니다.

어느 경로가 여러분의 것인가

여러분의 애플리케이션경로얻는 것얻지 못하는 것
호출 하나에 답 하나(서비스, HTTP 엔드포인트, 나누고 싶지 않은 프레임워크 체인)A, 블랙박스검색 지표, 인용 검사, 근거성 심사 모델, 게이팅, 비교통제된 개입: diagnose는 아무것도 다시 실행하지 않음
검색과 생성을 따로 호출할 수 있음B, 단계형A의 모든 것, 단계별 캐싱, 그리고 대조군 옆에서 정답 컨텍스트, top-k, 리랭커로 하는 diagnose그 세 가지 외의 개입

확실하지 않다면 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.yamlHTTP 서버를 대상으로 하는 같은 스위트
release.yaml단일 실행에 대한 릴리스 정책
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은 애플리케이션을 그대로 호출하고, 응답을 검색 및 인용 평가기가 읽는 기록인 세 가지 타입의 아티팩트로 옮깁니다:

@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), reason이 top_k 또는 token_budget인 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 시스템은 레코더를 호출할 수 없으므로, 대신 응답이 위의 세 가지 형태로 근거를 담고, 구성이 그 위치를 지정합니다:

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 본문으로 POST됩니다. 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합니다. 답 하나가 아무것도 인용하지 않았고, require_citations는 그것을 잘못된 것으로 셉니다.
  • answer-floor는 73.3%가 70%보다 높은데도 PASS가 아니라 INSUFFICIENT_EVIDENCE입니다. 케이스 15개로는 구간이 44.8%까지 내려가므로, 근거가 하한 충족을 보일 수 없습니다.
  • hit_rate_at_2는 2 excluded로 나옵니다. 레이블 없는 두 케이스입니다. 분모는 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는 한 케이스의 입력, 기대값, 출력, 모든 판정을 출력합니다. 기록된 아티팩트는 내보낸 번들에 있습니다:

oloproof export RUN_ID

.oloproof/bundles/RUN_ID/cases.jsonl의 각 줄은 한 케이스의 기록이며, 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": []}]}

기록된 근거만으로 네 실패를 읽으면:

케이스기록이 보여 주는 것의미 있는 다음 행동
money_back검색이 아무것도 반환하지 않음: 질문이 환불 단락과 공유하는 단어가 없음질의 재작성이나 동의어, 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)

변경은 목표로 한 케이스를 고쳤습니다(답 하나 추가, 짝지은 케이스 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은 없지만, 두 규칙이 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…

실패한 케이스로 자식 실행 두 개가 만들어집니다. 하나는 검색된 컨텍스트 대신 케이스의 gold_context를 넣은 것이고, 다른 하나는 그대로 다시 실행하는 대조군입니다. 대조군이 해석을 안전하게 만듭니다. 단순히 다시 실행해서 통과하는 케이스는 진단된 것이 아니라 불안정했던 것입니다. 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), 근거가 누락됨그 케이스에 관한 어떤 것도

모든 레이블은 이 케이스들에 대한 하나의 개입 아래에서 실패와 단계 사이의 연관입니다. 입증된 원인이 아닙니다. "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)로 올랐습니다. 레이블 없는 케이스는 분모에서 빠집니다. 통과로 세지 않으며, 더 적은 케이스에 대한 지표는 애플리케이션의 실제보다 좋아 보일 수 있습니다. 어려운 케이스부터 레이블을 다십시오.

수정하기 전에 시험하기: top-k와 리랭커

두 가지 개입이 더 있으며, 기록된 검색을 다른 설정으로 재생하므로 검색기를 다시 호출하지 않습니다:

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와 예산은 검색의 정체성 밖에 있으므로 모든 검색이 재사용되었습니다. 컨텍스트가 바뀐 여섯 케이스만 다시 생성되었습니다.

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)

실험은 도움이 되지 않았습니다. 판정이 바뀐 케이스가 하나도 없으므로, 진단이 제시한 가설은 이 케이스들에 대해 뒷받침되지 않습니다. 이것도 유용한 결과입니다. 다음 실험은 더 작은 청크, 또는 두 컨텍스트 조립 케이스의 프롬프트이며, 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, 리랭커입니다. 청킹, 임베딩, 프롬프트 개입은 없습니다.
  • 진단 레이블은 대조군 옆에서 하나의 개입 아래 선택된 실패 케이스를 기술합니다. 실패를 단계와 연관 지을 뿐 원인을 입증하지 않으며, 선택되지 않은 케이스에 대해서는 아무것도 주장하지 않습니다.
  • 검색 지표에는 관련성 레이블이, 진단에는 정답 단락이 필요합니다. Oloproof는 어느 것도 만들어 내지 않습니다.
  • 결정적 예제는 실제 검색기와 모델을 대신합니다. generate의 실제 모델이나 심사 모델 평가기는 제공자를 호출하며, 자격 증명이 필요하고 케이스마다 비용이 듭니다.
  • SDK, YAML, 브라우저 중 어디에서 무엇이 동작하는지는 지금 동작하는 것에 있습니다.