JARVIS/verde/PLAN-ARRANQUE.md
sito 1e3e5ca20d carril verde (Hermes Agent): documentacion, panel, voz local y RAG
Rama JARVIS-GREEN, independiente de master (el nucleo naranja queda intacto).

- README propio del carril verde con diagrama de arquitectura y capturas del panel.
- verde/: arranque, panel web, puente de voz (escucha local con faster-whisper +
  habla con la voz del naranja), pruebas (07 voz, 08 escucha), config y notas.
- Integracion RAG: nucleo/saber/busca_cli.py + skill buscar-en-apuntes, para que
  el agente consulte el mismo indice que el nucleo.
- Todo local (127.0.0.1); sin datos personales (rutas y modelo de GPU scrubeados).
2026-08-18 11:26:42 +02:00

188 lines
8.8 KiB
Markdown

# Carril verde: dejarlo listo para lanzar de un tirón
> **Ejecutado el 16 de agosto de 2026.** Este fichero se deja como estaba, que es
> el registro de lo que se planeó. Lo que pasó al ejecutarlo —incluidos dos topes
> que el plan no anticipaba, el suelo de 64k de Hermes y el directorio de trabajo
> en `$HOME`— está en `NOTAS.md`. Y una parte del plan quedó desmentida por los
> hechos: la escalera de contexto de `arrancar.sh` (24576 → 20480 → 16384) buscaba
> el número equivocado, porque por debajo de 64.000 Hermes no arranca.
## Contexto
El verde está instalado y configurado, pero **sin estrenar**. El primer arranque
quedó aplazado por dos motivos, uno técnico y uno de agenda:
1. **El prompt fijo de Hermes no cabe.** Medido con `hermes prompt-size` desde el
directorio real de arranque: 26.281 B de sistema + 55.978 B de esquemas de 19
herramientas = **82.259 B ≈ 20.500 tokens**, contra los **4.096** de `num_ctx`
de `qwen3.5:4b-jarvis`. Y un segundo tope escondido, `num_predict 300`, que el
naranja hereda del modelo *base* y que cortaría el JSON de una tool call por
la mitad. Ya existe `qwen3.5:4b-verde` para resolverlo, pero a 32k de contexto
da `cudaMalloc failed: out of memory` y falta encontrar el techo real.
2. **La gráfica está ocupada** por `entrena/dataset.py`, un trabajo tuyo de 7-10
horas que va por `100/2261` fragmentos.
**Objetivo de este plan:** que cuando el dataset termine, arrancar y probar el
verde sea **un comando**, sin re-derivar nada de lo anterior ni recordar en qué
orden iba. Todo lo que una máquina puede decidir sola, automatizado; lo que
necesita tu oído y tu criterio, escrito en una escalera con huecos para anotar.
## Paso 0 — Guardar esto en el repo (primero, y son dos segundos)
Este plan vive en `~/.claude/plans/`, fuera del repo. Lo primero es copiarlo a
**`verde/PLAN-ARRANQUE.md`** y enlazarlo desde `verde/README.md`, para que esté
donde está todo lo demás y sobreviva a cerrar la terminal.
Ya está a salvo en el repo, y no hace falta rehacerlo: `NOTAS.md` (17 KB, con el
bloqueo del contexto, la variante del modelo, las trampas del `config.yaml` y los
pasos para retomar), `README.md`, `config.yaml`, `env.ejemplo`,
`qwen3.5-4b-verde.Modelfile`, `instalar.sh`, `verde-launcher.sh`, `voz-verde.sh`,
`jarvis-verde.svg` y `boveda/README.md`. La configuración aplicada en
`~/.hermes/` y el modelo `qwen3.5:4b-verde` en ollama también persisten.
`model.default` sigue apuntando a `qwen3.5:4b-jarvis` **a propósito**: cambiarlo
al verde sin fijar antes `context_length` sería peor que dejarlo, porque Hermes
se creería los 262.144 que reporta `/api/show`. Lo cambia `arrancar.sh` cuando
haya medido el techo real.
## Lo que se construye
### 1. `verde/arrancar.sh` — el comando único
Hace en orden lo que hoy habría que hacer a mano, y **se planta en cuanto algo
no cuadra** en vez de seguir y dar un fallo confuso más adelante.
```bash
./verde/arrancar.sh # medir, configurar y dictaminar
./verde/arrancar.sh --solo-medir # sin tocar la configuracion
```
Pasos:
- **Guarda de entrada.** Si `entrena/dataset.py` sigue vivo, se para y lo dice:
competir con él por la tarjeta estropea las dos cosas. `--igual` lo salta.
También cierra los restos del naranja (`nucleo/jarvis.py`, `whisper-server`) y
hace `ollama stop qwen3.5:4b-jarvis`, comprobando que la VRAM baja a ~140 MiB.
- **Busca el techo de contexto, midiendo.** Recrea `qwen3.5:4b-verde` bajando
`num_ctx` hasta que cargue de verdad, y anota la VRAM de cada intento:
| Intento | `num_ctx` | Nota |
|---|---|---|
| 1 | 24576 | el objetivo |
| 2 | 20480 | |
| 3 | 16384 | **suelo**: por debajo no cabe el prompt fijo con holgura |
| 4 | 16384 con `num_gpu 24` | si ni así |
Si ninguno entra, se para y propone `OLLAMA_FLASH_ATTENTION=1` +
`OLLAMA_KV_CACHE_TYPE=q8_0` **sin aplicarlo**: es del servicio, no del modelo,
y afectaría también al naranja. Esa decisión es tuya.
- **Configura Hermes con el número que salió.** En `~/.hermes/config.yaml`:
`model.default` (línea 53) y `context_length` (línea 113, ya está escrita y
comentada — la propia documentación del fichero dice que es justo para *"a
local server with a custom num_ctx"*). Copia de seguridad antes, y verificación
**parseando** después, nunca leyendo:
```bash
python3 -c "import yaml;print(yaml.safe_load(open('$HOME/.hermes/config.yaml'))['model'])"
```
Dos trampas ya conocidas que el script evita: las **claves duplicadas** dentro
de `model:` (`provider` y `base_url` aparecen dos veces y en YAML gana la
última — por eso hoy casi sale el tráfico por OpenRouter), y que la línea 122
`# max_tokens: 8192` **está sin indentar**, así que descomentarla tal cual la
dejaría fuera del bloque.
- **La prueba decisiva**, antes de abrir nada: `curl` al endpoint con un `tools`
dentro. Separa dos preguntas que juntas se contestan mal — *¿sabe el modelo
emitir una llamada?* y *¿funciona Hermes?*. Dictamen explícito:
`tool_calls` válido → seguir; prosa o JSON roto → parar y decidir modelo mayor
por CPU (hay 49 GB y 8 núcleos) o recortar herramientas.
- **Resumen final** con lo medido y el comando siguiente.
### 2. `verde/pruebas/` — la suite, con tu convención
Misma forma que `pruebas/` del naranja: scripts numerados y un `ejecutar.sh` que
los pasa y resume. Ninguna abre el TUI.
| | Comprueba |
|---|---|
| `01_gpu.sh` | tarjeta libre, sin naranja ni dataset compitiendo |
| `02_modelo.sh` | `4b-verde` existe con sus parámetros **y `4b-jarvis` sigue intacto** |
| `03_config.sh` | parseado: modelo, `context_length`, `base_url` en loopback, **cero URLs de nube** |
| `04_tool_calling.sh` | **la decisiva**: el modelo emite `tool_calls` bien formado |
| `05_cabe.sh` | `hermes prompt-size` < `context_length`, con margen |
| `06_privacidad.sh` | 0 credenciales, 0 tokens de mensajería, nada fuera de loopback |
| `07_voz.sh` | `voz-verde.sh` genera WAV a 22050 Hz (hoy: 0,34 s para 3,2 s) |
La 04 y la 05 son las que hoy no se pudieron pasar. La 06 replica el espíritu de
tu `pruebas/06_privacidad.sh`.
### 3. `verde/ESCALERA.md` — lo que solo puedes juzgar tú
El guion del primer arranque interactivo, con huecos para anotar tiempo y
resultado. De trivial a real, y **se para en el primer escalón que falle**,
que es el que informa:
| # | Prueba | Qué contesta |
|---|---|---|
| 1 | "hola, ¿quién eres?" | el endpoint responde y el prompt cabe |
| 2 | "¿cuánto espacio libre queda?" | **una** herramienta, terminal |
| 3 | "lee verde/README.md y resúmelo en una línea" | herramienta de ficheros |
| 4 | "dime cuál de los .md de verde/ es el más largo" | **varias vueltas encadenadas** |
| 5 | algo que dispare una skill | el paso 6 del vídeo |
| 6 | que hable | debe sonar **igual que el naranja** |
| 7 | que escuche | **el último**: 839 MiB de pico contra la tarjeta casi llena |
El escalón 4 es el que separa un chatbot de un agente: encadenar llamadas y
razonar sobre el resultado de la anterior.
El 7 puede dar `CUDA error: out of memory`, y **no sería un fallo nuevo**: es el
mismo reparto que documenta tu README. Salidas por orden: bajar a `base`, fiarse
de `unload_after_idle_seconds: 300`, o probar la escucha con el modelo
descargado.
### 4. Notas al día
`verde/NOTAS.md` y `verde/README.md` ya recogen el bloqueo, la variante del
modelo y las trampas. Se actualizan para apuntar a `arrancar.sh` como la puerta
de entrada, y `NOTAS.md` recibe la tabla de VRAM por intento cuando se mida.
## Lo que sigue sin hacerse
- **No se toca `qwen3.5:4b-jarvis`**, ni `nucleo/`, `config/`, `voz/` o
`newelle/`. El naranja se cierra como proceso y se reabre igual.
- **No se mata `dataset.py`.** El script se planta si lo encuentra vivo.
- **No se ponen claves** ni se activa ningún canal de mensajería.
- **No se cambia nada del servicio de ollama** sin decírtelo: `OLLAMA_KV_CACHE_TYPE`
se propone, no se aplica.
## Verificación
Con `dataset.py` ya terminado:
```bash
./verde/arrancar.sh # mide, configura y dictamina
./verde/pruebas/ejecutar.sh # las 7, ninguna abre el TUI
./verde/verde-launcher.sh # el TUI en verde fosforo -> ESCALERA.md
```
Y devolver la máquina a su sitio al acabar: `ollama stop qwen3.5:4b-verde`, y
comprobar que el naranja vuelve a arrancar con su VRAM de siempre. Sigue
pendiente, para cuando pares de desarrollar:
```bash
cd pruebas && ./ejecutar.sh # las 104 del naranja
```
Hoy no se corrieron a propósito: abren la app y cargan el modelo.
## Y antes de comparar los dos carriles
El naranja tiene **121 acciones rápidas que se saltan el modelo**; Hermes no
tiene ese atajo y toda orden le pasa por el cerebro. **El verde va a medir más
lento y no será culpa del modelo.** Para comparar hay que usar solo frases que
en el naranja también acaben en el cerebro: están en
`config/jarvis-sin-accion.jsonl`.