Разбор кейса: AgeCode: ML System Design
System design поиска по базе статей: BM25 baseline, hybrid поиск, reranker и offline/online evaluation.
Этапы
5
Вопросы
9
Практика
9
Кейс простыми словами
Кейс AgeCode был про поиск по базе статей. Важная развилка появилась в самом начале: продукт может показывать suggest-подсказки до полного вопроса или обрабатывать свободный текстовый запрос пользователя.
Рабочая структура здесь не начинается с LLM. Сначала команда строит BM25 baseline по статьям или чанкам, собирает offline-разметку, смотрит online-сигналы успеха, затем добавляет hybrid retrieval и reranker.
LLM появляется только там, где он меняет продуктовый результат: синтезирует ответ из нескольких статей, выбирает финальный порядок сложных кандидатов или формирует grounded suggest. Если пользователю нужен список статей, обычный search pipeline может быть лучше.
5
этапов с вопросами, просадками и сильной структурой ответа.
4
повторяющихся слабых мест вынесены наверх перед деталями.
9
связанных вопросов открываются прямо из этапов разбора.
Главные просадки
- Не хватило явной единицы поиска: целая статья, раздел, chunk или FAQ-ответ.
- Стоило сразу сказать, что suggest может считаться заранее, а свободный запрос требует online retrieval и reranking.
- Offline-разметку можно было описать конкретнее: кто размечает пары query-article, что такое graded relevance и как хранится regression set.
- Online-метрики были полезными, но стоило добавить reformulation rate, zero-result rate, возврат к выдаче и переход в поддержку.
Постановка: suggest и свободный поиск - разные режимы
Что спрашивали
- Интервьюер дал кейс с базой статей, а кандидат разделил два режима: подсказки статей и свободный текстовый вопрос.
- Следом обсуждался BM25 baseline как первая измеримая версия поиска.
Что было хорошо
- Кандидат правильно не начал с RAG и LLM. BM25 был назван как быстрый, понятный baseline для статей.
- Разделение suggest и free-text search было полезным: у этих режимов разные triggers, candidates и метрики.
Где просело
- Не хватило явной единицы поиска: целая статья, раздел, chunk или FAQ-ответ.
- Стоило сразу сказать, что suggest может считаться заранее, а свободный запрос требует online retrieval и reranking.
Сильная структура ответа
- 1Сильнее было бы начать с двух product flows. Suggest показывает заранее подготовленные подсказки из заголовков, FAQ и query logs. Free-text search принимает вопрос, ищет статьи или чанки и возвращает список или короткий ответ.
- 2Для baseline команда индексирует статьи BM25, измеряет relevance на golden queries и только после этого добавляет embeddings, hybrid retrieval и reranker.
Проверка качества: offline relevance и online success
Что спрашивали
- Интервьюер спросил, как оценивать поиск: offline-разметка, NDCG и признаки того, что пользователь нашел ответ.
- Вопрос проверял, отделяет ли кандидат метрики ранжирования от поведения в продукте.
Что было хорошо
- Кандидат назвал NDCG и начал говорить не только про клик, но и про то, решил ли пользователь свою задачу.
- В ответе появилась связь между offline ranking quality и online user success.
Где просело
- Offline-разметку можно было описать конкретнее: кто размечает пары query-article, что такое graded relevance и как хранится regression set.
- Online-метрики были полезными, но стоило добавить reformulation rate, zero-result rate, возврат к выдаче и переход в поддержку.
Сильная структура ответа
- 1Сильнее было бы разделить три слоя: candidate generator проверяем recall@k, финальный порядок - nDCG/MRR, продукт - time-to-answer, solved feedback, reformulations, клики и latency.
- 2После каждого релиза команда сравнивает новую версию на fixed golden set и отдельно смотрит online guardrails, чтобы reranker не улучшал NDCG ценой задержки или пустых результатов.
Hybrid retrieval и reranker: как собрать финальный pipeline
Что спрашивали
- Интервьюер подвел к архитектуре: candidate generator, hybrid retrieval и отдельный reranker.
- Проверялось, понимает ли кандидат, что BM25 остается полезным даже после embeddings.
Что было хорошо
- Кандидат правильно разложил систему на recall-oriented candidate stage и final ranking stage.
- BM25 не был выброшен после появления semantic retrieval, что для доменных статей обычно верно.
Где просело
- Не хватило деталей про объединение кандидатов: как дедуплицировать статьи и чанки, как применять metadata filters и какой top-K передавать дальше.
- Reranker можно было описать как отдельный сервис или stage с понятным latency budget.
Сильная структура ответа
- 1Сильнее было бы описать pipeline: BM25 и dense retrieval параллельно возвращают candidates, система объединяет и дедуплицирует их, затем cross-encoder или learning-to-rank модель переставляет top-K.
- 2RAG включается после reranker, когда уже выбран контекст. Если пользователь ждет список статей, генерация может быть лишней; если нужен ответ, генератор обязан показать источники.
Suggest-вопросы из статей: генерация без фантазий
Что спрашивали
- В отдельном фрагменте обсуждалось, как генерировать suggest-вопросы из статей.
- Этот блок короткий, но он важен: suggest не должен обещать то, чего нет в статье.
Что было хорошо
- Кандидат предложил короткий вопрос или summary, который ведет на конкретную статью.
Где просело
- Не хватило проверки grounding: каждый suggest должен быть поддержан текстом статьи.
- Стоило разделить редакторские подсказки, query logs и LLM-generated candidates.
Сильная структура ответа
- 1Сильнее было бы сделать offline generator: берем заголовки, FAQ, headings и реальные queries, LLM предлагает короткие формулировки, а pipeline проверяет поддержку в статье, дубли и токсичность.
- 2После публикации suggest оценивается по acceptance rate, downstream click, solved feedback и жалобам. Для чувствительных тем нужен ручной review.
Related articles, сигналы обучения и LLM поверх поиска
Что спрашивали
- Финальная часть ушла в related articles, online-сигналы для cross-encoder и вариант LLM как final reranker.
- Интервьюер проверял, умеет ли кандидат выбирать между precomputed related articles, query-aware reranking и LLM поверх поиска.
Что было хорошо
- Кандидат назвал клики, переходы между статьями и статью, где пользователь нашел ответ, как сигналы для обучения reranker.
- Была видна идея precomputed блока related articles и более контекстного варианта.
Где просело
- Online-сигналы нужно дебайсить: клик зависит от позиции, а dwell time не всегда означает релевантность.
- LLM-reranker прозвучал как возможность, но нужно сразу обсудить privacy, latency, cost и стабильность порядка.
Сильная структура ответа
- 1Сильнее было бы разделить: для каждой статьи заранее считаем related по BM25/embeddings/co-clicks, а для конкретного запроса строим query-aware candidates и reranker.
- 2LLM стоит включать только на top-N, когда нужно синтезировать ответ или сравнить несколько источников. Для обычного списка статей cross-encoder чаще дешевле и стабильнее.
Термины
- BM25
- Lexical baseline поиска: хорошо ловит точные слова, названия и доменные термины в статьях.
- Hybrid retrieval
- Поиск, который объединяет lexical candidates из BM25 и semantic candidates из embeddings.
- Reranker
- Модель второго этапа, которая берет top-K кандидатов и переставляет их по точной релевантности к запросу.
- NDCG
- Метрика ранжирования, которая учитывает порядок результатов и graded relevance: лучший результат наверху ценится больше.
- Grounded suggest
- Подсказка, которая опирается на конкретную статью и не обещает информацию, которой в этой статье нет.