Brings the python fork in line with the new feature/pc-tools work that
landed in rust. Same UX, same trigger phrases, same env vars.
config.py:
+ LLM_AUTO_FALLBACK = True
+ LLM_AUTO_FALLBACK_MIN_CHARS = 4
Mirrors the rust config knobs. The old "скажи X" trigger still works
(VA_TBR strips it before intent matching, so what remains hits this
fallback anyway) — but now ANY unrecognized query goes to Groq, not
just "скажи" ones.
main.py:
va_respond: replaced the fuzz-on-"скажи" gate with a unified auto-
fallback that fires whenever no command matches, GROQ_TOKEN is set,
and the utterance is at least LLM_AUTO_FALLBACK_MIN_CHARS long.
+ _speak(text): recorder.stop() → tts.va_speak → start, used by the
new action handlers so the mic doesn't pick up the assistant.
+ _set_clipboard(text): subprocess to PowerShell Set-Clipboard, no
new python deps.
+ _strip_trigger(voice, triggers): shared helper for codegen/file_search
where we need the text AFTER the trigger phrase.
New action handlers (registered in run_action dispatch):
+ groq_codegen — extracts query, calls Groq with strict "code only"
system prompt at temp 0.2, strips ```lang ... ``` fences, puts the
result in the clipboard, speaks "Код в буфере, сэр. Строк: N".
+ ocr_screen — PowerShell System.Drawing screenshot to a temp PNG,
shells to tesseract.exe (-l rus+eng), speaks a 120-char preview,
clipboard. Looks for tesseract on PATH first then standard install
dirs; gives a clear "Tesseract не установлен" if missing.
+ sysinfo — CIM-based battery/cpu/ram/disk via PS one-liners, time
via python datetime (gets us localized weekday for free). Topics:
time / battery / cpu / ram / disk / all.
+ file_search — strips trigger, recursive Get-ChildItem in Desktop/
Documents/Downloads (depth 3, top 5), opens explorer /select on
the first hit, speaks count and basename.
+ audio_devices_panel — opens mmsys.cpl. Proper COM-based device
switching (like the rust IPolicyConfig version) is deferred — TODO
in backlog.
commands.yaml:
Total 33 commands (was 19). New:
+ open_notepad / open_calculator / open_explorer / open_terminal
/ open_settings / open_task_manager / lock_screen / screenshot
— all via shell action (no AHK exes needed).
+ volume_up / volume_down — five chained keys=volumeup/volumedown
presses each, like rust's _volume_helper.ps1 with Times=5.
+ media_stop — keys=stop.
+ sysinfo_time / sysinfo_battery / sysinfo_cpu / sysinfo_ram /
sysinfo_disk / sysinfo_all — sysinfo action.
+ file_search, codegen, read_screen, switch_audio_device.
Replaced (were AHK exes that Priler ships and we don't have):
~ music → keys playpause
~ music_off → keys playpause (toggle)
~ music_next → keys nexttrack
~ music_prev → keys prevtrack
Removed (Priler hardware/setup specific, can't sensibly port):
- gaming_mode_on / gaming_mode_off (display config switch)
- music_save (depends on the specific player AHK was driving)
- switch_to_headphones / switch_to_dynamics (replaced with the
generic switch_audio_device that opens mmsys.cpl)
Kept as-is (worked already, no AHK dependency):
open_browser / open_youtube / open_google (url action)
sound_off / sound_on (pycaw via system.volume_mute/unmute)
thanks / stupid / off
Smoke-tested: yaml.safe_load → 33 commands, ast.parse main.py → OK.
Portability: USERPROFILE for screenshot path, $env:SystemDrive for disk,
PATH lookup for tesseract before falling back to standard install dirs.
No hardcoded user-specific paths.
66 lines
3.1 KiB
Python
66 lines
3.1 KiB
Python
from dotenv import load_dotenv
|
||
import os
|
||
|
||
# Find .env file with os variables
|
||
load_dotenv("dev.env")
|
||
|
||
# Конфигурация
|
||
VA_NAME = 'Jarvis'
|
||
VA_VER = "0.4.1"
|
||
VA_ALIAS = ('джарвис',)
|
||
VA_TBR = ('скажи', 'покажи', 'ответь', 'произнеси', 'расскажи', 'сколько', 'слушай')
|
||
|
||
# Wake-words распознаются Vosk'ом с grammar-constraint. Добавляйте сюда
|
||
# варианты написания — Vosk с русской моделью может расшифровать "jarvis"
|
||
# как "джарвис", "жарвис" и т.п.
|
||
WAKE_WORDS = ('jarvis', 'джарвис')
|
||
|
||
# ID микрофона (можете просто менять ID пока при запуске не отобразится нужный)
|
||
# -1 это стандартное записывающее устройство
|
||
MICROPHONE_INDEX = -1
|
||
|
||
BROWSER_PATHS = {
|
||
'yandex': 'C:/Program Files/Yandex/YandexBrowser/Application/browser.exe',
|
||
'chrome': 'C:/Program Files/Google/Chrome/Application/chrome.exe',
|
||
'firefox': 'C:/Program Files/Mozilla Firefox/firefox.exe',
|
||
'edge': 'C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe',
|
||
}
|
||
|
||
# Токен Groq
|
||
GROQ_TOKEN = os.getenv('GROQ_TOKEN')
|
||
GROQ_BASE_URL = "https://api.groq.com/openai/v1"
|
||
GROQ_MODEL = "llama-3.3-70b-versatile"
|
||
|
||
# LLM auto-fallback: route unrecognized commands straight to Groq instead of
|
||
# playing the "not_found" sound. The old "скажи X" trigger still works (TBR
|
||
# strips it before intent matching, so what remains hits this fallback anyway).
|
||
LLM_AUTO_FALLBACK = True
|
||
LLM_AUTO_FALLBACK_MIN_CHARS = 4
|
||
|
||
# VAD (webrtcvad) — определяет конец команды по тишине вместо фиксированных 10 сек.
|
||
# 0..3, выше — агрессивнее режет шум (но и обрезает речь).
|
||
VAD_AGGRESSIVENESS = 2
|
||
COMMAND_END_SILENCE_MS = 1200
|
||
COMMAND_MIN_SPEECH_MS = 500
|
||
COMMAND_MIN_LISTEN_MS = 1000
|
||
COMMAND_MAX_LISTEN_MS = 15000
|
||
|
||
TTS_EFFECTS_ENABLED = False
|
||
TTS_BANDPASS_LOW_HZ = 200
|
||
TTS_BANDPASS_HIGH_HZ = 7000
|
||
TTS_REVERB_WET = 0.20
|
||
TTS_REVERB_DECAY_MS = 100
|
||
TTS_PITCH_SEMITONES = 0
|
||
|
||
# Семантический матчинг команд через эмбеддинги MiniLM-L6-v2 (ONNX, CPU).
|
||
# Порог — косинусная близость [0..1]. На вход поступает уже отфильтрованная
|
||
# фраза (без алиасов и vа_tbr); 0.45 эмпирически отделяет валидные команды
|
||
# от шума, оставляя запас на разговорные перефразировки.
|
||
INTENT_SIMILARITY_THRESHOLD = 0.45
|
||
|
||
# Шумоподавление аудио перед Vosk на этапе захвата команды (после wake-word).
|
||
# Спектральное гейтирование через noisereduce; даёт небольшую латентность,
|
||
# поэтому выключено по умолчанию и применяется только к буферу команды.
|
||
DENOISE_ENABLED = False
|
||
DENOISE_PROP = 0.85
|
||
DENOISE_STATIONARY = False
|