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

8.8 KiB
Raw Permalink Blame History

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 install.sh    # первый раз
bash run.sh

macOS

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)

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:

{
  "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 ГБ свободного места.

# Опционально: запиши свой голос (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):

@tool
def my_tool(param: str) -> str:
    """
    Описание что делает инструмент — LLM читает это.

    Args:
        param: описание параметра
    """
    # реализация
    return "результат"

Добавь в список ALL_TOOLS в конце файла — агент автоматически получит доступ.

TODO / Идеи

  • ChatterBox TTS вместо Silero — более живой голос с эмоциями и клонированием голоса (10-30 сек сэмпла). Источник: 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).

Для тестирования агента без голоса:

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('открой браузер'))
"