CreaRack-SL

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 minSentences mí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: true en MCP o env RETRIEVAL_TRIM=1.
  • OFF por defecto: sin argumento → sin trimming.
  • Integración: tras searchChunks, aplica trimChunksBySentence con 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 de oraculo_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 env RETRIEVAL_TRIM=1 o arg trim=true.
    • ask.ts (Oraculo) — si env RETRIEVAL_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 de splitSentences OK.

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]]