Каскад ранжирования и обслуживание (serving)

Рейтинг: 72.2% · 10 голосов
Полный курс об устройстве веб-поиска: обход, индексирование, факторы ранжирования, нейропоиск, поведенческие сигналы, антиспам, SEO. 23 модуля по главам с разбором и обсуждением.
Ответить
Аватара пользователя
kirill_ir
Сообщения: 25
Зарегистрирован: 11 май 2026, 05:31

Каскад ранжирования и обслуживание (serving)

Сообщение kirill_ir »

Оглавление курса (23)
  1. Введение
  2. Теоретический фундамент (Information Retrieval)
  3. Краулинг (обход)
  4. Идентичность документа: каноникализация и дубли
  5. Индексирование и хранение
  6. Обработка и понимание запроса
  7. Текстовая релевантность
  8. Анализ ссылочного графа
  9. Таксономия факторов ранжирования
  10. Машинное обучение ранжированию (Learning-to-Rank)
  11. Нейросетевой поиск (Neural IR)
  12. Поведенческие сигналы и клик-модели
  13. Каскад ранжирования и обслуживание (serving) (вы здесь)
  14. Инфраструктура и распределённое обслуживание
  15. Метапоиск и федерация источников
  16. Группировка, схлопывание, разнообразие
  17. Постранжирование, антиспам и качество выдачи
  18. Свежесть и реалтайм
  19. Локализация, гео и персонализация
  20. Измерение качества и эксперименты
  21. SEO: оптимизация под факторы
  22. Этика, приватность и борьба со злоупотреблениями
  23. Capstone: сквозной проект
Часть IV · ~9 ч · Сложность: (продвинутый) · Пререквизиты: Модуль 6, 9, 10
Обзор модуля

Каскад ранжирования (ranking cascade) — это инженерный ответ на фундаментальный конфликт поиска: самые точные модели релевантности слишком дороги, чтобы применять их ко всему индексу. Глубокая нейросетевая модель (Модуль 10) может оценить пару «запрос–документ» с великолепным качеством, но если в индексе сотни миллионов документов, прогнать её по каждому за отведённые на ответ десятки миллисекунд физически невозможно. Каскад разрешает конфликт, разбивая ранжирование на последовательность стадий нарастающей точности и стоимости: каждая следующая стадия дороже и умнее предыдущей, но получает на вход всё меньше документов, потому что предыдущая стадия уже отсеяла безнадёжных кандидатов.

В сквозном конвейере «обход → индекс → факторы → ранжирование → выдача → постобработка → измерение» этот модуль — сердце стадии «ранжирование» и начало стадии «выдача». На вход он принимает понятый и классифицированный запрос (Модуль 5), обращается к обратному индексу (Модуль 4), считает текстовые факторы (Модуль 6), факторы графа (Модуль 7) и поведенческие сигналы (Модуль 11), применяет обучаемые модели ранжирования (Модуль 9) и нейропоиск (Модуль 10), а на выходе отдаёт упорядоченный список, который дальше обрабатывает постранжирование (Модуль 16) и измеряют метрики (Модуль 19). Каскад — это архитектура исполнения, которая всё это связывает в единый поток, укладывающийся в бюджет латентности.

В этом модуле вы научитесь проектировать каскад L0→L1→L2→L3, понимать компромисс «точность против стоимости» на каждой стадии, строить дешёвый отбор кандидатов (matching) и быстрые признаки, выбирать главную модель и реранк, переключать формулу ранжирования под класс запроса (прямая связь с классификатором интента из Модуля 5), а также управлять бюджетом латентности, глубиной выдачи (пейджинг) и кэшированием результатов.
Интуиция. Представьте отбор в большую компанию. Сначала автоматический фильтр резюме по формальным признакам отсеивает 99% (дёшево, грубо). Потом короткое телефонное интервью отсеивает ещё часть (дороже, точнее). Потом очное собеседование с командой (ещё дороже). И наконец — финал с руководителем для двух-трёх кандидатов (очень дорого, очень точно). Никто не зовёт сразу всех на финал — это и есть каскад: чем дороже стадия, тем меньше кандидатов до неё доходит.
Как читать по трекам
  • Студент CS — обязательно всё. Ядро — глава 12.1 (зачем многоступенчатость, математика воронки точность/стоимость) и 12.3 (модель L2 и реранк L3). Лабы по расчёту бюджета стоимости и по матрице правил выбора формулы — делать руками.
  • Инженер поиска/ML — обязательно всё, особенно инженерные заметки про отсечение постинг-листов, ранний выход (early termination), бюджет латентности и инвалидацию кэша. Это ваша повседневная работа по эксплуатации поиска.
  • SEO-специалист — обязательно глава 12.1 (почему попасть в кандидаты L0 — необходимое условие, без него ничего не поможет) и врезки про выбор формулы под интент (12.3) и про глубину выдачи/пейджинг (12.4). Математику воронки — обзорно.
  • Смешанный/руководитель — Обзор модуля, интуиции, заблуждения, итоги; глава 12.4 целиком (латентность и кэш — это прямые деньги и UX). Формулы стоимости — по диагонали, но запомните идею «дорогая стадия видит мало документов».
Карта модуля
  • 12.1. Стадии L0→L1→L2→L3: зачем многоступенчатость, компромисс точность/стоимость (продвинутый)
  • 12.2. Дешёвый отбор кандидатов (matching) и быстрые фичи на ранних стадиях (продвинутый)
  • 12.3. Главная модель (L2) и реранк (L3); выбор формулы под класс запроса (продвинутый)
  • 12.4. Бюджет латентности, пейджинг/глубина выдачи, кэширование результатов (средний)
Глава 12.1. Стадии L0→L1→L2→L3: зачем многоступенчатость, компромисс точность/стоимость (продвинутый)

Цели обучения

После главы студент сможет:
  • Объяснить, почему одной модели ранжирования недостаточно и откуда берётся многоступенчатость.
  • Сформулировать центральный компромисс каскада: точность стадии против её стоимости на документ.
  • Описать роль каждой стадии L0, L1, L2, L3 и сужение воронки (сколько документов доходит до каждой).
  • Вывести и оценить общую стоимость каскада как сумму «стоимость на документ × число документов» по стадиям.
  • Объяснить, почему ошибки ранних стадий необратимы (потеря recall), а ошибки поздних — нет.
Конспект

Зачем вообще многоступенчатость

Сформулируем задачу строго. Дан запрос q и индекс из N документов (N ∼ 10⁸–10¹¹). Нужно за бюджет времени T_budget (обычно десятки–сотни миллисекунд на серверной части) вернуть k лучших по релевантности документов (k ∼ 10–1000 в зависимости от глубины запрошенной выдачи). Пусть score(q, d) — «идеальная» функция релевантности, и пусть её вычисление стоит c единиц времени на один документ.

Наивное решение «посчитать score для всех N и отсортировать» стоит N · c. Подставим числа: даже если N = 10⁹, а c = 1 мкс (оптимистично для лёгкой формулы и нереалистично для нейромодели, где c ∼ миллисекунды), получаем 10⁹ · 10⁻⁶ с = 1000 с. Это в десятки тысяч раз больше бюджета. Вывод жёсткий: полный перебор индекса с дорогой моделью невозможен в принципе.
Интуиция. У нас есть дешёвая глупая оценка и дорогая умная. Если применять умную ко всему — не уложимся во время. Если применять дешёвую ко всему и на этом остановиться — потеряем качество. Каскад берёт лучшее: дешёвой оценкой быстро отсекаем заведомо плохих, а дорогую тратим только на горстку финалистов.
Ключевое наблюдение, на котором держится весь каскад: чтобы найти топ-k, не нужно точно ранжировать всё — достаточно точно ранжировать только тех, кто имеет шанс попасть в топ. Остальных можно грубо отбросить дешёвым фильтром. Если дешёвый фильтр не выбрасывает истинных финалистов (сохраняет recall@k), то итоговое качество почти не страдает, а стоимость падает на порядки.

Стадии каскада: L0 → L1 → L2 → L3

Канонический каскад веб-поиска состоит из четырёх логических стадий. Конкретные границы и названия в разных системах плавают, но структура «воронки» одинакова.

Код: Выделить всё

Стадия                                      |  Что делает                                                         |  Модель/механизм                                                   |  Сколько на входе      |  Сколько на выходе                  |  Стоимость на документ
--------------------------------------------+---------------------------------------------------------------------+--------------------------------------------------------------------+------------------------+-------------------------------------+----------------------------------------------
L0 — отбор кандидатов (matching/retrieval)  |  Найти все документы, что вообще «про запрос»                       |  Пересечение/объединение постинг-листов, ANN-поиск по эмбеддингам  |  весь индекс N (∼10⁹)  |  ∼10³–10⁵ кандидатов                |  почти ноль (обход индекса)
L1 — предварительный отбор (pre-ranking)    |  Грубо отсортировать кандидатов, оставить перспективных             |  Лёгкая линейная формула / маленькое дерево на дешёвых фичах       |  ∼10³–10⁵              |  ∼10²–10³                           |  очень мало
L2 — главное ранжирование (full ranking)    |  Точно упорядочить по богатой модели                                |  Большой ансамбль GBDT / нейромодель (Модуль 9, 10)                |  ∼10²–10³              |  ∼10²–10³ (то же, переупорядочены)  |  дорого
L3 — реранк / постобработка (re-ranking)    |  Доработать верх выдачи: контекст, листинг-эффекты, диверсификация  |  Listwise-модель, cross-encoder, бизнес-правила                    |  топ ∼10–100           |  финальные k                        |  очень дорого на документ, но документов мало
Интуиция (главная мысль модуля). Стоимость стадии на документ растёт слева направо — от «почти ноль» до «очень дорого». Число документов на входе стадии падает слева направо — от миллиарда до десятков. Эти два движения компенсируют друг друга: суммарное время каждой стадии остаётся в рамках бюджета. Чем дороже стадия — тем меньше документов до неё доходит. Это и есть форма воронки.
Нарисуем воронку:

Код: Выделить всё

            весь индекс N ≈ 10^9
   ┌───────────────────────────────────────┐
L0 │  отбор кандидатов (matching)           │  стоимость/док ≈ 0
   └───────────────┬───────────────────────┘
                   │  ≈ 10^3 – 10^5 кандидатов
            ┌──────┴──────────────┐
L1          │  pre-ranking        │            стоимость/док: низкая
            └──────┬──────────────┘
                   │  ≈ 10^2 – 10^3
              ┌────┴────────┐
L2            │ full ranking │                  стоимость/док: высокая
              └────┬────────┘
                   │  ≈ 10^2 – 10^3 (переупорядочены)
                ┌──┴───┐
L3              │rerank│                          стоимость/док: оч. высокая
                └──┬───┘
                   │  топ k ≈ 10 – 100  →  постобработка (Модуль 16) → выдача
Компромисс «точность против стоимости» — почему он работает математически

Обозначим: стадия i принимает n_i документов, тратит c_i времени на документ. Суммарное время каскада:

Код: Выделить всё

T = Σ  n_i · c_i  =  n_0·c_0 + n_1·c_1 + n_2·c_2 + n_3·c_3
   i
Воронка строится так, чтобы каждое слагаемое было примерно одного порядка и помещалось в бюджет. Это возможно, потому что n_i падает быстрее (на порядки между стадиями), чем растёт c_i.
Пример (порядки величин). Пусть бюджет на ранжирование T_budget ≈ 100 мс. Распределим:
- L0: обход индекса даёт n_1 = 50 000 кандидатов; стоимость отбора ≈ 20 мс (доминирует чтение постингов, не «на документ»).
- L1: n_1 = 50 000 документов, лёгкая формула c_1 = 0.5 мкс/док → 50 000 · 0.5 мкс = 25 мс. Оставляем топ n_2 = 1000.
- L2: n_2 = 1000 документов, GBDT-ансамбль c_2 = 30 мкс/док → 1000 · 30 мкс = 30 мс. Оставляем топ n_3 = 50.
- L3: n_3 = 50 документов, тяжёлый cross-encoder c_3 = 400 мкс/док → 50 · 400 мкс = 20 мс.
Итого ≈ 20 + 25 + 30 + 20 = 95 мс — уложились. А теперь представьте L2-модель на всех 50 000: 50 000 · 30 мкс = 1.5 с — провал. Или L3-cross-encoder на 1000: 1000 · 400 мкс = 400 мс — тоже провал. Воронка — единственный способ задействовать дорогие модели в бюджете.
Инженерная заметка. Бюджет каждой стадии — это управляемая ручка: можно увеличить n_2 (точнее, но дороже L2) или взять более лёгкую L2-модель (быстрее, но грубее). Эти настройки балансируют по A/B-тестам (Модуль 19) против целевой метрики качества при ограничении на p99-латентность. Каскад — это пространство компромиссов, а не одна жёсткая конфигурация.
Почему ошибки ранних стадий необратимы

Это центральное свойство каскада, которое определяет всю инженерную дисциплину.
Интуиция. Поздняя стадия может только переупорядочить то, что ей дали, — она физически не видит документов, отброшенных раньше. Если истинно лучший документ выкинули на L0 или L1, никакая гениальная L3-модель его не вернёт. Кандидата нет в воронке — значит, его нет в выдаче. Точка.
Отсюда асимметрия требований к стадиям:
  • Ранние стадии (L0, L1) оптимизируют recall — «не потерять хорошего». Им разрешено пропускать много мусора вперёд (низкая precision), но нельзя выбрасывать истинных финалистов. Метрика ранних стадий — recall@(размер выхода): какая доля истинного топ-k дошла до следующей стадии.
  • Поздние стадии (L2, L3) оптимизируют precision/порядок — точное ранжирование уже отобранного множества. Их метрика — NDCG/MAP по финальной выдаче (Модуль 19).

Код: Выделить всё

recall важен здесь          precision/порядок важны здесь
   ▼                                        ▼
  L0  ───────►  L1  ───────►  L2  ───────►  L3
 (не теряй)   (не теряй)   (упорядочь)  (доработай верх)
Инженерная заметка. Поэтому пороги отсечения на ранних стадиях ставят с запасом: лучше пропустить лишнюю тысячу кандидатов (немного больше стоимость L1/L2), чем потерять одного настоящего финалиста (необратимая потеря качества). Запас отсечения — это плата за страховку recall.
Частые заблуждения
Заблуждение. «Главное — самая умная модель в конце, остальное неважно.» Нет: качество финала ограничено сверху тем, что отобрали ранние стадии. Если recall L0/L1 низкий, даже идеальная L3 не вытащит — лучшего документа просто нет во входе. Ранние стадии не менее критичны, чем поздние; они задают потолок.
Заблуждение. «Каскад нужен только из-за нехватки железа; добавим серверов — и сделаем одну большую модель на всё.» Нет: проблема не только в железе, а в физике латентности. Пользователь ждёт ответ десятки–сотни миллисекунд; прогнать дорогую модель по миллиарду документов нельзя ни на каком разумном числе машин в этот бюджет. Каскад — структурное, а не временное решение.
Заблуждение (SEO). «Если страница хорошая, она пробьётся в топ.» Сначала страница должна попасть в кандидаты L0 — то есть содержать термины запроса (или их близкие эмбеддинги) в индексируемых зонах. Не попала в matching — выбыла до всякого ранжирования, и качество контента уже неважно. Условие «быть найденным» предшествует условию «быть ранжированным высоко».
Лаба / практика

Расчёт бюджета каскада. Дано: бюджет ранжирования T_budget = 80 мс; четыре варианта L2-модели со стоимостями c_2 ∈ {10, 30, 80, 200} мкс/док и относительным качеством (условный NDCG-выигрыш) {0.0, +0.8, +1.2, +1.4}; L0 фиксированно даёт 40 000 кандидатов за 18 мс; L1 стоит 0.4 мкс/док и сужает до n_2; L3 стоит 350 мкс/док на топ-40 (фикс).

Шаги:
  1. Для каждого варианта L2 найдите максимальное n_2, при котором весь каскад укладывается в 80 мс.
  2. Постройте таблицу «вариант L2 → допустимое n_2 → ожидаемое качество». Учтите, что слишком маленькое n_2 режет recall перед L2 (примите штраф к качеству −0.5, если n_2 < 300).
  3. Выберите конфигурацию с лучшим итоговым качеством в бюджете. Обоснуйте.
Время ~50 мин. Критерий «сделано»: для каждого варианта корректно решено неравенство 18 + 40000·0.4мкс + n_2·c_2 + 40·350мкс ≤ 80мс, выбран оптимум, и сформулирован компромисс «дороже модель → меньше кандидатов до неё доходит».

Контрольные вопросы
  1. Почему наивное «посчитать дорогую модель для всех документов и отсортировать» неосуществимо? Оцените порядок времени.
  2. Сформулируйте центральный компромисс каскада одной фразой. Как n_i и c_i компенсируют друг друга?
  3. Какую метрику оптимизируют ранние стадии и какую — поздние? Почему по-разному?
  4. Почему ошибка ранней стадии необратима, а поздней — нет? Приведите пример.
  5. Вы хотите внедрить тяжёлую нейромодель. На какой стадии каскада это реалистично и почему именно там?
  6. Что произойдёт с качеством выдачи, если поднять порог отсечения L1 слишком высоко (оставлять мало кандидатов)? А если слишком низко?
  7. (SEO) Почему «попасть в кандидаты L0» — необходимое, но не достаточное условие высокой позиции?
  8. Как изменится распределение бюджета по стадиям, если T_budget урезали вдвое?
Глава 12.2. Дешёвый отбор кандидатов (matching) и быстрые фичи на ранних стадиях (продвинутый)

Цели обучения

После главы студент сможет:
  • Реализовать отбор кандидатов (L0) через постинг-листы: пересечение, объединение, режимы AND/OR.
  • Объяснить алгоритмы раннего выхода (WAND/Block-Max WAND, MaxScore) и зачем они сокращают обход индекса.
  • Добавить векторный отбор (ANN-поиск по эмбеддингам) и гибридную выборку кандидатов (Модуль 10).
  • Спроектировать быстрые признаки L1, вычислимые без обращения к телу документа.
  • Обосновать, почему L1-формула должна быть дешёвой и монотонной по recall.
Конспект

L0: отбор кандидатов как работа с постинг-листами

L0 не ранжирует тонко — он отвечает на вопрос «какие документы вообще стоит рассматривать?». Источник кандидатов — обратный индекс (Модуль 4). Для запроса из терминов {t1, t2, …} система берёт их постинг-листы (отсортированные списки docID) и комбинирует.

Два базовых режима:
  • Конъюнктивный (AND): документ-кандидат должен содержать все обязательные термины. Это пересечение постинг-листов — мало кандидатов, высокая precision, риск нулевой выдачи (если совпадений нет).
  • Дизъюнктивный (OR): достаточно любого термина. Это объединение — много кандидатов, высокий recall, дороже.
На практике используют гибкую логику из дерева запроса (Модуль 5): обязательные термины — конъюнкция, синонимы и расширения — дизъюнкция внутри синсета, стоп-слова — опционально. Это контракт между пониманием запроса и отбором.
Пример. Запрос «купить смартфон x2 дёшево». Дерево запроса: купить (опционально, коммерческий маркер), смартфон x2 (обязательно + синсет {модель x2}), дёшево (опционально, синсет {недорого, цена}). L0 берёт пересечение по обязательному смартфон x2, добавляет документы из синсета, опциональные термины не сужают, а влияют на скор позже. Так из миллиарда документов остаётся, скажем, 30 000 кандидатов.
Инженерная заметка. Чистый OR по частым терминам может дать миллионы кандидатов — это убивает бюджет. Поэтому применяют динамическое отсечение: обходят постинг-листы не до конца, а пока есть шанс улучшить топ-k. Алгоритмы: WAND (Weak AND) и Block-Max WAND, MaxScore. Идея — хранить верхнюю границу вклада каждого терма (max_score по листу), и если даже максимально возможный довесок не поднимет документ выше текущего k-го порога, документ/блок пропускают целиком. Это ранний выход (early termination): индекс не дочитывается, экономятся обращения к памяти/диску.
Векторный и гибридный отбор кандидатов

Лексический отбор по постингам не находит документ, в котором нет ни одного термина запроса, даже если он идеально про тему (проблема словарного разрыва, vocabulary mismatch). Здесь подключается плотный отбор (dense retrieval, Модуль 10): запрос и документы кодируются в эмбеддинги, кандидаты ищутся как ближайшие соседи в векторном пространстве через ANN-индекс (HNSW, IVF-PQ и т.п.).
Интуиция. Лексический отбор спрашивает «есть ли эти слова?», векторный — «про это ли по смыслу?». Запрос «как убрать жвачку с одежды» найдёт по векторам статью «удаление липких пятен с ткани», даже без общих слов.
Гибридный отбор объединяет два пула кандидатов (лексический + векторный) перед L1. Это повышает recall L0 за счёт покрытия и точных совпадений, и смысловых. Объединение — по docID, дубли сливаются, сигналы из обоих каналов сохраняются как фичи.

Код: Выделить всё

запрос
  ├──► лексический отбор (постинги, WAND)  ──┐
  │                                          ├──► объединить → кандидаты L0
  └──► векторный отбор (ANN по эмбеддингам) ─┘
L1: быстрые признаки и предварительное ранжирование

После L0 у нас тысячи–десятки тысяч кандидатов — слишком много для дорогой L2. Задача L1 — дёшево отсортировать и сузить до сотен, не потеряв финалистов. Отсюда требования к признакам L1:
  • Дёшево вычислимы — желательно из самого индекса/постингов, без чтения тела документа и без сетевых обращений.
  • Предвычислимы — статические факторы документа (длина, авторитет, язык) считаются на этапе индексации и лежат рядом с постингом.
  • Монотонны по recall — формула не должна систематически выбрасывать классы релевантных документов.
Типичные быстрые фичи L1:

Код: Выделить всё

Группа                 |  Примеры                                                    |  Откуда                                       |  Стоимость
-----------------------+-------------------------------------------------------------+-----------------------------------------------+-----------------------------------------
Текстовые лёгкие       |  BM25 по индексу, число совпавших термов, покрытие запроса  |  постинги (Модуль 6)                          |  низкая (часто уже посчитано при отборе)
Статические документа  |  авторитет/PageRank, длина, язык, спам-скор                 |  предвычислено при индексации (Модуль 7, 16)  |  ≈ ноль (чтение поля)
Векторные              |  косинус запрос–документ                                    |  из ANN-отбора (Модуль 10)                    |  ≈ ноль (побочный продукт отбора)
Запросные              |  класс интента, длина запроса                               |  из понимания запроса (Модуль 5)              |  ≈ ноль (один на запрос)
L1-модель — обычно линейная свёртка этих фич или маленькое дерево: дёшево применить к десяткам тысяч документов. Её цель — не идеальный порядок, а надёжное отделение «возможных финалистов» от «явного мусора».
Внимание. Соблазн «впихнуть в L1 побольше точности» опасен: каждая лишняя фича умножается на n_1 (десятки тысяч) и съедает бюджет. Дорогие фичи (proximity по позициям, тело документа, кросс-энкодер) — это L2/L3, где документов уже сотни. Правило: фича живёт на той стадии, где её суммарная стоимость n_i · c_feature терпима.
Инженерная заметка. Чтобы L1 не читал тело документа, его данные форвард-индексируют: рядом с документом хранят предвычисленный вектор статических фич. Тогда L1 — это «дешёвое скалярное произведение по уже лежащим в памяти числам». Архитектурно ранние стадии живут как можно ближе к индексу (часто на тех же шардах), чтобы не платить за сеть на десятках тысяч кандидатов.
SEO-врезка. Чтобы пройти L0, страница должна содержать термины запроса (или семантически близкий текст) в индексируемых, видимых зонах (Модуль 6: title, заголовки, тело). Чтобы пройти L1, помогают сильные статические сигналы — авторитет домена (Модуль 7) и отсутствие спам-меток (Модуль 16): они дёшевы и потому учитываются рано, фактически решая, доберётесь ли вы до главной модели вообще.
Частые заблуждения
Заблуждение. «Отбор кандидатов — это и есть поиск, дальше просто сортировка.» Нет: L0 даёт множество без точного порядка; качество итоговой выдачи определяется в основном L2/L3. Но L0 задаёт потолок (что вообще можно показать).
Заблуждение. «Векторный отбор всегда лучше лексического, лексика устарела.» Нет: плотный отбор размывает точные совпадения (имена, артикулы, редкие термины, точные фразы). На навигационных и точных запросах лексика точнее. Промышленное решение — гибрид, а не замена.
Заблуждение. «WAND/ранний выход портят качество, ведь индекс не дочитан.» При корректной верхней границе вклада терма ранний выход не меняет топ-k — он пропускает только тех, кто заведомо не пройдёт порог. Это точная оптимизация, а не приближение (для точных границ).
Лаба / практика

Отбор кандидатов и L1-скоринг. Дан мини-индекс: 12 документов с постинг-листами по 5 терминам, предвычисленные статические фичи (authority ∈ [0,1], length, spam ∈ {0,1}) и для трёх документов — векторные косинусы к запросу.

Шаги:
  1. Для запроса из 3 термов (один обязательный, два — синсет) постройте пул кандидатов в режимах AND и OR. Сравните размеры и состав.
  2. Добавьте к лексическому пулу 3 «векторных» кандидата (нет общих термов, но высокий косинус). Получите гибридный пул.
  3. Посчитайте L1-скор s = 1.0·BM25 + 0.7·authority + 0.4·cos − 2.0·spam и оставьте топ-5.
  4. Проверьте, попал ли в топ-5 заранее отмеченный «эталонный финалист». Если нет — какой признак его «утопил» и не нарушает ли это требование recall?
Время ~50 мин. Критерий: корректно построены оба режима и гибрид, посчитан L1-скор, и явно объяснено, как настройка весов влияет на recall перед L2.

Контрольные вопросы
  1. Чем отличаются конъюнктивный и дизъюнктивный режимы отбора по precision/recall и стоимости?
  2. Что такое ранний выход (WAND/MaxScore) и почему он не портит топ-k при корректных границах вклада терма?
  3. Что такое словарный разрыв и как векторный отбор его закрывает? Где векторный отбор уступает лексическому?
  4. Перечислите три требования к признакам L1 и объясните каждое.
  5. Почему proximity по позициям — плохая фича для L1, но хорошая для L2?
  6. Как форвард-индексирование статических фич помогает удержать стоимость L1?
  7. (SEO) Какие два класса сигналов чаще всего решают, пройдёт ли страница ранние стадии, и почему именно дешёвые?
  8. Почему чистый OR по частым терминам опасен и чем его ограничивают?
Глава 12.3. Главная модель (L2) и реранк (L3); выбор формулы под класс запроса (продвинутый)

Цели обучения

После главы студент сможет:
  • Описать роль главной модели L2 (full ranking) и её типичную реализацию (GBDT-ансамбль, нейроранкер; Модуль 9, 10).
  • Объяснить, чем реранк L3 отличается от L2: listwise-эффекты, контекст листинга, диверсификация, cross-encoder.
  • Спроектировать механизм выбора формулы под класс запроса: флаги интента → набор правил → конкретная модель (связь с Модулем 5).
  • Обосновать, почему одна универсальная формула проигрывает специализированным профилям.
  • Понимать, как класс интента становится признаком модели и как обрабатывается неоднозначность.
Конспект

L2: главная модель ранжирования

На L2 приходят сотни–тысячи кандидатов с уже посчитанными лёгкими фичами. Здесь система впервые позволяет себе дорогие признаки и богатую модель:
  • Дорогие текстовые фичи: proximity, минимальное покрывающее окно, фразовость, зональные веса (Модуль 6) — требуют позиций и/или тела документа.
  • Графовые и поведенческие: авторитет, клик-модели, dwell-time (Модуль 7, 11).
  • Семантические: скоры нейромоделей, dense/late-interaction совпадение (Модуль 10).
L2-модель — обычно обучаемая модель ранжирования (learning-to-rank, Модуль 9): большой ансамбль градиентного бустинга над деревьями (GBDT) либо нейронный ранкер. Она принимает вектор из десятков–сотен фич на пару (q, d) и выдаёт скор. Обучается на размеченных/кликовых данных под ранжирующую функцию потерь (pairwise/listwise; Модуль 9).
Интуиция. L2 — это «очное собеседование»: на каждого кандидата тратим заметно больше, смотрим много сигналов, получаем точный балл. Но именно поэтому кандидатов уже не миллионы, а сотни — иначе не успеть.
L3: реранк и постранжирование

L2 ранжирует каждый документ независимо (pointwise по входу: фичи пары (q,d), без оглядки на соседей по выдаче). Но качество выдачи — это свойство списка целиком, а не суммы независимых баллов. Этим занимается L3.

Что добавляет L3 поверх топа от L2:
  • Listwise-эффекты: учёт взаимного влияния позиций; например, два почти одинаковых документа не должны занимать места 1 и 2 — нужна диверсификация (передаётся в постобработку; разнообразие — Модуль 15).
  • Контекст листинга: как документ смотрится среди соседей, в каком блоке/вертикали (Модуль 14 — федерация, если есть).
  • Тяжёлая семантика: cross-encoder — модель, которая совместно кодирует запрос и документ (а не по отдельности, как dense-отбор), давая высшую точность совпадения, но стоящая сотни микросекунд–миллисекунды на пару. Применима только к десяткам финалистов — ровно потому, что их мало.
  • Бизнес-правила и фильтры: возрастные/правовые ограничения, family-фильтры, региональные требования.
Интуиция. L3 — это «финал с руководителем»: смотрим не на каждого отдельно, а на команду в сборе — кто кого дополняет, нет ли дублей, как набор выглядит как ответ целиком. Очень дорого на кандидата, но кандидатов единицы.
Инженерная заметка. Граница L2/L3 подвижна: часть систем делают «L2 = GBDT по всем фичам, L3 = cross-encoder + диверсификация», другие сливают их в одну тяжёлую стадию. Важна не буква, а принцип: pointwise-точность → listwise/контекстная доработка верха, на всё меньшем числе документов.
Выбор формулы под класс запроса — мост к Модулю 5

Это центральный механизм главы и прямое продолжение классификатора интента (Модуль 5.3). Идея: не существует одной формулы, оптимальной для всех запросов. Навигационный, информационный, коммерческий и свежий запросы хотят разного порядка факторов.
Интуиция. Класс интента — это «режим работы» ранжирования. Навигационный запрос («сайт банка X») — «найди одну правильную дверь»: доминирует точное совпадение + авторитет домена, свежесть почти не важна. Свежий запрос («что случилось сегодня») — «принеси новое прямо сейчас»: вес даты огромен, авторитет вторичен. Одна формула не обслужит оба режима хорошо.
Механизм выбора — трёхзвенная цепочка (флаги интента → правила → модель):

Код: Выделить всё

[Модуль 5: понимание запроса]
   classify(q) → флаги интента:
      intent ∈ {informational, navigational, commercial, fresh}
      geo_flag ∈ {0,1},  freshness_flag ∈ {0,1},  ambiguous (распределение p(intent))
                 │
                 ▼
[Звено 1: набор правил выбора профиля]
   правила (декларативный конфиг), напр.:
      IF navigational            → profile = NAV
      IF commercial AND geo_flag → profile = COMMERCE_LOCAL
      IF fresh OR freshness_flag → profile = FRESH
      ELSE                       → profile = GENERAL
                 │
                 ▼
[Звено 2: конкретная модель/набор весов]
   profile → (ranking_model_id, feature_weights, источники, фильтры)
      NAV   → модель с высоким весом exact-match и authority, низким — freshness
      FRESH → модель с высоким весом date/recency, подмешать свежий индекс
      COMMERCE_LOCAL → подмешать товарную вертикаль + геофильтр радиусом
                 │
                 ▼
[применяется на L2/L3 к кандидатам]
Звено 1 — правила. Декларативный слой: набор условий над флагами интента, отображающий каждый запрос в профиль (NAV / GENERAL / FRESH / COMMERCE_LOCAL / …). Правила версионируются и тестируются отдельно от моделей; их легко аудировать и менять без переобучения.

Звено 2 — модель/веса. Профиль выбирает конкретный артефакт ранжирования: либо отдельную обученную L2-модель, либо набор весов/гиперпараметров над общей моделью, плюс настройку источников (какие индексы подмешать) и фильтров (Модуль 16).
Инженерная заметка. На практике это реализуют тремя способами, часто в комбинации:
1. Жёсткое переключение: предсказанный класс выбирает одну из специализированных моделей.
2. Мягкая смесь: итоговый скор — взвешенная по p(intent) смесь скоров профилей (плавно для неоднозначных запросов).
3. Класс как признак: флаги интента подаются внутрь единой модели как фичи, и она сама учится менять поведение. Чаще всего сочетают: грубое переключение профиля + интент-фичи внутри модели.
Внимание. Ошибка классификатора интента дорогая: она выбирает не ту формулу для всего запроса, а не для одного документа. Навигационный запрос, ошибочно принятый за информационный, выдаст «библиотеку статей» вместо одной нужной двери. Поэтому пары классов с дорогой путаницей (нав↔инфо) контролируют отдельно (Модуль 5, 19).
Пример. Запрос «лук». Классификатор даёт распределение: p(commercial)=0.4, p(informational)=0.4 (овощ vs оружие), сигналов мало → ambiguous. Правила: при неоднозначности не выбирать жёсткий профиль, а включить диверсификацию в постобработке (Модуль 15) — в топ по одному представителю каждой интерпретации. Если же запрос «лук репчатый цена» — commercial уверенно → профиль COMMERCE, товарная вертикаль, вес цены/наличия вверх.
SEO-врезка. Поскольку под класс запроса включается своя формула и свой набор источников, оптимизировать страницу надо под доминирующий интент конкретного запроса, а не «вообще». Навигационный запрос ранжирует по бренду и авторитету — туда не пробиться обзорной статьёй; коммерческий хочет карточку с ценой; информационный — разбор. Посмотрите, какой тип страниц система уже держит в топе — это её ответ на вопрос «какой здесь интент» — и приведите тип своей страницы в соответствие (мост к Модулю 5.3).
Частые заблуждения
Заблуждение. «L2 уже даёт идеальный список, L3 — косметика.» Нет: L2 оценивает документы независимо и не видит листинг целиком. Дубли, отсутствие разнообразия, листинг-контекст и тяжёлая семантика (cross-encoder) — задача L3, и она ощутимо меняет верх выдачи.
Заблуждение. «Хорошая модель сама разберётся со всеми интентами, профили — лишнее.» Единая модель с интент-фичами помогает, но специализированные профили + правильные источники под класс дают выигрыш, который трудно выжать из одной формулы: разные интенты хотят разных источников и фильтров, а не только весов.
Заблуждение. «Класс интента — это выход ранжирования (метка результата).» Нет: класс интента — это вход, управляющий сигнал, который выбирает формулу, источники и постобработку ещё до скоринга (Модуль 5.3).
Лаба / практика

Матрица выбора формулы под интент. Дано: 8 запросов с предсказанными флагами интента (класс + geo_flag, freshness_flag, признак неоднозначности) и четыре профиля ранжирования с описанными приоритетами факторов (NAV, GENERAL, FRESH, COMMERCE_LOCAL).

Шаги:
  1. Напишите набор правил (звено 1) в виде упорядоченного списка IF-условий над флагами, отображающий запрос → профиль. Учтите ортогональность гео/свежести (могут комбинироваться).
  2. Для каждого запроса примените правила и выпишите выбранный профиль; для неоднозначных — пометьте «диверсификация (Модуль 15)» вместо жёсткого профиля.
  3. Для двух запросов опишите набор весов профиля (какие факторы вверх/вниз) и какие источники подмешиваются.
  4. Подберите запрос, на котором ошибка классификатора (нав→инфо) даёт заметно плохую выдачу; объясните, почему именно эта пара классов дорогая.
Время ~55 мин. Критерий: правила однозначны и покрывают все запросы, корректно обработаны неоднозначность и ортогональные флаги, явно показана цепочка «флаги → правила → модель/веса/источники».

Контрольные вопросы
  1. Какие классы признаков впервые появляются на L2 и почему их нельзя было считать на L1?
  2. Чем принципиально L3 отличается от L2 (pointwise vs listwise/контекст)? Назовите три задачи L3.
  3. Что такое cross-encoder и почему его место — на L3, а не на L0/L1?
  4. Опишите трёхзвенную цепочку выбора формулы под класс запроса. Что делает каждое звено?
  5. Назовите три способа реализовать зависимость ранжирования от интента; чем хороша «мягкая смесь»?
  6. Почему ошибка классификатора интента дороже ошибки в скоре одного документа?
  7. Как система поступает с неоднозначным запросом и в каком модуле это реализуется?
  8. (SEO) Почему оптимизировать страницу надо под доминирующий интент конкретного запроса, и как этот интент определить по текущей выдаче?
Глава 12.4. Бюджет латентности, пейджинг/глубина выдачи, кэширование результатов (средний)

Цели обучения

После главы студент сможет:
  • Разложить бюджет латентности ответа по компонентам и объяснить роль хвостовых перцентилей (p95/p99).
  • Применять приёмы удержания бюджета: тайм-ауты, деградация качества, ранний выход (связь с 12.2).
  • Спроектировать пейджинг и глубину выдачи: почему глубокие страницы дороги и как их ограничивают.
  • Спроектировать кэширование результатов на разных уровнях и обосновать политику инвалидации.
  • Оценить эффект кэша на латентность и нагрузку.
Конспект

Бюджет латентности и хвостовые перцентили

Время ответа поиска — сумма по компонентам, и каждый отъедает от общего бюджета T_budget:

Код: Выделить всё

T_total ≈ T_сеть + T_понимание_запроса + T_отбор(L0) + T_ранжирование(L1..L3)
          + T_федерация + T_постобработка + T_сборка_выдачи
Целевой бюджет задаётся не по среднему, а по хвостовым перцентилям: p95 и p99 (а иногда p999). Причина:
Интуиция. Поиск — распределённая система: запрос «разлетается» по сотням шардов индекса, ответ собирается из всех. Итоговая латентность определяется самым медленным шардом (эффект «отстающего», straggler). Поэтому даже если медиана 30 мс, p99 может быть 200 мс — и именно его чувствует пользователь на «плохих» запросах. Оптимизируют хвост, а не среднее.
Инженерная заметка. Приёмы удержания хвоста: тайм-ауты на стадии (если шард/стадия не успела — берём, что есть), hedged requests (дублировать запрос к реплике, взять первый ответ), деградация качества (под нагрузкой урезать n_2, отключить L3-cross-encoder, сузить расширение запроса). Деградация — это осознанный размен «чуть хуже качество ↔ уложиться в бюджет», лучше, чем тайм-аут в ноль результатов.
Заблуждение. «Оптимизируй среднее время — и всё хорошо.» Нет: пользователи и SLA живут в хвосте. Система с отличным средним и ужасным p99 ощущается «тормозной», потому что заметные задержки бьют по самым сложным/ценным запросам.
Пейджинг и глубина выдачи

Пользователь видит страницами по m результатов (например, 10). Запрос «страница 1» просит топ-10, «страница 5» — результаты 41–50. Наивно «страница p» = «посчитать топ-(p·m) и отдать хвост». Проблема:
Интуиция. Чтобы отдать результаты 41–50, надо корректно ранжировать как минимум топ-50 — а это значит протащить через дорогие стадии больше кандидатов (увеличить n_2, n_3). Глубина выдачи прямо увеличивает стоимость: чем глубже страница, тем больше документов надо точно отранжировать. При этом ценность глубоких страниц для пользователя мала (почти никто не ходит дальше первых страниц).
Отсюда инженерные решения:
  • Ограничение глубины: система не отдаёт результаты глубже некоторого предела (например, нескольких сотен) — дальше качество ранжирования всё равно низкое, а стоимость высокая.
  • Курсорный пейджинг вместо offset: вместо «пропусти 1000, дай 10» передают «продолжи после вот этого результата» — позволяет дешевле и стабильнее листать, не пересчитывая всё с нуля.
  • Стабильность между страницами: топ кэшируют на сессию запроса, чтобы при переходе на страницу 2 порядок не «прыгал» из-за свежей переиндексации.
SEO-врезка. Поскольку глубокие позиции дороги и почти не получают трафика, борьба идёт за первые позиции первой страницы. «Быть в индексе на странице 7» практически эквивалентно отсутствию: глубину часто и не ранжируют точно, и не показывают пользователю. Релевантность под доминирующий интент (12.3) — путь в видимый топ, а не объём страниц.
Кэширование результатов

Кэш — главный рычаг и латентности, и нагрузки. Распределение запросов сильно неравномерно (закон Ципфа): небольшая доля популярных запросов даёт огромную долю трафика. Их результат можно посчитать один раз и переиспользовать.

Уровни кэширования:

Код: Выделить всё

Уровень                                         |  Что кэшируется                                   |  Ключ                                                       |  Выигрыш
------------------------------------------------+---------------------------------------------------+-------------------------------------------------------------+---------------------------------------------
Кэш результатов (results cache)                 |  готовая выдача (топ-k)                           |  нормализованный запрос + контекст (регион, язык, фильтры)  |  максимальный: ответ без ранжирования вообще
Кэш постинг-листов / промежуточных пересечений  |  горячие постинги, пересечения частых пар термов  |  термы                                                      |  ускоряет L0 для разных запросов
Кэш фич/скоров документов                       |  предвычисленные статические фичи, скоры пар      |  docID / (q,d)                                              |  ускоряет L1/L2
Внимание. Ключ кэша результатов должен включать весь контекст, влияющий на выдачу: нормализованный запрос (после понимания запроса, Модуль 5), регион/гео, язык, активные фильтры, иногда сегмент персонализации. Иначе пользователь получит чужой контекстный ответ. Слишком грубый ключ — неверные ответы; слишком детальный — низкий hit-rate.
Инвалидация — главная сложность кэша. Результат устаревает, когда:
  • изменился индекс (новые/удалённые документы) — особенно критично для свежего интента (12.3): для него кэш должен быть короткоживущим или отключённым;
  • изменилась модель ранжирования или правила выбора формулы (12.3) — после деплоя кэш надо сбрасывать или версионировать ключом модели.
Политики: TTL (время жизни записи; короткое для свежих запросов, длинное для стабильных навигационных), событийная инвалидация (сброс по апдейту индекса/модели), версионирование ключа (в ключ входит версия модели/индекса — старые записи естественно перестают читаться).
Пример. Запрос «новости сегодня» — свежий интент: TTL кэша минуты или кэш выключен. Запрос «сайт центрального банка» — навигационный, ответ стабилен месяцами: TTL часы/сутки, высокий hit-rate. Один кэш, разные TTL по классу интента — снова видна связь с Модулем 5.
Инженерная заметка. Эффект кэша оценивают через hit-rate. Если доля попаданий h, средняя латентность ≈ h · T_кэш + (1−h) · T_полныйрасчёт, где Tкэш ≪ T_полныйрасчёт. При h = 0.5 и Tкэш ≈ 0 средняя латентность падает примерно вдвое, а нагрузка на ранжирующий кластер — на долю h. Поэтому кэш популярных запросов — самый дешёвый способ выиграть и скорость, и ёмкость.
Частые заблуждения
Заблуждение. «Глубокий пейджинг бесплатен — просто отдать хвост уже посчитанного.» Нет: чтобы корректно отдать глубокую страницу, надо точно отранжировать больше кандидатов через дорогие стадии. Глубина прямо повышает стоимость, поэтому её ограничивают.
Заблуждение. «Кэш всегда ускоряет и ничего не портит.» Кэш с неверным ключом отдаёт чужой контекстный ответ; кэш без инвалидации отдаёт устаревшее (особенно больно для свежих запросов и после деплоя модели). Кэш требует дисциплины ключа и инвалидации.
Заблуждение. «Оптимизировать надо среднюю латентность.» Нет: целевая метрика — хвост (p95/p99), потому что распределённый сбор по шардам упирается в самый медленный из них.
Лаба / практика

Бюджет, кэш и глубина. Дано: лог из 20 запросов с пометками класса интента и частоты; стоимость полного расчёта T_full = 90 мс, кэш-ответ T_cache = 2 мс; политика TTL «свежий = 1 мин, навигационный = 6 ч, прочее = 30 мин».

Шаги:
  1. Оцените hit-rate, если повторяются только частые запросы в пределах своего TTL; посчитайте ожидаемую среднюю латентность по формуле h·T_cache + (1−h)·T_full.
  2. Для свежего запроса покажите, как короткий TTL снижает hit-rate, но защищает от устаревания; обоснуйте компромисс.
  3. Для запроса «дайте страницу 6 по 10» оцените, во сколько раз вырастет n_2 относительно «страницы 1», и предложите ограничение глубины.
  4. Опишите, что должно произойти с кэшем после деплоя новой L2-модели, и как версионирование ключа решает проблему.
Время ~45 мин. Критерий: посчитан hit-rate и средняя латентность, корректно связан TTL с классом интента, обоснованы ограничение глубины и инвалидация по версии модели.

Контрольные вопросы
  1. Из каких компонентов складывается T_total ответа поиска?
  2. Почему бюджет задают по p95/p99, а не по среднему? Что такое эффект «отстающего» (straggler)?
  3. Назовите три приёма удержания хвоста латентности и поясните «деградацию качества».
  4. Почему глубокий пейджинг дороже мелкого? Какие два решения снижают его стоимость?
  5. Перечислите уровни кэширования и что выигрывает каждый.
  6. Что обязательно должно входить в ключ кэша результатов и почему слишком грубый/детальный ключ плохи?
  7. Когда и как инвалидируют кэш? Почему свежий интент требует особой политики TTL?
  8. Запишите формулу средней латентности через hit-rate и объясните эффект кэша на нагрузку.
Итоги модуля
  1. Каскад существует из-за конфликта «точность ↔ стоимость»: самые точные модели нельзя применить ко всему индексу в бюджете латентности, поэтому ранжирование разбивают на стадии.
  2. Главный принцип воронки: стоимость стадии на документ растёт (L0→L3), а число документов на входе падает на порядки — слагаемые n_i·c_i остаются в бюджете. Чем дороже стадия, тем меньше документов до неё доходит.
  3. Ранние стадии (L0/L1) оптимизируют recall, поздние (L2/L3) — точный порядок. Ошибка ранней стадии необратима: выброшенного кандидата поздние стадии не вернут — L0 задаёт потолок качества.
  4. L0 — отбор кандидатов (постинги + WAND/ранний выход + ANN/гибрид); L1 — дешёвый предотбор на быстрых, предвычисленных и монотонных по recall фичах.
  5. L2 — главная обучаемая модель на дорогих фичах (proximity, графовые, нейро); L3 — listwise-реранк: cross-encoder, диверсификация, контекст листинга, бизнес-правила.
  6. Формула выбирается под класс запроса по цепочке флаги интента (Модуль 5) → набор правил → конкретная модель/веса/источники. Реализации: жёсткое переключение, мягкая смесь по p(intent), интент как признак модели. Ошибка интента дорогая — она меняет формулу для всего запроса.
  7. Бюджет латентности оптимизируют по хвосту (p95/p99), а не по среднему; держат тайм-аутами, hedged-запросами и осознанной деградацией качества.
  8. Глубина выдачи стоит денег (ограничивают глубину, курсорный пейджинг), а кэш результатов — главный рычаг скорости/нагрузки при дисциплине ключа (весь контекст) и инвалидации (TTL по интенту, версия модели/индекса).
Глоссарий модуля
  • Каскад ранжирования (ranking cascade) — последовательность стадий L0→L3 нарастающей точности и стоимости с сужением числа документов.
  • L0 / отбор кандидатов (matching, retrieval) — стадия выбора множества потенциально релевантных документов из всего индекса.
  • L1 / предотбор (pre-ranking) — дешёвое грубое ранжирование кандидатов для сужения перед главной моделью.
  • L2 / главное ранжирование (full ranking) — точная обучаемая модель на богатом наборе фич.
  • L3 / реранк (re-ranking) — listwise/контекстная доработка верха выдачи (cross-encoder, диверсификация, правила).
  • Воронка точность/стоимость — структурный компромисс: дорогая стадия видит мало документов, дешёвая — много.
  • Recall ранней стадии — доля истинного топ-k, дошедшая до следующей стадии; ключевая метрика L0/L1.
  • WAND / Block-Max WAND / MaxScore — алгоритмы раннего выхода при обходе постинг-листов, отсекающие заведомо непроходные документы/блоки.
  • Ранний выход (early termination) — прекращение обхода индекса, когда улучшить топ-k уже невозможно.
  • Плотный / векторный отбор (dense retrieval, ANN) — поиск кандидатов по близости эмбеддингов; закрывает словарный разрыв.
  • Гибридный отбор — объединение лексического и векторного пулов кандидатов перед L1.
  • Cross-encoder — модель, совместно кодирующая пару (запрос, документ); высшая точность, высокая стоимость на пару, место — L3.
  • Профиль ранжирования — набор модели/весов/источников/фильтров, выбираемый под класс запроса.
  • Флаги интента → правила → модель — трёхзвенная цепочка выбора формулы под класс запроса (мост к Модулю 5).
  • Бюджет латентности — целевое время ответа, задаваемое по хвостовым перцентилям (p95/p99).
  • Эффект «отстающего» (straggler) — итоговая латентность распределённого сбора определяется самым медленным шардом.
  • Деградация качества — осознанное упрощение ранжирования под нагрузкой ради удержания бюджета.
  • Пейджинг / глубина выдачи — выдача результатов страницами; глубокие страницы дороже ранжировать.
  • Кэш результатов (results cache) — хранение готовой выдачи по ключу «запрос + контекст».
  • Инвалидация кэша — сброс/устаревание записей по TTL, событию (апдейт индекса) или версии модели.
  • Hit-rate — доля запросов, обслуженных из кэша.
Связи с другими модулями
  • Опирается на: Модуль 6 (текстовые фичи: BM25 дёшев для L1, proximity/phrase — дороги, место L2); Модуль 9 (learning-to-rank: GBDT/нейроранкеры — это и есть L2); Модуль 10 (нейропоиск: dense-отбор на L0, cross-encoder на L3).
  • Использует результаты: Модуль 5 (флаги интента, дерево запроса — вход для отбора кандидатов и для выбора формулы под класс запроса); Модуль 4 (обратный/позиционный индекс, постинги — субстрат L0/L1); Модуль 7 (авторитет — дешёвая статическая фича L1); Модуль 11 (поведенческие сигналы — фичи L2).
  • Питает дальше: Модули 15–16 (диверсификация, постранжирование, фильтры — продолжение L3); Модуль 14 (федерация вертикалей — переплетается с реранком и выбором источников под интент); Модуль 19 (A/B-тесты и метрики — как настраивают бюджеты стадий, пороги, профили и кэш).
  • Тесно связан: Модуль 5.3 (классификация интента как переключатель конвейера — реализуется именно здесь, на стадиях L2/L3 и в выборе источников).
Материалы для углубления
  • Классические работы по каскадному ранжированию (cascade ranking models) и компромиссу эффективность/эффективность (efficiency–effectiveness trade-off) в IR.
  • Обзоры по динамическому отсечению постинг-листов: WAND, Block-Max WAND, MaxScore и ранний выход в обходе индекса.
  • Литература по плотному и гибридному отбору кандидатов (dense retrieval, ANN-индексы, late interaction) и его комбинации с лексическим поиском.
  • Работы по listwise learning-to-rank и реранкингу с cross-encoder; место тяжёлых нейромоделей в каскаде.
  • Материалы по инженерии латентности распределённого поиска: хвостовые перцентили, эффект отстающего, hedged requests, деградация качества.
  • Обзоры по кэшированию в поисковых системах: уровни кэша, ключи, политики инвалидации, влияние закона Ципфа на hit-rate.
👍5 ❤️2 🔥2 😄 🤔1
Аватара пользователя
bridgett
Сообщения: 1
Зарегистрирован: 19 май 2026, 10:04

Re: Каскад ранжирования и обслуживание (serving)

Сообщение bridgett »

наконец дошло почему L0-L1 такие тупые по фичам, они же гоняются по миллионам доков а уже на L2-L3 остается пара тыщ кандидатов и туда можно совать тяжелую нейронку. раньше думал что каскад это про надежность а не про бюджет на инференс
👍 ❤️ 🔥 😄 🤔
Аватара пользователя
yo2121
Сообщения: 1
Зарегистрирован: 11 май 2026, 14:40

Re: Каскад ранжирования и обслуживание (serving)

Сообщение yo2121 »

вопрос по отсечке между ярусами: вы рекалл считаете на каждом уровне отдельно или сквозной? у нас на проде самая дорогая ошибка это когда хороший док выкидывают на L1 и до реранкера он уже не доезжает, обратно его не вернуть
👍1 ❤️1 🔥 😄 🤔
Аватара пользователя
mrhardon
Сообщения: 1
Зарегистрирован: 31 май 2026, 16:37

Re: Каскад ранжирования и обслуживание (serving)

Сообщение mrhardon »

тут спорный момент про дорогую модель. мы мерили p99 латенси, и не глубина модели нас убивала а сериализация фич между шардами. BM25 как кандидатогенератор тащил норм, узкое место было в пересылке
👍2 ❤️2 🔥 😄 🤔
Ответить
← Предыдущая глава
Поведенческие сигналы и клик-модели
Следующая глава →
Инфраструктура и распределённое обслуживание

Все главы курса «Поисковые системы: индексирование, факторы ранжирования и формирование выдачи»

Поделиться темой: ✈ Telegram VK

Вернуться в «Поисковые системы: индекс, факторы, выдача»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 0 гостей