← к модулям

System design: case studies (E2)

Один каркас — жизненный цикл рекомендательной системы с петлями — и четыре продукта, отвечающие на одни и те же вопросы по-разному: видео-платформа, короткая лента, маркетплейс, новости. Включи режим самопроверки — и сформулируй свои ответы, прежде чем раскрывать готовые.

⚠ Разборы — честный конспект инженерной практики и типовых trade-offs, а не описание внутренних систем реальных компаний. Каждая стадия ссылается на модуль учебника, где она построена вживую.

Каркас: жизненный цикл рекомендательной системы

Один и тот же скелет для любого продукта — с петлями: офлайн не устроил → назад к данным; мониторинг поймал дрейф → снова данные и ретрейн. Ниже четыре продукта отвечают на одни и те же вопросы по-разному.

1. Бизнес-задача и метрики успеха2. Сбор данных / логирование3. Обработка данных4. Протокол офлайн-оценки5. Выбор архитектуры6. Обучение и офлайн-оценка7. Деплой / serving8. Онлайн-оценка (A/B)9. Мониторинг10. Поддержка и итерация

Петли: 6 → 2 (офлайн-метрики не устроили — чините данные и лейблы, не слои) · 10 → 2 (дрейф/петля обратной связи — новые данные, ретрейн). Цикл не заканчивается деплоем.

Как пользоваться: выбери продукт → включи самопроверку → для каждого шага сначала ответь сам → раскрой решение → сравни этот же шаг между продуктами (таблица ниже).

🎬 Design: Видео-платформа

длинное видео, YouTube-подобная

❓ Вопросы себе перед этим шагом (9)
  • Какую продуктовую проблему решаем и как выглядит успех через год (а не через неделю)?
  • Кто пользователи и в каких сценариях они встречают рекомендации? Откуда берутся айтемы — платформа двусторонняя (продавцы/авторы)?
  • Какие действия возможны и что из них — сигнал ценности, а что шум (клик ≠ удовлетворённость)?
  • Какая одна метрика (north-star) отражает долгосрочную ценность — и можно ли её «накрутить» нежелательным поведением?
  • Какие guardrails нельзя просадить? Есть ли этические / регуляторные / well-being ограничения?
  • Что нужно ЛОГИРОВАТЬ, чтобы north-star и guardrails были измеримы (dwell, возвраты, позиции)? — это техзадание шагу 2.
  • Где в продукте живёт выдача (surface) и что там было до рекомендаций — какой baseline опыта?
  • Какой масштаб: юзеров, айтемов, RPS? Как быстро оборачивается каталог (годы / дни / часы)?
  • Что случится, если рекомендации просто выключить? Какая доля ценности продукта реально на них — от этого зависит бюджет всей системы.
  • Цель — долгосрочное удержание через ценность просмотра, а не клики: north-star — «satisfied watch time» (время просмотра, взвешенное сигналами удовлетворённости), потому что сырой CTR оптимизируется кликбейтом.
  • Пользователи: зрители с длинной историей вкуса. Айтемы: видео (каталог в сотни миллионов, гигантский long-tail, айтем живёт годами). Действия: показ → клик → доля досмотра, лайк/дизлайк, подписка, «не интересно».
  • Guardrails: жалобы/дизлайки, доля кликбейта (клик без досмотра), разнообразие каналов, время до первого качественного просмотра.
❓ Вопросы себе перед этим шагом (6)
  • Какие события уже логируются, а какие надо НАЧАТЬ логировать (impressions? позиции? surface? контекст запроса)?
  • Можем ли отличить «показали и не заинтересовался» от «не показали»? Есть ли наблюдаемые негативы, или лог positive-only?
  • Показ = реально увиден? Что с viewability и позицией в ленте?
  • Какие идентификаторы (логин / аноним / кросс-девайс) — и что с PII, приватностью, согласиями?
  • Какие смещения зашиты в лог текущей системой (position bias, exposure bias) — и что мы потом с ними сделаем?
  • Пишем ли model_version / experiment_id в каждое событие (без этого потом не отладиться)?
  • Логируем impressions с позицией и поверхностью (главная / сайдбар / поиск) — position bias тут реален и его придётся вычитать.
  • Watch-прогресс пишем тиками (25/50/75/100%), не одним числом в конце — сессии обрываются.
  • Контекст запроса: устройство, время суток, вход с уведомления или органика — всё это фичи и срезы для аналитики.

Вживую в учебнике: схема event-лога и position bias — B1

❓ Вопросы себе перед этим шагом (7)
  • Что считаем позитивом — клик, dwell, покупка? Не учим ли мы кликбейт этим выбором?
  • Откуда негативы: наблюдаемые (скипы), impression-aware или сэмплированные — и какое смещение каждый вариант вносит?
  • Как атрибутируем целевое действие к показу (окно атрибуции)? Есть ли delayed feedback?
  • Split строго по времени? Нет ли утечки будущего — в том числе через ФИЧИ (агрегаты, посчитанные по всему логу)?
  • Какие фичи считаются офлайн, какие в real-time — и считаются ли они ОДИНАКОВО в train и serving?
  • Дубли, боты, автоплей, аномалии — как чистим? Нужна ли сессионизация?
  • Повторное потребление: seen-айтемы — валидный таргет (музыка, POI) или их надо убирать (фильмы)?
  • Лейбл — не «клик», а «satisfied watch»: доля досмотра с порогом, зависящим от длины видео (30 сек шортса ≠ 30 сек двухчасовой лекции), калибруется опросами.
  • Негативы — impression-aware: показали и не кликнул / кликнул и бросил. «Не показали» негативом не считаем.
  • Split — только временной: глобальная отсечка, никакого random (утечка будущего).

Вживую в учебнике: почему только temporal split — B2

❓ Вопросы себе перед этим шагом (7)
  • Какая офлайн-метрика лучше всего аппроксимирует north-star (заданный на шаге 1) — и в каких случаях они разойдутся?
  • Что из желаемого протокола данные вообще позволяют? Нет impressions → нет честных негативов; нет propensities → нет IPS.
  • Что мерим на retrieval (recall пула — не потеряли ли), а что на ранкере (NDCG/MRR верха)?
  • Один релевантный айтем на юзера или много? (тогда recall = hit-rate, а precision@K ≤ 1/K — как читать значения?)
  • Чем ловим схлопывание в популярное: coverage, novelty, diversity?
  • Что принципиально мерится только онлайн (retention, конверсия) — и не обманываем ли себя офлайн-прокси?
  • С какими baseline сравниваем (popularity, прошлая модель) и на одном ли протоколе?
  • Офлайн: recall@K по стадии retrieval (не потеряли ли хорошее), NDCG/hit ранкера на watch-лейблах, coverage/novelty как анти-схлопывание.
  • Онлайн-only: watch time на пользователя, возвраты (Day-1 / Day-7 retention), доля отписок от рекомендаций — это не посчитать на истории.
  • Помним про offline↔online gap: офлайн-выигрыш — фильтр гипотез, решение принимает A/B.

Вживую в учебнике: какая метрика что ловит — /metrics

❓ Вопросы себе перед этим шагом (8)
  • Можно ли скорить весь каталог одной моделью, или масштаб требует воронку retrieval → ranking → re-rank?
  • Какие candidate sources и зачем несколько — что уникального добавляет каждый (recall-ценность)?
  • Какие фичи реально доступны ранкеру в момент запроса (и не подглядывают ли они в будущее)?
  • Что делает re-rank: разнообразие, дедуп, бизнес-правила, sponsored — и что из этого ДОЛЖНО отработать до ранкера (eligibility)?
  • Как отвечаем холодному юзеру / айтему / при отказе компонента — какова лестница fallback целиком?
  • Где нужен exploration и какой у него бюджет? Как новый контент получает первые показы?
  • Есть ли контекст запроса (гео, устройство, время) и куда его класть — query-башня / ранкер (item-башня предрассчитана)?
  • Build vs buy: что берём готовым (ANN-библиотека, feature store, vector DB), а что пишем сами — и почему?
  • Retrieval из нескольких источников: two-tower по истории просмотров, co-watch item-CF, подписки, свежее/трендовое — union + provenance.
  • Ranker — multi-task: pWatch, pLike, pDislike, pReport → комбинируются в value-модель (веса — продуктовое решение, не ML).
  • Re-rank: разнообразие каналов/тем (MMR-подобное), дедуп почти-дублей, свежие слоты.
  • Cold-start: новый юзер — onboarding-интересы + популярное по гео; новое видео — контентные фичи канала + exploration-бюджет.

Вживую в учебнике: воронка вживую — системный дизайн · лестница fallback — B5

❓ Вопросы себе перед этим шагом (6)
  • Насколько обучающие данные смещены текущей системой (учимся на том, что сами показали)?
  • Каков честный протокол оценки — и кому он льстит (напр., popularity при пороге «понравилось»)?
  • Бьём ли простые baseline? Если нет — что чиним ПЕРВЫМ: данные, лейблы, фичи — и лишь потом модель?
  • Какие абляции покажут, что реально несёт сигнал (а не «коэффициент большой»)?
  • Офлайн растёт, а есть ли риск, что мы просто переобучились на прокси-метрику?
  • Воспроизводимость: зафиксированы ли данные, сиды, версии — можно ли повторить число из отчёта?
  • Обучение на собственных логах смещено экспозицией: то, что не показывали, не имеет лейблов — контролируем через exploration-трафик и взвешивание.
  • Валидация — временная, с бейзлайнами: не бьём popularity/предыдущую модель — не выкатываем.
  • Если офлайн не устраивает — чаще всего проблема в лейблах и фичах, а не в архитектуре: возвращаемся к шагам 2–3, а не наращиваем слои.

⚠️ Классическая ошибка: месяц тюнить архитектуру ранкера, когда лейбл «watch» не отделяет автоплей от осознанного просмотра.

❓ Вопросы себе перед этим шагом (6)
  • Какой latency-бюджет на запрос и как он делится по стадиям воронки?
  • Что предрассчитано офлайн (эмбеддинги, индексы, кандидаты) и с какой частотой обновляется?
  • Какие eligibility-фильтры обязаны отработать ДО ранжирования (наличие, регион, возраст, safety)?
  • Что происходит при отказе каждого компонента — есть ли graceful degradation и куда падаем?
  • Как выкатываем (shadow → канарейка → 100%), есть ли parity-тесты фич — и за сколько минут откатимся?
  • Где живёт состояние (сессия, кеши) и что случится при рестарте?
  • Item-эмбеддинги предрассчитаны и лежат в ANN-индексе; user-вектор считается на запрос.
  • Latency-бюджет делится по стадиям (retrieval единицы мс через ANN, ранкер — основная часть); деградация — сначала урезать кандидатов, потом fallback на популярное.
  • Раскатка новой модели — shadow → канарейка → 100%, с parity-тестами фич (train/serve skew).

Вживую в учебнике: почему ANN и что он даёт — two-tower

❓ Вопросы себе перед этим шагом (6)
  • Какая целевая метрика эксперимента, какие guardrails остановят выкатку — и зафиксированы ли критерии решения ДО запуска?
  • Какая нужна мощность: размер выборки, длительность — с учётом novelty-эффекта и отложенных эффектов (retention)?
  • Как делим трафик? Нет ли interference между группами (общий инвентарь, соцграф, петли)?
  • Годится ли interleaving как дешёвая проверка ранжирования до полного A/B?
  • Что делаем при противоречии «офлайн лучше — онлайн хуже»? (обычно это skew или смещённый офлайн)
  • Меняет ли эксперимент сами данные для будущего обучения (петля через логи)?
  • A/B: целевая — satisfied watch time / retention; guardrails — жалобы, доля кликбейта, coverage.
  • Novelty-эффект: новая модель первое время выигрывает просто новизной выдачи — эксперимент держат недели.
  • Interleaving — дешёвый способ сравнить ранкеры на коротком горизонте; долгосрочные эффекты (retention, доверие) он не ловит — их проверяет A/B.
❓ Вопросы себе перед этим шагом (6)
  • Что мониторим на каждом слое: данные (свежесть, дрейф, объём) / модель (score-распределение, coverage) / система (p99, ошибки, fallback-rate — «не empty» ещё не значит «здоров») / бизнес?
  • Какие РАННИЕ диагностические сигналы поймают проблему до просадки выручки (freshness lag, PSI, p99)?
  • На каких срезах может прятаться деградация при стабильном среднем (новые юзеры, хвост, регион)?
  • С каким baseline-окном сравниваем (тот же день недели / сезон), чтобы промо и сезонность не давали ложных алертов?
  • Как заметить петлю обратной связи: head-share / coverage / Gini ВО ВРЕМЕНИ, а не одним средним?
  • Пороги алертов: кто получает, что в ранбуке, не устанем ли от ложных срабатываний?
  • Данные: freshness lag фич и ANN-индекса (устаревший индекс = невидимые новые видео).
  • Модель: дрейф распределения score, head-share/coverage во времени — ловим петлю «богатые богатеют».
  • Система: p99 по стадиям, fallback-rate (сколько юзеров тихо получили популярное).

Вживую в учебнике: симулятор инцидентов — B7

❓ Вопросы себе перед этим шагом (7)
  • Как часто ретрейним по плану — и что триггерит внеплановый ретрейн (дрейф-алерт)?
  • Как система размечает новый контент — работает ли exploration-конвейер постоянно?
  • Что в системе усиливает само себя (петли популярности, промо-петля) и что этому противопоставлено?
  • Главные failure modes этого продукта — как каждый из них поймать заранее (монитор/guardrail)?
  • Какой техдолг копится (фичи, логи, индексы, старые эксперименты) и когда его чистим?
  • Что попадает в постмортем после инцидента и превращается ли он в новый монитор/тест?
  • Когда продукт изменится (новый surface, новый тип айтемов) — какие части системы переживут это, а какие придётся переделать?
  • Ретрейн по каденсу (сутки/недели) + непрерывное дообучение лёгких частей; тяжёлые башни — реже.
  • Петля обратной связи — главный хронический риск: без exploration хвост умирает, метрики какое-то время даже растут.
  • Failure modes: кликбейт-спираль (оптимизация кликов), rabbit holes (узкие туннели интересов), каннибализация подписок рекомендациями.
Итог дизайна

Главное — satisfied watch time и долгосрочная ценность, а не клики. Архитектура: multi-source retrieval → multi-task ранкер (value-модель) → re-rank на разнообразие и свежесть. Главные риски — кликбейт-спираль, rabbit holes и петля популярности; лечатся лейблом качества, diversity и exploration.

🧠 Проверь себя: Почему north-star видео-платформы — не CTR, хотя клик проще всего мерить?

Сравнение: один вопрос — четыре продукта

Выбери стадию каркаса — и посмотри, как продукт меняет ответ. В этих различиях — суть системного проектирования: каркас один, решения продуктовые.

🎬 Видео-платформаnorth-star: satisfied watch time; guardrails: жалобы, кликбейт-доля, разнообразие
📱 Короткая лентаnorth-star: возвраты/сессии; guardrails: скрытия, репорты, разнообразие, well-being
🛒 Маркетплейсnorth-star: долгосрочная ценность — GMV/conversion с поправкой на возвраты, маржу, качество и seller health
📰 Новостная лентаnorth-star: качественное чтение + возвраты; guardrails: кликбейт, разнообразие точек зрения
📖 Мини-глоссарий терминов из кейсов (13)
OOS
out-of-stock — товар закончился; OOS-доля в выдаче = сколько рекомендованного нельзя купить прямо сейчас
out-of-stock
товар закончился; доля таких в выдаче — прямой прокси сломанного инвентарь-пайплайна
CUPED
метод снижения дисперсии в A/B за счёт пред-экспериментальных данных пользователя — эксперимент быстрее достигает значимости
rabbit hole
«кроличья нора»: система загоняет пользователя во всё более узкий туннель однотипного контента
dwell
время, реально проведённое с контентом — отличает «кликнул и закрыл» от «прочитал/посмотрел»
replay
офлайн-прогон модели по недавним залогированным событиям («как если бы она работала тогда») — оценка на свежих срезах
creator-side
метрики стороны авторов: получают ли новые авторы показы, как быстро набирается первая аудитория
promo-aware
с поправкой на промо: сравниваем с сопоставимым периодом (та же распродажа / день недели), а не с «вчера»
delayed feedback
отложенный отклик: целевое действие (покупка) случается спустя дни после показа — на момент обучения часть лейблов ещё «не произошла»
GMV
gross merchandise value — суммарный оборот товаров через площадку
novelty-эффект
временный всплеск метрик от новизны выдачи: «новое» кликают, потому что оно новое; проходит за дни-недели
interleaving
смешивание выдач двух ранкеров в один список: чьи айтемы кликают чаще, тот и лучше — чувствительнее A/B, но только про ранжирование
seller health
здоровье экосистемы продавцов: разнообразие, выживаемость новых, отсутствие монополизации выдачи

Теория простым языком

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

Зачем case studies, если модули уже пройдены
БылоКаждый модуль учебника учит один компонент: логи, split, воронку, cold-start, мониторинг.
ПроблемаВ реальной работе нужна целая система: компоненты надо собрать под конкретный продукт и обосновать trade-offs.
ИдеяОдин фиксированный каркас-цикл × разные продукты: одинаковые вопросы, разные ответы — и видно, почему они разные.
Стало лучшеПереносимый навык: новый продукт = пройти каркас, а не вспоминать заученный дизайн.
Осталось слабымРазборы — конспект инженерной практики, а не внутренности реальных систем компаний; детали в индустрии различаются.
ДальшеСобрать один такой пайплайн руками — capstone (E3); честная онлайн-оценка — Фаза 14 (A/B, IPS).

Как применять каркас (метод)

1. Начинай с шага 1, а не с модели — и метрики успеха задавай там же. North-star и guardrails объявляются вместе с задачей, до сбора данных: логирование проектируется под метрику, а не наоборот. Половина решений определяется этим выбором — satisfied watch time против GMV дают разные системы при одинаковых алгоритмах. А шаг 4 — не «выбор метрик», а протокол офлайн-оценки: он стоит после данных, потому что ограничен тем, что лог реально содержит (нет impressions — нет честных негативов, нет propensities — нет IPS).
2. Проговаривай данные до архитектуры. «Какие сигналы у нас есть и каких нет» — вопрос, который отделяет зрелый дизайн: без impressions нет честных негативов, без позиций не вычесть position bias.
3. Называй петли. Офлайн не устроил → чинить лейблы/данные (шаги 2–3), не наращивать слои. Мониторинг поймал дрейф → ретрейн и новые данные. Цикл не заканчивается деплоем.
4. Заканчивай failure modes. Кликбейт-спираль, петля популярности, распроданный топ, старая новость наверху — умение назвать, как система ломается, ценится выше лишнего слоя в ранкере.

North-star vs guardrailsnorth-star — одна метрика, ради которой всё; guardrails — «предохранители», которые нельзя просадить, пока её растишь. Пара выбирается продуктом, а не ML — и именно она разводит наши четыре кейса сильнее всего.

Что общее у всех четырёх (и почти любого продукта)

Многостадийная воронка (retrieval → ranking → re-rank), impression-aware лейблы (B1), временная валидация (B2), лестница cold-start (B5), мониторинг по слоям (B7) и петля обратной связи как хронический риск. Различия — в весах: новостям свежесть важнее персонализации, маркетплейсу наличие важнее релевантности, короткой ленте exploration важнее точности.

⚠️ Что может пойти не так

  • Начинать проектирование с модели («возьмём трансформер») — сначала цель, данные и метрики, модель предпоследняя.
  • Один дизайн на все продукты: если ответ для новостей совпал с ответом для маркетплейса — ты не учёл продукт.
  • Забыть онлайн-часть: дизайн без A/B, мониторинга и failure modes — половина системы.
  • Выдавать разборы за устройство реальных компаний: это конспект практики, детали везде свои.
  • Игнорировать двусторонность платформ: fairness / exposure-diversity guardrails — часть дизайна, и в зависимости от продукта это продавцы (marketplace), авторы (короткая лента), источники и точки зрения (новости) или каналы (видео).

Где это в дорожной карте

Это E2 — case studies: замковый камень поверх модулей. Дальше — E3 capstone: собрать один такой пайплайн руками на реальном implicit-логе (D2a/D2b уже дают данные и ранкер), и Фаза 14 — честная онлайн-оценка (A/B, interleaving, IPS/DR).