Guías
Tutorial: evaluar una aplicación RAG
Un recorrido ejecutable por una aplicación aumentada con recuperación, en dos caminos: una aplicación de caja negra existente cuya recuperación, contexto y citas usted registra desde fuera, y una aplicación por etapas que Oloproof ejecuta etapa por etapa para que oloproof diagnose pueda volver a ejecutar los casos fallidos bajo cambios controlados. Ambos se ejecutan en local sin credenciales de proveedor.
Los conceptos que hay detrás de cada paso (etapas, etiquetas de relevancia, contexto de referencia, las cuatro etiquetas de fallo) están en la página Evaluación RAG; los términos caso, evaluador, métrica, intervalo y gate están en Conceptos básicos. Esta página es el recorrido práctico por ellos.
Qué camino es el suyo
| Su aplicación | Camino | Qué obtiene | Qué no obtiene |
|---|---|---|---|
| Una llamada de entrada, una respuesta de salida (un servicio, un endpoint HTTP, una cadena de un framework que no quiere dividir) | A, caja negra | Métricas de recuperación, comprobaciones de citas, jueces de fundamentación, gates, comparación | Intervenciones controladas: diagnose no vuelve a ejecutar nada |
| Recuperación y generación que puede llamar por separado | B, por etapas | Todo lo de A, caché por etapa, y diagnose con contexto de referencia, top-k y un reranker junto a un control | Intervenciones distintas de esas tres |
Empiece por A si no está seguro. No necesita ningún cambio en la aplicación, y pasar a B más adelante conserva el conjunto de datos, los evaluadores y la política.
Requisitos previos
- Python 3.11 o posterior, y Oloproof instalado (pip install oloproof).
- Los proyectos de ejemplo, que vienen con el paquete: blackbox_rag para el camino A y support_rag para el camino B. Copie uno en un directorio nuevo y trabaje allí:
oloproof init --example blackbox_rag my-rag
cd my-ragCada comando de abajo se ejecuta dentro del directorio copiado. Las ejecuciones, los juicios y los diagnósticos se guardan allí, en .oloproof/.
Camino A: una aplicación existente como caja negra
Los archivos
| Archivo | Qué es |
|---|---|
| app.py | support_api(question), que hace las veces de su aplicación, y run(case), el adaptador |
| server.py | La misma aplicación sobre HTTP, para la variante HTTP de abajo |
| data/corpus.jsonl | La base de conocimiento de 14 pasajes en la que busca la aplicación |
| data/support.jsonl | 15 casos: 13 con etiquetas de relevancia y pasajes de referencia, 2 sin ninguno de los dos |
| oloproof.yaml | La suite: conjunto de datos, sistema, evaluadores, segmentos |
| oloproof.http.yaml | La misma suite contra el servidor HTTP |
| release.yaml | La política de publicación para una sola ejecución |
| compare.yaml | La política para comparar una ejecución candidata con una línea base |
Qué devuelve la aplicación
support_api se comporta como una aplicación que usted ya tiene: busca, construye un prompt con las mejores fuentes que caben en un presupuesto de palabras, responde y cita. Su respuesta ya lleva lo que hizo:
{
"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"}]
}Los nombres de campo de su aplicación serán distintos. Lo que importa es que pueda decirle, por pregunta, las fuentes ordenadas que recuperó, las que llegaron al modelo y las que citó. Si no puede, añádalas primero a su respuesta o a sus registros: Oloproof mide lo que se registra y nunca deduce la recuperación a partir de una respuesta.
El adaptador
run llama a la aplicación sin cambios y traslada la respuesta a tres artefactos tipados, los registros que leen los evaluadores de recuperación y de citas:
@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"]}| Artefacto | Forma | Leído por |
|---|---|---|
| retrieval/v1 | query, depth, y candidates en el orden en que los devolvió su recuperador, cada uno un Passage(doc_id, chunk_id, score, text) | hit_rate, recall, mrr, ndcg |
| context/v1 | los items que llegaron al modelo (doc_id, position, tokens, text), los elementos dropped con un reason de top_k o token_budget, y token_budget | citation_validity, groundedness_judge, citation_support_judge |
| citations/v1 | ids, cada uno un doc_id o doc_id#chunk_id | citation_validity, citation_support_judge |
Oloproof registra las posiciones tal como se dan y nunca reordena. Un artefacto mal formado detiene la ejecución con el código de salida 2 en lugar de guardarse. case es el objeto input del caso, así que case["question"] es la pregunta del conjunto de datos.
Para usar su propia aplicación, sustituya el cuerpo de support_api por una llamada a ella (una llamada a un SDK, una petición HTTP) y conserve run. Apunte system.callable en oloproof.yaml hacia ella como module:function.
La variante HTTP
Un sistema HTTP no puede llamar al registrador, así que su respuesta lleva la evidencia en su lugar, ya en las tres formas de arriba, y la configuración indica dónde:
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 sirve exactamente eso. Inícielo y luego ejecute contra él:
python server.py 8766
oloproof run --config oloproof.http.yamlLa entrada del caso se envía como cuerpo JSON. output_path extrae la salida de la respuesta, y cada entrada de artifacts registra una ruta con puntos como ese tipo; un campo ausente o mal formado detiene la ejecución con el código de salida 2. Los resultados son idénticos a los del camino con callable de abajo. En su propio servicio, el objeto de evidencia suele ser un campo de depuración que se activa para el tráfico de evaluación.
Qué declara un caso
{"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 enumera los pasajes que responden a la pregunta. Las métricas de recuperación lo leen. Un caso sin él, como office_hours, queda excluido de ellas con no_relevance_labels: sale del denominador en lugar de contar como aprobado o como fallo.
- expected.gold_context es el propio texto del pasaje. El camino A nunca lo usa; el camino B lo pone en lugar del contexto recuperado durante el diagnóstico.
Los casos sin etiquetar son normales en la práctica, ya que etiquetar la relevancia cuesta trabajo. Siguen contando para las comprobaciones de la respuesta y de las citas.
Elegir los evaluadores
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 comprueba que la respuesta contiene el texto esperado. Es la comprobación de la tarea: ¿obtuvo el usuario la respuesta correcta? Use en su lugar un juez exacto o de rúbrica cuando la redacción varíe.
- hit_rate y recall con k: 2 miden la recuperación a la profundidad que la aplicación pone de verdad en el prompt. Una métrica de recuperación a una profundidad que el modelo nunca ve describe el índice, no la aplicación.
- citation_validity comprueba que cada id citado nombra un pasaje que llegó al modelo; require_citations: true también hace fallar una respuesta que no cita nada.
- groundedness_judge y citation_support_judge (opcionales) preguntan a un modelo si el contexto respalda la respuesta. Necesitan un proveedor, un modelo y credenciales en una variable de entorno, y cuestan dinero por caso; vea en Jueces lo que un juez debe superar antes de poder hacer gate.
Los segmentos relevant_position y context_truncated no están disponibles aquí: comparan posiciones con el top-k de la aplicación, que solo declara un sistema por etapas. Pedirlos detiene la ejecución con slice 'relevant_position' compares relevant positions with top_k, so it needs a staged system.
La política de publicación
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: 0Una regla min pasa solo cuando todo el intervalo supera el mínimo, falla cuando todo el intervalo queda por debajo, y es INSUFFICIENT_EVIDENCE en otro caso. Una regla observed_count decide sobre los casos realmente ejecutados, sin intervalo: "ninguna cita inválida en esta suite". Vea Gates en CI.
Ejecútelo
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 missCómo leerlo:
- Gate: BLOCK (exit 1): una regla dio FAIL. La salida 1 significa un FAIL; la salida 3 significa que el gate bloqueó sin un FAIL (aquí sería INSUFFICIENT_EVIDENCE); la salida 0 significa nada en lo que la política bloquee. [DECIDED/COMPLETE] es el estado de ejecución: se ejecutaron todos los casos.
- citations-valid da FAIL: una respuesta no citó nada, y require_citations lo cuenta como inválido.
- answer-floor es INSUFFICIENT_EVIDENCE, no PASS, aunque 73.3% está por encima del 70%: con 15 casos el intervalo baja hasta 44.8%, así que la evidencia no puede mostrar que se alcanza el mínimo.
- hit_rate_at_2 indica 2 excluded: los dos casos sin etiquetar. Su denominador es 13, no 15.
- La tabla Slices que sigue es exploratoria y nunca hace gate; un segmento por debajo de min_slice_support no muestra intervalo.
Inspeccionar los fallos
El id de la ejecución está en la primera línea de su salida.
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 imprime la entrada, los valores esperados, la salida y todos los juicios de un caso. Los artefactos registrados están en el paquete exportado:
oloproof export RUN_IDCada línea de .oloproof/bundles/RUN_ID/cases.jsonl es el registro de un caso; su campo artifacts contiene lo que se registró. Para money_back, ese campo dice:
{"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": []}]}Leer los cuatro fallos solo a partir de la evidencia registrada:
| Caso | Qué muestra el registro | Una siguiente acción con sentido |
|---|---|---|
| money_back | La recuperación no devolvió nada: la pregunta no comparte ninguna palabra con el pasaje de reembolsos | Reescritura de la consulta o sinónimos, medidos con hit_rate_at_2 |
| refund_review, security_review | hit_rate_at_2 pasó, y sin embargo la respuesta salió de otro pasaje | Inspeccionar context/v1: ¿se descartó el pasaje relevante por el presupuesto? |
| seat_count | Se recuperó, se conservó y se citó el pasaje correcto; la respuesta dice "five", el caso espera "5" | Corregir la expectativa o el formato de la respuesta, no la recuperación |
Esa tabla es su lectura del registro. Es una asociación entre un fallo y una etapa, no una causa demostrada: nada volvió a ejecutar el caso con la etapa cambiada.
Qué hace diagnose con una caja negra
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:8809e100ab2ec1dad8ffeacc136cd510300081a0edf01ec11f881c543ed104bcTodos los casos son UNRESOLVED con el motivo intervention_unsupported. Oloproof no puede darle a una caja negra el pasaje de referencia en lugar de su propia recuperación, así que no finge hacerlo. Las intervenciones controladas necesitan el camino B.
Hacer un cambio candidato y comparar
El registro dice que money_back falló en la recuperación. El cambio candidato amplía la pregunta con sinónimos antes de buscar. En app.py:
EXPAND_QUERY = TrueCambiar el código cambia la versión del sistema registrada para la ejecución. Ejecute de nuevo y luego compare el candidato con la línea base:
oloproof run
oloproof compare CANDIDATE_RUN_ID BASELINE_RUN_ID --policy compare.yamlLa ejecución candidata por sí sola: citations-valid ahora da PASS, hit_rate_at_2 indica 100.0% [75.2%, 100.0%], y el gate sigue bloqueando con la salida 3 porque answer-floor y retrieval-floor siguen en INSUFFICIENT_EVIDENCE. La comparación:
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)El cambio arregló el caso al que apuntaba (una respuesta más, +6.7 puntos sobre 15 casos emparejados). La comparación todavía no puede establecer que el candidato no sea peor que la línea base en más del margen: 15 casos emparejados dejan un intervalo de unos 67 puntos de ancho. La línea de planificación dice cuántos casos emparejados más lo decidirían si la diferencia se mantuviera. La siguiente acción es una suite más grande, no un margen distinto. Vea Comparar dos ejecuciones y Reglas de comparación.
Camino B: una aplicación por etapas con diagnóstico
Los archivos por etapas
El camino B ejecuta el ejemplo support_rag, descrito en la página Evaluación RAG. Cópielo:
oloproof init --example support_rag my-staged-rag
cd my-staged-rag| Archivo | Qué es |
|---|---|
| app.py | SupportRag, una clase decorada con @rag_system: retrieve(input, depth), generate(input, context), count_tokens(passage) |
| data/corpus.jsonl, data/support.jsonl | La base de conocimiento, y 13 casos, cada uno con relevant y gold_context |
| oloproof.yaml | system.rag apunta a la clase y fija depth, top_k, token_budget, index_version |
| release.yaml, compare.yaml | Las mismas políticas que en el camino A |
La diferencia con el camino A es quién arma el contexto. Aquí Oloproof llama a retrieve, conserva los primeros top_k candidatos, descarta los pasajes que superan token_budget y pasa el resto a generate. Como mantiene las etapas separadas, puede guardarlas en caché por separado y volver a ejecutar la generación con otro contexto. Para adaptar su propia aplicación, sustituya los cuerpos de retrieve (llame a su índice, devuelva Retrieval(candidates=[Passage(...)]) en el orden de su recuperador) y de generate (llame a su modelo con los pasajes dados). Fije index_version a algo que cambie cuando cambie su índice: forma parte de la identidad de la recuperación, y un valor desactualizado reutiliza recuperaciones en caché contra un índice que ya no las devuelve.
La misma configuración también permite los segmentos relevant_position y context_truncated, y un evaluador ndcg sobre toda la profundidad de recuperación.
Ejecutar la suite por etapas
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 missLa línea Stages es la caché propia del sistema por etapas. Salida 3: nada dio FAIL, pero a dos reglas les falta la evidencia para dar PASS.
Diagnosticar con contexto de referencia, junto a un control
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…Se crean dos ejecuciones hijas a partir de los casos fallidos: una con el gold_context del caso en lugar del contexto recuperado, y un control que los vuelve a ejecutar sin cambios. El control es lo que hace segura la lectura: un caso que pasa en una simple repetición era inestable, no diagnosticado. diagnose termina con 0 sea lo que sea lo que encuentre; no decide nada sobre la publicación.
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 2Leer las etiquetas
| Etiqueta | Qué se observó | Qué no establece |
|---|---|---|
| RETRIEVAL_MISS | No se recuperó ningún pasaje relevante, y el caso pasó con el pasaje de referencia | Que la recuperación sea lo único que falla, o que un cambio concreto de recuperación lo vaya a arreglar |
| RANKED_OUT | Se recuperó un pasaje relevante por debajo de top_k, y el caso pasó con el pasaje de referencia | Que ampliar el top-k vaya a ayudar a otros casos |
| CONTEXT_ASSEMBLY_LOSS | Un pasaje relevante dentro del top-k se descartó del contexto, y el caso pasó con el pasaje de referencia | Qué presupuesto bastaría |
| GENERATION_FAILURE | El caso siguió fallando con el pasaje de referencia en mano | Que la culpa sea del modelo, y no del prompt o de la expectativa |
| UNRESOLVED | No se pudo concluir nada: el sistema no es por etapas (intervention_unsupported), el caso se recuperó bajo el control (unstable_under_control), no tiene etiquetas de relevancia (no_relevance_labels), o falta evidencia | Nada sobre el caso |
Cada etiqueta es una asociación entre un fallo y una etapa bajo una intervención sobre estos casos. No es una causa demostrada: "Implicated" y "Candidate experiment" son las palabras más fuertes que usa la salida, y los recuentos describen solo los casos seleccionados ("no population claim"). seat_count es un buen recordatorio: falla con el pasaje correcto porque la base de conocimiento dice "five" y el caso espera "5", algo que ningún cambio de recuperación puede arreglar.
Casos con y sin pasajes de referencia
Solo se pueden volver a ejecutar los casos fallidos que declaran expected.gold_context. Quite el pasaje de referencia de seat_count y money_back (y la etiqueta de relevancia de money_back) y el mismo comando informa:
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 contextLos casos excluidos se enumeran, no se descartan en silencio. Fíjese también en lo que quitar una etiqueta de relevancia le hace a la propia ejecución: hit_rate_at_2 subió al 100.0% (12 / 12 observed, 1 excluded), porque el único caso que la recuperación falló ya no se mide. Los casos sin etiquetar salen del denominador; no cuentan como aprobados, y una métrica sobre menos casos puede parecer mejor de lo que es la aplicación. Etiquete primero los casos difíciles.
Probar un arreglo antes de hacerlo: top-k y un reranker
Otras dos intervenciones reproducen la recuperación registrada con otro ajuste, de modo que no se vuelve a llamar al recuperador:
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 recoveredUn reranker es una función (input, candidates) -> candidates que usted escribe. Guárdela como rerank.py junto a app.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 recoveredNinguna recupera nada, que es lo que predecían las etiquetas del contexto de referencia: ningún fallo aquí era un pasaje clasificado justo por debajo del corte. Cada reproducción arrastra las etiquetas del contexto de referencia, de modo que los diagnósticos se leen juntos.
Ejecutar el experimento que nombró el diagnóstico, y comparar
Suba token_budget a 120 en oloproof.yaml y luego:
oloproof run
oloproof compare CANDIDATE_RUN_ID BASELINE_RUN_ID --policy compare.yamlStages: retrieve 13 hit/0 miss; generate 7 hit/6 missSe reutilizaron todas las recuperaciones, porque top_k y el presupuesto quedan fuera de la identidad de la recuperación; solo se volvieron a generar los seis casos cuyo contexto cambió.
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)El experimento no ayudó: ni un solo caso cambió de veredicto, así que la hipótesis que ofreció el diagnóstico no se sostiene para estos casos. Es un resultado útil. El siguiente experimento son fragmentos más pequeños, o los prompts de los dos casos de armado del contexto; seat_count necesita que se corrija su expectativa.
Resolución de problemas
| Síntoma | Causa | Solución |
|---|---|---|
| Configuration error: slice 'relevant_position' ... needs a staged system | Un segmento de posición en un sistema callable o HTTP | Quite el segmento, o pase al camino B |
| La ejecución se detiene con la salida 2 y malformed retrieval/v1 artifact | Un campo que el esquema no permite, o más candidatos que depth | Traslade solo los campos documentados; fije depth al menos al número devuelto |
| citations_valid indica 0 / 0 observed · 15 missing y su regla es INSUFFICIENT_EVIDENCE con no_observations | El adaptador no registró citations/v1 (o context/v1); cada caso así está ausente, no aprobado | Registre ambos en todos los caminos del adaptador, incluido "sin respuesta"; oloproof inspect RUN_ID --failures muestra el error por caso |
| Una métrica de recuperación muestra muchos excluded | Casos sin expected.relevant | Etiquételos, o acepte a sabiendas el denominador más pequeño |
| diagnose dice UNRESOLVED ... not staged | Camino A | Es lo esperado; use el camino B para las intervenciones |
| diagnose se niega con an intervention must re-execute the same system | El código o la configuración cambiaron desde la ejecución | Diagnostique una ejecución de la versión actual, o restaure la versión que se ejecutó |
| El diagnóstico selecciona menos casos de los que fallaron | Casos fallidos sin expected.gold_context | Añada los pasajes de referencia; los casos excluidos se nombran en la salida |
| Las recuperaciones se reutilizan después de cambiar el índice | index_version sin cambiar | Cambie index_version cuando cambie el índice |
Limitaciones
- Oloproof llama a su aplicación; no la aloja, no la aísla ni la reinicia. Su índice, sus cachés y cualquier estado que guarde son suyos.
- En una caja negra no hay intervenciones disponibles: diagnose etiqueta todos los casos como UNRESOLVED y no vuelve a ejecutar nada.
- Las intervenciones son el contexto de referencia, el top-k y un reranker. No hay intervención sobre la fragmentación, los embeddings ni el prompt.
- Las etiquetas de diagnóstico describen los casos fallidos seleccionados bajo una intervención junto a un control. Asocian un fallo con una etapa; no demuestran una causa, y no afirman nada sobre los casos no seleccionados.
- Las métricas de recuperación necesitan etiquetas de relevancia, y el diagnóstico necesita pasajes de referencia; Oloproof no crea ninguna de las dos cosas.
- Los ejemplos deterministas hacen las veces de un recuperador y un modelo reales. Un modelo real en generate o un evaluador juez llama a un proveedor, necesita credenciales y cuesta dinero por caso.
- Qué funciona dónde, el SDK frente a YAML frente al navegador, está en Qué funciona hoy.