Files
cosmo-voice-assistant/CLAUDE.md
Daniil Klimov 110d9cde29 Mac M1 optimizations, fix train pipeline, add Hey Cosmo wake word model
- Fix install_mac.sh: use venv + Python 3.12 (3.14 incompatible with ML libs)
- Fix run_mac.sh: activate venv, add CPU thread optimization env vars
- Fix agent.py: remove f-string from SYSTEM_PROMPT template (NameError on import)
- Add missing deps: sounddevice, pydub, imageio-ffmpeg, omegaconf
- Optimize for M1: torch.inference_mode, set_num_threads, OMP/MKL tuning
- Switch to qwen2.5:3b for faster LLM responses on Mac
- Switch Whisper to medium model with auto compute (small+int8 had poor Russian)
- Add initial_prompt for better Russian transcription
- Add open_app tool for native macOS app launching
- Fix TTS: sanitize Latin text to Cyrillic for Silero compatibility
- Fix wake word echo: add cooldown after TTS, reset model state, raise threshold
- Make "Слушаю" TTS synchronous to avoid mic interference
- Fix train Dockerfile: remove tensorflow/onnx2tf (only ONNX needed), fix deps
- Fix train.sh: use wget for dataset download, add --shm-size=2g
- Add trained hey_cosmo.onnx wake word model
- Add TODO section to CLAUDE.md (ChatterBox TTS, Ollama Modelfile ideas)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 11:19:53 +03:00

214 lines
8.8 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.
# Cosmo — локальный голосовой ассистент
Полностью локальный голосовой ассистент на Python. Не использует облачные API, всё работает на твоём железе.
## Архитектура
```
Микрофон → Wake Word → STT → LLM-агент → TTS → Динамики
↓ ↓ ↓
openWakeWord Whisper smolagents
(hey_jarvis) (cuda) + Ollama
Инструменты:
run_shell, find_program,
open_browser, read/write_file,
memory_get/set
```
**Поток работы:**
1. `wake_word.py` — непрерывно слушает микрофон, детектирует слово-триггер
2. `transcriber.py` — записывает команду, транскрибирует через Whisper
3. `agent.py` — отправляет текст в Ollama, LLM вызывает инструменты в цикле пока не решит задачу
4. `tts.py` — озвучивает ответ через Silero
## Структура файлов
```
cosmo/
├── main.py — точка входа, класс Cosmo
├── wake_word.py — детект wake word (openWakeWord + onnxruntime)
├── transcriber.py — STT (RealtimeSTT + faster-whisper + Silero VAD)
├── agent.py — LLM-агент (smolagents ToolCallingAgent + Ollama)
├── tools.py — инструменты агента для Windows (Git Bash)
├── tools_mac.py — инструменты агента для macOS (нативный bash)
├── memory.py — персистентная память (data/memory.json)
└── tts.py — TTS (Silero V4 через torch.hub + sounddevice)
config/
├── config.yaml — настройки для Windows
└── config_mac.yaml — настройки для macOS (CPU, int8)
train_wakeword/
├── record_samples.py — запись голосовых примеров
├── cosmo_config.yaml — конфиг обучения wake word
├── Dockerfile — среда Python 3.11 для обучения
├── entrypoint.sh — шаги обучения внутри Docker
└── train.sh — главный скрипт обучения
data/
└── memory.json — долгосрочная память агента (создаётся автоматически)
models/
└── *.onnx — кастомные wake word модели (после обучения)
```
## Железо (Windows машина)
- CPU: Intel i5-13400F (10 ядер / 16 потоков)
- RAM: 32 ГБ DDR5 6000
- GPU: RTX 4060 8 ГБ VRAM
- OS: Windows 11, Python 3.13
## Стек технологий
| Компонент | Технология | Версия |
|---|---|---|
| Wake word | openWakeWord + onnxruntime | 0.6.0 |
| STT | RealtimeSTT + faster-whisper | 0.3.104 / 1.1.1 |
| VAD | Silero VAD (внутри RealtimeSTT) | — |
| LLM | Ollama + qwen2.5:7b | ollama 0.6.1 |
| Agent | smolagents ToolCallingAgent | 1.11.0 |
| TTS | Silero V4 (torch.hub) + sounddevice | — |
| Shell | Git Bash (Windows) / bash (macOS) | — |
## Запуск
### Windows
```bash
bash install.sh # первый раз
bash run.sh
```
### macOS
```bash
bash install_mac.sh # первый раз
bash run_mac.sh
```
При первом запуске автоматически скачаются:
- Whisper модель (~1.5 ГБ на Windows / ~150 МБ на Mac)
- Silero TTS модель (~38 МБ)
## Активация
Сейчас: говори **"Hey Jarvis"** — это fallback пока нет кастомной модели.
После обучения кастомной модели: говори **"Hey Cosmo"**.
После активации говори команду на русском: *"открой браузер"*, *"найди в гугле погоду"*, *"запусти WebStorm"*.
## Конфиг (config/config.yaml)
```yaml
whisper:
model_size: "distil-large-v3" # Windows GPU
# model_size: "small" # Mac CPU
device: "cuda" # "cpu" для Mac
compute_type: "float16" # "int8" для CPU
ollama:
model: "qwen2.5:7b" # модель должна быть скачана: ollama pull qwen2.5:7b
max_agent_steps: 10 # макс. шагов агента на одну команду
tts:
silero_speaker: "eugene" # голоса: xenia (ж), baya, aidar, eugene, kseniya
```
## Память агента
Агент автоматически запоминает информацию в `data/memory.json`:
```json
{
"facts": {
"app.webstorm": "C:/Program Files/JetBrains/WebStorm.../webstorm64.exe",
"user.name": "Даниил"
},
"history": [...]
}
```
**Ключи памяти:**
- `app.<название>` — пути к программам
- `user.<поле>` — данные о пользователе
- `pref.<что>` — предпочтения
После первого поиска программы агент запомнит её путь и больше не будет искать.
## Инструменты агента
| Инструмент | Описание |
|---|---|
| `run_shell` | Выполнить bash команду |
| `find_program` | Найти программу (PATH, Program Files, реестр / Spotlight на Mac) |
| `open_browser` | Открыть URL или поиск Google |
| `read_file` | Прочитать файл |
| `write_file` | Записать файл |
| `memory_get` | Получить факт из памяти |
| `memory_set` | Сохранить факт в память |
| `memory_list` | Показать все факты |
## Обучение кастомной wake word "Hey Cosmo"
Требования: Docker Desktop, ~25 ГБ свободного места.
```bash
# Опционально: запиши свой голос (30 примеров)
python train_wakeword/record_samples.py
# Запусти обучение (~1 час)
bash train_wakeword/train.sh
```
Датасет (~20 ГБ) скачается в `train_wakeword/docker_data/` и сохранится для повторного использования.
После обучения `.onnx` модель автоматически появится в `models/` и `wake_word.py` подхватит её.
## Известные ограничения
- Wake word только английский ("Hey Jarvis" / "Hey Cosmo") — openWakeWord не поддерживает русский TTS для обучения
- На Mac нет CUDA — Whisper работает на CPU, латентность выше (~2-3 сек вместо ~0.5 сек)
- smolagents требует модель с поддержкой tool calling — qwen2.5:7b, llama3.2, mistral v0.3+
## Добавление новых инструментов
В `cosmo/tools.py` (Windows) или `cosmo/tools_mac.py` (Mac):
```python
@tool
def my_tool(param: str) -> str:
"""
Описание что делает инструмент — LLM читает это.
Args:
param: описание параметра
"""
# реализация
return "результат"
```
Добавь в список `ALL_TOOLS` в конце файла — агент автоматически получит доступ.
## TODO / Идеи
- [ ] **ChatterBox TTS вместо Silero** — более живой голос с эмоциями и клонированием голоса (10-30 сек сэмпла). Источник: [vndee/local-talking-llm](https://github.com/vndee/local-talking-llm). Параметр `exaggeration` (0.01.0) управляет экспрессивностью. Заменить `cosmo/tts.py`, интерфейс `say()`/`say_async()` не меняется. Проверить латентность на M1 CPU.
- [ ] **Ollama Modelfile** — запечь системный промпт и параметры (короткие ответы, русский язык) прямо в модель через Modelfile, вместо передачи в каждом запросе.
## Разработка
Логи пишутся в `logs/cosmo.log`. Уровень логирования меняется в конфиге (`logging.level: DEBUG`).
Для тестирования агента без голоса:
```bash
python -c "
import yaml, sys
sys.path.insert(0, '.')
from cosmo.memory import Memory
from cosmo.agent import Agent
config = yaml.safe_load(open('config/config.yaml'))
agent = Agent(config, Memory())
print(agent.run('открой браузер'))
"
```