REGISTRADO 2026-10-19 · REV A
Dieciséis modelos, una puerta: cómo el conserje consiguió su cerebro
El conserje de jordimp.net responde con citas o no responde. Su cerebro de 4B sostenía el contrato, pero también sostenía 2,4 GB de VRAM. Esta es la ronda donde dieciséis modelos se midieron contra la puerta de producción, quince fueron rechazados con causa y el último aprendió la diferencia entre responder y responder con recibos.
La restricción: la mitad de VRAM, el mismo contrato
El modelo del conserje vive en VRAM día y noche, en un servidor que hace otras cosas. Un GGUF de clase 4B ocupa 2,4 GB de una tarjeta de 16 GB para una tarea que atiende a un visitante cada vez en 120 palabras o menos. Era la línea más cara del despliegue y la menos ejercida.
El objetivo se escribió como una restricción: la misma puerta, la mitad de huella. 1,2 GB residentes, respuestas en ~350 ms y el gigabyte liberado de vuelta a la máquina. Lo innegociable: la puerta no se mueve. Veintiuna preguntas golden, tres rechazos fuera de corpus, o el modelo no nave.
Un solo harness cubrió toda la búsqueda: el mismo retrieval, los mismos prompts que envía producción, la misma política de citas que elimina cualquier [n] que no apunte a un fragmento recuperado, prompts en el idioma del visitante y re-ejecuciones deterministas. Cuando una re-ejecución reproduce la puntuación dígito a dígito, un 21/21 significa algo.
La puerta: veintiuna preguntas y tres trampas
La puerta tiene dos mitades. La visible son veintiuna preguntas golden en inglés, español y catalán, incluidas preguntas compuestas cuya respuesta vive en dos documentos distintos. Un modelo pasa respondiendo con citas que apuntan a fragmentos recuperados — y la política elimina cualquier [n] que referencie algo no recuperado, así que un marcador erróneo vale lo mismo que ninguno.
La mitad silenciosa son tres preguntas que nadie debería responder. Capitales de Francia, masas madre, precios de la vivienda en Sabadell. A un conserje que responde eso nunca le pidieron saberlo; le pidieron decir lo que dice el portafolio y parar. Los modelos fallan esta mitad más a menudo que la cubierta.
La puerta también es aburrida a propósito. Mismo retrieval, mismos prompts, temperatura cero. Las re-ejecuciones reproducen las puntuaciones byte a byte, y eso convierte una tabla de benchmark en evidencia.
Dieciséis candidatos
Dieciséis modelos, tres rondas, una tabla. Cubiertas = preguntas golden respondidas con citas supervivientes; fuera de corpus = las tres trampas rechazadas. Todo a temperatura cero contra el retrieval de producción.
| candidate | GGUF | covered | off-corpus | verdict |
|---|---|---|---|---|
| Qwen3-4B-Instruct-2507 (baseline) | 2.4 GB | 21/21 | 3/3 | kept, then replaced |
| Qwen3.5-2B (base) | 1.2 GB | 20/21 | 3/3 | fine-tuned → this model |
| Qwen3-1.7B Q4_K_M | 1.0 GB | 19/21 | 3/3 | drops [n] on compounds |
| Qwen3-1.7B Q3_K_M | 0.9 GB | 17/21 | 3/3 | same, worse |
| Qwen3-1.7B Q6_K | 1.4 GB | 16/21 | 3/3 | quant ≠ discipline |
| Qwen3-1.7B Q8_0 | 1.8 GB | 15/21 | 3/3 | quant ≠ discipline |
| Ministral-3-3B-Instruct-2512 | 2.0 GB | 16/21 | 3/3 | 4B cost, less coverage |
| LFM2.5-1.2B | 0.7 GB | 15/21 | 1/3 | fabricates citations |
| LFM2-1.2B | 0.7 GB | 11/21 | 1/3 | fabricates citations |
| Qwen3-0.6B | 0.6 GB | 10/21 | 3/3 | floor of the size curve |
| granite-4.0-1b | 1.0 GB | 8/21 | 2/3 | leaks + anglocentric |
| SmolLM3-3B | 1.8 GB | 6/21 | 3/3 | cites in the wrong place |
| gemma-3-1b-it | 0.8 GB | 3/21 | 3/3 | ignores [n] entirely |
| Pleias-RAG-1B | 0.7 GB | 0/21 | 3/3 | native syntax, not [n] |
| salamandra-2b-instruct | 1.4 GB | 0/21 | 2/3 | never cites, leaks |
| LFM2.5-2.6B | 1.6 GB | — | — | thinks past the budget |
Las rondas enseñaron al harness tanto como a los modelos. La primera ejecutó todos los prompts en inglés; un 21/21 para Qwen3-1.7B Q3_K_M se hundió a 17/21 cuando el archivo golden llevó claves de idioma explícitas — un bug del harness, corregido, y un recordatorio útil: un benchmark puede halagar a un modelo haciendo la pregunta equivocada. La segunda probó el determinismo: re-ejecuciones idénticas, puntuaciones idénticas, hasta en qué preguntas fallan. La tercera es la tabla.
Un resultado merece línea propia: la curva de cuantización no es monótona. En Qwen3-1.7B, Q4 anotó 19, Q6 anotó 16, Q8 anotó 15. La disciplina de citas a esta escala es un comportamiento al filo, y más precisión no la compra.
El salón de la vergüenza de las citas inventadas
Los fallos descalificantes no fueron citas omitidas. Fueron citas inventadas. La mitad fuera de corpus de la puerta existe para cazar exactamente esto, y cuatro modelos cayeron de cabeza.
Un conserje que inventa una cita para una pregunta que nunca debía responder es peor que ningún conserje. Estos se rechazaron solo por eso — las puntuaciones cubiertas dejaron de importar.
El que estaba a una pregunta de distancia
Qwen3.5-2B cerró la ronda en 20/21, la mitad de latencia y la mitad de memoria que el modelo anterior. Su único fallo fue honesto: un rechazo en la pregunta compuesta de RabbitMQ-o-Kafka, exactamente la clase de respuestas multi-fuente donde los modelos pequeños pierden sus marcadores [n].
Para entonces el patrón era claro. Todo lo que estaba en o bajo 1,2 GB fallaba el contrato — omitiendo citas, ignorando el formato o inventándolas. La disciplina no viene del tamaño, ni de la precisión, ni de ser un especialista en citas (Pleias lo es, y anotó cero). Así que la mejor base consiguió un maestro.
Enseñando el contrato
El dataset salió del 4B en funciones de maestro sobre el pipeline real de retrieval. Inventó 174 preguntas de visitante en tres lenguas — 77 simples, 65 fuera de corpus, 32 compuestas — y las respondió bajo los prompts exactos de producción. Cada completación pasó por la política de citas de producción antes de entrar en el dataset; nada que no sobreviviera a la puerta se convirtió en lección. Las 21 preguntas golden quedaron excluidas del dataset, así que la puntuación final mide cómo generaliza el modelo a preguntas que nunca vio en el entrenamiento.
La primera receta falló de forma útil. Tres épocas con loss sobre la secuencia completa anotaron 15/21 — peor que la base. El modelo había aprendido tan bien la forma de una respuesta citada que empezó a rechazar respuestas que antes daba.
La segunda receta cambió dos cosas: loss sobre la completación únicamente, y entrenamiento más suave — dos épocas, learning rate 7e-5, unos cinco minutos en una GPU de consumo. Resultado: 21/21 cubiertas, 3/3 rechazos honestos, determinista entre re-ejecuciones, a ~310-355 ms y 1,2 GB.
Producción, verificada
El cambio fue un archivo de modelo y una variable de entorno para fijar la plantilla de chat en modo no-thinking. Verificación en vivo: la pregunta compuesta que la base rechazaba ahora responde cubierta, citando tanto el CV como el repo de Kafka. La puerta de evals corre la batería completa dentro del contenedor en cada despliegue, y el rollback es una línea — el viejo 4B sigue en la carpeta de modelos, por si la puerta y yo volvemos a discrepar.
Marcador final: 21/21 cubiertas, 3/3 rechazos honestos, ~310-355 ms p50, 1,2 GB residentes — la mitad de latencia y la mitad de memoria del modelo al que sustituyó. El modelo, el dataset y los tres scripts de entrenamiento son públicos.
Recibos
El modelo afinado está en Hugging Face, con el dataset y el pipeline. Los scripts de entrenamiento y merge viven en el directorio ask-api/finetune del repo jordimp, al lado de la puerta de evals que tuvieron que pasar. Y el conserje está abajo, junto a la puerta — toca el timbre y pregúntale lo que quieras. Ahora sabes cómo se eligió su cerebro.