Полгода назад Vera была консольным голосовым ассистентом, который умел открывать приложения, управлять громкостью и искать информацию в интернете. Я собирался просто добавить графический интерфейс. В итоге переписал значительную часть архитектуры, сменил движки распознавания и синтеза речи, добавил память, зрение, Skills, работу с документами и полноценную агентную систему инструментов.
Фактически от старой Vera осталось название, общая идея и часть системных команд.
При этом Vera изначально проектировалась под небольшие локальные модели до 10B параметров. Все основные сценарии - обычный диалог, работа с инструментами, анализ документов и генерация презентаций - выполняются одной и той же локальной моделью, без отдельной большой модели для «сложных» задач.


Консольная версия Vera была хорошим способом проверить саму идею: может ли небольшая локальная модель управлять компьютером, пользоваться инструментами и при этом нормально работать на обычном пользовательском железе.
Но довольно быстро стало понятно, что для повседневного использования одной консоли недостаточно. Через неё было неудобно вести длинные диалоги, работать с файлами, переключаться между сессиями, просматривать результаты выполнения инструментов и настраивать модель.
По мере роста проекта консоль быстро стала ограничением. Появились память, работа с документами, изображения, заметки, периодические задачи и генерация файлов. Все эти возможности требовали полноценного интерфейса.
На что я ориентировался при создании интерфейса
При проектировании новой версии я во многом ориентировался на Hermes Agent Desktop. Мне понравился общий подход к интерфейсу: разные цветовые схемы, боковая навигация, отдельные рабочие разделы и ощущение не обычного чат-бота, а полноценной среды для взаимодействия с агентом.
При этом я не ставил перед собой задачу скопировать интерфейс один в один. Hermes скорее стал визуальным и функциональным ориентиром, от которого я отталкивался при разработке собственной структуры приложения.
В итоге Vera получила:
отдельное окно чата;
плавающий виджет поверх остальных окон; (в дальнейшем будет "персонажем" по типу питомца в Claude Code, Codex)
управление сессиями;
раздел заметок;
раздел созданных проектов;
настройки локальной модели;
просмотр системных логов;
работу с файлами через drag-and-drop;
встроенную рабочую панель с деревом файлов и терминалом.



Но новый интерфейс оказался только началом
Изначально я думал, что просто добавлю к существующему Python-приложению графическую оболочку. На практике это быстро превратилось в переделку значительной части проекта.
Старая архитектура была рассчитана в первую очередь на последовательную работу из консоли:
Голосовая команда ↓ Распознавание речи ↓ Определение намерения ↓ Выполнение команды или запрос к LLM ↓ Голосовой ответ
Для новой версии этого уже было недостаточно. Теперь агенту нужно было одновременно обслуживать графический интерфейс, голосовой ввод, текстовые сообщения, фоновые задачи, несколько диалоговых сессий и вызовы инструментов.
Поэтому приложение пришлось разделить на две основные части:
Electron + React Интерфейс, сессии, настройки, файлы ↓ локальный API ↓ Python backend LLM, голос, память, инструменты и задачи
GUI отвечает за взаимодействие с пользователем, а Python backend - за основную агентную логику. Electron также запускает backend вместе с приложением, следит за его состоянием и при необходимости пытается перезапустить его.
Сначала нужно было исправить распознавание речи
Для первого прототипа vosk-model-small-ru хватало: она работала локально, быстро запускалась и почти не нагружала компьютер. Но в обычной разговорной речи модель регулярно искажала короткие команды и названия приложений. Для диктовки такая ошибка не всегда критична, а для агента фраза «открой Telegram», распознанная как «открой теле гра», уже означает неправильное действие или его отсутствие.
Поэтому первым делом я решил полностью заменить движок распознавания речи.
Переход с Vosk на Sherpa-ONNX
В новой версии Vera использует Sherpa-ONNX и потоковую модель:
sherpa-onnx-streaming-zipformer-small-ru-vosk-2025-08-16
Несмотря на довольно длинное название, с точки зрения пользователя всё работает просто: микрофон постоянно передаёт небольшие участки аудио в распознаватель, а тот обрабатывает речь по мере её поступления, не дожидаясь окончания всей записи.
В коде для этого создаётся OnlineRecognizer, состоящий из трёх ONNX-компонентов:
encoder.onnx;decoder.onnx;joiner.onnx.
Encoder обрабатывает входные аудиопризнаки, decoder учитывает уже распознанную последовательность, а joiner объединяет их результаты и предсказывает следующие токены.
Распознавание работает с частотой 16 кГц, может выполняться на CPU и по умолчанию использует всего один вычислительный поток. Поэтому новая система по-прежнему нормально работает на обычных компьютерах без дискретной видеокарты.
stt_recognizer = sherpa_onnx.OnlineRecognizer.from_transducer( tokens=tokens_path, encoder=encoder_path, decoder=decoder_path, joiner=joiner_path, num_threads=1, sample_rate=16000, feature_dim=80, decoding_method="greedy_search", provider="cpu", enable_endpoint_detection=True, )
В моих тестах новая модель заметно реже ошибалась на коротких командах и названиях приложений. Формальный WER-бенчмарк я не проводил - сравнивал на собственном микрофоне и реальных сценариях Vera.
Для меня важнее было не получить лучшие цифры в абстрактном датасете, а улучшить конкретные сценарии. В первую очередь я проверял распознавание активационного слова, коротких команд, названий приложений и фраз с паузами на обычном CPU.
Потоковое распознавание вместо записи целой фразы
Ещё одно важное изменение - Vera теперь использует именно потоковое распознавание.
Старая логика голосового ассистента часто выглядит так:
Пользователь начал говорить ↓ Запись всей фразы ↓ Остановка записи ↓ Распознавание ↓ Обработка команды
В новой версии аудио передаётся в Sherpa-ONNX постоянно:
Микрофон ↓ Небольшие фрагменты аудио ↓ OnlineRecognizer ↓ Частичный результат ↓ Определение конца фразы ↓ Готовая команда
Sherpa-ONNX самостоятельно определяет конец реплики по продолжительности тишины. В Vera параметры endpoint detection вынесены в конфигурацию: можно настроить, сколько агент должен ждать после короткой или длинной фразы.
Это позволило избавиться от жёстко заданной продолжительности записи. Пользователь может произнести как короткое:
Вера, погода
так и более длинную команду:
Вера, найди последние новости про локальные языковые модели и коротко перескажи главное.
Агент сам понимает, когда пользователь закончил говорить.
Затем я занялся голосом
С синтезом речи история получилась случайно.
Предыдущая Vera использовала системные голоса Windows через pyttsx3. Для прототипа это почти идеальный вариант: ничего не нужно скачивать, генерация начинается быстро, а интеграция занимает несколько строк.
Но звучит такой голос всё равно как системный диктор. Для утилиты это нормально, а для агента, с которым пользователь регулярно разговаривает, голос является полноценной частью интерфейса.
Мне требовался локальный TTS с поддержкой русского языка, достаточно естественной речью, небольшими требованиями к железу и без зависимости от платных API.
Supertonic я нашёл практически случайно
Я просто листал GitHub в поисках интересных проектов и идей для дальнейшего развития Vera и наткнулся на Supertonic. Скачал его скорее из любопытства, сгенерировал несколько русских фраз и почти сразу понял, что это именно то, что нужно.
Supertonic работает локально через ONNX Runtime, поддерживает разные голосовые стили и позволяет управлять скоростью речи и количеством шагов генерации. При этом ему не нужен отдельный сервер или облачный API.
После системных голосов Windows разница оказалась особенно заметной. Vera перестала звучать как экранный диктор и стала больше напоминать отдельного голосового персонажа.
В текущей версии Vera используется голос Lily, которому внутри Supertonic соответствует стиль F2. Перед синтезом агент получает голосовой стиль, передаёт русский текст модели, а затем воспроизводит готовый аудиомассив через sounddevice.
voice_style = tts.get_voice_style("F2") wav, duration = tts.synthesize( text=text, voice_style=voice_style, lang="ru", total_steps=4, speed=1.15, ) sd.play(wav.T, samplerate=tts.sample_rate)
Настройки голоса без повторной загрузки модели
Параметры синтеза читаются перед каждой новой репликой, поэтому пользователь может изменить их в настройках приложения без перезапуска Vera:
используемый голос;
громкость;
скорость речи;
количество шагов генерации.
Количество шагов влияет на компромисс между скоростью и качеством синтеза. Для Vera я оставил достаточно небольшое значение, по умолчанию - 4, поскольку для голосового агента время ответа не менее важно, чем идеальная детализация голоса.
Сам Supertonic инициализируется один раз в отдельном фоновом потоке. После этого текстовые ответы складываются в очередь и последовательно озвучиваются. Благодаря этому загрузка TTS не блокирует основной цикл агента и не мешает обработке команд.
Схематично это выглядит так:
Ответ LLM или системной команды ↓ Очистка текста ↓ TTS-очередь ↓ Фоновый поток Supertonic ↓ Генерация аудио ↓ sounddevice
Что получилось в итоге
После замены обеих частей голосового конвейера схема стала выглядеть так:
Микрофон ↓ Sherpa-ONNX Streaming ↓ Распознанная команда ↓ Маршрутизатор / LLM / инструмент ↓ Текстовый ответ ↓ Supertonic ↓ Голос
Обе системы работают локально, запись с микрофона не отправляется во внешние сервисы.
При этом переход на более современные модели не превратил Vera в приложение, которому обязательно нужна мощная видеокарта. Sherpa-ONNX настроен на CPU, а Supertonic достаточно лёгкий, чтобы использовать его как основной голосовой движок, а не как отдельный медленный режим «повышенного качества».
Однако после решения проблем со слухом и голосом проявилось другое ограничение: возможностей становилось всё больше, а небольшая локальная модель должна была выбирать инструменты из постоянно растущего списка.
Почему нельзя просто отдать модели все инструменты
После добавления новых возможностей появилась другая проблема: чем больше инструментов получает небольшая локальная модель, тем чаще она начинает путаться.
Если передать ей одновременно веб-поиск, Telegram, чтение документов, создание файлов, Python-интерпретатор и системные команды, увеличивается системный промпт, а модель чаще выбирает неподходящий инструмент.
Поэтому в Vera используется многоуровневая маршрутизация.
Сначала запрос проверяют обычные обработчики. Команды вроде:
Вера, громкость 50
Вера, открой Telegram
Вера, поставь таймер на 10 минут
выполняются напрямую, без обращения к LLM. Для предсказуемых системных действий нейросеть просто не нужна.
Если готового обработчика нет, запрос передаётся в центральный маршрутизатор route_intent. Он определяет, какие инструменты могут понадобиться модели. Сейчас маршрутизатор умеет выделять запросы к веб-поиску, Telegram, документам и Python-интерпретатору, а также отдельно определяет создание презентаций и текстовых документов.
Схема выглядит примерно так:
Запрос пользователя ↓ Проверка системных команд ↓ Определение намерения ↓ Выбор подходящих инструментов ↓ LLM или отдельный skill ↓ Результат
При этом модель получает не весь список инструментов, а максимум два, выбранных для конкретного запроса. Это ограничение явно задано в route_intent и повторно применяется перед вызовом LLM.
Например:
«Найди последние новости про Python» → web_search «Прочитай документ report.pdf» → read_document «Посчитай медиану этого списка» → code_interpreter «Отправь сообщение в Telegram» → telegram
Обычный разговор инструментов вообще не получает. Это снижает вероятность того, что Vera внезапно запустит поиск или попытается создать файл в ответ на простое сообщение.
Для запросов, где нужен только веб-поиск, есть ещё более короткий путь: Vera вызывает поиск напрямую и возвращает результат, не запуская полный цикл tool calling.
Простые команды по-прежнему работают без LLM
Этот принцип сохранился ещё с первой версии Vera.
Перед вызовом модели route_command_simple сначала запускает детерминированные обработчики. Только если ни один из них не подошёл, запрос отправляется в LLM.
То есть команда:
Вера, яркость 70
не превращается в prompt и не ждёт генерации ответа. Она сразу попадает в соответствующий системный обработчик.
Это даёт три преимущества:
команда выполняется быстрее;
результат не зависит от поведения модели;
LLM не получает лишние полномочия.
Нейросеть подключается только там, где действительно нужно понять свободную формулировку, составить ответ или выбрать инструмент.
Skills для составных задач
Некоторые запросы нельзя свести к одному вызову инструмента. Например, создание презентации включает несколько этапов: исследование темы, подготовку структуры, генерацию содержимого и сохранение готового файла.
Для таких сценариев в Vera появились Skills.
Сейчас встроены два основных skill-конвейера:
presentations - создание презентаций;



documents - создание текстовых документов, докладов и отчётов.
Маршрутизатор определяет такой запрос до обычного вызова LLM и запускает специализированный pipeline. Например, запрос «сделай презентацию про искусственный интеллект» направляется в presentations, а «подготовь доклад про локальные модели» - в documents.
В коде эти конвейеры выполняются отдельно:
if skill_name == "presentations": return execute_presentation_creation(...) if skill_name == "documents": return execute_text_document_creation(...)
Презентации и документы могут использовать веб-поиск, локальную модель и собственные функции генерации файлов. После завершения готовый файл появляется в разделе проектов интерфейса.
Главное отличие от обычного tool calling в том, что модель не должна самостоятельно придумывать весь порядок действий. Последовательность уже определена внутри конкретного skill, а LLM используется только на тех этапах, где действительно нужна генерация или анализ.
В итоге Vera не пытается решать любую задачу одним огромным промптом:
Системная команда → прямой обработчик Простой вопрос → LLM без инструментов Поиск или вычисление → LLM с 1-2 инструментами Презентация или документ → отдельный skill-конвейер
Так небольшая локальная модель работает стабильнее, а добавление новых функций не приводит к бесконечному разрастанию системного промпта.
Память между запусками
В первой версии Vera фактически жила в пределах текущего диалога. После перезапуска агент уже не помнил имя пользователя, его город, предпочтения или проекты.
Теперь долгосрочная память хранится локально в data/memory.json, а история диалогов и сессий в SQLite-базе data/vera.db.
Факты автоматически распределяются по категориям:
личная информация;
контакты;
предпочтения;
проекты;
остальные факты.
Для поиска подходящих воспоминаний я не стал подключать векторную базу и отдельную embedding-модель. Вместо этого используется BM25 с учётом давности, категории и закреплённых фактов.
В system prompt попадает не вся память сразу, а только профиль пользователя, закреплённые данные и несколько наиболее подходящих фактов. Контекст памяти дополнительно ограничен по размеру, чтобы не занимать значительную часть контекстного окна небольшой локальной модели.
Память можно контролировать обычными командами:
Вера, запомни, что меня зовут Тимур
Вера, что ты знаешь обо мне
Вера, забудь про мой проект
Кроме явных команд, Vera умеет извлекать некоторые факты из обычного разговора и сохранять их автоматически.
Работа с файлами и изображениями
В чат теперь можно перетаскивать документы и изображения или вставлять их из буфера обмена.
Vera поддерживает чтение PDF, DOCX, XLSX, PPTX, TXT, Markdown, исходного кода и других текстовых форматов. Извлечённое содержимое передаётся модели вместе с вопросом пользователя.
Например, можно загрузить отчёт и попросить: Коротко перескажи документ и выдели основные проблемы
Для изображений используется локальная мультимодальная модель с соответствующим mmproj. Текст и изображение передаются в одном запросе, поэтому Vera может анализировать скриншоты, фотографии и элементы интерфейса.
При этом мультимодальность зависит от выбранной пользователем модели: обычная текстовая GGUF-модель изображения обрабатывать не сможет.
Периодические и фоновые задачи
Ещё одно заметное изменение - Vera теперь умеет выполнять задачи по расписанию.
Можно создать обычное напоминание:
Вера, напомни через полчаса позвонить другу
или повторяющуюся задачу:
Вера, рассказывай мне новости каждое утро в 9:00
Простые напоминания не отправляются в LLM: в нужное время Vera просто показывает и озвучивает сохранённый текст. Если задача требует поиска или обработки информации, она проходит через обычный маршрутизатор и получает необходимые инструменты.
Все задачи хранятся локально. Для каждой сохраняются время запуска, интервал, статус последнего выполнения и текст ошибки. Управлять расписанием можно как голосом, так и через отдельный раздел интерфейса.

Локальная модель
Vera изначально разрабатывалась с расчётом на небольшие модели до 10B параметров, которые можно запускать локально на обычном пользовательском компьютере.
Во время разработки я в основном использовал Qwen3.5 2B. Эта же модель обрабатывает диалоги, выбирает инструменты, анализирует документы, работает с памятью и участвует в генерации презентаций и текстовых файлов.
То есть для создания презентации Vera не переключается на отдельную облачную или более крупную модель. Один локальный LLM последовательно выполняет все этапы: помогает собрать материал, сформировать структуру, подготовить содержимое и передать его генератору файла.
На маленькой модели это работает только потому, что я не заставляю её решать всё самой. Простые команды обрабатывает код, инструментов она видит максимум два, а сложные сценарии вынесены в отдельные pipeline. .
Также можно подключить уже запущенный OpenAI-совместимый сервер, например Ollama или LM Studio.
Адрес сервера задаётся в настройках.

Там же можно изменить размер контекста, включить или отключить режим размышления и задать его токенный бюджет.
Установка без Python и Node.js
В прошлой версии для запуска Vera пользователю приходилось скачивать исходники, устанавливать Python, зависимости и отдельно разбираться с моделями.
Теперь я собрал полноценный установщик для Windows в формате .exe.
Пользователю достаточно скачать установщик, запустить его и дождаться завершения установки. Не нужно отдельно устанавливать Python, Node.js и зависимости проекта, приложение устанавливается как обычная программа для Windows.
После запуска Vera остаётся работать в системном трее. Основное окно можно закрыть, не завершая работу агента, а полностью выйти через контекстное меню иконки в трее.
При этом проект остаётся открытым. Те, кто хочет изменить архитектуру, добавить собственные команды, Skills или инструменты, по-прежнему могут клонировать репозиторий и запустить Vera из исходного кода. Инструкция для разработки и список необходимых зависимостей находятся в README проекта.
Итоги
За почти год Vera прошла путь от консольного голосового ассистента до локального приложения, в котором появились:
графический интерфейс и отдельные сессии;
Sherpa-ONNX и потоковое распознавание речи;
локальный нейросетевой голос Supertonic;
долгосрочная память;
работа с документами и изображениями;
маршрутизация инструментов;
Skills для составных задач;
фоновые и периодические задачи;
поддержка локальных и внешних LLM-серверов;
готовый установщик для Windows.
При этом главный принцип проекта не изменился: пользовательские данные, голос, история диалогов и модель могут оставаться на компьютере пользователя.
Все команды в статье я намеренно перечислять не стал, их уже стало слишком много. Полный справочник, инструкция по установке и описание конфигурации находятся в README проекта.
Проект всё ещё активно развивается, поэтому буду рад сообщениям об ошибках, предложениям и pull request.
Если Vera показалась вам интересной, можно поддержать проект звездой на GitHub - это действительно помогает open-source-проекту становиться заметнее.
Новости разработки, новые сборки и планы я публикую в Telegram-канале: @agent_vera_ai.
P.S. Качество ответов и вызова инструментов сильно зависит от выбранной модели, а небольшие локальные LLM всё ещё могут ошибаться. Для комфортной работы рекомендую 16 ГБ оперативной памяти, хотя базовые функции запускаются и на менее мощных компьютерах. Мультимодальность доступна только при использовании совместимой vision-модели.
Комментарии (7)

Redfordym
14.07.2026 03:21Сам хотел подобного ассистента сделать, и вот увидел пост
Есть ли прямая ссылка на гит хаб?
Есть или планируется версия под macos?
Какие минимальные характеристики и есть ли выбор модели?
tripleguard Автор
14.07.2026 03:21Да, держите: tripleguard/Vera
Под macOS и Linux руки никак не дойдут доделать. Постараюсь в ближайшее воемя собраться с силами.
По минимальным характеристикам: CPU 2 ядра с AVX2. RAM: 8 ГБ. Свободное место минимум 4 ГБ. GPU не обязателен, агент работает на CPU.
Выбор модели как таковой есть, только самостоятельно закидывать модель в папку с проектом. В будущем планирую сделать хаб с моделями

kox
14.07.2026 03:21Скачал. Запустил. Работает. С хостом llama cpp и моделью qwen3.6-35b. Только на втором вопросе в чат выкинуло: "
Не удалось выполнить инструмент(ы):
telegram: error timeout after 20.0s
" Хотя в самом агенте ни одного упоминания про телегу. Кстати планируется добавлять телегу Агент наотрез отказывается читать, редактировать и запускать файлы на компе. А так проект интересный, буду понаблюдать.)))
cry_san
Скачал. Запустил. Висит.
tripleguard Автор
Написал вам в личку, разберемся с проблемой
cry_san
Спасибо