Guide
Valutazione RAG
La versione inglese di questa pagina è cambiata da quando è stata tradotta. La pagina inglese è quella aggiornata. Leggila in inglese
Una risposta generata con recupero può essere sbagliata per quattro ragioni diverse: il passaggio giusto non è mai stato recuperato, è stato recuperato ma classificato troppo in basso, è stato classificato abbastanza in alto ma poi scartato dal contesto, oppure ha raggiunto il modello e il modello ha sbagliato comunque. Un unico numero di accuratezza non può distinguerle. Oloproof esegue un sistema RAG come due stadi che può osservare, misura ciascuno e riesegue i casi falliti sotto modifiche controllate per scoprire quale ragione si applica.
examples/support_rag/ è il progetto eseguito in questa pagina. Non richiede credenziali di provider.
Un sistema a stadi
Il sistema è una classe con uno stadio di recupero e uno stadio di generazione, decorata con @rag_system:
from oloproof import Passage, Retrieval, rag_system
@rag_system(
name="support-rag",
version="slice-b-example",
depth=6,
top_k=2,
token_budget=40,
index_version="kb-2026-09-16",
)
class SupportRag:
def retrieve(self, input, depth):
...
return Retrieval(query=input["question"], depth=depth, candidates=tuple(passages))
def generate(self, input, context):
...
return {"answer": answer, "citations": [best.doc_id]}
def count_tokens(self, passage):
return len((passage.text or "").split())retrieve(input, depth) restituisce fino a depth candidati, come Passage(doc_id=..., score=..., text=...), nell'ordine in cui li ha prodotti il tuo retriever. Oloproof registra le posizioni e non riordina mai. Poi conserva i primi top_k, scarta i passaggi oltre token_budget e passa ciò che resta a generate(input, context). count_tokens(passage) serve solo con un token_budget; Oloproof non stima mai i token.
oloproof.yaml punta alla classe e può sovrascrivere qualsiasi sua impostazione:
system:
name: support-rag
version: slice-b-example
rag:
object: app:SupportRag
depth: 6
top_k: 2
token_budget: 40
index_version: kb-2026-09-16index_version fa parte dell'identità del recupero. Cambialo quando cambia l'indice, altrimenti i recuperi in cache verranno riutilizzati con un indice che non li restituisce più.
Che cosa dichiara un caso
Un caso RAG riporta sotto expected due campi di cui nessun altro tipo di caso ha bisogno:
{"id":"refund_annual","input":{"question":"How long do refunds take for annual plans?"},"expected":{"answer":"14 days","relevant":[{"doc_id":"kb-01"}],"gold_context":[{"doc_id":"kb-01","text":"Refunds for annual plans are issued within 14 days of an approved request. Support reviews each request on the same business day."}]},"metadata":{"topic":"billing"}}- expected.relevant elenca i documenti che rispondono alla domanda. Le metriche di recupero lo
leggono, e un caso che ne è privo viene escluso da esse con no_relevance_labels.
- expected.gold_context è il testo stesso del passaggio. La diagnosi lo sostituisce al contesto
recuperato, e un caso fallito che ne è privo non può essere diagnosticato.
I valutatori
evaluators:
- {type: contains, criterion: answer_correct, field: answer, expected_field: answer}
- {type: hit_rate, k: 2}
- {type: recall, k: 2}
- {type: ndcg, k: 6}
- {type: citation_validity}
slices: [metadata.topic, relevant_position, context_truncated]
min_slice_support: 4hit_rate, recall, mrr e ndcg accettano k e ne derivano il nome del proprio criterio: hit_rate_at_2. Una voce in expected.relevant può anche riportare un chunk_id e un grade, che vale 1 per impostazione predefinita; relevance_unit: chunk conta allora ogni chunk come unità a sé anziché documenti interi. citation_validity verifica che ogni id citato da una risposta indichi un passaggio del contesto che le è stato fornito, e con require_citations: true una risposta che non cita nulla fallisce. groundedness_judge e citation_support_judge sono giudici LLM che leggono il contesto assemblato, e accettano un provider e un model come qualsiasi altro giudice.
oloproof runTre righe della tabella delle metriche:
│ answer_correct │ 69.2% │ [38.5%, 91.0%] │ 9 / 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 │Tra queste, hit_rate_at_2 e recall_at_2 riportano entrambe 92,3%, 12 su 13 osservati, con un limite inferiore di 63,9%: il passaggio rilevante di una domanda non è mai stato recuperato.
Cache: execution 0 hit/13 miss; judgment 0 hit/65 miss
Stages: retrieve 0 hit/13 miss; generate 0 hit/13 missLa riga Stages è la cache propria del sistema a stadi. Recupero e generazione sono in cache separatamente, quindi una modifica alla generazione non riesegue mai il recupero.
Scoprire il perché
Quattro domande sono fallite. diagnose le riesegue con il passaggio gold al posto del contesto recuperato, accanto a un controllo che le riesegue senza modifiche:
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:b2846cbe04099225bda4bf21beb1738f54d6cc0e9a7ce210bb3eb467619cbd69
Child runs: gold context run_01M3C3REAAZDF9FD8N2C8BG17P, control run_01M3C3REAFVXK2VM4MYAQYH6KE
Cases: oloproof inspect sha256:b2846cbe04099225bda4bf21beb1738f54d6cc0e9a7ce210bb3eb467619cbd69Un caso che passa con il passaggio gold e fallisce senza di esso è fallito a monte del modello. Un caso che fallisce con il passaggio gold a disposizione è imputabile al modello. È il controllo a rendere sicura questa lettura: un caso che si recupera con una semplice riesecuzione era instabile, non diagnosticato.
L'id della diagnosi elenca il caso dietro ogni conteggio:
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 2Nomina un fattore, mai una causa. "Implicated" e "candidate experiment" sono le parole più forti che usa, perché quattro casi che si recuperano sotto un intervento non stabiliscono perché sono falliti.
Testare una correzione prima di applicarla
Altri due interventi riproducono il recupero registrato con un'impostazione diversa, quindi non viene effettuata alcuna chiamata al retriever. top-k allarga il taglio:
oloproof diagnose RUN_ID --intervention top-k --top-k 4 --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 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:b2846cbe04099225bda4bf21beb1738f54d6cc0e9a7ce210bb3eb467619cbd69): 3 of 4 recovered
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
Diagnosis sha256:668084c3e99df84f7b63f138792aa96f48e5cb8251fee3acae8e1cc0500ba085
Child runs: gold context run_01M3C3REAAZDF9FD8N2C8BG17P, control run_01M3C3REAFVXK2VM4MYAQYH6KE, top-k 4 run_01M3C3RKHTGGV37079V11JJ78M, replay control run_01M3C3RKJ076K7MSVQ94J4ZE2P
Cases: oloproof inspect sha256:668084c3e99df84f7b63f138792aa96f48e5cb8251fee3acae8e1cc0500ba085Nulla si è recuperato, ed è ciò che le etichette prevedevano: nessun fallimento qui era un passaggio classificato appena sotto il taglio. La riproduzione porta avanti le etichette del contesto gold, così le due diagnosi si leggono insieme. reranker accetta --reranker con un module:function e riproduce invece il recupero attraverso il tuo reranker.
Eseguire l'esperimento
La diagnosi ha indicato un budget di token più ampio. Porta token_budget a 120 ed esegui di nuovo:
Cache: execution 0 hit/13 miss; judgment 0 hit/65 miss
Stages: retrieve 13 hit/0 miss; generate 7 hit/6 missOgni recupero è stato riutilizzato, perché top_k e il budget di token sono al di fuori dell'identità del recupero; sono stati generati di nuovo solo i sei casi il cui contesto è cambiato. Poi confronta, con la policy di confronto dell'esempio:
oloproof compare CANDIDATE_RUN_ID BASELINE_RUN_ID --policy compare.yamlComparison sha256:d801ed897f1fa1b196ca1e3f73a1ef4ffe6845d6ee8bddaea8a44da94d27a75b of run_01M3C3RYJZ4PAJ8P4P9NT71360 against run_01M3C3R5Y9D18WGSZQFA7N4XRT · 13 paired cases
answer_correct: +0.0 points [-33.6, +33.6] · 13 paired · 0 missing · 0 excluded
hit_rate_at_2: +0.0 points [-33.6, +33.6] · 13 paired · 0 missing · 0 excluded
recall_at_2: +0.0 points [-33.6, +33.6] · 13 paired · 0 missing · 0 excluded
ndcg_at_6: +0.0 points [-33.6, +33.6] · 13 paired · 0 missing · 0 excluded
citations_valid: +0.0 points [-33.6, +33.6] · 13 paired · 0 missing · 0 excludedSegue una riga esplorativa per ogni slice e metrica, e poi le decisioni:
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)L'esperimento non è servito: nessuno dei tredici casi ha cambiato verdetto. E tredici casi appaiati non avrebbero potuto stabilire una modifica di qualsiasi entità che interessi a un rilascio, che è l'altra cosa che dice l'intervallo.
Dove andare dopo
- Slice tratta relevant_position e context_truncated.
- Regole di confronto tratta le regole con cui è stato deciso l'ultimo
passaggio.
- Giudici tratta ciò che un giudice di groundedness deve superare prima di poter
fare da gate.