Saltar al contenido principal

Prueba exploratoria de threshold: 256/32 y top-8

Resultado y decisión propuesta​

Se probaron diez umbrales y el control sin filtro sobre las 40 preguntas guardadas. 0,82 es un candidato provisional para probar con el pipeline, no un valor óptimo validado ni una modificación aplicada al retriever.

En esta muestra solo cambia q30 (tiempo) y q31 (restaurantes): elimina sus 16 fragmentos. Las otras 38 preguntas conservan exactamente los mismos resultados. No resuelve q24/q25 (sin respuesta), q32/q33 (fuera de alcance) ni los casos personales. Con 0,84 ya se pierden testigos de las comparaciones anuales q20/q21. Con 0,85, q15 queda sin documentos, pese a que antes tenía evidencia suficiente. El umbral 0,5 no descarta ningún resultado de esta muestra.

Método​

  • Colección corpus_256_32, k=8, ranking de la ejecución 20261004T134946547175Z.
  • Se acepta un fragmento si cosine_similarity >= threshold; igualdad incluida.
  • La puntuación guardada es 1 - distancia cosine, no una probabilidad.
  • Filtrado posterior sobre el mismo top-8, sin nueva búsqueda ni rellenar huecos.
  • No se ejecutaron embeddings, indexación ni generación LLM.
  • Retención de evidencia: se exige conservar todos los IDs de cada conjunto testigo S de la revisión asistida. Son 22 conjuntos; no son 22 respuestas del LLM evaluadas. Perder un testigo no prueba que no haya otra evidencia; conservarlo no garantiza una respuesta correcta. Las etiquetas no son gold aprobado por el equipo.
  • No hay etiquetas exhaustivas de todos los fragmentos: no se calcula precision, recall ni una tasa global de eliminación de ruido.
  • Las preguntas personales no se consideran negativas que necesariamente deban quedar sin documentos: pueden necesitar evidencia para explicar reglas generales.

Resultados​

UmbralFragmentos conservados /320Testigos completos conservados /22Documento /30Página /28Tokens mediosSin respuesta: vacías /2Fuera de alcance: vacías /4
Sin filtro3202230241944.000
0.53202230241944.000
0.783202230241944.000
0.83082230241872.301
0.823042230241847.502
0.842722030241654.602
0.852351829221429.503
0.861811424191100.013
0.8795101813578.223
0.88454137273.924
0.9201011.924

Los tokens medios corresponden al texto recuperado de las 40 preguntas, incluyendo overlap, sin prompt/citas. Con 0,82 bajan de 1.944,0 a 1.847,5 (aproximadamente 5 %), solo porque q30/q31 quedan vacías. No reduce el contexto de las preguntas fiscales.

Evidencia concreta que se pierde​

  • 0,84, q20: posiciones 5 (0,839885) y 8 (0,837123).
  • 0,84, q21: posiciones 5 (0,839270) y 8 (0,834374).
  • 0,85, q02: posición 3 (0,845482), que aporta excepciones a la regla general.
  • 0,85, q15: posición 1 (0,848989); desaparecen todos sus resultados.

Las comparaciones utilizan precisión completa; los valores anteriores están redondeados solo para mostrarlos. La conservación de page-hit a 0,84 no detecta la pérdida en q20/q21, ya que esas preguntas no tienen expected_page.

Comprobaciones​

440 comparaciones (40 preguntas x 11 condiciones) coinciden con el resultado de VectorRetriever.invoke, usando store y EmbeddingService simulados y las distancias guardadas. Se comprobó una sola llamada embed_query por invocación, top_k=8 y filtro público. No fue una nueva búsqueda contra Chroma real ni una prueba de generación.

Se verificaron hashes de entrada, correspondencia de IDs y textos de testigos, 320 fragmentos en el control, 24/28 páginas y 22/22 conjuntos retenidos sin filtro, y que aumentar el umbral solo quite resultados. No hubo warnings en el replay. No se repitió la suite completa: esta tarea solo añade resultados/documentación, sin modificar código ejecutable del proyecto.

Límites e integración​

Esta selección usa el mismo benchmark de desarrollo: necesita validación del equipo y nuevas preguntas para estimar generalización. 0,82 se propone entre los valores ensayados; no se afirma que sea el mejor de todos los posibles.

Un contexto vacío no garantiza abstención. Las preguntas fuera de alcance y los casos personales requieren tratamiento del pipeline. Este experimento no modifica su comportamiento ni sus prompts y no evalúa documentos privados.

La configuración de producción no ha cambiado: el default actual del retriever sigue siendo top_k=4, score_threshold=0.5. Para un ensayo posterior habría que pasar explícitamente top_k=8 y score_threshold=0.82 sobre la colección 256/32. No confundir una propuesta experimental con un cambio ya aplicado.

Reproducción desde los resultados guardados​

El JSON detallado threshold_sweep_256_32.json está junto a results.json, fuera del repositorio, bajo la carpeta de esta ejecución. Incluye IDs retenidos por pregunta, categorías, testigos perdidos y resúmenes de cada umbral. El siguiente cálculo reproduce la tabla de retención de testigos, sin modelo:

import json
from pathlib import Path

# Ejecutar desde la raíz del repositorio; sustituir RUN por la carpeta de la ejecución.
run = Path(RUN)
data = json.loads((run / "results.json").read_bytes())
review = json.loads(Path("docs/retrieval_review_matrix.json").read_bytes())
labels = {r["question_id"]: r for r in review["rows"]
if r["configuration"] == "corpus_256_32" and r["status"] == "S"}
rows = data["results"]["corpus_256_32"]["questions"]
for threshold in (None, .5, .78, .80, .82, .84, .85, .86, .87, .88, .90):
kept_count = retained_sets = 0
for row in rows:
kept = {r["id"] for r in row["ranked"]
if threshold is None or r["cosine_similarity"] >= threshold}
kept_count += len(kept)
label = labels.get(row["question"]["id"])
if label:
retained_sets += all(e["id"] in kept for e in label["evidence"])
print(threshold, kept_count, retained_sets)

Resultados originales SHA-256: b52ba84de1cbf6c9971b6108e5da0c4e0bb46d93c56497e6e05bf42428aebf04.

Revisión de testigos SHA-256: 3a831161a167ed19d7dcede7d65aa1535f2e8d0365ce8d56ece88b4ce2ed544c.

Barrido detallado SHA-256: c281730c59ab937a7a9de7e6ba84ef692dcb04084f5248f4f1c4cb45bf6b9446.