Resumen
Al migrar el backend de Auto-Plan a llama-server self-hosted con Gemma 4 E4B-it (sesión 41), el modelo entraba en bucles repetitivos al procesar imágenes de planos de sala reales con el prompt EXHAUSTIVE. Generaba 3 000+ tokens sin terminar, provocando que Daphne timeoutara antes de recibir respuesta válida.
| Campo | Valor |
|---|---|
| Fecha detección | 2026-04-29 |
| Severidad | Alta (feature Auto-Plan inutilizable con planos reales) |
| Componente | blueprints/services/autoplan.py → _analyze_with_ollama() |
| Backend afectado | Solo path Ollama/llama-server (OpenRouter, Gemini y DeepSeek no afectados) |
| Fix commit | 111ba056f402de22f934e68e56baa425a20d3eca |
Síntomas
_analyze_with_ollama()no retornaba en prompts con imágenes reales.- Daphne lanzaba timeout antes de obtener respuesta del LLM.
- Logs mostraban el modelo generando tokens durante decenas de segundos sin
stop_reason.
Diagnóstico
Prueba de aislamiento: con una imagen dummy 1×1 px el modelo respondía correctamente en ~14 s con JSON válido y completo.
Causa raíz: el sampling greedy por defecto (top_p=1.0, sin top_k, sin repeat_penalty) hacía que Gemma 4 E4B-it se atascara en bucles cuando el prompt EXHAUSTIVE enumera 60+ entidades similares (racks, conexiones, walls, texts). El modelo repetía tokens de alta probabilidad sin llegar al token de parada.
Esto es un patrón conocido en modelos de la familia Gemma cuando se usan con llama.cpp/llama-server sin ajuste de sampling.
Fix aplicado
Cambios en blueprints/services/autoplan.py (commit 111ba05):
# Antes
temperature=0.1,
max_tokens=16384,
extra_body={
"num_ctx": 32768,
"chat_template_kwargs": {"enable_thinking": False},
}
# Después
temperature=0.1,
top_p=0.9, # nucleus sampling — elimina tokens de baja prob.
max_tokens=8192, # reducido de 16384; JSON Auto-Plan cabe holgado
extra_body={
"top_k": 40, # limita candidatos por step
"repeat_penalty": 1.15, # penaliza repetición de tokens recientes
"num_ctx": 32768,
"chat_template_kwargs": {"enable_thinking": False},
}
Parámetros siguiendo recomendaciones estándar de llama.cpp para evitar degenerate repetition.
Razonamiento de cada parámetro
| Parámetro | Valor | Motivo |
|---|---|---|
top_p | 0.9 | Nucleus sampling: descarta la cola de baja probabilidad, fuerza diversidad suficiente |
top_k | 40 | Límite duro de candidatos por paso; reduce el espacio donde el bucle puede formarse |
repeat_penalty | 1.15 | Penalización moderada de tokens ya generados; rompe el ciclo sin distorsionar el JSON |
max_tokens | 8192 | Un Auto-Plan típico raramente supera 4 000 tokens; 8 192 da margen y recorta el presupuesto de divague |
Impacto del fix
- Auto-Plan con Gemma 4 E4B-it vuelve a responder correctamente con planos reales.
- No hay cambio de comportamiento para los backends OpenRouter, Gemini y DeepSeek: los parámetros
top_kyrepeat_penaltyse pasan enextra_bodyy sólo los consume llama-server. - El límite
max_tokens=8192no supone riesgo de truncado: el JSON de un plano con 60+ entidades en modo EXHAUSTIVE se genera dentro de ese límite en tests verificados.
Lecciones aprendidas
- El sampling greedy es peligroso con modelos instruction-tuned en tareas de enumeración larga. Siempre configurar
top_p,top_kyrepeat_penaltyal integrar un nuevo modelo local. - Diagnóstico por aislamiento de input: la prueba con imagen dummy
1×1permitió descartar el stack de inferencia y apuntar al prompt/contenido como variable determinante. max_tokensdebe reflejar el output real esperado, no el límite técnico del modelo. Un budget excesivo amplifica los bucles.- La guía
OLLAMA_SELF_HOSTED_AI.mddebería actualizarse para incluir estos parámetros de sampling como configuración base recomendada.
Véase también
- [[entity—blueprints—service—autoplan]]
- [[feature—blueprints—autoplan]]
- [[entity—blueprints—model—aiprompt]]
- [[entity—blueprints—model—blueprint]]