Baza — современный, интеллектуальный Telegram-бот для каталогизации, гибридного семантического поиска, автоматической модерации и игрового сравнения мемов. Проект построен на базе Spring Boot и Spring AI с интеграцией мультимодальных моделей Google Gemini.
При загрузке изображения бот обрабатывает его в асинхронном пайплайне (AsyncMemeService):
- OCR-распознавание: Точное извлечение любого текста с картинки.
- Описание контекста: ИИ описывает визуальную составляющую и смысл мема на русском языке.
- ИИ-Цензура: Автоматический сканер проверяет изображение на NSFW, пропаганду запрещенных веществ, насилие и язык вражды. При нарушении мем помещается в карантин.
- Векторная дедупликация: Бот проверяет степень схожести нового мема с уже существующими (порог
0.95). Дубликаты автоматически изолируются.
Бот реализует современный подход к поиску мемов:
- Семантический поиск:
pgvector+gemini-embedding-001ищут мемы по смыслу (даже если ключевых слов нет на картинке). - Текстовый поиск: Полнотекстовый поиск по OCR-тексту и описанию через
ILIKEс нормализацией букв «е/ё» и регистронезависимостью. - Reciprocal Rank Fusion (RRF): Комбинация и взвешенное ранжирование результатов из векторного и текстового поисковых движков.
- Контроль видимости: Учитывает приватность мемов (
PUBLIC,PRIVATE,GROUP) в соответствии с правами пользователя.
- Интеллектуальный подбор оппонента: Бот выбирает первый случайный мем, а второго оппонента подбирает через векторную базу данных по семантическому сходству. Это гарантирует, что в баттле будут участвовать мемы на схожую тематику (например, коты против котов).
- ELO-рейтинг: Победители и проигравшие пересчитывают свой рейтинг по официальной формуле Elo (K-factor = 32).
- Пользователи могут бросить вызов друг другу на очки баланса:
/duel @username <ставка>. - Выбор оружия происходит в ЛС с ботом, где каждый участник выбирает один из своих одобренных мемов.
- Битва транслируется в общий чат. Победитель забирает двойную ставку и очки славы, проигравший теряет ставку, а в случае ничьей или истечения времени ставки возвращаются.
- Интерактивная оценка мемов в ЛС с ботом через кнопки BASE и CRINGE.
- Алгоритм выдает пользователю только те новые мемы, которые он еще не оценивал.
- Лайки начисляют очки автору мема и увеличивают ELO-рейтинг изображения.
- Автоматическая генерация подборок лучших мемов за неделю (на основе ELO-рейтинга).
- ИИ-редактор Gemini принимает описания и OCR-текст топ-3 мемов и генерирует саркастический, ироничный дайджест с разметкой Markdown для отправки участникам группы.
| Команда | Описание | Пример использования |
|---|---|---|
/start |
Запуск бота, инициализация сессии | /start |
/save |
Сохранить мем (ответом на фото или интерактивно в ЛС) | /save public, /save group 101 |
/find |
Поиск мем-картинки по смыслу или тексту | /find грустный программист |
/battle |
Запустить случайный мем-баттл в чате | /battle |
/duel |
Вызвать пользователя на PvP-дуэль на очки | /duel @username 50 |
/swipe |
Войти в режим оценки мемов (Tinder-лайки) | /swipe |
/leaderboard |
Показать топ-5 мемов и авторов | /leaderboard |
/digest |
Сгенерировать дайджест лучших мемов вручную | /digest |
В проекте используются следующие важные параметры:
app.battle.duration-minutes— длительность голосования в баттлах и дуэлях (по умолчанию10).app.battle.default-elo— стартовый ELO-рейтинг для новых мемов (по умолчанию1000).app.digest.days— за сколько последних дней собирать лучшие мемы для дайджеста (по умолчанию7).app.bot.complaints-threshold— количество жалоб пользователей для автоматической отправки мема в карантин (по умолчанию3).app.bot.search-limit— лимит возвращаемых мемов в результатах поиска (по умолчанию50).
docker-compose up -dСоздайте файл .env в корневой папке или передайте переменные окружения при запуске:
TELEGRAM_TOKEN— Токен вашего Telegram-бота.GEMINI_API_KEY— Ваш Google Gemini API-ключ.GOOGLE_CLOUD_PROJECT— Идентификатор проекта Google Cloud (необязательно).
Сборка JAR-файла:
./gradlew clean buildЗапуск Spring Boot приложения:
./gradlew bootRunЗапуск юнит и интеграционных тестов:
./gradlew testЗапуск нагрузочных тестов (k6): Для проверки производительности API поиска выполните команду:
k6 run load-test.js