Virtual Assistant — Asistente IA local en iGPU, diseñado con V-Model y playbook de agentes
Asistente de IA local-first con tres interfaces (CLI, Telegram, Voz), Home Assistant, búsqueda web y memoria persistente. Inferencia sobre AMD Radeon 680M iGPU con llama-router, 5 capas aisladas, metodología V-Model NASA + Loop Engineering y playbook de agentes documentado en wiki-brain. ~2s en intents simples, p50 0.5s en el tier standard.
Problema
Soluciones de agentes existentes (OpenClaw, Hermes y similares) están dimensionadas para GPUs dedicadas o cloud. En una iGPU AMD Radeon 680M con 24 GB de RAM compartida, esos agentes no caben, van lentos, o se quedan en bucles de tool-calling por usar modelos sin fine-tuning. Faltaba un asistente personalizado, fluido, que corriese 24/7 en ese hardware modesto.
Solución
Construir un asistente propio en Python con 5 capas aisladas (Interfaces → Core → Tooling → Memory → LLM Gateway), router de modelos con 2 tiers activos (standard / capable) servido por llama.cpp + Vulkan en la iGPU, y un playbook de agentes en el wiki-brain que recoge las decisiones arquitectónicas y los conceptos aprendidos. La construcción se gobierna por V-Model NASA (ConOps → Requirements → HLD → LLD → V&V) y la iteración por Loop Engineering (Generator-Verifier con turn budget). Cada feature va en su propia rama y se mergea a main solo cuando los tests pasan y la aceptación humana está documentada.
Logros clave
- Tres interfaces operativas: CLI, Telegram (raw httpx) y Voz (Wyoming + Parakeet STT + Piper TTS es_ES-davefx-medium)
- 5 dominios de herramientas: domótica, web, sistema, información, grounding
- llama-router con 2 tiers activos en routing real: standard (Qwen3.5-2B) y capable (LFM2.5-8B-A1B MoE)
- Inferencia local en iGPU AMD Radeon 680M (Vulkan) con ~50 tok/s en el modelo standard, sin GPU dedicada
- 800 tests pytest pasando, 30 escenarios de evaluación, runtime analyzer + métricas automáticas
- Playbook de agentes en el wiki (LLM Wiki Pattern): glosario, fundamentos, contexto, guardrails, validación, multi-agente, debate
- V-Model NASA aplicado: 11 iteraciones documentadas en `designs/` con ConOps, Requirements, HLD, LLD, V&V
- Cascada determinista 3-stage en Perception: el ~80% del tráfico se resuelve sin llamar al LLM en <50ms
Motivación
OpenClaw recomienda “usar el modelo más potente disponible” y en la práctica los modelos sin fine-tuning de tool-calling “se quedan en bucles o fallan al formatear JSON”. Hermes Agent pide 64K+ tokens de contexto y modelos cloud. En una iGPU AMD Radeon 680M con 24 GB de RAM compartida y sin VRAM dedicada, esas soluciones no caben, van lentas, o son poco prácticas para uso 24/7.
Quería un asistente personalizado, fluido, que corriese en ese hardware. Y quería aprender a construir agentes de verdad, no consumir un framework.
Por eso, antes de tocar código:
- Adopté el LLM Wiki Pattern de Karpathy: el conocimiento del proyecto se escribe en un wiki persistente, no en historiales de chat.
- Creé el playbook de agentes en ese wiki — glosario, fundamentos, gestión de contexto, guardrails, validación, sistemas multi-agente y debate multi-agente — como marco conceptual propio antes de implementar.
- Definí las reglas de git (rama por feature, atomic commits, validación automática antes de merge, clean code rule) en el fichero de reglas del proyecto (
AGENTS.md). - Adopté el V-Model NASA como metodología de desarrollo para cada iteración.
El resultado: un asistente de IA local-first con tres interfaces, integración con Home Assistant, búsqueda web, memoria persistente y un sistema de reflexión que analiza su propio rendimiento. Un asistente fluido en hardware modesto es alcanzable — y las páginas siguientes muestran cómo se hizo y qué latencias se consiguen.
La aproximación: wiki primero, código después
La diferencia entre “usar un framework” y “construir un agente” está en el orden: primero las decisiones (wiki), luego la implementación (código).
| Capa de conocimiento | Dónde vive | Para qué sirve |
|---|---|---|
| Playbook de agentes | wiki/concepts/playbook-* | Marco conceptual: agent loop, tool calling, context rot, guardrails, eval sets |
| V-Model NASA | wiki/concepts/v-model-nasa-desarrollo | Metodología: ConOps → Requirements → HLD → LLD → V&V por cada feature |
| Git workflow | Fichero de reglas de cada proyecto | Reglas operativas: una rama por feature, validación antes de merge, clean code |
| Diseños del proyecto | las páginas de diseño del proyecto | Producto de trabajo de cada iteración V-Model |
Esta estructura se autorrefuerza: cuando una feature entra en bucle (un test falla dos veces seguidas, una decisión arquitectónica se tambalea), el wiki explica por qué y el V-Model obliga a volver a la fase de Requirements antes de seguir tocando código.
El git workflow se aplica con disciplina: 11 iteraciones mergeadas a main desde el 16 de junio (v0.7 → v1.5.1), cada una en su propia rama con un merge commit dedicado.
Arquitectura: 5 capas con contrato único
Las 5 capas son el mínimo que aísla I/O, lógica de agente, tools, memoria y LLM en boundaries testeables independientemente. El Core tiene un dispatcher determinista (cascada de 3 niveles: keywords → cross-encoder → embeddings) que resuelve el ~80% del tráfico en <50ms sin llamar al LLM; el ~20% restante atraviesa las 6 fases completas con round loop y tool-calling.
Estado real de cada capa
- Interfaces — CLI en REPL, Telegram vía raw httpx (30 tests), Voz con adaptador propio que habla Wyoming con Parakeet STT y Piper TTS
es_ES-davefx-medium. - Tooling — ~16 herramientas organizadas en 5 dominios de intents:
- Domótica (Home Assistant): encender/apagar dispositivos, ajustar valores (luces, clima, persianas), consultar el estado de cualquier entidad, listar el catálogo de dispositivos, lanzar rutinas del aspirador.
- Web: búsqueda general y lectura de páginas concretas, con grounding de los resultados para evitar alucinaciones.
- Sistema: inspección de contenedores Podman y diagnóstico básico de la flota.
- Información y contexto: meteorología, eventos cercanos, fecha y hora como anclaje temporal, y dos síntesis que combinan múltiples fuentes cuando el usuario hace una pregunta abierta tipo “qué hacer hoy”.
- Grounding transversal: valida que cada afirmación del agente esté respaldada por un resultado real de una herramienta, en <1ms sin LLM adicional.
- Memory — Working en memoria, Episodic persistido en JSONL, Semantic con detección de routines y procedures, y un
/memory consolidateque batchea patrones. Todo accesible vía subcomandos/memorydel CLI. - LLM Gateway —
llama-routercon dos tiers activos en routing:standard(Qwen3.5-2B) ycapable(LFM2.5-8B-A1B MoE). El CLI admite--model capablepara enrutar a propósito.
Metodología: V-Model NASA + Loop Engineering
El V-Model se ejecuta operativamente como una cadena de loops Generator-Verifier con presupuesto duro (Loop Engineering, Addy Osmani 2026). Cada fase del V tiene su budget: si el Verifier falla dos veces seguidas, se escala al humano. Si el budget se agota, también. El acceptance final lo hace el humano ejecutando el CLI en REPL — el LLM nunca valida acceptance.
En este proyecto el V se materializa como: 11 páginas de diseño que cubren las iteraciones v0.7 a v1.5.1, 800 tests pytest que cubren unit + integration + voice mocks, 30 escenarios de evaluación ejecutables desde el eval runner, y la acceptance matrix que se actualiza con cada merge. El reflection phase (RuntimeAnalyzer, métricas de tool_error_rate y memory_hits_rate) cierra el círculo: detecta cuándo una feature degrada el sistema y propone IMPs al humano.
Inferencia: llama-router en la iGPU
llama-router es el servidor HTTP de llama.cpp compilado con backend Vulkan (la única opción real para acelerar modelos pequeños en GPUs AMD) y extendido con la opción --models-preset. En vez de exponer un único modelo a la vez, lee un archivo models.ini con secciones y mapea cada sección a un GGUF distinto. El agente HTTP recibe un parámetro model= y el router sirve el GGUF correspondiente; el cambio de tier no requiere reiniciar nada.
# models.ini (extracto del perfil activo lfm25-8b-capable)
[standard]
m = /models/Qwen3.5-2B-Q4_K_M.gguf
ctx-size = 16384
n-gpu-layers = 99
temp = 0.3
top-p = 0.8
[capable]
m = /models/LFM2.5-8B-A1B-Q4_K_M.gguf # MoE 8.3B / 1.5B activos
ctx-size = 16384
n-gpu-layers = 99
temp = 0.3
top-p = 0.9
reasoning-budget = 4096
Tiers activos en el routing real del agente:
| Tier | Modelo | Tamaño | Rol en el agente |
|---|---|---|---|
| standard | Qwen3.5-2B (Q4_K_M) | 2B params | Ejecutor: tool calls, respuestas cortas, ~80% del tráfico |
| capable | LFM2.5-8B-A1B (Q4_K_M, MoE) | 8.3B / 1.5B activos | Planificador: razonamiento, multi-paso, búsqueda web, vague-query grounding |
Las secciones [coding] y [finance] están definidas en models.ini (con Qwen2.5-Coder-3B y Qwen3-4B-Instruct-Alpha respectivamente) pero no se usan en el routing actual: el agente solo enruta entre standard y capable. Coding se reserva para una iteración futura de auto-mejora del propio asistente (UX); finance no es una necesidad del proyecto.
El routing predictivo envía ~80% de las peticiones al tier standard y solo escala a capable cuando la fase de Perception detecta señales de complejidad (multi-step, multi-entity, composite, ambiguo) o cuando la cascada de 3 niveles no resuelve con confianza suficiente.
Latencias obtenidas (medidas en AMD Radeon 680M Vulkan)
| Tier | p50 (latencia) | p95 (latencia) | Velocidad | Uso típico |
|---|---|---|---|---|
| standard | 0.5s | 1.5s | ~50 tok/s | ”enciende la luz”, “¿qué temperatura hace?”, tool calls cortos |
| capable | ~15s | ~60s | ~25 tok/s (MoE) | “búscame horarios de cine”, “qué hacer hoy en Madrid” |
Datos medidos en AMD Ryzen 5 6600U + Radeon 680M iGPU (Vulkan), 24 GB de RAM compartida, contenedor Podman con --device /dev/dri. Perfil activo: lfm25-8b-capable.
Punto clave: el tier standard — el que se usa en 4 de cada 5 interacciones — responde en medio segundo en el caso típico y en poco más de un segundo en el peor caso (p95). Es la zona donde un asistente se siente “fluido” en conversación, indistinguible de un bot que llama a una API cloud.
Para poner el hardware en perspectiva: LFM2.5-8B-A1B en un DGX Spark (NVIDIA GB10, 128 GB unificada, 273 GB/s) hace ~53 tok/s; en esta iGPU (Radeon 680M, ~100 GB/s de RAM compartida) hace ~25 tok/s. La diferencia es ~2x, explicable por la combinación de mayor ancho de banda de memoria (~2.7x) más la ventaja computacional del DGX. No es 10x, como sugeriría la diferencia de precio.
Conclusión: un asistente fluido en hardware modesto es alcanzable
Con el hardware correcto (Vulkan sobre iGPU AMD, modelos MoE activos pequeños, cuantización Q4_K_M), una arquitectura de 5 capas, una metodología rigurosa (V-Model + Loop Engineering + playbook) y un router de tiers — sí se puede. El sistema corre 24/7 en un servidor casero que consume ~25W en reposo y ~35W bajo carga. La factura de luz del asistente es la de una bombilla.
Las claves que hicieron el proyecto viable:
- Wiki primero — el playbook de agentes en el wiki forzó claridad conceptual antes de tocar código.
- V-Model por feature — cada iteración tiene su página de diseño (una por cada fase del V-Model: ConOps, Requirements, HLD, LLD, V&V). Sin requisitos no se implementa.
- Router de tiers — el 80% de las interacciones usan el modelo small y rápido; el 20% que necesita razonamiento escala a MoE.
- Cascada determinista — Perception resuelve la mayoría de intents sin LLM en <50ms. Esto cambia la sensación de fluidez más que cualquier otra cosa.
- Grounding sin IA — la validación de respuestas (grounding) usa regex y reglas de dominio, <1ms; ningún LLM adicional compite por la GPU.
- Tool registry MCP-style — una tool se registra una vez y queda disponible para CLI, Telegram y Voz.
- Reflection que se autocorrige — RuntimeAnalyzer detecta degradación y propone IMPs; memory persistente permite aprender entre sesiones.
Estado actual y roadmap
El proyecto está activo y en producción casera. Lo que funciona hoy:
-
✅ 3 interfaces operativas: CLI, Telegram, Voz
-
✅ ~16 herramientas agrupadas en 5 dominios (domótica, web, sistema, información, grounding)
-
✅ 2 tiers de LLM activos en routing (standard, capable)
-
✅ Memory persistente (JSONL episodic + JSON semantic con routines/procedures)
-
✅ Reflection completo (RuntimeLogger, RuntimeAnalyzer, métricas, /health, /sugerencias)
-
✅ Eval runner con 30 escenarios YAML (
--eval) -
✅ 800 tests pytest pasando
-
⏳ Tier
codingpara auto-mejora del asistente — no implementado todavía, está en el roadmap como objetivo de UX -
⏳ Tier
finance— no es una necesidad del proyecto, queda enmodels.inicomo definición teórica
El roadmap de iteraciones (v0.7 → v1.5+) está documentado en la página de roadmap del proyecto. Las próximas áreas de trabajo incluyen explorar el tier coding para tareas internas del propio agente (revisar PRs, refactors) y seguir reduciendo latencias en Perception y Context.
Referencias
- V-Model (Wikipedia) — metodología de desarrollo
- Loop Engineering (Addy Osmani, 2026) — práctica Generator-Verifier con turn budget
- Model Context Protocol — manifests de tools