Files
cosmo-voice-assistant/train_wakeword/train.sh
d.klimov 6010816f1d Initial commit: Cosmo voice assistant
Полностью локальный голосовой ассистент на Python.

Стек:
- Wake word: openWakeWord (onnxruntime)
- STT: RealtimeSTT + faster-whisper + Silero VAD (CUDA)
- LLM-агент: smolagents ToolCallingAgent + Ollama qwen2.5:7b
- TTS: Silero V4 (torch.hub) + sounddevice
- Shell: Git Bash (Windows) / bash (macOS)

Поддерживает Windows и macOS. Агент с памятью и tool calling —
находит программы самостоятельно, запоминает пути, выполняет
произвольные shell-команды.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 15:58:12 +03:00

120 lines
4.4 KiB
Bash
Raw 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.
#!/usr/bin/env bash
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
MODELS_DIR="$PROJECT_DIR/models"
SAMPLES_DIR="$SCRIPT_DIR/samples"
DATA_DIR="$SCRIPT_DIR/docker_data"
echo "============================================"
echo " Cosmo Wake Word — обучение модели"
echo "============================================"
echo ""
# Проверяем Docker
if ! command -v docker &>/dev/null; then
echo "ОШИБКА: Docker не найден."
echo "Установи Docker Desktop: https://www.docker.com/products/docker-desktop/"
exit 1
fi
if ! docker info &>/dev/null; then
echo "ОШИБКА: Docker не запущен. Запусти Docker Desktop и попробуй снова."
exit 1
fi
# Проверяем что есть записанные примеры
POSITIVE_DIR="$SAMPLES_DIR/positive"
if [ ! -d "$POSITIVE_DIR" ] || [ -z "$(ls "$POSITIVE_DIR"/*.wav 2>/dev/null)" ]; then
echo "Записанные примеры не найдены."
echo "Сначала запусти запись голоса:"
echo " python train_wakeword/record_samples.py"
echo ""
read -p "Продолжить без записанных примеров? (используются только TTS) [y/N]: " yn
case "$yn" in
[Yy]*) echo "Продолжаем с только TTS примерами..." ;;
*) exit 0 ;;
esac
fi
mkdir -p "$MODELS_DIR" "$DATA_DIR"
# Собираем Docker образ
echo "[1/4] Собираю Docker образ (первый раз ~5-10 мин)..."
docker build -t cosmo-wakeword-trainer "$SCRIPT_DIR" --quiet
echo " Образ готов."
echo ""
# Скачиваем датасет негативных примеров если нет
NEGATIVE_FEATURES="$DATA_DIR/openwakeword_features_ACAV100M_2000_hrs_16bit.npy"
VALIDATION_FEATURES="$DATA_DIR/validation_set_features.npy"
if [ ! -f "$NEGATIVE_FEATURES" ]; then
echo "[2/4] Скачиваю негативный датасет (~20 GB, один раз)..."
echo " Это займёт время в зависимости от скорости интернета."
docker run --rm \
-v "$DATA_DIR:/data" \
cosmo-wakeword-trainer \
python -c "
from datasets import load_dataset
import numpy as np, os
print('Скачиваю ACAV100M features...')
ds = load_dataset('davidscripka/openwakeword_features', 'ACAV100M_2000_hrs_16bit', split='train')
arr = np.array(ds['features'])
np.save('/data/openwakeword_features_ACAV100M_2000_hrs_16bit.npy', arr)
print('Скачиваю validation features...')
ds_val = load_dataset('davidscripka/openwakeword_features', 'validation_set', split='train')
arr_val = np.array(ds_val['features'])
np.save('/data/validation_set_features.npy', arr_val)
print('Датасет скачан.')
"
echo " Датасет готов."
else
echo "[2/4] Негативный датасет уже скачан. Пропускаю."
fi
echo ""
# Запускаем обучение
echo "[3/4] Запускаю обучение в Docker..."
echo " Это займёт ~30-60 минут."
echo ""
SAMPLES_MOUNT=""
if [ -d "$POSITIVE_DIR" ] && [ -n "$(ls "$POSITIVE_DIR"/*.wav 2>/dev/null)" ]; then
SAMPLES_MOUNT="-v $POSITIVE_DIR:/samples/positive"
fi
docker run --rm \
-v "$SCRIPT_DIR/cosmo_config.yaml:/app/cosmo_config.yaml" \
-v "$DATA_DIR:/data" \
-v "$MODELS_DIR:/output" \
$SAMPLES_MOUNT \
cosmo-wakeword-trainer
echo ""
echo "[4/4] Копирую модель в проект..."
# Ищем готовую модель
ONNX_FILE=$(ls "$MODELS_DIR"/*.onnx 2>/dev/null | head -1)
if [ -n "$ONNX_FILE" ]; then
echo ""
echo "============================================"
echo " Готово! Модель сохранена:"
echo " $ONNX_FILE"
echo ""
echo " Обновляю wake_word детектор..."
# Обновляем путь в конфиге
MODEL_FILENAME=$(basename "$ONNX_FILE")
sed -i "s|wakeword_models=\[\"hey_jarvis\"\]|wakeword_models=[\"models/$MODEL_FILENAME\"]|g" \
"$PROJECT_DIR/cosmo/wake_word.py" 2>/dev/null || true
echo " Теперь запускай: bash run.sh"
echo " и говори 'Hey Cosmo' для активации!"
echo "============================================"
else
echo "ОШИБКА: .onnx файл не найден в $MODELS_DIR"
echo "Проверь логи Docker выше."
exit 1
fi