ArcRift cherry-pick #1: sentence-trimming opcional + harness A/B en retrieval
Resumen
Se integra sentence-trimming opcional en el pipeline de retrieval de la Biblioteca (archivo-core.ts + archivo.ts + oraculo/ask.ts) para reducir ruido y consumo de tokens en el contexto del LLM. La feature es OFF por defecto — no altera el comportamiento en PROD hasta validar con el harness A/B.
Commits: ArcRift cherry-pick #1, ref aa855a6.
Cambios principales
1. Nuevas funciones de procesamiento (archivo-core.ts)
splitSentences(text: string): string[]
- Trocea markdown respetando estructuras que no deben partirse:
- Code blocks (``` / ~~~) → unidades atómicas (no trocea comandos).
- Filas de tabla (| …) → una unidad por línea.
- Bullets/listas/blockquotes (- / * / +, >, N.) → sin partir.
- Abreviaturas (e.g., v1.2.3, IPs tipo 192.168.1.1) → protegidas contra split erróneo.
- Separador:
. ! ?seguidos de espacio + mayúscula/apertura. - Conservador: ante la duda, no parte.
Fuente: functions/api/mcp/handlers/archivo-core.ts:440–510.
trimChunksBySentence(ai, queryVec, chunks, opts): Promise<ChunkMatch[]>
- Embebe todas las frases de todos los chunks en un único batch (eficiente).
- Puntúa cada frase por coseno contra
queryVec. - Conserva frases con score ≥
threshold(default 0.38) + ventana opcional de contexto (±N frases). - Garantiza
minSentencesmínimas por chunk (default 1) para no vaciarlo. - Marca huecos entre tramos no contiguos con
[...]. - Devuelve chunks recortados en
content; mantiene metadatos (id, score original, source).
Fuente: functions/api/mcp/handlers/archivo-core.ts:550–610.
retrieve(env, queryVec, topK, opts, filters): Promise<RetrievalResult>
- Wrapper unificado: búsqueda vectorial → trimming opcional → estimación de tokens.
- Retorna
{ chunks, tokensInContext, tokensBefore }para que consumidores midan ahorro. - Parámetros:
opts.trim: boolean— activa el trimming.opts.trimThreshold: number— coseno mínimo (default 0.38).opts.trimMinSentences: number— frases mínimas por chunk (default 1).opts.trimWindow: number— contexto ±N (default 0).
Fuente: functions/api/mcp/handlers/archivo-core.ts:620–650.
2. Toggle en bib_ask (Workers)
- Activación: arg
trim: trueen MCP o envRETRIEVAL_TRIM=1. - OFF por defecto: sin argumento → sin trimming.
- Integración: tras
searchChunks, aplicatrimChunksBySentencecon threshold 0.38, minSentences 1, window 1.
Fuente: functions/api/mcp/handlers/archivo.ts:191–202.
3. Toggle en Oraculo (ask.ts)
- Activación: env
RETRIEVAL_TRIM=1. - OFF por defecto: sin flag → comportamiento actual.
- Integración: identica a Workers (threshold 0.38, window 1).
Fuente: functions/api/oraculo/ask.ts:138–149.
4. Nueva tool MCP: bib_eval_retrieval
Harness A/B reproducible para validar trimming sin redeploy.
Parámetros:
questions?: string[]— preguntas a evaluar. Si faltan, usa las últimas 15 reales deoraculo_queries.variants?: ('baseline' | 'trim')[]— variantes a comparar (default['baseline', 'trim']).top_k: number— chunks a recuperar (default 5, max 20).trim_threshold: number— coseno mínimo (default 0.38).trim_window: number— contexto ±N (default 1).synthesize?: boolean— sintetizar respuesta con Gemma por variante (más lento/caro).source_type?, app?— filtros de búsqueda.
Salida:
{
"summary": {
"questions": 15,
"top_k": 5,
"trim_threshold": 0.38,
"trim_window": 1,
"avg_tokens_baseline": 156,
"avg_tokens_trim": 89,
"token_reduction_pct": 43,
"avg_overlap_vs_baseline": 0.92
},
"results": [
{
"question": "¿Cómo configuro...?",
"variants": {
"baseline": {
"chunk_ids": [1, 2, 3],
"top_score": 0.845,
"tokens": 180,
"tokens_before": 200
},
"trim": {
"chunk_ids": [1, 2],
"top_score": 0.845,
"tokens": 95,
"tokens_before": 200,
"overlap_vs_baseline": 0.67,
"answer": "..."
}
}
}
]
}
Fuente: functions/api/mcp/handlers/archivo.ts:467–574 + functions/api/mcp/tools.ts:999–1015.
5. Flags de entorno (functions/types.ts)
RETRIEVAL_TRIM?: string; // '1' → activa trimming
RETRIEVAL_TRIM_THRESHOLD?: string; // default '0.38'
Impacto en producción
-
Consumidores afectados:
bib_ask(Workers MCP handler) — si envRETRIEVAL_TRIM=1o argtrim=true.ask.ts(Oraculo) — si envRETRIEVAL_TRIM=1.- Help Widget (proxy Django) — no env actualizado → sin cambio.
-
Compatibilidad: full backward-compatible. OFF por defecto. El help widget sigue viendo chunks enteros hasta que se valide con
bib_eval_retrieval. -
Verificación pre-merge:
tsc --noEmit, build Astro, smoke desplitSentencesOK.
Calibración sin redeploy
El harness bib_eval_retrieval permite ajustar trim_threshold y trim_window sin redeploy:
bib_eval_retrieval(
questions: ["¿Multi-tenancy?", "¿RLS?"],
trim_threshold: 0.42,
trim_window: 2,
synthesize: false
)
Lanzar múltiples runs con diferentes parámetros para hallar el óptimo (máx reducción de tokens, mín overlap loss). Una vez validado → actualizar env vars en Prod.
Véase también
- [[entity—functions—service—sentence-trimming]]
- [[entity—functions—tool—bib-eval-retrieval]]
- [[concept—biblioteca—retrieval-pipeline]]
- [[concept—observability—token-estimation]]