Vera — ваш личный десктопный агент. github.. github. python.. github. python. qwen3.. github. python. qwen3. windows.. github. python. qwen3. windows. агент.. github. python. qwen3. windows. агент. голосовой ассистент.. github. python. qwen3. windows. агент. голосовой ассистент. искусственный интеллект.. github. python. qwen3. windows. агент. голосовой ассистент. искусственный интеллект. пк.

В прошлой статье я описывал свой эксперимент по возможностям маленьких LLM. Эта статья идет как продолжение, в которой я расскажу о проделанной работе по изменению и улучшению функционала голосового агента. И поверьте, мне есть что рассказать.

Когда я задумывал своего агента, меня дико раздражали три вещи в существующих решениях:

  1. “Дай денег”: Либо плати подписку за ChatGPT Plus, либо привязывай свою карту к API OpenAI/Anthropic/Perplexity.

  2. “Дай данные”: Чтобы включить музыку или открыть папку, мой голос должен улететь на сервер, обработаться там и вернуться обратно. Зачем?

  3. “Установи Python и 100+ библиотек”: Большинство OpenSource-проектов требуют танцев с бубном, установки зависимостей и настройки окружения, docker и т.д. и т.п.

Привет, Хабру!

Привет, Хабру!

Я пошел по другому пути. Vera Agent – является полностью бесплатным и локальным агентом. Никаких API, никаких подписок, никакой настройки окружения, вы просто скачиваете portable-версию с сайта агента или с Github репозитория (а можете установить исходники и работать с ними) и пользуетесь.

Главная цель была сделать инструмент, который принадлежит пользователю, а не сдает его в аренду.

В первой версии агента я использовал Gemma 3 1B. Это отличная модель, но в процессе разработки я столкнулся с ограничениями, которые мешали сделать продукт удобным для обычного пользователя. Поэтому в релизной версии я переехал на Qwen 3 1.7B.

Вот причины этого решения:

  1. Лицензия: У Gemma своя специфическая лицензия. Вроде бы открытая, но с нюансами. У Qwen — классическая Apache 2.0. Это развязывает руки мне, как разработчику, и пользователям. Никаких подводных камней.

  2. Tool Use «из коробки»: Это самое важное. Чтобы агент не просто болтал, а реально мог использовать команды по управлению компьютером (открывал файлы, менял настройки). Qwen справляется с этим на порядок лучше маленьких версий Gemma, понимая контекст команды без танцев с бубном и километровых системных промптов.

Несмотря на то, что под капотом по умолчанию стоит Qwen, я решил не ограничивать пользователей. Вера работает на базе llama-cpp-python и поддерживает формат GGUF. Это значит, что вы не привязаны к моему выбору, и можете поставить свою модель, а агент просто подхватит файл .gguf из папки и начнет работать с ним. Полная свобода.

Что умеет Вера прямо сейчас?

Основной задачей было создать не просто чат-бота, с которым можно поболтать, а реального ассистента, который берет на себя рутину. На данный момент агент закрывает большинство базовых сценариев управления ПК.

По функционалу я разделил возможности на несколько кластеров:

  • Управление системой: Громкость, яркость, создание скриншотов, замер скорости (через tele2), определение IP адреса. Реализовано через стандартные библиотеки, поэтому работает быстро.

  • Питание: Выключение или перезагрузка (можно сказать «Перезагрузи через час» — агент поставит системный таймер).

  • Веб-информеры (без платных API-ключей):

    • Погода: Парсинг публичных страниц. Никаких токенов OpenWeather.

    • Валюты: Данные ЦБ РФ.

    • Кто такой?: Парсинг страниц Википедии для запросов “кто такой/что такое”.

    • Открытие сайтов: Пока реализована система открытия сайтов через готовые алиасы.

  • Файловая система и приложения: Запуск программ и поиск файлов, папок. Здесь используется нечеткий поиск (fuzzy matching), чтобы агент понимал «Открой телегу» так же хорошо, как «Открой Telegram».

«А как же интернет?»: Собственный движок веб-поиска

Обычно разработчики локальных ассистентов идут двумя путями: либо прикручивают платные API (Serpdev, Google Search API), либо заставляют пользователя получать свои ключи.

Я написал собственный модуль веб-поиска, который работает по принципу RAG.

Как это работает под капотом:

  1. Вы спрашиваете: “Вера, кто такой Эйнштейн?” или “Найди информацию про Python”.

  2. LLM определяет нужно ли вызывать функцию веб-поиска.

  3. Если LLM определила, что нужен вызов функции веб-поиска, то пишет в чат <|tool_call|>
    {“name”: “web_search”, “arguments”: {“query”: “<запрос>”}}
    <|tool_call|>

  4. Далее скрипт сканирует ответ LLM на наличие вызова функции, если определяет вызов, то обращается к DuckDuckGo (через парсинг, без API).

  5. Собирает ссылки и открывает 3 наиболее релевантных источника.

  6. Парсит текст с этих страниц, очищает от мусора.

  7. Скармливает собранный контекст LLM, которая формирует краткий и понятный ответ.

    Пример веб-поиска

    Пример веб-поиска

Так как процесс включает в себя загрузку страниц и генерацию ответа на локальном железе, среднее время ответа составляет 10-15 секунд. Да, это не мгновенно, но зато бесплатно и приватно. Чтобы постараться избежать галлюцинаций модели, я добавил команду «Вера, открой источники». Если вы сомневаетесь в ответе, агент откроет в браузере те самые три страницы, на основе которых был сгенерирован ответ.

Ниже представлен фрагмент кода движка-парсера

def search_duckduckgo(query: str, max_results: int = 6) -> List[str]:
    links = []
    try:
        headers = get_default_headers()
        url = f"https://html.duckduckgo.com/html/?q={quote_plus(query)}"
        resp = requests.get(url, headers=headers, timeout=10)
        if resp.status_code == 200:
            pattern = r'uddg=([^&"]+)'
            matches = re.findall(pattern, resp.text)
            seen = set()
            for m in matches:
                try:
                    decoded = unquote(m)
                    if decoded.startswith("http") and decoded not in seen:
                        links.append(decoded)
                        seen.add(decoded)
                        if len(links) >= max_results:
                            break
                except Exception:
                    continue
    except Exception as e:
        print(f"[SEARCH] DuckDuckGo error: {e}")
    return links


def extract_visible_text(html: str) -> str:
    soup = BeautifulSoup(html, "html.parser")
    for tag in soup(["script", "style", "noscript", "header", "footer", "nav", "aside"]):
        tag.decompose()
    for infobox in soup.find_all("table", class_=lambda x: x and "infobox" in x):
        infobox.decompose()
    for infobox in soup.find_all("div", class_=lambda x: x and "infobox" in str(x)):
        infobox.decompose()
    root = soup.find("main") or soup.find("article") or soup.body or soup
    parts: list[str] = []
    for t in root.find_all(["h1", "h2", "h3", "p", "li"]):
        txt = t.get_text(" ", strip=True)
        if txt:
            parts.append(txt)
    for t in root.find_all(["td", "th"]):
        txt = t.get_text(" ", strip=True)
        if txt and (re.search(r"d", txt) or len(txt) <= 40):
            parts.append(txt)
    for t in root.find_all(["span", "strong", "b", "time"]):
        txt = t.get_text(" ", strip=True)
        if txt and re.search(r"d", txt):
            parts.append(txt)
    text = " ".join(parts)
    return re.sub(r"s+", " ", text).strip()

Архитектура: Почему (пока) LLM не используется для всего?

Здесь кроется важный технический нюанс. Многие стремятся засунуть в LLM абсолютно всё, используя вызов функций для каждого чиха. Но я разрабатывал Веру с прицелом на работу даже на слабых устройствах (от 4 ГБ RAM).

Если прогонять команду “Сделай громкость 50%” через нейросеть весом в несколько гигабайт, вы будете ждать отклика 5-10 секунд. Это убивает UX.

Поэтому сейчас реализована гибридная маршрутизация:

  1. Быстрые команды: Открытие программ, управление громкостью, таймеры — обрабатываются мгновенно через жесткую логику и нечеткий поиск.

  2. Сложные запросы (LLM): Веб-поиск и суммаризация ��нформации — идут через нейросеть.

Это компромисс ради скорости. В будущем, по мере оптимизации квантования и железа, я планирую перевести маршрутизацию большинства функций на LLM, чтобы агент лучше понимал контекст и сложные составные просьбы. Но сейчас приоритет — скорость.

Чтобы обеспечить работу агента на обычном домашнем ноутбуке без топовой видеокарты, я подбирал максимально легкие и эффективные инструменты:

  • STT (Распознавание речи): Vosk (модель vosk-model-small-ru-0.22). Выбрана за скорость и работу полностью оффлайн.

  • TTS (Синтез речи): pyttsx3. Использует системные голоса Windows, что дает нулевую задержку при ответе (в отличие от тяжелых нейросетевых голосов).

  • Инференс LLM: llama-cpp-python + Qwen3-1.7B-Q4_K_M. Позволяет запускать GGUF модели на CPU/GPU (В portable-версии используется CPU версия библиотеки, для того, чтобы добавить поддержку CUDA ядер, вы можете самостоятельно скомпилировать exe из исходников, предварительно установив библиотеку с поддержкой CUDA)

Минимальные требования для запуска: Так как я оптимизировал агента для слабых машин, порог входа очень низкий:

  • ОС: Windows 10/11 (x64)

  • RAM: от 4 ГБ (для Qwen 1.7B этого достаточно, но лучше 8 ГБ).

  • Место на диске: ~2 ГБ (основной вес занимает модель).

Что дальше?

Проект находится в активной стадии разработки, и текущая версия — это крепкий фундамент, но далеко не финал. Вот над чем я работаю прямо сейчас:

  • Кроссплатформенность (macOS и Linux): Сейчас Вера работает только на Windows, так как многие системные вызовы (управление звуком, окнами, питанием) завязаны на WinAPI и специфичные библиотеки. Я понимаю, что значительная часть аудитории (и разработчиков) сидит на nix-системах, поэтому адаптация под macOS и Linux — приоритетная задача на ближайшее время. Архитектура на Python позволяет это сделать достаточно «малой кровью».

  • Полноценный GUI: Сейчас агент живет в консоли. В разработке находится версия с полноценным графическим интерфейсом. Это сделает настройку удобнее (не придется лезть в JSON-файлы руками) и позволит визуализировать диалог с LLM.

  • Глубокая интеграция: Я планирую расширить взаимодействие с ОС. Цель — научить агента не просто запускать софт, но и выполнять более сложные цепочки действий внутри системы, приближаясь к концепции «второго пилота» для ПК.

  • Интеграция с Home Assistant: Это один из самых ожидаемых этапов. Я планирую научить Веру общаться с API Home Assistant. Идея в том, чтобы создать идеальную приватную экосистему: локальный голосовой ассистент управляет локальным умным домом. Никаких облаков, задержек и умных колонок.

  • Ну и определенные секретные функции, о которых я расскажу по мере их добавления.

Итог

Vera — это полностью Open Source проект, рожденный из желания вернуть приватность и контроль над собственным ПК. Я верю, что голосовой ассистент не должен быть «шпионом», работающим только при наличии интернета, или требовать подписку за базовые функции.

Проект сейчас в активной фазе, и мне очень нужна ваша поддержка. Самое лучшее, что вы можете сделать — это просто скачать агента, «погонять» его на своих задачах и поставить звездочку репозиторию на GitHub. Это реально мотивирует работать над проектом дальше и показывает, что тема локального ИИ жива и интересна сообществу.

Если у вас есть идеи по оптимизации, мысли по архитектуре или вы знаете, как заставить LLM работать еще быстрее — оставляйте комментарии в репозитории или под этой статьей (если проект оказался интересным, заведу телеграмм канал). Любая активность помогает посту продвигаться, а проекту — находить новых контрибьюторов.

Сайт проекта: agentvera.ru

Репозиторий: github.com/tripleguard/agent_vera

Автор: tripleguard

Источник

Rambler's Top100