Skip to content

Anatolt/NeiroTolikBot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

136 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NeiroTolikBot

Telegram и Discord бот с поддержкой генерации текста через OpenRouter или OpenClaw OAuth (Codex) и изображений через PiAPI.ai.

Основные функции

  • Генерация изображений
  • Обработка кастомных промптов
  • Память контекста для последних сообщений
  • Получение списка моделей
  • Загрузка списка моделей в бота, чтобы к ним можно было обращаться
  • Работа в групповых чатах
  • LLM-роутинг с подтверждением действий через /yes
  • Пагинация /models_free и выбор текстовой модели через /set_text_model

Список задач вынесен в todo.md.

Управление роутингом

  • Переключение для конкретного пользователя в чате: отправьте текстом «роутинг алгоритмами» или «роутинг ллм».
  • Аналогичные слеш-команды: /rout_algo, /rout_llm, /rout для просмотра текущего режима.
  • По умолчанию используется режим из конфигурации, но пользовательский выбор сохраняется в настройках.
  • В режиме LLM бот сообщает о запросе к роутеру и предлагает подтвердить действие командой /yes.

Управление моделями (Telegram)

  • /models_free — список бесплатных моделей с пагинацией (кнопки).
  • /set_text_model <номер> — закрепить модель генерации текста для пользователя в чате.
  • /models_pic и /set_pic_model <номер> — список и выбор модели генерации изображений.

Контроль объема контекста

  • Перед отправкой запроса на OpenRouter бот оценивает примерный объем контекста (символы/токены) с учетом системных сообщений, истории и текущего запроса. Лимит берется из витрины моделей MODEL_CATALOG или из CONTEXT_GUARD.DEFAULT_CONTEXT_LENGTH.
  • При заполнении более CONTEXT_GUARD.WARNING_RATIO отправляется предупреждение пользователю, а при достижении HARD_RATIO бот скрывает самые старые сообщения из запроса и, при необходимости, делает краткую саммари переполненных частей (стратегия OVERFLOW_STRATEGY). Исходная история в БД не меняется, саммари складываются в summaries.
  • Настройки порога и стратегии находятся в config.py (CONTEXT_GUARD): можно выбрать truncate или summarize, указать модель для саммаризации и лимиты токенов. Логи фиксируют срабатывание механизма и добавление саммари.

Инструкции и персональные подсказки

  • Раздел INSTRUCTION_SETTINGS в config.py резервирует настройки для двух типов инструкций: пользовательские подсказки (от самого пользователя для конкретного чата) и заметки администратора о пользователях. Пока функциональность не реализована, но можно управлять включением и максимальной длиной заранее.

Структура проекта

NeiroTolikBot/
├── handlers/              # Обработчики команд и сообщений
│   ├── commands.py       # Обработчики команд (например, /start)
│   ├── messages.py       # Обработчики сообщений Telegram
│   └── message_service.py # Общая бизнес-логика для всех платформ
├── services/             # Сервисы генерации и другие сервисы
│   ├── generation.py     # Функции для генерации текста и изображений
│   ├── memory.py        # Управление памятью и контекстом диалогов
│   └── consilium.py     # Функционал консилиума (параллельные запросы к моделям)
├── utils/                # Вспомогательные функции
│   └── helpers.py        # Утилиты (экранирование, инициализация)
├── config.py            # Конфигурация бота
├── tbot.py              # Основной файл Telegram-бота
├── discord_bot.py       # Основной файл Discord-бота
├── .env                 # Переменные окружения
└── README.md           # Документация

Установка и запуск

⚠️ Рекомендуется работать в виртуальном окружении, чтобы не трогать системный Python.

  1. Клонируйте репозиторий
  2. Создайте и активируйте виртуальное окружение:
    cd NeiroTolikBot
    python3 -m venv venv
    source venv/bin/activate
  3. Установите зависимости:
    pip install -r requirements.txt
  4. Создайте файл .env со следующими переменными:
    TELEGRAM_BOT_TOKEN=ваш_токен_бота
    DISCORD_BOT_TOKEN=ваш_discord_бот_token
    OPENROUTER_API_KEY=ваш_ключ_openrouter
    # Альтернатива OpenRouter для текста: OpenClaw OAuth
    OPENCLAW_OAUTH_ENABLED=1
    OPENCLAW_BASE_URL=https://de.hohohosting.ru:18789
    OPENCLAW_GATEWAY_TOKEN=ваш_gateway_token
    OPENCLAW_MODEL=openclaw:main
    PIAPI_KEY=ваш_ключ_piapi (опционально)
    CUSTOM_SYSTEM_PROMPT=ваш_промпт (опционально)
    # или можно указать файл: CUSTOM_SYSTEM_PROMPT_FILE=neiro-tolik-promt.txt
    
  5. Запустите бота:
    python tbot.py

Запуск Discord бота

  1. Создайте Discord-приложение и бота в Developer Portal.
  2. На вкладке Bot включите привилегированные интенты: MESSAGE CONTENT INTENT (для чтения текста), SERVER MEMBERS INTENT не требуется, но оставьте включенными MESSAGE CONTENT и базовые GUILD/MESSAGE.
  3. Скопируйте токен бота и пропишите его в .env как DISCORD_BOT_TOKEN=<ваш_токен> вместе с OPENROUTER_API_KEY.
  4. Добавьте бота на сервер: вкладка OAuth2 → URL Generator, отметьте bot и applications.commands, дайте права Send Messages/Read Message History, перейдите по сгенерированной ссылке.
  5. Запустите Discord-бота отдельной точкой входа:
    python discord_bot.py
  6. Поведение в Discord:
    • бот игнорирует собственные сообщения;
    • в серверах отвечает только на упоминание @ИмяБота или сообщения с префиксами !//;
    • в личных сообщениях отвечает на любой текст;
    • доступны команды !start//start и !help//help.

Команды Discord:

  • /start — подсказка по использованию
  • /help — справка по командам
  • /join — подключиться к голосовому каналу, где вы сейчас
  • /leave — выйти из голосового канала
  • /autojoin_on — включить автоподключение к голосу
  • /autojoin_off — отключить автоподключение к голосу

Голосовые сообщения:

  • Telegram голосовые распознаются через OpenAI Whisper (нужен OPENAI_API_KEY).
  • В Discord можно присылать аудио-вложения (.ogg/.mp3/.wav/.m4a) — бот распознает и отвечает.
  • Для локального Whisper можно указать VOICE_LOCAL_WHISPER_URL (по умолчанию http://127.0.0.1:8000/transcribe).
  • Режимы отправки в STT: raw (целый файл) и segmented (кусочки по паузам речи). Переключаются командами /voice_send_raw и /voice_send_segmented.
  • Жёсткий лимит файла для STT: 25 MB.
  • TTS в Discord: команда /say <текст> озвучивает текст в голосовом канале автора (нужен OPENAI_API_KEY и ffmpeg).

Приглашение Discord-бота:

  • OAuth2 ссылка для добавления бота на сервер доступна через администратора.

Команды Telegram (админ):

  • /flow — показать текущие связи Discord → Telegram
  • /setflow — выбрать связь Discord → Telegram (без аргументов покажет списки; пример: /setflow 2 C)
  • /unsetflow — удалить связь (без аргументов покажет список с римскими цифрами; пример: /unsetflow ii)
  • /user_profile [chat_id] <user_id> — показать профиль пользователя (админ)
  • /models_voice — список моделей распознавания речи
  • /set_voice_model <номер> — выбрать модель распознавания речи
  • /voice_send_raw — слать аудио целиком, без нарезки (дороже, лимит 25MB)
  • /voice_send_segmented — слать аудио кусками по паузам речи (лимит 25MB)
  • /say <текст> — озвучить текст и отправить голосовуху (TTS)
  • /tts_voices — список голосов TTS
  • /set_tts_voice <номер> — выбрать голос TTS

Запуск как systemd-сервис

В репозитории уже есть файл neirotolikbot.service (на сервере de используется Docker).

sudo cp neirotolikbot.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable neirotolikbot.service
sudo systemctl start neirotolikbot.service

Логи: sudo journalctl -u neirotolikbot.service -f

Запуск в Docker

Бот запускается в одном контейнере через start-bot.sh (внутри поднимаются tbot.py и discord_bot.py).

  1. Постройте образ и запустите через Docker Compose (в docker-compose.yml лимит памяти 1 GB):

    docker-compose up --build -d
  2. Перезапуск контейнера:

    docker-compose restart
  3. Или запустите вручную, задав ограничение по памяти:

    docker build -t neirotolikbot .
    docker run --rm -d --env-file .env --memory=150m --name neirotolikbot neirotolikbot

Через переменные окружения можно управлять дополнительными настройками для экономии ресурсов:

  • UPDATE_QUEUE_MAXSIZE — максимальный размер очереди обновлений (по умолчанию 50)
  • MAX_CONCURRENT_UPDATES — максимальное число одновременно обрабатываемых обновлений (по умолчанию 2)

Регрессионный тест голоса (Discord)

Для автопроверки STT добавлен отдельный тестовый Discord-бот voice_test_sender. Он заходит в заданный voice-канал, проигрывает .wav-файл и выходит. После этого раннер проверяет свежие записи в data/memory.db (voice_logs) и печатает PASS/FAIL. По умолчанию sender запускается локально (через .venv/bin/python, если есть), без Docker-сети.

  1. Добавьте в .env:
    DISCORD_TEST_BOT_TOKEN=...
    DISCORD_TEST_GUILD_ID=123456789012345678
    DISCORD_TEST_CHANNEL_ID=123456789012345678
  2. Убедитесь, что локальный piper доступен на http://127.0.0.1:8001/tts (или передайте --piper-url).
  3. Запуск:
    ./scripts/run_voice_regression.sh
  4. Ручной запуск:
    python3 tests/voice/run_voice_regression.py --generate-fixtures

Файлы:

  • tests/voice/cases.json — сценарии, эталонные фразы, таймауты
  • tests/voice/generate_fixtures.py — генерация .wav фикстур через локальный piper
  • tests/voice/run_voice_regression.py — проигрывание + SQL-проверка результата
  • tools/voice_test_sender/send_voice.py — одноразовый плеер в Discord voice

Talker: бесконечные анекдоты в голосовом

Talker может непрерывно озвучивать анекдоты в voice-канале:

  • каждый следующий анекдот новый;
  • при исчерпании базы автоматически генерируются новые;
  • стиль голоса чередуется: male -> female.

Запуск:

./scripts/run_talker_jokes.sh

Ограничить количество анекдотов (для прогона):

./scripts/run_talker_jokes.sh --max-jokes 8

Файлы:

  • tools/voice_test_sender/talker_joker.py — runtime Talker
  • tools/voice_test_sender/data/talker_jokes_seed.json — стартовая база анекдотов
  • data/talker_jokes_db.json — рабочая база (автодополняется)
  • data/talker_jokes_state.json — позиция в базе

Автоматическое обновление из GitHub

В проекте есть простой механизм CI/CD, который подтягивает изменения из GitHub и перезапускает бота после каждого push в main/master.

Компоненты

  • webhook_server.py — небольшой Flask-сервер, принимающий webhook от GitHub
  • deploy.sh — скрипт, который:
    • делает git pull
    • определяет, запущен бот через systemd или Docker
    • перезапускает нужный сервис/контейнер
  • webhook.service — пример systemd-сервиса для webhook-сервера

Настройка

  1. Переменные окружения (добавьте в .env):

    GITHUB_WEBHOOK_SECRET=случайная_строка_из_32_символов
    WEBHOOK_PORT=5000
    WEBHOOK_HOST=0.0.0.0
    

    Сгенерировать секрет: python3 -c "import secrets; print(secrets.token_urlsafe(32))"

  2. Убедитесь, что зависимости установлены (см. раздел «Установка и запуск»).

  3. Запустите webhook-сервер как сервис:

    sudo cp webhook.service /etc/systemd/system/
    sudo systemctl daemon-reload
    sudo systemctl enable webhook.service
    sudo systemctl start webhook.service
    sudo journalctl -u webhook.service -f  # проверки
  4. Настройте GitHub Webhook:

    • GitHub → Settings → Webhooks → Add webhook
    • Payload URL: http(s)://ВАШ_СЕРВЕР:5000/webhook
    • Content type: application/json
    • Secret: то же значение, что GITHUB_WEBHOOK_SECRET
    • Events: Just the push event
  5. Пробросьте порт:

    • откройте 5000/TCP в файрволе (sudo ufw allow 5000/tcp)
    • либо повесьте nginx/Cloudflare/ngrok поверх сервиса
  6. Тест: в настройках webhook нажмите «Redeliver» или сделайте тестовый push.

Как это работает

  1. GitHub присылает запрос на /webhook
  2. webhook_server.py проверяет подпись и запускает deploy.sh
  3. Скрипт определяет окружение:
    • если поднят Docker (docker-compose.yml), пересобирает и перезапускает контейнер
    • иначе перезапускает neirotolikbot.service
    • если ничего из перечисленного не найдено — только делает git pull
  4. Бот обновляется до последнего коммита

Возможности

  • Генерация текста через различные модели (ChatGPT, Claude, DeepSeek)
  • Генерация изображений через PiAPI.ai
  • Работа в группах (требуется упоминание бота или ответ на сообщение бота)
  • Гибкая маршрутизация запросов
  • Управление памятью и контекстом диалогов
  • Консилиум моделей — получение ответов от нескольких моделей одновременно

Использование

Личные сообщения

  • Просто напишите свой вопрос
  • Укажите модель в начале или конце запроса
  • Для генерации изображений используйте ключевые слова "нарисуй" или "сгенерируй картинку"
  • Используйте консилиум для получения ответов от нескольких моделей одновременно

Консилиум моделей

Консилиум позволяет получить ответы от нескольких моделей одновременно для сравнения их мнений.

Использование:

  1. Автоматический выбор моделей (3 модели по умолчанию):

    /consilium какая погода в Москве?
    консилиум: объясни квантовую физику
    
  2. Указание конкретных моделей:

    /consilium через chatgpt, claude, deepseek: напиши стихотворение
    консилиум через chatgpt, claude: какой сегодня день?
    

Примеры:

  • /consilium какая погода в Москве? — автоматический выбор 3 моделей
  • /consilium через chatgpt, claude, deepseek: объясни квантовую физику — указанные модели
  • консилиум: напиши стихотворение — через текстовое сообщение

Бот параллельно запросит ответы у всех указанных моделей и покажет результаты с указанием времени выполнения.

Групповые чаты

⚠️ Важно: перед использованием бота в группах необходимо отключить Privacy Mode!

Настройка бота для работы в группах

  1. Отключите Privacy Mode через @BotFather:

    • Откройте @BotFather в Telegram
    • Отправьте команду /mybots
    • Выберите вашего бота (NeiroTolikBot)
    • Нажмите "Bot Settings"
    • Выберите "Group Privacy"
    • Нажмите "Turn off" (выключить)

    Это необходимо, чтобы бот мог получать все сообщения из групп, а не только команды и ответы на свои сообщения.

  2. Добавьте бота в группу:

    • Добавьте бота в группу как обычного участника
    • Бот должен иметь возможность читать сообщения
  3. Использование в группе:

    • Упомяните бота в сообщении: @NeiroTolikBot привет
    • Или ответьте на сообщение бота (бот автоматически обработает ответ без упоминания)
    • Используйте те же команды, что и в личных сообщениях
    • Бот будет реагировать на сообщения с упоминанием или на ответы к его сообщениям

Управление памятью

  • /new - Начать новый диалог (сохраняет историю для будущего использования)
  • /clear - Полностью очистить память бота
  • /help - Показать справку по командам
  • /consilium - Получить ответы от нескольких моделей одновременно (см. раздел "Консилиум моделей")

Консольное тестирование без Telegram

Для быстрого прогона смоук-тестов и проверки ключа OpenRouter можно использовать скрипт utils/console_tester.py. Он также умеет офлайн проверять команды /help и /models.

Запуск смоук-тестов

python utils/console_tester.py --run-tests --api-key "<OPENROUTER_API_KEY>"

Тесты проверяют:

  • доступность основной модели;
  • базовую генерацию ответа;
  • переключение на альтернативную модель;
  • работу памяти и наличие истории в SQLite.

Если основная модель недоступна, отчёт помечает остальные шаги как пропущенные, но тестирование не прерывается.

Офлайн-проверка команд

Можно прогнать ответы на /help и /models без доступа к OpenRouter:

python utils/console_tester.py --run-command-tests

Интерактивный режим

python utils/console_tester.py --interactive --api-key "<OPENROUTER_API_KEY>"

Дополнительные параметры:

  • --model — основная модель (по умолчанию anthropic/claude-3-haiku);
  • --alternate-model — модель для проверки переключения;
  • --prompt — отправить один промпт и вывести ответ;
  • --run-command-tests — запустить офлайн-тесты команд /help и /models.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors