Назад к подготовке
Dodo2026-04-30

Разбор кейса: Dodo: ML System Design

Системный дизайн pricing-policy для доставки с guardrails по конверсии и операционной нагрузке.

Этапы

7

Вопросы

15

Практика

10

Кейс простыми словами

Кейс не про то, чтобы “предсказать стоимость доставки”. Dodo хочет управлять предложением в корзине: когда дать бесплатную доставку от порога, когда показать платную доставку ниже порога и как не потерять пользователя из-за неожиданной цены.

Разложение такое: бизнес выбирает действие, а модель оценивает последствия этого действия. Действие - порог бесплатной доставки или размер платы. Последствия - заказал ли пользователь, какая маржа заказа, не сорвали ли сроки кухни и курьеров, не вырос ли негатив.

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

Карта разбора

7

этапов с вопросами, просадками и сильной структурой ответа.

Быстро подтянуть

4

повторяющихся слабых мест вынесены наверх перед деталями.

Практика

15

связанных вопросов открываются прямо из этапов разбора.

Главные просадки

  • Слишком рано начался разговор про модель. Не хватило первой фразы: “какую бизнес-метрику оптимизируем и что запрещено ухудшать”.
  • Ограничительные метрики были названы позже и местами абстрактно. Нужно сразу сказать, что прибыль нельзя поднимать ценой резкого падения заказов, жалоб или срыва доставки.
  • Не хватило жесткого продуктового инварианта: цена на оплате не должна стать хуже, чем цена, которую пользователь уже видел в корзине.
  • Было мало конкретики про события пересчета: изменение адреса, ресторана, состава корзины, промокода или слота доставки.
Этап 1

Цель бизнеса и границы решения

00:00:41-00:04:11

Что спрашивали

  • Интервьюер просил не просто назвать алгоритм, а спроектировать систему: данные, проверку, обучение, запуск и обратную связь после запуска.
  • Кейс звучал как персонализация минимальной суммы заказа и платной доставки ниже порога. Значит, продукт управляет ценой или порогом, а не расписанием курьеров.

Что было хорошо

  • Кандидат быстро понял, что это ML System Design, а не отдельная задачка на классификацию.
  • В ответе появились нужные блоки: данные, валидация, эксперимент и производственный контур.

Где просело

  • Слишком рано начался разговор про модель. Не хватило первой фразы: “какую бизнес-метрику оптимизируем и что запрещено ухудшать”.
  • Ограничительные метрики были названы позже и местами абстрактно. Нужно сразу сказать, что прибыль нельзя поднимать ценой резкого падения заказов, жалоб или срыва доставки.

Сильная структура ответа

  1. 1Сильнее было бы начать с цели: увеличиваем прибыль или маржу на пользователя, но держим нижние границы по конверсии в заказ, повторным заказам, жалобам, отменам и времени доставки.
  2. 2Затем зафиксировать действие: система выбирает порог бесплатной доставки или плату за доставку из заранее разрешенного диапазона. Она не управляет сменами курьеров и не обещает решить всю логистику.
Этап 2

Путь пользователя и момент обещания цены

00:06:56-00:09:18

Что спрашивали

  • Интервьюер подвел к разбору пути заказа: пользователь открывает приложение, выбирает адрес или ресторан, собирает корзину, видит условия доставки и идет на оплату.
  • Главный вопрос: где именно система принимает решение и что пользователь уже видит как обещание.

Что было хорошо

  • Кандидат начал раскладывать процесс заказа, а не пытался сразу выбрать CatBoost или нейросеть.
  • Были упомянуты корзина, оформление заказа, кухня, курьеры и доступность доставки.

Где просело

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

Сильная структура ответа

  1. 1Сильнее было бы описать путь словами: на входе в корзину считаем предложение, при изменении корзины или адреса пересчитываем, на оплате валидируем, но не ухудшаем уже показанное обещание без явного объяснения.
  2. 2Отдельно проговорить срок жизни обещания цены: например, оно фиксируется на короткое время, а при существенном изменении корзины создается новое обещание.
Этап 3

Данные: что известно до показа цены

00:12:17-00:27:38

Что спрашивали

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

Что было хорошо

  • В ответе появились правильные источники: состояние кухни, курьеры, текущие заказы, ресторан, зона, корзина и пользовательская история.
  • Кандидат не ограничился “возьмем фичи из базы”, а начал думать про реальный операционный процесс.

Где просело

  • Часть признаков звучала как названия без формулы. Например, “нагрузка курьеров” нужно разложить на активные заказы, свободные минуты курьеров, ожидаемое освобождение и риск опоздания.
  • Не хватило проверки доступности признаков: если сигнал обновляется раз в 10 минут, он не подходит как точная картина для решения прямо сейчас.

Сильная структура ответа

  1. 1Сильнее было бы назвать единицу расчета: ресторан или зона доставки на ближайшие 15-30 минут. Нагрузка = ожидаемые минуты работы по активным и новым заказам / доступные курьерские минуты.
  2. 2Для каждого быстрого признака сразу задать срок годности: когда считаем устаревшим, чем заменяем и сколько таких замен допустимо до ухода в запасной сценарий.
Этап 4

Модель: предсказывать реакцию, а не цену

00:14:33-00:22:25

Что спрашивали

  • Ключевой поворот был в том, что цена или минимальная сумма заказа - это действие, а не целевая переменная модели.
  • Интервьюер уточнял, как собрать датасет: что является строкой, какие признаки известны до решения и какой результат наблюдаем после показа цены.

Что было хорошо

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

Где просело

  • Сначала прозвучало слишком близко к “предсказываем цену”. Это опасно: модель просто повторит старые решения менеджеров или старого правила.
  • Не хватило явной строки датасета: показ конкретного предложения конкретному пользователю в конкретном контексте в конкретное время.

Сильная структура ответа

  1. 1Сильнее было бы сказать: строка обучения - момент показа предложения. В строке есть пользователь, корзина, ресторан, зона, время, состояние кухни и курьеров, а также само действие: плата или порог.
  2. 2Метка - что случилось после показа: заказ, сумма заказа, маржа, отмена, жалоба, повторный заказ. Признаки после оплаты и фактическую задержку доставки в обучение на момент показа не подмешиваем.
Этап 5

Выбор действия и запасной сценарий

00:27:38-00:36:51

Что спрашивали

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

Что было хорошо

  • Кандидат обсуждал перебор вариантов цены и понимал, что решение нужно ограничивать бизнес-правилами.
  • Был назван риск обучаться только на собственной истории новой модели.

Где просело

  • Не хватило фразы “нет разнообразия действий - нет надежного сигнала об эластичности”. Если всем почти всегда показывали одну цену, обычное обучение не скажет, что было бы при другой.
  • Запасной сценарий нужно описывать конкретно: старое правило, популярный для зоны порог, ручной лимит или скрытие динамики при плохих данных.

Сильная структура ответа

  1. 1Сильнее было бы предложить малую управляемую разведку: несколько безопасных вариантов цены на маленьком трафике, заранее заданные ограничения по конверсии и жалобам, отдельные срезы по городам и ресторанам.
  2. 2После модели перебираем сетку действий, считаем ожидаемую прибыль и отбрасываем варианты, которые нарушают ограничения. Если уверенность низкая, признаки устарели или пользователь в редком сегменте, включаем запасной сценарий.
Этап 6

Эксперимент: что доказывает A/B-тест

00:40:25-00:56:01

Что спрашивали

  • Финальный блок был про метрики, статистику, разбиение пользователей и проверку алгоритма до запуска.
  • В доставке есть зависимость между пользователями: общая кухня и курьеры могут сделать простое разбиение по пользователям недостаточным.

Что было хорошо

  • Кандидат не забыл A/B-тест и начал обсуждать разные статистические тесты.
  • Были затронуты разбиение по пользователям, минимальный заметный эффект и предварительная проверка.

Где просело

  • Метрики нужно связывать с бизнесом: прибыль на пользователя или маржа не заменяют контроль конверсии, жалоб, отмен и времени доставки.
  • Статистический тест нельзя выбирать отдельно от единицы разбиения. Если курьеры и кухня общие, пользователи в разных группах могут мешать друг другу.

Сильная структура ответа

  1. 1Сильнее было бы задать основную метрику: например, маржа на подходящего пользователя. Рядом поставить ограничения: конверсия в заказ, средний чек, отмены, жалобы, время доставки, повторные заказы и доля ухудшенных цен.
  2. 2Перед запуском сделать A/A или сухой прогон без изменения цены: проверить логи, долю запасных сценариев, задержку ответа сервиса, пропуски признаков и перекос разбиения.
Этап 7

Запуск в продукте: как модель отвечает и где риски

00:47:32-00:49:06

Что спрашивали

  • Интервьюер возвращался к вопросу, можно ли использовать новые данные от текущей модели для следующего обучения.
  • Это проверка на понимание замкнутого круга: модель меняет поведение пользователей, а потом учится на измененном распределении данных.

Что было хорошо

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

Где просело

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

Сильная структура ответа

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

Термины

Quote
Зафиксированное обещание цены или условия доставки, которое пользователь уже увидел. Его нельзя тихо ухудшить на оплате.
Fallback
Запасной сценарий: старое правило, ручной лимит или простая эвристика, которая включается при плохих данных, низкой уверенности или сбое сервиса.
Guardrails
Ограничительные метрики: показатели, которые нельзя ухудшить ради роста основной метрики. Здесь это конверсия, жалобы, отмены, сроки доставки и доля неприятных изменений цены.
Serving
То, как модель отвечает в продукте: какие данные получает сервис, сколько миллисекунд он может думать и что возвращает пользователю.
Drift
Изменение распределения данных. Например, поменялся спрос по районам или новая политика стала показывать совсем другие цены, и обучающая история больше не похожа на текущие запросы.
Latency
Задержка ответа сервиса. В корзине это время между изменением корзины и показом новой цены; если оно велико, пользователь видит тормоза или устаревшее предложение.