Files
umb/README.md
T

258 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div align="center">
# 🤖 UMB — Telegram Bot
**Универсальный бот-модератор с AI-ассистентом "Астра"**
[![License: MIT](https://img.shields.io/badge/license-MIT-lightgrey.svg)](LICENSE)
[![Python 3.11](https://img.shields.io/badge/python-3.11-blue.svg)](https://www.python.org/)
[![aiogram 3.x](https://img.shields.io/badge/aiogram-3.x-2CA5E0.svg)](https://docs.aiogram.dev/)
[![SQLite](https://img.shields.io/badge/sqlite-async-003B57.svg)](https://www.sqlite.org/)
[![Docker](https://img.shields.io/badge/docker-ready-2496ED.svg)](https://www.docker.com/)
[![Tests](https://img.shields.io/badge/tests-pytest-brightgreen.svg)](tests/)
[![SOCKS5 Proxy](https://img.shields.io/badge/proxy-SOCKS5-orange.svg)](#настройка)
</div>
---
UMB — это Telegram-бот для модерации стикеров/GIF, восстановления раскладки, получения погоды и общения с AI-ассистентом **Астра**.
## ✨ Функции
- **🛡️ Модерация стикеров и GIF** — если пользователь отправляет 25+ стикеров/GIF за 60 секунд, бот удаляет все последующие стикеры и GIF от этого пользователя в течение 5 минут. Текстовые сообщения не затрагиваются.
- **⌨️ Восстановление раскладки (`/res`)** — ответьте командой `/res` на сообщение с текстом в неправильной раскладке, и бот переведёт его (например, `gbdj``пиво`).
- **🌤️ Погода (`/weather`)** — покажет подробную погоду в указанном городе через OpenWeatherMap API.
- **🤖 AI-ассистент "Астра" (`/ai`)** — задайте вопрос, ответьте командой `/ai` на сообщение или перешлите сообщение, и Astra проанализирует его с учётом контекста и ранее сохранённых выжимок диалогов.
- **💬 Диалог с Астрой** — после `/ai` без вопроса начинается диалог. Отвечайте на сообщения бота, чтобы продолжать.
- Фаза 1: до 50 сообщений.
- Фаза 2: дополнительно до 20 сообщений.
- После исчерпания лимита — перерыв 1 час.
- **🔒 Управление AI (`/aino`, `/aiyes`)** — владелец чата может заблокировать/разблокировать пользователя от AI.
- **🧦 Поддержка SOCKS5 прокси** — настраивается через `.env`.
## 🏗️ Структура проекта
```
umb/
├── .env # настройки: токен, прокси, API ключи
├── .gitignore
├── requirements.txt
├── main.py # точка входа
├── config.py # конфигурация
├── Dockerfile
├── docker-compose.yml
└── bot/
├── __init__.py
├── bot.py # инициализация бота и сессии
├── setup_commands.py # меню команд
├── routers/
│ ├── __init__.py
│ ├── moderation.py # роутер модерации стикеров/GIF
│ ├── layout.py # роутер /start, /res
│ ├── weather.py # роутер /weather
│ ├── ai.py # роутер /ai, /aino, /aiyes, /aiclear, /aiuser
│ ├── dialogue.py # диалоговый режим с Астрой
│ ├── voice.py # распознавание голосовых сообщений
│ └── yadisk.py # скачивание с Яндекс.Диска
└── utils/
├── __init__.py
├── proxy.py # общий SOCKS5-коннектор
├── layout_converter.py # конвертер раскладки en→ru
├── weather.py # функция получения погоды
├── ai_client.py # OpenRouter/RouterAI клиент
├── memory.py # саммари и эмбеддинги
├── database.py # SQLAlchemy модели и функции БД
├── voice.py # загрузка и транскрибация голоса
├── yadisk_download.py # загрузка файлов с Яндекс.Диска
├── s3_client.py # загрузка больших файлов в S3
└── logging_config.py # настройка логирования
```
## 📊 Системные требования
### Память (RAM)
| Компонент | Расход |
|-----------|--------|
| Whisper `base` (int8) в памяти | ~600900 МБ |
| Whisper пик при транскрибации | дополнительно ~200–400 МБ |
| aiogram + SQLAlchemy + aiohttp | ~100200 МБ |
| SQLite | ~1050 МБ |
| ffmpeg (пиково) | ~50100 МБ |
| **Рекомендуемый минимум** | **2 ГБ** |
| **Без распознавания голоса** | **~512 МБ** |
### Процессор
| Параметр | Значение |
|----------|----------|
| Количество ядер | минимум 2, рекомендовано **4+** |
| Нагрузка при транскрибации | ~80–100% на 4 ядрах на 2–8 сек |
| Нагрузка в простое | ~1–5% |
| Архитектура | x86_64 / ARM64 |
> Без голосовых сообщений достаточно **1 ядра**.
### Диск
| Данные | Размер |
|--------|--------|
| Whisper `base` модель | ~500 МБ на диске |
| SQLite база | ~50–200 МБ (растёт со временем) |
| Голосовые файлы (временно) | ~1–5 МБ на сообщение, удаляются сразу |
| Логи (ротация 5×10 МБ) | ~50100 МБ |
| **Рекомендуемое свободное место** | **510 ГБ** |
### Сеть
- Пропускная способность: минимальная (несколько КБ/с в среднем).
- Все API-запросы могут идти через SOCKS5-прокси.
- Для скачивания Whisper-модели через прокси: ~150 МБ одним файлом, нужна стабильность.
### Итого
| Ресурс | Минимум | Рекомендовано |
|--------|---------|---------------|
| **RAM** | 2 ГБ | 4 ГБ |
| **CPU** | 2 ядра | 4+ ядра |
| **Disk** | 5 ГБ | 10 ГБ |
| **ОС** | Linux (x86_64) | то же, Python 3.11 |
## 🚀 Установка
```bash
cd umb
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
## ⚙️ Настройка
Откройте `.env` и укажите необходимые ключи:
```env
BOT_TOKEN=your_bot_token_here
PROXY_ENABLED=false
PROXY_URL=socks5://user:pass@host:port
API_WEATHER=your_openweather_api_key
OPENROUTER_API_KEY=your_openrouter_api_key
ROUTERAI_API_KEY=your_routerai_api_key
ROUTERAI_BASE_URL=https://routerai.ru/api/v1
# Опционально: периодическая проверка работоспособности бесплатных моделей.
# Внимание: проверка расходует токены API. По умолчанию отключена.
AI_HEALTH_CHECK_ENABLED=false
AI_HEALTH_CHECK_INTERVAL=600
# Настройки модели Whisper для распознавания голоса.
WHISPER_MODEL_SIZE=base
WHISPER_MIN_FREE_SPACE_BYTES=5368709120
```
Для включения прокси установите `PROXY_ENABLED=true` и укажите корректный `PROXY_URL`.
## ▶️ Запуск
```bash
source .venv/bin/activate
python main.py
```
## 🐳 Запуск в Docker
```bash
docker compose up -d --build
```
Модели Whisper сохраняются в `./models`, база данных и логи — в `./bot/data`.
## 🎙️ Распознавание голосовых сообщений
Бот автоматически распознаёт все голосовые сообщения с помощью локальной модели [faster-whisper](https://github.com/SYSTRAN/faster-whisper).
### Поведение загрузки модели
- При запуске бота проверяется наличие модели в `./models/faster-whisper/<WHISPER_MODEL_SIZE>/`.
- Если модель уже скачана — бот сразу готов к работе.
- Если модели нет — бот проверяет свободное место на диске и **скачивает модель автоматически** перед началом polling.
- Для скачивания используется прокси из `.env`, если `PROXY_ENABLED=true`.
### Требования к месту
| Модель | Размер модели | Рекомендуемое свободное место |
|--------|---------------|-------------------------------|
| `base` | ~150 MB архив, ~500 MB на диске | 5 GB (`WHISPER_MIN_FREE_SPACE_BYTES=5368709120`) |
| `small` | ~500 MB архив, ~1.5 GB на диске | 5 GB+ |
| `medium` | ~1.5 GB архив, ~5 GB на диске | 10 GB+ |
> 💡 По умолчанию используется модель `base`. Для смены модели измените `WHISPER_MODEL_SIZE` в `.env`.
### Логирование
В логах будет видно:
```
Free disk space: 45.23 GB, required: 5.00 GB
Whisper model 'base' found locally at /app/models/faster-whisper/base
Whisper model 'base' is ready
```
или при скачивании:
```
Whisper model 'base' not found locally. Starting download to /app/models/faster-whisper...
Whisper model 'base' downloaded and loaded in 125.4s
Whisper model 'base' is ready
```
## 🧪 Тесты
```bash
source .venv/bin/activate
pytest tests/ -v
```
## 📋 Команды
| Команда | Описание |
|---------|----------|
| `/start` | Приветствие и информация о боте |
| `/res` | Восстановить раскладку (ответить на сообщение) |
| `/weather <город>` | Погода в указанном городе |
| `/ai <вопрос>` | Задать вопрос Астре |
| `/ai` (ответом/пересылкой) | Проанализировать сообщение |
| `/ai` (без вопроса) | Начать диалоговый режим |
| `/aiclear` | Очистить диалог и сохранить выжимку |
| `/aiuser` | Список пользователей чата (только creator) |
| `/aino @username` | Заблокировать пользователя от AI (только creator, 24ч) |
| `/aiyes @username` | Разблокировать пользователя от AI (только creator) |
| `/ydf <ссылка>` | Скачать файл с Яндекс.Диска |
| `/ydf (new) <ссылка>` | Скачать файл, игнорируя кеш Telegram |
## ⚖️ Настройки модерации
Изменяются в `config.py`:
- `MODERATION_LIMIT = 25` — количество стикеров/GIF за окно
- `MODERATION_WINDOW = 60` — окно подсчёта в секундах
- `MODERATION_BAN_DURATION = 300` — длительность бана в секундах
## 🧠 AI-ассистент "Астра"
- **Бесплатные модели** (OpenRouter): пробует по очереди доступные модели с суффиксом `:free`. При rate-limit автоматически переключается на следующую.
- **Платный fallback** (RouterAI): если все бесплатные модели недоступны, используется `deepseek/deepseek-v4-flash` через `routerai.ru`. В ответе добавляется уведомление `⚡ Обработано через платный API`.
- **Контекст**: хранит последние 10 сообщений каждого пользователя в SQLite.
- **Долгосрочная память**: при переходе между фазами диалога и при `/aiclear` создаётся краткая выжимка, которая затем подбирается по смыслу к новым вопросам.
- **Стиль**: отвечает кратко и по делу, если не просят развёрнуто.
- **Потеря контекста**: говорит что-то милое ("я потеряла мысль", "смотри, какая птичка!")
---
<div align="center">
Сделано с помощью [aiogram](https://docs.aiogram.dev/) · [SQLAlchemy](https://www.sqlalchemy.org/) · [faster-whisper](https://github.com/SYSTRAN/faster-whisper)
</div>