ROOT CAUSE
User reported the Python edition showed "только пустой терминал" — empty
terminal — when launched. Three compounding issues:
1. `tts.py` called `torch.hub.load(...)` at MODULE IMPORT time. On first
use this downloads a 60MB Silero model with no progress output beyond
one "Using cache found in..." line. With no prior banner the user
couldn't tell if it crashed or was loading.
2. main.py's startup banner (`print("=" * 60)...J.A.R.V.I.S. v...`)
appeared AFTER all the heavy imports. So even when nothing was wrong,
visible feedback was delayed by 10-60 seconds.
3. If `pip install -r requirements.txt` failed for any package
(`simpleaudio` notoriously needs MSVC to build), `import simpleaudio`
crashed the whole process with a raw ModuleNotFoundError.
FIXES
- `tts.py`: Silero model load moved into `_ensure_model()` called lazily
from `synthesize()`. First synth pays the load cost (with a one-line
progress hint) — everything before that is visible immediately.
- `main.py`: print "J.A.R.V.I.S. loading..." banner BEFORE any heavy
imports. User sees the terminal is alive within ~100ms.
- `main.py`: scan required deps before importing them; if any are
missing, print "Run: pip install -r requirements.txt" with the
specific list and exit cleanly (exit code 2) instead of stack-tracing.
- `main.py`: `simpleaudio` is now soft-optional. Falls back to stdlib
`winsound` on Windows installs that couldn't build the C extension.
Sound cues still work; only the precise wait_done semantics are
slightly different.
VERIFIED LOCALLY
`.venv\Scripts\python.exe main.py` now prints:
```
============================================================
J.A.R.V.I.S. loading (Python edition)...
Heavy modules (vosk / torch / pvrecorder) take a few seconds.
============================================================
[scheduler] thread started (1 tasks loaded)
============================================================
J.A.R.V.I.S. v0.4.1 [Python edition]
Total commands: 200
============================================================
Using device: Микрофон (5- Fifine Microphone)
Jarvis (v0.4.1) начал свою работу ...
Yes, sir.
```
Total time to first banner: ~100ms (was 10-60s of nothing).
All 104 pytest tests still pass.
|
||
|---|---|---|
| .github/workflows | ||
| .idea | ||
| custom-commands | ||
| gui | ||
| model_small | ||
| models/all-MiniLM-L6-v2 | ||
| sound | ||
| tests | ||
| tools/command_builder | ||
| utils | ||
| .gitattributes | ||
| .gitignore | ||
| commands.yaml | ||
| config.py | ||
| dev.env.example | ||
| dev_handlers.py | ||
| effects.py | ||
| expenses_handlers.py | ||
| extensions.py | ||
| gui.bat | ||
| intent.py | ||
| LICENSE.txt | ||
| llm_backend.py | ||
| macros_store.py | ||
| main.py | ||
| memory_store.py | ||
| outlook_handlers.py | ||
| personality_handlers.py | ||
| plugins_store.py | ||
| profiles_store.py | ||
| README.md | ||
| requirements.txt | ||
| run.bat | ||
| run_builder.bat | ||
| scheduler_store.py | ||
| time_tracker_handlers.py | ||
| tts.py | ||
| vision_handler.py | ||
| wave1_handlers.py | ||
| wave68_handlers.py | ||
J.A.R.V.I.S (Python) — Bossiara13's fork
Голосовой ассистент для Windows с wake-word «jarvis». Распознаёт речь локально через Vosk (русская модель), отвечает голосом через Silero TTS, а свободные вопросы (фразы, начинающиеся со слова «скажи …») отправляет в LLM на Groq и зачитывает ответ.
Это форк
Форк репозитория Priler/jarvis (автор оригинала — Abraham Tugalov, 2022). Лицензия наследуется: CC BY-NC-SA 4.0 (см. 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 ряд зависимостей пока ставится с бубном).
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.
Vosk-модель для русского языка лежит в model_small/ (уже в репозитории). Запуск:
python main.py
GUI (Flet)
Опциональная графическая панель — те же 7 страниц, что и в Rust-форке (Главная / Команды / Макросы / Расписание / Память / Плагины / Настройки).
pip install flet>=0.85 # одноразово, уже в requirements.txt
python -m gui # или просто gui.bat
GUI не запускает ассистент сам — это панель управления. Кнопка «Запустить
J.A.R.V.I.S.» на главной запускает main.py отдельным процессом.
Плагины
Голосовые команды, которые лежат вне репозитория. Добавляются без правки проекта: создайте папку в
%APPDATA%\com.priler.jarvis\plugins\<имя_плагина>\
commands.yaml (тот же формат, что и корневой commands.yaml)
disabled (опционально — пустой файл, отключает плагин)
Плагины подхватываются при следующем запуске main.py. ID встроенных команд
выигрывают конфликты (плагин не может переопределить, например, open_browser).
GUI-страница «Плагины» показывает список, флажки enable/disable и кнопку
«Открыть папку».
Конфигурация
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-скрипты под конкретный сетап автора оригинала (переключение мониторов, управление Яндекс.Музыкой и т.п.). На вашей машине большая часть из них работать не будет, но ассистент запустится в любом случае.
Использование
- Скажите «Джарвис» (или «jarvis») — ассистент даст звуковой сигнал готовности.
- Произнесите команду — окно записи закрывается само, как только вы замолчите (см. ниже про 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 сравнение перед тем как переключать тумблер:
.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:
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 — тех же типов. Пример:
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).
- Зависимости из
requirements.txt(включаяpywebview,ruamel.yaml,pyautogui).
Подробности для разработчиков — tools/command_builder/README.md. TODO: добавить скриншот окна.
Лицензия
CC BY-NC-SA 4.0 — см. LICENSE.txt. Авторство оригинала — Abraham Tugalov / Priler. Изменения в этом форке — Bossiara13 (Dmitry Bykov), 2026.