163 lines
13 KiB
Markdown
163 lines
13 KiB
Markdown
# J.A.R.V.I.S (Python) — Bossiara13's fork
|
||
|
||
Голосовой ассистент для Windows с wake-word **«jarvis»**. Распознаёт речь локально через Vosk (русская модель), отвечает голосом через Silero TTS, а свободные вопросы (фразы, начинающиеся со слова «скажи …») отправляет в LLM на Groq и зачитывает ответ.
|
||
|
||
## Это форк
|
||
|
||
Форк репозитория [Priler/jarvis](https://github.com/Priler/jarvis) (автор оригинала — Abraham Tugalov, 2022). Лицензия наследуется: **CC BY-NC-SA 4.0** (см. [LICENSE.txt](LICENSE.txt)).
|
||
|
||
## Что отличается от оригинала
|
||
|
||
- Из истории удалены случайно закоммиченные секреты.
|
||
- Бэкенд LLM переключён с OpenAI на Groq (бесплатный тариф) через openai-совместимый API.
|
||
- Код обновлён под новую версию SDK `openai` (>=1.0); старый pre-1.0 интерфейс был сломан.
|
||
- Убрана зависимость от Picovoice Porcupine — wake-word распознаётся напрямую через Vosk с grammar-constraint (второй `KaldiRecognizer` со словарём из `WAKE_WORDS`). Ключ Picovoice больше не нужен.
|
||
- Обновлена ветка/тэги (`dev`, `v0.0.1-import`), причёсан README и `requirements.txt`.
|
||
|
||
## Установка
|
||
|
||
Требуется **Python 3.11** (на 3.13 ряд зависимостей пока ставится с бубном).
|
||
|
||
```bash
|
||
git clone https://github.com/DmitryBykov-ISPO/J.A.R.V.I.S-py.git
|
||
cd J.A.R.V.I.S-py
|
||
py -3.11 -m venv .venv
|
||
.venv\Scripts\activate
|
||
pip install --upgrade pip
|
||
pip install -r requirements.txt
|
||
```
|
||
|
||
Скопируйте `dev.env.example` в `dev.env` и заполните ключ:
|
||
|
||
- `GROQ_TOKEN` — бесплатно на [console.groq.com](https://console.groq.com/).
|
||
|
||
Vosk-модель для русского языка лежит в `model_small/` (уже в репозитории). Запуск:
|
||
|
||
```bash
|
||
python main.py
|
||
```
|
||
|
||
## Конфигурация
|
||
|
||
- `config.py`:
|
||
- `MICROPHONE_INDEX = -1` — индекс микрофона (`-1` означает устройство по умолчанию). Если микрофонов несколько и берётся не тот, поменяйте число.
|
||
- `WAKE_WORDS = ('jarvis', 'джарвис')` — варианты транскрипции wake-word, которые принимает Vosk. Если ваш голос/акцент стабильно расшифровывается как, например, `жарвис` — добавьте этот вариант сюда (всё в нижнем регистре).
|
||
- `GROQ_MODEL` — имя модели Groq (по умолчанию `llama-3.3-70b-versatile`).
|
||
- `INTENT_SIMILARITY_THRESHOLD = 0.45` — минимальная косинусная близость для срабатывания команды (см. ниже).
|
||
- `DENOISE_ENABLED = False` — шумоподавление перед Vosk (см. ниже).
|
||
- `commands.yaml` — набор голосовых команд и их вариантов; матчится семантически по эмбеддингам.
|
||
- `custom-commands/` — скомпилированные AHK-скрипты под конкретный сетап автора оригинала (переключение мониторов, управление Яндекс.Музыкой и т.п.). На вашей машине большая часть из них работать не будет, но ассистент запустится в любом случае.
|
||
|
||
## Использование
|
||
|
||
1. Скажите **«Джарвис»** (или **«jarvis»**) — ассистент даст звуковой сигнал готовности.
|
||
2. Произнесите команду — окно записи закрывается само, как только вы замолчите (см. ниже про VAD):
|
||
- либо одну из фраз из `commands.yaml` (открыть браузер, выключить звук и т.д.);
|
||
- либо начните со слова **«скажи …»** — остаток фразы уйдёт в Groq, ответ будет зачитан вслух.
|
||
|
||
## VAD (определение конца команды)
|
||
|
||
Окно записи команды закрывается по голосовой активности (webrtcvad), а не по таймеру. Параметры в `config.py`:
|
||
|
||
- `VAD_AGGRESSIVENESS` (0..3) — насколько агрессивно VAD режет шум; по умолчанию 2.
|
||
- `COMMAND_END_SILENCE_MS` — длительность тишины, после которой окно закрывается (по умолчанию 1200 мс).
|
||
- `COMMAND_MIN_SPEECH_MS` — минимальная длительность речи, иначе тишина не считается концом (500 мс).
|
||
- `COMMAND_MIN_LISTEN_MS` — минимальное время записи, чтобы не закрыться мгновенно (1000 мс).
|
||
- `COMMAND_MAX_LISTEN_MS` — жёсткий потолок (15000 мс).
|
||
|
||
## Семантический матчинг команд
|
||
|
||
Раньше распознанная фраза сравнивалась с фразами из `commands.yaml` через `fuzzywuzzy.fuzz.ratio` — это срабатывало только на формальное совпадение букв. Теперь используется sentence-transformer `all-MiniLM-L6-v2` (ONNX, CPU) — фраза кодируется в 384-мерный вектор, считается косинусная близость с фразами всех команд, побеждает самая близкая.
|
||
|
||
Это означает, что фраза `«запусти браузер»` сматчится с командой `open_browser`, даже если в YAML записано только `«открой браузер»` — у них близкий смысл.
|
||
|
||
- Модель лежит в `models/all-MiniLM-L6-v2/` (87 МБ, хранится через Git LFS — `git lfs pull` после клонирования).
|
||
- Порог `INTENT_SIMILARITY_THRESHOLD = 0.45` (косинус, диапазон [-1; 1], для близких смыслов обычно 0.7+). Ниже порога — «команда не распознана», сработает `not_found.wav` (или ветка `«скажи …»` для LLM).
|
||
- Все фразы из `commands.yaml` эмбеддятся один раз при старте; на каждой команде эмбеддится только распознанная пользователем фраза (~1-5 мс на CPU).
|
||
|
||
## Шумоподавление перед STT
|
||
|
||
Опциональный пре-процессинг аудио командного буфера через `noisereduce` (спектральное гейтирование). Помогает в шумных помещениях (кулер, кондиционер, фоновая музыка). К wake-word фазе не применяется — там важна отзывчивость.
|
||
|
||
В `config.py`:
|
||
|
||
- `DENOISE_ENABLED = False` — главный тумблер.
|
||
- `DENOISE_PROP = 0.85` — доля подавления (0..1).
|
||
- `DENOISE_STATIONARY = False` — `False` для меняющегося шума (рекомендуется), `True` для стабильного фона.
|
||
|
||
## Эффекты под AI-ассистента
|
||
|
||
Silero звучит естественно, но иногда хочется лёгкой «AI-окраски» в духе J.A.R.V.I.S. — узкую полосу, еле заметную реверберацию, при желании небольшой сдвиг высоты. Это тонкий постпроцессинг, голос и sample rate не меняются.
|
||
|
||
По умолчанию эффекты **выключены**. Включаются в `config.py`:
|
||
|
||
- `TTS_EFFECTS_ENABLED` — главный тумблер (`False` по умолчанию).
|
||
- `TTS_BANDPASS_LOW_HZ` / `TTS_BANDPASS_HIGH_HZ` — полоса пропускания (по умолчанию 200–7000 Гц). Сужение полосы даёт ощущение «голоса по радио».
|
||
- `TTS_REVERB_WET` (0..1) и `TTS_REVERB_DECAY_MS` — доля мокрого сигнала и длительность хвоста короткой реверберации (по умолчанию 0.20 и 100 мс).
|
||
- `TTS_PITCH_SEMITONES` — сдвиг высоты в полутонах (по умолчанию 0, разумный диапазон ±2).
|
||
|
||
Фильтры реализованы на `scipy.signal` (IIR, sosfiltfilt — нулевая фазовая задержка), реверберация — несколько затухающих задержанных копий, pitch — ресэмплинг по линейной интерполяции. Всё in-process, без временных файлов и лишних зависимостей.
|
||
|
||
Быстрое A/B сравнение перед тем как переключать тумблер:
|
||
|
||
```bash
|
||
.venv\Scripts\python.exe utils\preview_effects.py
|
||
```
|
||
|
||
Скрипт сгенерирует `sound/_preview_silero_raw.wav` и `sound/_preview_silero_fx.wav` — откройте оба в плеере и решите, нравится ли эффект. Параметры fx-версии берутся из текущего `config.py` (независимо от `TTS_EFFECTS_ENABLED`).
|
||
|
||
## Схема commands.yaml
|
||
|
||
Каждая команда — это пара `phrases` + `action`:
|
||
|
||
```yaml
|
||
open_browser:
|
||
phrases:
|
||
- открой браузер
|
||
- запусти браузер
|
||
action: {type: exe, file: "Run browser.exe"}
|
||
```
|
||
|
||
Типы действий:
|
||
|
||
- `exe` — запустить `.exe` из `custom-commands/`. Поля: `file` (имя файла), необязательные `wait: true` (ждать завершения), `delay_ms` (пауза после запуска). По умолчанию после `exe` проигрывается звук подтверждения `ok` — отключается через `confirm_sound: null`.
|
||
- `play_sound` — проиграть WAV из `sound/`. Поле `name` (без расширения). Имена `greet` и `ok` проигрываются с рандомным выбором из вариантов `greet1/2/3.wav`, `ok1/2/3.wav`.
|
||
- `system` — встроенные операции. `op: volume_mute`, `volume_unmute`, `exit`.
|
||
- `multi` — последовательность шагов: `steps: [...]`.
|
||
|
||
Шаги внутри `multi` — тех же типов. Пример:
|
||
|
||
```yaml
|
||
sound_off:
|
||
phrases: [выключи звук, отключи звук]
|
||
action:
|
||
type: multi
|
||
steps:
|
||
- {type: play_sound, name: ok}
|
||
- {type: system, op: volume_mute}
|
||
```
|
||
|
||
## Конструктор команд
|
||
|
||
GUI для добавления команд в `commands.yaml` без ручной правки YAML.
|
||
|
||
Запуск:
|
||
|
||
```
|
||
python -m tools.command_builder
|
||
```
|
||
|
||
Или из корня репо `run_builder.bat` (под Windows). Открывается окно pywebview с пошаговым мастером: фразы → тип действия → параметры → предпросмотр YAML и сохранение. На шаге «Действие» доступна вкладка «Подсказать (LLM)» — модель Groq предложит готовый блок по описанию на русском.
|
||
|
||
После сохранения команды Jarvis нужно перезапустить, чтобы она подхватилась.
|
||
|
||
Требования:
|
||
|
||
- Windows 10/11 с установленным WebView2 Runtime (обычно уже стоит вместе с Edge — иначе [скачать у Microsoft](https://developer.microsoft.com/microsoft-edge/webview2/)).
|
||
- Зависимости из `requirements.txt` (включая `pywebview`, `ruamel.yaml`, `pyautogui`).
|
||
|
||
Подробности для разработчиков — [tools/command_builder/README.md](tools/command_builder/README.md). TODO: добавить скриншот окна.
|
||
|
||
## Лицензия
|
||
|
||
CC BY-NC-SA 4.0 — см. [LICENSE.txt](LICENSE.txt). Авторство оригинала — Abraham Tugalov / Priler. Изменения в этом форке — Bossiara13 (Dmitry Bykov), 2026.
|