Merge feature/rebrand-and-groq into dev

This commit is contained in:
Bossiara13 2026-04-22 17:50:37 +03:00
commit 6dc8a85bf6
6 changed files with 80 additions and 51 deletions

7
.gitignore vendored
View file

@ -185,4 +185,9 @@ fabric.properties
.idea/caches/build_file_checksums.ser .idea/caches/build_file_checksums.ser
# idea folder, uncomment if you don't need it # idea folder, uncomment if you don't need it
# .idea # .idea
# Local secrets (real keys go here, not in dev.env.example)
dev.env
# Misc artifacts
.git-filter-redactions.txt

View file

@ -1,30 +1,57 @@
# Kesha v3.0 very early (aka Jarvis update) # J.A.R.V.I.S (Python) — Bossiara13's fork
Simple Voice Assistant made as an experiment using [Silero](https://github.com/snakers4/silero-models) & [Vosk](https://pypi.org/project/vosk/).
<br>Later on [Picovoice Porcupine Wake Word Detection](https://picovoice.ai/platform/porcupine/) & [ChatGPT](https://chat.openai.com/) was added.
![image](https://i.pinimg.com/originals/63/e9/b7/63e9b72b983793f64bffc07fd14a0e62.jpg) Голосовой ассистент для Windows с wake-word **«jarvis»**. Распознаёт речь локально через Vosk (русская модель), отвечает голосом через Silero TTS, а свободные вопросы (фразы, начинающиеся со слова «скажи …») отправляет в LLM на Groq и зачитывает ответ.
`The code has NOT been polished and is provided "as is". There are a lot of code that are redundant and there are tons of improvements that can be made.` ## Это форк
# Installation Форк репозитория [Priler/jarvis](https://github.com/Priler/jarvis) (автор оригинала — Abraham Tugalov, 2022). Лицензия наследуется: **CC BY-NC-SA 4.0** (см. [LICENSE.txt](LICENSE.txt)).
First, install the requirements, the `requirements.txt` file is just an output of `pip freeze` from my test venv 'k.<br>
Second, check `config.py` and set required values (api key, device index).<br>
Next, run the `main.py` script and Voilà, as simple as that.<br><br>
And don't forget to put models of Vosk to main folder.<br> ## Что отличается от оригинала
You can get the latest from the [official website.](https://alphacephei.com/vosk/models)
<br>The one I was using is `small`.
<br>p.s. If you don't understand how to install or where to put the Vosk model, I've made a [screenshot](https://i.imgur.com/N3bu2lC.png) for you.
# Python version - Из истории удалены случайно закоммиченные секреты.
I was using Python `3.8.3`, but it should work on any newer version. - Бэкенд LLM переключён с OpenAI на Groq (бесплатный тариф) через openai-совместимый API.
- Код обновлён под новую версию SDK `openai` (>=1.0); старый pre-1.0 интерфейс был сломан.
- Обновлена ветка/тэги (`dev`, `v0.0.1-import`), причёсан README и `requirements.txt`.
# ToDo ## Установка
- Адекватная архитектура кода, собрать всё и переписать from the ground up.
- Задержка воспроизведения звука на основе реальной длительности .wav файла (прогружать при запуске?)
- Speech to intent?
- Отключать self listening protection во время воспроизведения с наушников.
- Указание из списка или по имени будет реализовано позже.
# Author Требуется **Python 3.11** (на 3.13 ряд зависимостей пока ставится с бубном).
(2022) Abraham Tugalov
```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` и заполните ключи:
- `PICOVOICE_TOKEN` — бесплатно на [console.picovoice.ai](https://console.picovoice.ai/).
- `GROQ_TOKEN` — бесплатно на [console.groq.com](https://console.groq.com/).
Vosk-модель для русского языка лежит в `model_small/` (уже в репозитории). Запуск:
```bash
python main.py
```
## Конфигурация
- `config.py`:
- `MICROPHONE_INDEX = -1` — индекс микрофона (`-1` означает устройство по умолчанию). Если микрофонов несколько и берётся не тот, поменяйте число.
- `GROQ_MODEL` — имя модели Groq (по умолчанию `llama-3.3-70b-versatile`).
- `commands.yaml` — набор голосовых команд и их вариантов для fuzzy-матчинга.
- `custom-commands/` — скомпилированные AHK-скрипты под конкретный сетап автора оригинала (переключение мониторов, управление Яндекс.Музыкой и т.п.). На вашей машине большая часть из них работать не будет, но ассистент запустится в любом случае.
## Использование
1. Скажите **«Джарвис»** (или **«jarvis»**) — ассистент даст звуковой сигнал готовности.
2. В течение 10 секунд произнесите команду:
- либо одну из фраз из `commands.yaml` (открыть браузер, выключить звук и т.д.);
- либо начните со слова **«скажи …»** — остаток фразы уйдёт в Groq, ответ будет зачитан вслух.
## Лицензия
CC BY-NC-SA 4.0 — см. [LICENSE.txt](LICENSE.txt). Авторство оригинала — Abraham Tugalov / Priler. Изменения в этом форке — Bossiara13 (Dmitry Bykov), 2026.

View file

@ -6,7 +6,7 @@ load_dotenv("dev.env")
# Конфигурация # Конфигурация
VA_NAME = 'Jarvis' VA_NAME = 'Jarvis'
VA_VER = "3.0" VA_VER = "0.1.0"
VA_ALIAS = ('джарвис',) VA_ALIAS = ('джарвис',)
VA_TBR = ('скажи', 'покажи', 'ответь', 'произнеси', 'расскажи', 'сколько', 'слушай') VA_TBR = ('скажи', 'покажи', 'ответь', 'произнеси', 'расскажи', 'сколько', 'слушай')
@ -20,5 +20,7 @@ CHROME_PATH = 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s'
# Токен Picovoice # Токен Picovoice
PICOVOICE_TOKEN = os.getenv('PICOVOICE_TOKEN') PICOVOICE_TOKEN = os.getenv('PICOVOICE_TOKEN')
# Токен OpenAI # Токен Groq
OPENAI_TOKEN = os.getenv('OPENAI_TOKEN') GROQ_TOKEN = os.getenv('GROQ_TOKEN')
GROQ_BASE_URL = "https://api.groq.com/openai/v1"
GROQ_MODEL = "llama-3.3-70b-versatile"

View file

@ -1,2 +1,2 @@
PICOVOICE_TOKEN=<тут ключ-picovoice> PICOVOICE_TOKEN=<тут ключ-picovoice>
OPENAI_TOKEN=<тут ключ-openai> GROQ_TOKEN=<тут ключ-groq>

41
main.py
View file

@ -10,7 +10,7 @@ import time
from ctypes import POINTER, cast from ctypes import POINTER, cast
import openai import openai
from openai import error from openai import OpenAI
import pvporcupine import pvporcupine
import simpleaudio as sa import simpleaudio as sa
import vosk import vosk
@ -37,8 +37,7 @@ VA_CMD_LIST = yaml.safe_load(
system_message = {"role": "system", "content": "Ты голосовой ассистент из железного человека."} system_message = {"role": "system", "content": "Ты голосовой ассистент из железного человека."}
message_log = [system_message] message_log = [system_message]
# init openai client = OpenAI(api_key=config.GROQ_TOKEN, base_url=config.GROQ_BASE_URL)
openai.api_key = config.OPENAI_TOKEN
# PORCUPINE # PORCUPINE
porcupine = pvporcupine.create( porcupine = pvporcupine.create(
@ -59,33 +58,29 @@ q = queue.Queue()
def gpt_answer(): def gpt_answer():
global message_log global message_log
model_engine = "gpt-3.5-turbo"
max_tokens = 256 # default 1024
try: try:
response = openai.ChatCompletion.create( response = client.chat.completions.create(
model=model_engine, model=config.GROQ_MODEL,
messages=message_log, messages=message_log,
max_tokens=max_tokens, max_tokens=256,
temperature=0.7, temperature=0.7,
top_p=1, top_p=1,
stop=None stop=None,
) )
except (error.TryAgain, error.ServiceUnavailableError): except openai.BadRequestError as ex:
return "ChatGPT перегружен!" code = getattr(ex, "code", None) or ""
except openai.OpenAIError as ex: message = str(ex)
# если ошибка - это макс длина контекста, то возвращаем ответ с очищенным контекстом if code == "context_length_exceeded" or "context_length_exceeded" in message:
if ex.code == "context_length_exceeded":
message_log = [system_message, message_log[-1]] message_log = [system_message, message_log[-1]]
return gpt_answer() return gpt_answer()
else: return "Запрос отклонён моделью."
return "OpenAI токен не рабочий." except openai.RateLimitError:
return "Лимит запросов исчерпан."
except openai.APIConnectionError:
return "Не могу связаться с сервером."
except openai.APIError:
return "Groq токен не рабочий."
# Find the first response from the chatbot that has text in it (some responses may not have text)
for choice in response.choices:
if "text" in choice:
return choice.text
# If no response with text is found, return the first response's content (which may be empty)
return response.choices[0].message.content return response.choices[0].message.content
@ -283,7 +278,7 @@ recorder = PvRecorder(device_index=config.MICROPHONE_INDEX, frame_length=porcupi
recorder.start() recorder.start()
print('Using device: %s' % recorder.selected_device) print('Using device: %s' % recorder.selected_device)
print(f"Jarvis (v3.0) начал свою работу ...") print(f"Jarvis (v0.1.0) начал свою работу ...")
play("run") play("run")
time.sleep(0.5) time.sleep(0.5)

Binary file not shown.