feat: интеграция ML-скоринга с использованием RAG и DeepSeek

- Обновлен Dockerfile для установки необходимых зависимостей.
- Добавлены новые переменные окружения для настройки ML-скоринга в env.example.
- Реализованы методы для получения и обновления ML-скоров в AsyncBotDB и PostRepository.
- Обновлены обработчики публикации постов для интеграции ML-скоринга.
- Добавлен новый обработчик для получения статистики ML-скоринга в админ-панели.
- Обновлены функции для форматирования сообщений с учетом ML-скоров.
This commit is contained in:
2026-01-26 18:40:38 +03:00
parent e2b1353408
commit 7f6f0f028c
25 changed files with 2833 additions and 52 deletions

View File

@@ -15,7 +15,8 @@ def get_post_publish_service() -> PostPublishService:
db = bdf.get_db()
settings = bdf.settings
s3_storage = bdf.get_s3_storage()
return PostPublishService(None, db, settings, s3_storage)
scoring_manager = bdf.get_scoring_manager()
return PostPublishService(None, db, settings, s3_storage, scoring_manager)
def get_ban_service() -> BanService:

View File

@@ -29,12 +29,13 @@ from .exceptions import (BanError, PostNotFoundError, PublishError,
class PostPublishService:
def __init__(self, bot: Bot, db, settings: Dict[str, Any], s3_storage=None):
def __init__(self, bot: Bot, db, settings: Dict[str, Any], s3_storage=None, scoring_manager=None):
# bot может быть None - в этом случае используем бота из контекста сообщения
self.bot = bot
self.db = db
self.settings = settings
self.s3_storage = s3_storage
self.scoring_manager = scoring_manager
self.group_for_posts = settings['Telegram']['group_for_posts']
self.main_public = settings['Telegram']['main_public']
self.important_logs = settings['Telegram']['important_logs']
@@ -392,6 +393,9 @@ class PostPublishService:
async def _decline_single_post(self, call: CallbackQuery) -> None:
"""Отклонение одиночного поста"""
author_id = await self._get_author_id(call.message.message_id)
# Обучаем RAG на отклоненном посте перед удалением
await self._train_on_declined(call.message.message_id)
updated_rows = await self.db.update_status_by_message_id(call.message.message_id, "declined")
if updated_rows == 0:
@@ -485,6 +489,9 @@ class PostPublishService:
@track_errors("post_publish_service", "_delete_post_and_notify_author")
async def _delete_post_and_notify_author(self, call: CallbackQuery, author_id: int) -> None:
"""Удаление поста и уведомление автора"""
# Получаем текст поста для обучения RAG перед удалением
await self._train_on_published(call.message.message_id)
await self._get_bot(call.message).delete_message(chat_id=self.group_for_posts, message_id=call.message.message_id)
try:
@@ -493,6 +500,32 @@ class PostPublishService:
if str(e) == ERROR_BOT_BLOCKED:
raise UserBlockedBotError("Пользователь заблокировал бота")
raise
async def _train_on_published(self, message_id: int) -> None:
"""Обучает RAG на опубликованном посте."""
if not self.scoring_manager:
return
try:
text = await self.db.get_post_text_by_message_id(message_id)
if text and text.strip() and text != "^":
await self.scoring_manager.on_post_published(text)
logger.debug(f"RAG обучен на опубликованном посте: {message_id}")
except Exception as e:
logger.error(f"Ошибка обучения RAG на опубликованном посте {message_id}: {e}")
async def _train_on_declined(self, message_id: int) -> None:
"""Обучает RAG на отклоненном посте."""
if not self.scoring_manager:
return
try:
text = await self.db.get_post_text_by_message_id(message_id)
if text and text.strip() and text != "^":
await self.scoring_manager.on_post_declined(text)
logger.debug(f"RAG обучен на отклоненном посте: {message_id}")
except Exception as e:
logger.error(f"Ошибка обучения RAG на отклоненном посте {message_id}: {e}")
@track_time("_delete_media_group_and_notify_author", "post_publish_service")
@track_errors("post_publish_service", "_delete_media_group_and_notify_author")