Volver a la wiki

Ingest Bibliotecario en 3 capas: pre-LLM + Haiku + Sonnet caching

ADR — Ingest Bibliotecario en 3 capas: pre-LLM + Haiku + Sonnet caching

Contexto

El Bibliotecario-Ingest es el agente automático del Supercontexto que mantiene la wiki viva tras cada merge a main en CreaRack-Pro y CreaRackSL-workspace. Vive en .github/scripts/bib_ingest.py y se dispara desde .github/workflows/post-merge-ingest.yml (eventos pull_request: closed + merged==true y push: main).

En la sesión 7 del plan Supercontexto (Fase 3, 2026-04-22) el ingest quedó operativo con un único modelo: Claude Sonnet 4.6 procesando todo merge que llegara. Una primera medición arrojó ~$0.17 por run de ~55k tokens. Con un volumen estimado de ~10 pushes/día (CreaRack-Pro + workspace) la proyección era de ~$50/mes solo en ingest, sin contar Fase 4 (Query con cierre), Fase 5 (Lint automatizado) ni el Curator diario, todos consumidores adicionales de Anthropic API.

Edu pidió optimizar la economía antes de avanzar al resto del plan. La sesión 8 (2026-04-22) adelantó la evaluación Haiku que originalmente vivía en Fase 6 y la fundió con un filtro pre-LLM y prompt caching en una sola entrega.

Problema

Tres observaciones empíricas convergen:

  1. La mayor parte de los merges son triviales para la wiki: chore:, style:, test:, ci:, docs:, bumps de versión, refactors mecánicos, commits del propio Supercontexto que tocan src/content/wiki/. Estos no merecen análisis profundo y no aportan páginas nuevas.
  2. Los merges “no triviales” requieren juicio: distinguir un feat: con lógica nueva de un feat: cosmético no se resuelve con reglas duras — necesita un LLM que entienda el diff.
  3. El system prompt + las 7 tool definitions del Bibliotecario son idénticas en cada iteración del agentic loop: ~6-8k tokens repetidos entre 5 y 25 veces por run. Cobrarlos a precio completo en cada vuelta es desperdicio.

Pagar Sonnet 4.6 a tarifa plena en los tres escenarios es indefendible cuando el coste por commit trivial es el mismo que por commit valioso.

Opciones consideradas

1. Solo Sonnet, todo lo que merge llega. Simplicidad máxima: un único modelo, un único prompt. Calidad de extracción óptima en todos los casos. Coste base ~$50/mes con tendencia a crecer linealmente con el ritmo de commits del equipo. Descartada por economía insostenible — el ingest es solo una de las cinco fases consumidoras.

2. Solo Haiku, todo lo que merge llega. ~5× más barato que Sonnet por token. Suficiente para clasificar y para páginas simples, pero insuficiente para extraer correctamente entidades de PRs grandes con múltiples archivos ricos (modelos + endpoints + servicios + migraciones). Sacrifica calidad estructural de las páginas (tags densos, related correctos, secciones obligatorias del schema). Descartada porque la wiki Supercontexto tiene requisitos de densidad que Haiku cumple peor en runs largos.

3. Filtro humano (revisión manual de qué disparar). Coste API cero. Trasladar la decisión a Edu o Dani vía label de PR o aprobación explícita. Elimina por completo el riesgo de gastar en triviales. Descartada por dos razones: (a) introduce fricción en cada merge y un SPOF humano contrario a la Regla 17, y (b) el sistema dejaría de ser auto-mantenido — la promesa central del Supercontexto operativo.

4. Pipeline 3-tier (pre-LLM filter + Haiku triage + Sonnet con caching). Adoptada. Cascada de tres capas, cada una más cara y más informada que la anterior, con criterio de salida temprana en cualquiera de ellas.

Decisión

bib_ingest.py ejecuta tres tiers en cascada. La primera decisión skip corta el flujo y registra el motivo en bib_wiki_log vía log_skip_to_mcp para auditoría desde el Pulse.

Tier 1 — Filtro pre-LLM (coste 0)

decide_pre_llm_skip() aplica reglas estáticas en orden:

Coste de este tier: 0 tokens API. Filtra empíricamente el grueso del tráfico.

Tier 2 — Triage con Haiku 4.5 (~$0.01 por invocación)

triage_with_haiku() invoca claude-haiku-4-5 con un TRIAGE_SYSTEM_PROMPT corto (criterios process / skip) y el contexto del PR (título, descripción, lista de archivos, primeros ~12k chars del diff). Haiku responde JSON estructurado de una sola línea: {"decision":"process"|"skip","reason":"...","likely_type":"entity_page|feature_page|..."|null}.

Si Haiku falla o devuelve JSON inválido, el fallback es conservador: decision = "process". Es preferible pagar un Sonnet de más que perder una página por un parser frágil.

Tier 3 — Sonnet 4.6 con prompt caching

Solo si Tier 2 dice process. run_ingest() ejecuta el agentic loop contra claude-sonnet-4-6 con hasta 25 iteraciones y las 7 tools MCP (bib_impact_query, bib_context_query, bib_ask, bib_search_nodes, wiki_create_page, wiki_update_page, wiki_log_event).

El system prompt y la última tool definition se marcan con cache_control: {"type": "ephemeral"} (TTL 5 minutos). En la iteración 1 se paga cache_creation_input_tokens; en las iteraciones 2 a N se paga cache_read_input_tokens a aproximadamente ~10% del coste regular sobre los tokens cacheados. La telemetría loguea cache_read y cache_write por iteración para auditar la efectividad del caching.

Consecuencias

Status

Accepted. En producción desde 2026-04-22 (sesión 8). Métricas operativas pendientes de evaluación 1-2 semanas tras el cierre del plan.

Véase también

Subir