Files
smart-home-tablet/RUNBOOK.md
d.klimov be0a731738
All checks were successful
Deploy / deploy (push) Successful in 1m52s
voice: усиление умного дома — контекст, промпт, новые tools
- промпт: перечислены ВСЕ 15+ tools, разрешено уверенно управлять домом
- route.ts: живой контекст (время + снимок устройств из HA) в системный промпт
  для LLM-пути (defensive, с таймаутом)
- новые tools: control_climate (кондей/термостат), control_tv, set_scene
  (night/movie/morning/away), all_off, ha_service (универсальный HA с whitelist)
- env: CLIMATE_ENTITY, TV_ENTITY (см. RUNBOOK)
2026-07-22 23:49:50 +03:00

232 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RUNBOOK — вывод голосового помощника в продакшен
Пошаговая инструкция, чтобы всё завелось на мини-ПК (где развёрнут
`https://tablet.digital-home.site`). Рассчитана на то, что её выполняет
Claude-сессия **на мини-ПК** (`cosmo@192.168.31.60`), с пометками, что делается
на рабочей машине (Windows), а что — на мини-ПК.
## TL;DR — что это добавляет
1. **Локальный агент (intent+slots)** — sidecar-служба, распознаёт команды
офлайн за ~2 мс и исполняет действия (таймеры, свет, музыка, очиститель),
минуя облачный LLM. Инфо-запросы (погода/календарь) по-прежнему у LLM.
Модель обучена: **интент 40/40, слоты 40/40**.
2. **Голосовое управление светом** — новый tool `control_light` (2 лампы).
3. **Смелый визуал** — обновлённая тема (космический индиго/aurora), деплоится
с обычным билдом.
4. **Wake «Эй, космо»** — пайплайн переобучения готов и проверен end-to-end;
боевая модель требует досбора данных (см. раздел D).
Всё под фиче-флагами: без `AGENT_URL` планшет работает ровно как раньше →
безопасно для kiosk.
---
## Изменения в репозитории (уже в коде)
| Файл | Что |
|---|---|
| `lib/tools/lights.ts` | новый tool `control_light` (свет через HA) |
| `lib/tools/_registry.ts` | регистрация `control_light` |
| `lib/agent-local.ts` | быстрый путь: вызов агент-службы + исполнение действий |
| `app/api/voice/chat/route.ts` | вставка fast-path (под `AGENT_URL`, с fallback) |
| `app/globals.css`, `app/page.tsx` | смелый визуал (токены/aurora) |
| `agent/` | sidecar агента: `Dockerfile`, `predict.py`, `joint_model_def.py`, `tablet_map.py`, `requirements.txt` |
⚠️ **Эти изменения надо закоммитить и запушить** (с рабочей машины), чтобы мини-ПК
их подтянул `git pull`. Веса моделей в git НЕ идут (переносятся отдельно, ниже).
---
## Архитектура продакшена
```
Планшет (Android, kiosk-браузер)
├─ wake «Эй, космо» (public/wake/cosmo.onnx, WASM) ─┐
└─ UI (Next.js) │
tablet-контейнер (мини-ПК, network coolify) ── /api/voice/chat
│ fast-path: AGENT_URL задан?
│ ├─ да → POST http://tablet-agent:8091/predict
│ │ интент-действие + score≥0.7 → executeTool → короткий ответ
│ └─ нет/инфо/none → облачный LLM (Anthropic/Groq) как раньше
tablet-agent-контейнер (sidecar, network coolify)
└─ predict.py --serve (joint_model смонтирован томом)
```
---
## A. Агент (sidecar) — главный шаг
### A1. Перенести модель на мини-ПК (с рабочей машины)
Веса `joint_model/` (~115 МБ) в git нет. Скопировать на мини-ПК:
```bash
# на рабочей машине (Windows, Git Bash):
scp -i ~/.ssh/id_ed25519 -r "/d/Digital home/tablet-agent/joint_model" \
cosmo@192.168.31.60:/opt/digital-home/agent-model
```
Должно получиться `/opt/digital-home/agent-model/joint.pt` (+ tokenizer, config).
> Переобучить модель заново (если правил `tablet-agent/templates.txt`):
> `cd tablet-agent && python train_joint.py && python test_joint.py`, затем scp.
### A2. Собрать и запустить sidecar (на мини-ПК)
```bash
cd /opt/digital-home/smart-home-tablet
git pull origin main # подтянуть код (после пуша с рабочей машины)
docker build -t tablet-agent:latest ./agent
docker rm -f tablet-agent || true
docker run -d --name tablet-agent \
--network coolify \
--restart unless-stopped \
-v /opt/digital-home/agent-model:/app/joint_model \
tablet-agent:latest
# проверка службы:
docker exec tablet-agent python -c "import urllib.request,json; \
r=urllib.request.urlopen(urllib.request.Request('http://127.0.0.1:8091/predict', \
data=json.dumps({'text':'поставь таймер на 5 минут'}).encode(), \
headers={'Content-Type':'application/json'})); print(r.read().decode())"
# ждём: {"intent":"timer_set","slots":{"duration":"5 минут"},"score":...,"tool":{...}}
```
### A3. Включить fast-path в планшете
Добавить в `/opt/digital-home/tablet.env`:
```
AGENT_URL=http://tablet-agent:8091
AGENT_THRESHOLD=0.7
```
Пере-задеплоить планшет (push любой коммит ИЛИ вручную пере-`docker run` по
`deploy.yml`). После рестарта `route.ts` увидит `AGENT_URL` и начнёт использовать
агента.
> Откат агента: убрать `AGENT_URL` из `tablet.env`, пере-деплой. Мгновенно вернёт
> облачный LLM на все команды. Контейнер `tablet-agent` можно оставить.
---
## B. Свет — реальные entity Home Assistant
`control_light` по умолчанию шлёт на `light.bedside` / `light.reading` (заглушки).
Указать реальные entity_id твоих ламп в `/opt/digital-home/tablet.env`:
```
LIGHT_ENTITIES_JSON={"bedside":"light.ВАШ_СВЕТ_У_КРОВАТИ","reading":"light.ВАШААМПА_ДЛЯ_ЧТЕНИЯ","default":"light.ВАШ_СВЕТ_У_КРОВАТИ"}
```
Найти id ламп: HA → Developer Tools → States, отфильтровать `light.`. Ключи
`bedside`/`reading` соответствуют фразам «свет у кровати» / «лампа для чтения»
(маппинг в `lib/tools/lights.ts`, `DEVICE_ALIASES`). Пере-деплой планшета.
Без этой переменной команды света пройдут как mock (HA вернёт success, лампа не
переключится) — то есть безопасно, но не управляет реальным светом.
---
## C. Дизайн (смелый визуал)
Ничего дополнительно — тема живёт в `app/globals.css` (токены) и деплоится
обычным билдом. Раскладка/логика не менялись, kiosk не затронут. Если визуал не
зайдёт — откат = `git revert` коммита с globals.css.
---
## D. Wake «Эй, космо» — статус и деплой
Проект `tablet-wake` (на рабочей машине). Пайплайн переобучения **готов и
проверен end-to-end**: smoke-модель разделяет фразу (pos 0.96 / neg 0.01) через
тот же WASM-рантайм, что у планшета. Но это **не боевая модель** — нужен досбор
данных:
1. Реальная речь в негативах (корпус Golos) — главный убийца ложняков.
2. Фон Android-мика (запись, где планшет стоит).
3. Held-out тест своим голосом + подбор порога.
Полный прогон (на рабочей машине) — см. `tablet-wake/README.md`. Итог —
`tablet-wake/out/cosmo.onnx`.
**Деплой wake-модели** (когда готова): заменить файл в репозитории и запушить —
инференс планшета НЕ меняется (окно 25 сохранено), только веса:
```bash
# на рабочей машине:
cp "/d/Digital home/tablet-wake/out/cosmo.onnx" \
"/d/Digital home/smart-home-tablet/public/wake/cosmo.onnx"
# затем commit + push → Gitea пересоберёт планшет
```
Порог срабатывания подстраивается в клиенте (`WAKE_THRESHOLD` в
`components/VoiceController.tsx`). Также обнови фразу-подпись в UI: сейчас
«Космо» → «Эй, космо».
---
## Сводка новых переменных `tablet.env`
```
AGENT_URL=http://tablet-agent:8091 # включает локального агента
AGENT_THRESHOLD=0.7 # порог уверенности (опц.)
LIGHT_ENTITIES_JSON={"bedside":"...","reading":"...","default":"..."}
CLIMATE_ENTITY=climate.thermostat # кондиционер/термостат (control_climate)
TV_ENTITY=media_player.tv # телевизор (control_tv)
```
## Расширенный умный дом (облачный LLM)
Промпт теперь перечисляет ВСЕ tools и разрешает уверенно управлять домом; в
системный промпт каждый LLM-запрос инжектится живой снимок (время + состояния
устройств из `/api/ha`), поэтому модель понимает, что включено и что есть в доме.
Новые tools: `control_climate` (климат), `control_tv` (телевизор), `set_scene`
(сцены night/movie/morning/away), `all_off` (выключить всё), `ha_service`
(универсальный вызов сервиса HA по entity_id из снимка; домены light/switch/fan/
climate/media_player/cover/scene/humidifier/vacuum). Реальные entity_id ламп/ТВ/
климата задаются переменными выше; без них команды проходят как mock (безопасно).
> Локальный агент (fast-path) новые интенты climate/tv/scene/all_off пока не
> знает — эти команды обрабатывает облачный LLM. Чтобы они шли и локально,
> нужно дообучить `tablet-agent` (добавить интенты) и передеплоить модель.
---
## Проверка (после деплоя)
```bash
# планшет жив:
curl -sk -o /dev/null -w "%{http_code}\n" https://tablet.digital-home.site/
# агент отвечает изнутри сети:
docker exec tablet-yfh53kixpwkjlo4zibglx4n2 \
wget -qO- --post-data='{"text":"выключи свет у кровати"}' \
--header='Content-Type: application/json' http://tablet-agent:8091/predict
# логи планшета: fast-path пишет "[voice/chat] local-agent intent=..."
docker logs --tail 50 tablet-yfh53kixpwkjlo4zibglx4n2 | grep local-agent
```
Живой тест голосом: сказать «поставь таймер на 5 минут» (действие → агент,
мгновенно), затем «какая погода» (инфо → LLM). В логах у первой команды —
`local-agent`, у второй — обычный LLM-раунд.
---
## Откат всего
| Что | Откат |
|---|---|
| Агент | убрать `AGENT_URL` из `tablet.env`, пере-деплой |
| Свет | убрать `control_light` из `_registry.ts` ИЛИ просто не задавать `LIGHT_ENTITIES_JSON` |
| Дизайн | `git revert` коммита globals.css |
| Wake | вернуть прежний `public/wake/cosmo.onnx` из git-истории |
Каждая часть независима — можно катить и откатывать по отдельности.