Персонализация без Big Data: как ранжировать новости в Telegram с помощью pgvector и пяти сигналов
Коротко
- Система выбирает 10 рекомендаций из 50–300 новых постов, поступающих за сутки из 10–30 Telegram-каналов пользователя.
- При холодном старте работают популярность, выбранные темы и текст интересов; без них публикации сортируются только по engagement rate.
- BAAI/bge-m3 создаёт 1024-мерные эмбеддинги, а профиль пользователя строится как разность центроидов лайков и дизлайков.
- Rust-сервис параллельно выполняет до семи SQL-запросов и в типичном сценарии возвращает рекомендации за 12–25 мс.
- Ограничения текущей версии — медленный расчёт эмбеддингов на CPU, нестабильность min-max на малых батчах и ручные веса сигналов.
Итоговый рейтинг складывается из популярности поста, предпочтений к формату контента, семантического сходства с оценёнными публикациями, тематических тегов и текста интересов пользователя. Оценки каждого сигнала отдельно нормализуются, умножаются на заданные вручную веса и суммируются. При холодном старте система использует engagement rate, выбранные темы и текст интересов, а без этих данных ранжирует публикации только по популярности.
Для семантического сравнения используется многоязычная модель BAAI/bge-m3 с эмбеддингами размерностью 1024. Обычные центроиды лайков и дизлайков оказались почти одинаковыми: косинусное сходство между ними достигало 0,985, поэтому профиль строится как разность двух центроидов. Канальный профиль постепенно заменяет общий после накопления 20 оценок внутри канала, а по опыту автора уже после 10–15 оценок подборка начинает заметно лучше отделять интересные публикации.
Сервис написан на Rust с axum и tokio-postgres, выполняет до семи независимых SQL-запросов параллельно и обычно отвечает за 12–25 мс. Узкими местами остаются расчёт эмбеддингов на CPU, min-max-нормализация внутри маленького батча и ручная настройка весов; при росте аудитории автор планирует подбирать веса через A/B-тесты или Bayesian Optimization.
FAQ
Зачем использовать несколько простых сигналов вместо одной тяжёлой модели машинного обучения для ранжирования Telegram-постов?
При десятках каналов и нескольких сотнях кандидатов в сутки большого датасета для сложной модели нет. Независимые сигналы позволяют запустить персонализацию сразу и постепенно уточнять её по мере накопления оценок.
Когда рекомендации начинают учитывать реальное поведение пользователя, а не только популярность и явно указанные интересы?
Семантический профиль появляется после накопления оценок, а канальный профиль полностью заменяет общий после 20 оценок внутри конкретного канала. По опыту автора заметное улучшение начинается уже после 10–15 оценок.
Почему для семантического профиля используют контрастный вектор, а не обычный центроид всех понравившихся публикаций?
Центроиды лайков и дизлайков оказались слишком близки, поскольку обе группы состоят из новостных текстов. Вычитание центра дизлайков помогает выделить различия между желательными и нежелательными темами.
Читайте также
AI R&D DAY: два трека об исследованиях и продуктизации ИИ
OpenAI запускает рекламу в ChatGPT для пользователей Европы
Чтобы агентная реклама работала, нужно решить, чего ИИ никогда не должен касаться
Путешествие как пункт назначения: как меняется travel-маркетинг
Telegram 2026 в России: взгляд разработчика ботов
- Многосигнальное ранжирование без обученной ML-модели: Для небольших рекомендательных систем итоговый рейтинг можно собирать из нескольких независимых сигналов: популярности, характеристик контента, тематических предпочтений и семантического сходства. Оценки каждого сигнала следует нормализовать отдельно, умножать на настраиваемые веса и только затем объединять.
[Рекомендательные системы]
Зарегистрированные пользователи видят только два тезиса.
Зарегистрироваться

CleanNews ранжирует публикации из Telegram-каналов с помощью пяти независимых сигналов, pgvector и контрастного профиля пользователя — без большого обучающего датасета. В описанном сценарии система выбирает 10 рекомендаций из 50–300 постов, опубликованных за сутки в 10–30 каналах.