ChatGPT
ChatGPT

13 августа сайт X опубликовал значительно обновлённую версию исходного кода рекомендательной ленты. В репозитории под лицензией Apache 2.0 выложили код модели Phoenix, реальные значения основных коэффициентов ранжирования, механизмы отбора кандидатов, фильтрации видимости, поддержки новых авторов и обеспечения разнообразия ленты.

Заметная доля пользователей X предпочитает называть сайт микроблогов по старинке — Twitter. Другая неискоренимая вредная привычка — чтение алгоритмической ленты. Чтобы увеличить охват микроблога, было бы неплохо хотя бы в общих чертах разобраться, как работает рекомендательный алгоритм, а затем рассмотреть все основные коэффициенты. Этим в данной статье мы и займёмся.


X показала только то, что формирует ленту «Для вас». Вообще‑то на сайте ещё есть тренды и ранжирование комментариев под твитами, но интересно посмотреть хотя бы на этот рекомендательный алгоритм. Также надо оговориться, что многие значения поступают из внутренней конфигурационной системы и могут меняться без перекомпиляции кода, поэтому любые заявления о поведении X.com носят предположительный характер.

Как объясняется в README репозитория, единого глобального фида для всех нет, лента формируется заново для каждого аккаунта и для каждого запроса. В схеме архитектуры все стадии и шаги применяются для каждого пользователя индивидуально.

Для начала от пользователя должен поступить собственно запрос. Вместе с ним система загружает недавнюю историю взаимодействий, список подписок, блокировки, замьюченные аккаунты, заблокированные слова, уже показанные публикации и другие признаки. Этот контекст в дальнейшем будет нужен и для поиска подходящих материалов, и для фильтрации, и для прогнозирования поведения.

Первичный поиск кандидатов

В документации описаны три основных канала, откуда поступает до 3000 кандидатов:

  1. Thunder. Отсюда приходят свежие публикации из аккаунтов, на которые подписан пользователь, для которого формируется лента.

    Если судить по содержимому файла home-mixer/params/param.rs, значение параметра ThunderMaxResults составляет 1200. Так задаётся число твитов, которое Thunder может вернуть в Home Mixer в качестве кандидатов. Однако перед запросом это значение дополнительно обрабатывается через модуль quality_factor.

    Также в файле указано, что это выполненная 12 августа копия значений по умолчанию, а вообще эти параметры могут меняться через конфигурационную систему. То есть нет никаких гарантий, что на реальном X.com это значение составляет сейчас те же 1200.

  2. Phoenix Retrieval. Из данного источника идут публикации на темы, похожие на интересы пользователя. Для этого система строит векторное представление поведения пользователя и сравнивает его с векторным представлением постов. В Home Mixer от Phoenix поступает до 1000 постов (значение PhoenixMaxResults), хотя значение опять же может быть изменено.

    Phoenix Retrieval реализован по принципам двухбашенной архитектуры (two‑tower architecture). Это канонический подход для первичного отбора кандидатов в крупных системах ранжирования: он применяется в рекомендациях Instagram* Explore у Meta**, в системе Neural Deep Retrieval для рекомендаций YouTube у Google и для нейропрофиля «ВКонтакте».

    User Tower превращает историю поведения конкретного пользователя в нормализованный 1024-размерный вектор. Максимальная длина истории модели — 1023 элемента. В эту историю попадает информация о публикациях и их авторах, совершённых действиях и контексте взаимодействия. Дополнительно модель получает отдельный токен с признаками пользователя, куда входят страна и язык.

    Любопытно, что в выложенной в репозитории конфигурации проекта компонент Phoenix не хранит обученный уникальный вектор пользователя. Как объясняется в документации, кроме общих признаков профиля пользователь представлен прежде всего тем, с какими постами он взаимодействовал. Трансформер User Tower обрабатывает эту последовательность и получает текущее векторное представление его интересов.

    Вторая башня Candidate Tower заранее вычисляет нормализованные векторные представления публикаций. Твиты‑кандидаты представлены семантическими идентификаторами, полученными из мультимодальных эмбеддингов поста, и хэшированными идентификаторами авторов. Семантический идентификатор состоит из шести уровней, на каждом из которых выбирается один из 256 кодов. Публикации на схожие темы могут иметь общие префиксы этих Semantic ID.

    Готовый индекс кандидатов сохраняется вместе с чекпойнтом модели. При запросе остаётся вычислить вектор пользователя и найти в индексе публикации с наибольшим скалярным произведением с ним. Поскольку оба вектора нормализованы, по смыслу это поиск по косинусной близости. Именно так миллионы потенциальных публикаций быстро сокращаются до примерно тысячи кандидатов, которые Home Mixer сможет обработать дальше.

    При обычном свежем запросе ленты Home Mixer запрашивает у сервиса агрегации действий историю пользователя для Phoenix Retrieval. Затем PhoenixSource передаёт полученную последовательность в систему поиска кандидатов Phoenix.

    Очередное взаимодействие пользователя потенциально способно изменить подбор кандидатов уже при следующем свежем запросе после того, как действие попадёт в сервис истории. Хотя было бы крайне интересно узнать, как часто обновляются интересы, точная задержка поступления новых действий в этот сервис в открытом репозитории не указана.

  3. SimClusters. Это система кластеров, которая группирует аккаунты и посты по тому, кто с чем взаимодействует, а затем ищет публикации, подходящие людям из близких кластеров. Идея тут простая: если заметная часть условного сообщества (круга общения) любителей кройки и шитья внезапно начинает активно интересоваться кей‑попом, то свежую фотографию Чонгука имеет смысл показать и другим участникам этого же сообщества, включая даже тех, кто на Чонгука не подписан.

    Поэтому для продвижения твитов так важна аудитория, с которой автор взаимодействует, её реакции и подписки, место аккаунта в графе интересов.

    Реализация источника в home-mixer/sources/simclusters_source.rs берёт идентификаторы постов из недавних явных и неявных сигналов пользователя, ищет для каждого из них близких кандидатов, перемежает результаты и оставляет не более 800 твитов. Из того же файла становится понятно, что SimClusters работает только при наличии подходящей истории сигналов (has_post_signals(query)) и не вызывается, когда Home Mixer обслуживает запрос из кэша (!query.has_cached_posts).

Дополнение данными и фильтрация

Система получает список и подгружает данные: текст и медиаэлементы, данные автора, язык, сведения о цитируемом посте, метки безопасности контента и его видимости, статистику взаимодействий, является ли этот пост доступным только при платной подписке и прочие признаки, нужные фильтрам и моделям.

Дубликаты устраняются. До поступления в систему удаляются твиты старше 48 часов, посты самого пользователя, все заблокированные и замьюченные аккаунты, твиты с замьюченными словами, уже увиденное или недавно показанное, доступное только для платных подписчиков на аккаунт (это такой конкурент Patreon местного разлива). Ещё убираются повторные ретвиты, ретвиты и ответы либо от аккаунтов, на которые пользователь не подписан, и ответы, у которых родительский пост отсутствует.

Присуствуют в пайплайне разные специфические фильтры, которые по умолчанию отключены. К примеру, VideoFilter, как следует из названия, убирает все твиты с видеороликами, NewUserMinEngagementFilter удаляет для совсем новых пользователей (менее 30 минут) публикации вне подписок, не достигшие заданного порога вовлечения, а экспериментальный InventoryHoldoutFilter в значениях по умолчанию просто занулён.

Скоринг

Модель Phoenix проходит по постам‑кандидатам и для каждого из них предсказывает сразу несколько возможных реакций пользователя. Сама модель имеет куда более широкий набор выходов, чем впоследствии использует Home Mixer. В файле README в файловом каталоге модели выход ранжирующей модели описан как 64 слота для дискретных действий и 8 слотов для непрерывных показателей.

Текущий скорер Home Mixer берёт из результатов Phoenix 22 дискретных прогноза поведения пользователя. Это лайк, ответ, обычный ретвит и ретвит с цитированием, раскрытие изображения, открытие видео, клик по самому твиту, открытие внешней ссылки, переход в профиль его автора, три вида расшарки твита (обычная, через личные сообщения и через копирование ссылки), бинарный сигнал задержки на посте, переход к цитируемому твиту, качественный просмотр видео, качественный просмотр видео в цитируемом твите и подписка на автора.

Ещё 5 из этих 22 прогнозов описывают негативную реакцию: нажатие кнопки «Не интересно» у твита, блок автора, мьют автора, жалоба на твит, сигнал о том, что пользователь не задержался на публикации. Кроме дискретных прогнозов, скорер содержит три непрерывных выхода Phoenix: продолжительность взаимодействия с постом dwell_time, продолжительность взаимодействия после клика click_dwell_time и нормализованный остаточный показатель активного времени за пятиминутное окно active_secs_5m_residual_norm.

Наконец, в формулу входит отдельный сигнал post_unexplored, то есть показатель недостаточно исследованного поста. Суммарно в массиве terms текущего ranking_scorer.rs находится 26 элементов.

Впрочем, некоторые из этих параметров в формулах занулены.

Суммирование с помощью весов

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

В документации представлена простая и понятная формула: ranking_scorer.rs якобы комбинирует вероятности с разными весами по очевидной формуле

Final Score = Σ (weight_i × P(action_i))

Разные действия складываются с разными весами. Значения весов находятся в файле home‑mixer/params/param.rs.

Прогнозируемое действие или сигнал

Параметр

Вес

Комментарий

Копирование ссылки на твит

ShareViaCopyLinkWeight

20,0

Самый большой обычный положительный коэффициент

Ответ на оригинальный твит взаимного подписчика

ReplyWeight и его бонус BidirectionalFollowReplyWeightBoost

20,0

В коде это оформлено как добавка в 15,0 к базе за ответ в 5,0

Обычный ответ

ReplyWeight

5,0

Расшарка через личные сообщения

ShareViaDmWeight

5,0

Цитирование твита

QuoteWeight

5,0

Это не обычный ретвит, а цитата, то есть включение ссылки на цитируемый твит в собственный, где можно дополнительно дописать что‑то. Многие пользуются подобным вместо комментариев.

Подписка на автора

FollowAuthorWeight

4,0

Обычная расшарка

ShareWeight

2,0

Ретвит

RetweetWeight

1,0

Любопытно, что в коде осталось историческое название действия.

Лайк

FavoriteWeight

0,5

То же, хотя «Избранное» на сердечки заменили ещё в ноябре 2015 года, задолго до эпохи Маска.

Клик по твиту

ClickWeight

0,4

Если на твит нажать, он откроется на отдельной странице.

Переход по ссылке из твита на сторонний сайт

OpenLinkWeight

0,2

Долгое время считалось, что за внешние ссылки алгоритм наказывает; Маск сам рекомендовал их из первого твита убирать и засовывать в тред. Здесь значение положительное, пусть и мелкое.

Раскрытие изображения

PhotoExpandWeight

0,05

Запуск видеоролика

VideoOpenWeight

0,05

Просто открытие видео.

Качественный просмотр видеоролика

VqvWeight

0,05

По какой‑то причине применяется только для потенциальных зрителей, у которых меньше 10 000 подписчиков. Кроме того, этот вес учитывается лишь для видео длительностью строго больше MinVideoDurationMs, равного 10 секундам.

Переход к цитируемому твиту

QuotedClickWeight

0,05

Недостаточно исследованный твит

PostUnexploredWeight

0,02

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

Прогноз длительности взаимодействия

ContDwellTimeWeight

0,004

Умножается на прогнозируемые, по всей видимости, секунды. Значение при этом обрезается до 30 с.

Бинарный сигнал задержки

DwellWeight

0,0

Как видно, занулён, то есть никакой роли не играет.

Переход в профиль

ProfileClickWeight

0,0

То же.

Качественный просмотр видео в цитируемом посте

QuotedVqvWeight

0,0

То же.

Длительность взаимодействия после клика

ContClickDwellTimeWeight

0,0

То же.

Нормализованное активное время за пятиминутное окно

ContActiveSecs5mResidualNormWeight

0,0

То же.

Дополнительный бинарный бонус для взаимной подписки

BidirectionalFollowDwellWeightBoost

0,0

Некий июльский A/B‑эксперимент, который на широкую аудиторию не раскатили. Этот параметр был призван дополнительно повышать вес прогноза задержки для взаимных подписчиков.

Пользователь не задержится на твите

NotDwelledWeight

−0,02

Небольшой отрицательный вес для прогноза того, что пользователь твит быстро промотает.

Блокировка автора твита

BlockAuthorWeight

−31,2

Нажатие «Не интересно»

NotInterestedWeight

−43,2

Кнопка «Not interested in this post» в меню твита, доступном по нажатию на три точки в правом верхнем углу.

Мьют автора твита

MuteAuthorWeight

−58,8

Жалоба на твит

ReportWeight

−234,0

Кнопка жалобы расположена в том же меню твита.

Важно помнить, что таблица выше — это не стоимость каких‑либо совершённых действий, а то, как предсказанные вероятности этих действий складываются при ранжировании. Также не надо забывать, что это алгоритм персонализированных рекомендаций: если у твитов врагов нажимать «Не интересно», они попросту пропадут из вашей ленты. В са́мом плохом случае, когда группы аккаунтов путём массового сговора кого‑то блокируют или присылают жалобы, может незначительно измениться лента похожих на этих конспираторов людей. (Здесь мы рассматриваем просто рекомендательный алгоритм. В других системах безопасности сайта страйки и теневые баны за массовые репорты прилетают запросто. Также в репозитории X выложены исходники системы репутации аккаунтов Agatha, с которыми любопытно ознакомиться отдельно).

Заблуждения о значении этих весов сильны настолько, что на следующий день после релиза в README репозитория даже появилась пометка об этом.

Реальный код слегка сложнее формулы из документации. Сначала home-mixer/scorers/ranking_scorer.rs отдельно вычисляет положительную и отрицательную части оценки, а неотрицательные слагаемые складываются в pos, отрицательные — по модулю в neg. После этого получается разность pos − neg. Затем результат преобразуется: к неотрицательной оценке просто добавляется 0,001, а отрицательная оценка нормализуется относительно суммарных модулей весов и сжимается в узкий неотрицательный диапазон.

Окончательное место в ленте отсюда ещё не получить. Дополнительно применяются:

  • Поддержка малоизвестных авторов. Реализация механизма AuthorColdStart находится в home‑mixer/scorers/author_cold_start.rs, а актуальные значения параметров — в home‑mixer/params/param.rs.

    Речь не идёт про автоматический буст для непопулярных пользователей, это именно алгоритм. Механизм вообще включён параметром EnableViewerColdStart = true, однако в реализации присутствует разделение пользователей и авторов по экспериментальным веткам, поэтому перечисленные условия не следует воспринимать как обещание буста каждому подходящему аккаунту.

    В текущих параметрах системы сначала находится подходящий оригинальный (не ответ, не ретвит) пост с менее 1000 просмотров от автора с менее 1000 подписчиков. При этом твит не должен находиться в нижних 15% среди кандидатов с ненулевым скором (задаётся через LowImpressionsMaxPositionRatio, который сейчас равен 0,85).

    Публикация малоизвестного десятника или сотника должна показать хорошую конкурентоспособность. Если подходящих публикаций несколько, то функция pick_by_score выбирает из них твит с наибольшим уже имеющимся скором. Затем эта публикация получит буст.

    Параметры ColdStartSlotMin = 15 и ColdStartSlotMax = 16 задают диапазон, из которого берётся целевой скор. Диапазон полуоткрытый, поэтому при текущих настройках фактически существует только индекс 15 (то есть шестнадцатый элемент). Алгоритм сортирует текущие оценки и получает скор кандидата на этой позиции. Затем скор выбранного подходящего поста маленького автора повышается до этого значения; если он уже выше, то не меняется.

    Это не гарантирует шестнадцатое место в готовой ленте: после AuthorColdStart ещё применяются другие коэффициенты, переранжирование и фильтры.

  • Понижение повторных публикаций одного автора. Эта корректировка нужна, чтобы один фонтанирующий твитами аккаунт не забил своим чириканьем половину рекомендательной выдачи. Реализация находится непосредственно в ranking_scorer.rs.

    Сначала кандидаты сортируются по оценке, которую они получили до этой стадии. Затем алгоритм проходит список сверху вниз и для каждого автора считает, сколько его более высоко оценённых публикаций уже встретилось выше. Это число обозначим через k. Для самого высоко оценённого поста данного автора в конкретном кандидатном наборе k=0, для следующего — k=1, затем k=2 и так далее.

    Множитель вычисляется функцией diversity_multiplier со следующими коэффициентами:

    M(k)=0.75\cdot0.5^k+0.25.

    То есть первый пост автора не штрафуется вовсе, второй получает 0,625 скора, третий уже меньше половины (0,4375), четвёртый — 0,34375 и так далее, с постепенным приближением в 0,25.

    Важно, что значения времени в этих формулах нет. Штраф появляется тогда, когда несколько постов одного автора одновременно присутствуют среди кандидатов для конкретного запроса конкретного пользователя.

  • Коэффициент контента вне подписок. В том же ranking_scorer.rs прописано, что твиты от авторов, на которых пользователь не подписан, получают скор на 25% меньше (умножаются на 0,75). Твиты от тех, на кого пользователь подписан, такого штрафа не получают.

    Выглядит просто, но возможно упустить важную деталь. Тот же понижающий множитель применяется и тогда, когда аккаунт из подписок кого‑то ретвитит или кому‑то отвечает.

  • Семантическое переранжирование. Желательно получить не просто набор самых высоко оценённых публикаций, а что‑то разнообразное. Для этого придётся уже как‑то вчитываться в контент.

    Для твитов‑кандидатов компонент VMRanker получает их семантические эмбеддинги, алгоритм DPP (determinantal point process, детерминантный точечный процесс) вычисляет между ними косинусное сходство. Чем сильнее два поста похожи друг на друга в этом векторном пространстве, тем хуже они дополняют друг друга в одном наборе.

    Затем жадный алгоритм DPP выбирает из 150 кандидатов до 50 твитов с наивысшими оценками, стараясь одновременно сохранить сильных кандидатов и не заполонить всю выдачу схожими публикациями. К примеру, тест identical_embeddings_select_top_scorer_only проверяет, что из кандидатов с одинаковыми эмбеддингами выбирается только наиболее высоко оценённый, orthogonal_embeddings_promote_diversity — что менее похожий кандидат может попасть в итоговый набор вместо почти полного семантического дубля с более высокой исходной оценкой.

    Хотя этот шаг мы озаглавили как «переранжирование», отобранные твиты сохраняют свои прежние скоры, отсеянные — просто зануляются.

Наконец, список твитов сортируется по значению скора по убывающей и готовится к выдаче пользователю. Даже на этом этапе фильтрация продолжается: из лучших 50 твитов убираются посты с проблемным контентом, которые показывать нельзя, прогоняются последние проверки видимости, а DedupConversationFilter оставляет только лучший по скору элемент каждой ветки обсуждения. После этих фильтров список дополнительно обрезается до максимум 35 органических публикаций. При этом при наличии вакантных мест кандидаты с 51-й строчки и ниже обратно уже не подтягиваются — всё, они уже отброшены.

Контент перемешивается с рекламой, рекомендациями аккаунтов и другими блоками. Пользователь читает твиты. При этом он и не подозревает, что этот внешне простой алгоритм требует для запуска вычислительный кластер из дорогих ускорителей Nvidia стоимостью в десятки тысяч долларов каждый. Код умеет распознавать A100, H100 и H200 (8 видеоускорителей в ноде) или GB200 и GB300 (4 видеускорителя в ноде), при этом двухбашенная модель Phoenix Retrieval поддерживает параллелизм до 128 устройств для H100 и до 32 для GB300.

Практические рекомендации

Выводы из алгоритма напрашиваются сами собой.

  1. Пишите такие твиты, которыми хочется поделиться. Звучит как что‑то на уровне мемов «хорошо делайте, а плохо не делайте», но издёвки здесь нет: читатель в первую очередь должен испытать желание расшарить твит.

    Прогноз копирования ссылки на твит имеет коэффициент 20, отправки через личку — 5, цитирования — 5, а вот ретвита — всего 1. Если твит выглядит так, будто им хочется поделиться в мессенджере или показать в групповом чате внутри X, то у подобной публикации выше шансы оказаться в алгоритмической ленте.

  2. Не прячьте ссылки во втором твите треда. Как видно по весам, алгоритм больше не наказывает за ссылку на сторонний ресурс в основном посте. Когда‑то прятать ссылку рекомендовал сам владелец X Илон Маск, но это правило больше не работает.

  3. Разнесите публикации по времени или публикуйтесь с нескольких аккаунтов. При отборе твитов‑кандидатов второй и последующий (отсортированные по скору, не хронологически) посты штрафуются в алгоритмической ленте, при этом каждый последующий сильнее.

    Оптимальное время между публикациями из алгоритма установить невозможно, поскольку он завязан на конкретные запуски. Известно лишь, что в алгоритмический фид попадают посты младше 48 часов, но в остальном ограничений по времени нет, и какого‑то оптимального окна для публикации не существует.

  4. Премиальный аккаунт не приносит дополнительных просмотров. Какого‑либо коэффициента от платной галочки в ranking_scorer.rs нет.

    Нужно оговориться: в том же репозитории лежит код системы UserCredV2, которая рассчитывает репутацию аккаунтов при помощи алгоритма PageRank, и в этом коде наличие X Premium уже учитывается. При расчёте параметра вероятности телепортации в PageRank система смешивает два распределения — одно зависит от взаимодействий пользователей, а второе равномерно распределяется между аккаунтами, которые система считает премиальными. Под Premium здесь понимаются аккаунты с синими, серыми и золотыми галочками, верифицированные организации и их аффилированные аккаунты.

    Насколько UserCredV2 отражается на показах конкретного твита, определить невозможно, это в первую очередь сигнал доверия в системе борьбы со спамом и прочими злоупотреблениями. Отрицать полное отсутствие эффекта от X Premium нельзя, но явного преимущества в алгоритме ранжирования нет.

  5. Лайки — слабый и одновременно необходимый показатель. Если не ознакомиться с README репозитория и смотреть только на широко растиражированную таблицу с весами, то легко списать со счетов сердечки: на этапе ранжирования их коэффициент составляет всего 0,5.

    Однако алгоритм ранжирования публикаций для начала должен их откуда‑то получить. Один из главных источников — Phoenix Retrieval, который при обучении, как указывает документация, использует лайки как положительный сигнал. Другой источник, SimClusters, берёт публикации, с которыми пользователь недавно взаимодействовал, и ищет похожие на них посты. При этом для поиска нужны представления публикаций с говорящими названиями LOG_FAV_LONGEST_L2_EMBEDDING_TWEET и LOG_FAV_BASED_TWEET.

    Если у твита недостаточно лайков, шансов попасть в ранжирование у него куда меньше.

  6. Пишите ясные, понятные посты, уже из самого твита всё должно быть очевидно.

    Различные компоненты рекомендательной системы понимают содержание публикации. В Phoenix Retrieval из мультимодального эмбеддинга твита строится Semantic ID (SID) из шести последовательных кодов, каждый из которых принимает одно из 256 значений. При этом у публикаций на одну тему совпадают начала таких последовательностей.

    Коды этих семантических идентификаторов заданы не вручную, SID получают методом остаточного квантования многомерного представления содержимого поста. Но смысл механизма именно в том, чтобы похожие по содержанию публикации получали похожее представление. Благодаря этому Phoenix Retrieval умеет находить аудиторию даже для ранее не встречавшихся модели твитов: система опирается на то, на какие посты она семантически похожа. На следующем этапе в Phoenix Ranking эти же SID входят в набор признаков как публикаций‑кандидатов, так и истории пользователя.

    Также при работе алгоритма DPP выбираются семантически разнообразные посты, а твиты‑кандидаты даже с хорошим скором могут быть отброшены при похожести на существующий в наборе. Не следует часто публиковать одно и то же, слегка меняя формулировки; нет смысла чаще одного раза в двое суток писать на одну ту же тему примерно те же мысли.

  7. Самостоятельный твит — основа выхода к потенциальным подписчикам. Если пользователь на вас не подписан, то ваш ответ или ретвит до ранжирования в его рекомендательной ленте, скорее всего, вообще не доживёт.

    В последнее время популярной стала тактика отвечать под крупными аккаунтами, чтобы попасться на глаза их аудитории. Подобных пользователей иногда уничижительно называют reply guy. Что ещё более обидно, для алгоритмической ленты этот приём не работает: на этапе фильтрации кандидат удаляется, если автор находится вне сети подписок пользователя и публикация представляет собой ответ или ретвит. Обычные самостоятельные твиты этот фильтр пропустит.

    Понятно, что самостоятельный твит незнакомого автора находится в менее выгодном положении, чем публикация аккаунта из подписок, поскольку при ранжировании к его скору будет применён коэффициент 0,75. Но это всяко лучше, чем быть отфильтрованным без следа.

    Важно также, что твит с цитированием чужого твита в данном фильтре ретвитом не считается.

  8. Вызывайте желание ответить. Для подписанных друг на друга аккаунтов применяется вес 20 к предсказанной вероятности ответа на твит. Поэтому особенно выгодно формировать круг взаимных подписок среди заинтересованных в вашей тематике людей, а не заниматься массфолловингом.

    Даже при отсутствии подписки вероятность ответа на твит оценивается высоко, с весом 5. Многие популярные микроблогеры в X научились задавать вызывающе глупые вопросы, публиковать нарочито спорные утверждения и всячески рейджбейтить. С точки зрения коэффициентов логика здесь действительно имеется.

    Но не надо забывать про отрицательные веса: высокая вероятность мьюта и нажатия «Не интересно» оцениваются резко негативно. Если твит разлетается среди аудитории, которая хочет автора заблокировать, то модель ранжирования имеет все основания пессимизировать такой пост для подобных пользователей соцсети.

  9. Первый твит треда должен быть самодостаточным. Не рассчитывайте, что алгоритмическая лента покажет пользователю сразу несколько сообщений из одной цепочки.

    Как мы разобрались по механизму работы фильтра DedupConversationFilter, публикации из одного треда объединяются, остаётся только один твит с наивысшим скором. При этом это не обязан быть первый твит треда: фильтр это не учитывает и лишь сравнивает скор всех кандидатов одной ветки и заменяет уже выбранный элемент, если встречает публикацию с более высоким значением.

    Если так, то не лучше ли расположить в первом твите треда тему, основной вывод и достаточный контекст, чтобы публикация имела смысл без продолжения, а остальные сообщения треда использовать для доказательств, подробностей и оговорок? В таком случае выше вероятность, что в ранжировании наверх выплывет первый твит, а не очередное звено цепочки‑треда.


Деятельность экстремистской организации Meta (**) и принадлежащей ей социальной сети Instagram (*) запрещена.