Нейросетевой поиск (Neural IR)

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

Нейросетевой поиск (Neural IR)

Сообщение 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 · ~10 ч · Сложность: (продвинутый) · Пререквизиты: Модуль 1, 6, 9
Обзор модуля

Все предыдущие модели релевантности — булева, векторная tf-idf, BM25 (Модуль 6), обучаемое ранжирование на ручных признаках (Модуль 9) — роднит одно: они оперируют поверхностным совпадением слов. Если запрос «как лечить простуду», а документ написан про «терапию ОРВИ», лексические модели увидят ноль общих значимых терминов и поставят документу почти нулевой текстовый скор, хотя по смыслу это идеальный ответ. Это проблема лексического разрыва (vocabulary mismatch): одно и то же значение выражают разными словами, а одно и то же слово значит разное в разных контекстах («лук» — растение или оружие). Нейросетевой поиск (neural IR) — это семейство методов, которые сопоставляют запрос и документ в пространстве смыслов, а не строк, и тем самым закрывают этот разрыв.

Ключевой объект модуля — эмбеддинг (embedding): плотный вектор фиксированной размерности (например, 768), который нейросеть-энкодер сопоставляет тексту так, что близкие по смыслу тексты получают близкие векторы. Поиск превращается в геометрию: индексируем документы как точки в d-мерном пространстве, запрос — тоже точка, релевантность ≈ близость (косинус или скалярное произведение). На этом стоит вся глава 10.1. Но наивная реализация — «прогнать нейросеть на паре (запрос, документ) для каждого из миллиардов документов» — невозможна по стоимости. Поэтому в сквозном конвейере «обход → индекс → факторы → ранжирование → выдача → постобработка → измерение» нейропоиск распадается надвое. Документные эмбеддинги вычисляются офлайн, при индексации, и материализуются прямо в индекс (глава 10.2, прямая связь с Модулем 4): это самая дорогая часть, и она делается один раз на документ. Близость запроса к документам считается в рантайме (глава 10.3, связь с каскадом ранжирования Модуля 12): запрос пришёл — мы кодируем только его и ищем ближайшие векторы. Это и есть центральная инженерная идея модуля, которой посвящена глава 10.4: «половина скалярного произведения» — документную половину считаем заранее, запросную и само произведение — на лету.

После модуля вы сможете: объяснить разницу между bi-encoder (две независимые башни, dual-tower) и cross-encoder (запрос и документ кодируются совместно) и понять, почему первый годится для индекса, а второй — только для переранжирования горстки кандидатов; устроить приближённый поиск ближайших соседей (ANN) структурами HNSW и IVF/PQ, чтобы не сравнивать запрос со всеми векторами; применить дистилляцию (distillation) — перенос «знания» тяжёлого cross-encoder в лёгкий bi-encoder; и спроектировать гибридный поиск, где лексический сигнал (BM25) и векторный объединяются в один ранжированный список.
Интуиция. Лексический поиск спрашивает: «встречаются ли в документе те же слова, что в запросе?» Нейропоиск спрашивает: «находится ли документ в той же области смысла, что и запрос?» Первый точен на редких терминах и опечатках-как-есть, второй силён на перефразировках и синонимии. Поэтому в проде их почти всегда комбинируют, а не противопоставляют.
Внимание. Нейропоиск не отменяет BM25. На точных совпадениях, артикулах, кодах ошибок, именах собственных и редких терминах лексика часто бьёт вектора, потому что эмбеддинг «размывает» точные строки. Грамотная система — гибрид, а не замена.
Как читать по трекам
  • Студент CS — обязательно всё. Ядро — 10.1 (архитектуры энкодеров) и 10.2 (геометрия ANN, HNSW, IVF/PQ). Прорешайте обе лабы. Глава 10.4 — концептуальный стержень, его надо понять до конца.
  • Инженер поиска/ML — обязательно всё. Особое внимание — инженерным заметкам про материализацию эмбеддингов в индекс (связь с Модулем 4), про параметры HNSW (M, efSearch) и IVF/PQ (nlist, nprobe, число суб-квантизаторов), про переиндексацию при смене модели и про место ANN в каскаде L0–L1 (Модуль 12).
  • SEO-специалист — обязательно SEO-врезки во всех главах. Главное к усвоению: вектора ранжируют по смыслу, поэтому переспам ключевыми словами теряет силу, а ясная, тематически связная подача текста — выигрывает. Формулы и устройство ANN — обзорно.
  • Смешанный/руководитель — Обзор, интуиции, заблуждения, глава 10.4 целиком и Итоги. Запомните принцип «документ кодируем офлайн, близость — онлайн» и идею гибрида.
Карта модуля
  • 10.1. Эмбеддинги документов и запросов; bi-encoder vs cross-encoder; dual-tower (продвинутый)
  • 10.2. Офлайн-эмбеддинги документа при индексации; ANN-поиск, HNSW, IVF/PQ (продвинутый)
  • 10.3. Рантайм-близость query↔doc; дистилляция тяжёлых моделей в лёгкие (продвинутый)
  • 10.4. «Половина скалярного произведения»: что считать офлайн (документ), что онлайн (близость) (средний)
Глава 10.1. Эмбеддинги документов и запросов; bi-encoder vs cross-encoder; dual-tower (продвинутый)

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

После главы студент сможет:
  • Объяснить, что такое плотный эмбеддинг текста и чем он отличается от разреженного tf-idf/BM25-представления.
  • Сформулировать, как близость в векторном пространстве (косинус / скалярное произведение) выражает семантическую релевантность.
  • Сравнить bi-encoder (dual-tower) и cross-encoder по архитектуре, выразительности и вычислительной стоимости.
  • Обосновать, почему только bi-encoder допускает офлайн-индексацию документов, а cross-encoder применим лишь к переранжированию кандидатов.
  • Объяснить, как обучают bi-encoder контрастной функцией потерь с негативами.
Конспект

Что такое эмбеддинг

Эмбеддинг (embedding) текста — это отображение E: текст → R^d, переводящее произвольный фрагмент (запрос, абзац, документ) в плотный вектор фиксированной длины d (типично d ∈ {256, 384, 768, 1024}). Сеть-энкодер обучается так, чтобы семантически близкие тексты давали близкие векторы, а далёкие — далёкие. Близость измеряют скалярным произведением или косинусом:

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

cos(q, d) = (q · d) / (|q| · |d|)
Если векторы предварительно нормированы к единичной длине (|q| = |d| = 1), то cos(q, d) = q · d — косинус и скалярное произведение совпадают. Это удобно: вся релевантность сводится к одному скалярному произведению, на котором стоит весь дальнейший модуль.
Интуиция. tf-idf/BM25 представляют документ разреженным вектором размером со словарь (миллионы измерений, почти все нули): измерение = слово. Два текста близки, только если делят буквально одни и те же слова. Эмбеддинг — плотный вектор из сотен чисел, где измерения — это абстрактные «направления смысла», а не конкретные слова. Поэтому «простуда» и «ОРВИ» оказываются рядом, хотя в лексическом пространстве они ортогональны.
Пример. Запрос «недорогой отель у моря». Документ A: «бюджетная гостиница на первой береговой линии». Документ B: «дорогая яхта в открытом океане». Лексически A почти не пересекается с запросом (другие слова), B делит «море/океан»-окрестность. В пространстве эмбеддингов A окажется ближе к запросу: «недорогой ≈ бюджетная», «отель ≈ гостиница», «у моря ≈ береговая линия» — все эти пары близки по смыслу, а «дорогая яхта» уезжает в сторону.
Как из токенов получается один вектор

Современный энкодер — это трансформер (базовые понятия про эмбеддинги слов и self-attention предполагаются известными). Он принимает последовательность токенов и выдаёт по вектору на каждый токен (контекстные представления). Чтобы получить один вектор на весь текст, применяют пулинг (pooling):
  • CLS-пулинг — берут представление специального служебного токена, который сеть учится использовать как «сводку».
  • Mean-пулинг (усреднение) — усредняют токенные векторы; на практике часто устойчивее.
Результат — единый вектор текста. Он и есть эмбеддинг запроса или документа.

Две архитектуры: bi-encoder и cross-encoder

Есть принципиально разные способы получить оценку релевантности пары (запрос q, документ d) нейросетью.

Cross-encoder (совместное кодирование). Запрос и документ склеивают в один вход [q || d] и прогоняют через трансформер целиком. Self-attention позволяет каждому слову запроса «смотреть» на каждое слово документа на всех слоях — это богатейшее взаимодействие. На выходе — одно число: оценка релевантности.

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

   q ──┐
       ├──►  [ один трансформер: q⇄d взаимодействуют ]  ──►  score(q,d)
   d ──┘
Bi-encoder / dual-tower (раздельное кодирование). Запрос и документ кодируются двумя независимыми проходами (часто весами одной и той же сети — «сиамская» схема, либо двумя разными «башнями»). Получаем два вектора, релевантность — их скалярное произведение:

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

   q ──►  [ энкодер-запрос ]  ──►  vec(q) ─┐
                                            ├──►  score = vec(q) · vec(d)
   d ──►  [ энкодер-документ ] ──►  vec(d) ─┘
Отсюда термин dual-tower (две башни): две параллельные ветви, которые встречаются только в самом конце, в дешёвом скалярном произведении.
Интуиция. Cross-encoder читает запрос и документ вместе, как экзаменатор, держащий перед глазами и вопрос, и ответ — и оттого точен. Bi-encoder читает их по отдельности и сводит каждый к точке-«адресу» в пространстве смыслов; сравнение адресов дёшево, но информации в одной точке меньше, чем в совместном чтении.
Почему архитектура решает всё для индексации

Это — главный водораздел модуля. Сравним стоимость поиска по корпусу из N документов.

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

Свойство                            |  Cross-encoder                      |  Bi-encoder (dual-tower)
------------------------------------+-------------------------------------+----------------------------------
Кодирование                         |  совместное [q‖d]                   |  раздельное q и d
Взаимодействие q⇄d                  |  глубокое, на всех слоях            |  только финальное q·d
Точность (качество)                 |  выше                               |  ниже
Можно ли посчитать vec(d) заранее?  |  нет — нужен q                      |  да — d не зависит от q
Прогонов сети на запрос             |  N (по разу на каждый документ)     |  1 (только сам запрос)
Где применим                        |  переранжирование топ-K кандидатов  |  первичный отбор по всему индексу
Решающая строка — «можно ли посчитать vec(d) заранее». У cross-encoder вектор документа не существует в отрыве от запроса: вход — это склейка, и менять её надо при каждом новом q. Значит, на каждый запрос пришлось бы прогнать тяжёлую сеть N раз (миллиарды раз) — неприемлемо.

У bi-encoder vec(d) зависит только от документа. Поэтому его можно вычислить один раз при индексации и положить в индекс (глава 10.2). В рантайме на запрос — ровно один прогон сети (кодируем q) плюс дешёвые скалярные произведения. Это и есть «половина скалярного произведения» из главы 10.4.
Инженерная заметка. На практике их совмещают в каскаде (Модуль 12): bi-encoder + ANN дёшево достаёт топ-K кандидатов (скажем, 1000) из всего индекса (этап L0–L1), затем cross-encoder, который дорог, но точен, переранжирует только эти K на верхних уровнях (L2–L3). Получаем и охват, и точность. Cross-encoder никогда не запускают по всему корпусу.
Как обучают bi-encoder: контрастная потеря и негативы

Bi-encoder надо научить тянуть релевантные пары (q, d⁺) ближе, а нерелевантные (q, d⁻) — дальше. Стандартный приём — контрастная функция потерь (contrastive loss), частный случай — InfoNCE / softmax по списку кандидатов:

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

L = − log  exp(q·d⁺ / τ)
          ────────────────────────────────
          exp(q·d⁺/τ) + Σ_j exp(q·d⁻_j / τ)
где τ — температура. Качество модели критически зависит от негативов:
  • Случайные (in-batch) негативы — другие документы из того же батча; дёшево, но слишком «лёгкие».
  • Жёсткие негативы (hard negatives) — документы, которые лексически или поверхностно похожи на релевантный, но на деле нерелевантны. Их часто добывают самим BM25 или предыдущей версией модели. Именно жёсткие негативы учат модель тонким различиям.
Внимание. Bi-encoder, обученный только на случайных негативах, в проде «всплывает мусором» — документами, которые «вообще про ту же тему», но не отвечают на запрос. Грамотный майнинг жёстких негативов — половина успеха.
SEO-врезка. Поскольку релевантность считается по смыслу всего фрагмента, а не по плотности ключа, выигрывает текст с ясной, связной формулировкой темы и явными ответами на типичные формулировки запроса. Перечисление синонимов «для роботов» теряет смысл: близкие по смыслу слова и так лягут рядом в пространстве, а несвязный «винегрет» из ключей даёт «размазанный» эмбеддинг, далёкий от любого конкретного запроса.
Частые заблуждения
Заблуждение. «Эмбеддинги поняли смысл, лексический поиск больше не нужен.» Нет. На точных строках (артикулы WX-7740, коды, имена, редкие термины) эмбеддинг усредняет и теряет точность, а BM25 попадает точно. Прод почти всегда гибрид (глава 10.3).
Заблуждение. «Bi-encoder и cross-encoder — это просто две реализации одного и того же.» Нет: разница архитектурная и определяет всё. Только bi-encoder даёт офлайн-вектор документа и потому масштабируется на весь индекс; cross-encoder — лишь финальный переранжировщик горстки кандидатов.
Заблуждение. «Больше размерность вектора — всегда лучше.» Нет: рост d увеличивает память индекса и стоимость ANN линейно, а прирост качества выходит на плато. Размерность — компромисс «качество ↔ стоимость», а не «чем больше, тем лучше».
Лаба / практика

Цель: на пальцах ощутить разницу bi- vs cross-encoder и роль негативов. Время ~60 мин.
  1. Возьмите готовую предобученную модель-bi-encoder (любая открытая sentence-эмбеддинг-модель) и мини-корпус из 20–30 коротких документов на 3–4 темы, где есть перефразировки (запрос и релевантный документ почти не делят слов).
  2. Закодируйте все документы (vec(d)), нормируйте к единичной длине. Для 5 запросов закодируйте vec(q) и отсортируйте документы по q·d.
  3. Параллельно посчитайте BM25 (из Модуля 6) на тех же запросах. Сравните топ-3 двух методов на запросах-перефразировках и на запросе с редким точным термином/кодом.
  4. (Если есть cross-encoder) переранжируйте топ-10 bi-encoder’а cross-encoder’ом и сравните порядок.
Ожидаемый результат: на перефразировках вектора находят релевантный документ, который BM25 пропускает; на точном редком термине BM25 точнее. Cross-encoder улучшает порядок в топе.

Критерий «сделано»: для каждого запроса выписано, какой метод выиграл и почему (синонимия vs точное совпадение); объяснено, почему cross-encoder нельзя было применить ко всему корпусу сразу.

Контрольные вопросы
  1. Чем плотный эмбеддинг принципиально отличается от разреженного tf-idf-вектора? Какое измерение что означает в каждом случае?
  2. Почему при нормировке к единичной длине косинус равен скалярному произведению?
  3. Опишите, как из последовательности токенных векторов получают один вектор текста. Что такое CLS- и mean-пулинг?
  4. Сформулируйте, почему vec(d) можно посчитать офлайн для bi-encoder, но нельзя — для cross-encoder.
  5. Сколько прогонов тяжёлой сети на один запрос требует cross-encoder при поиске по N документам, а сколько — bi-encoder? Почему?
  6. Что такое жёсткие негативы и зачем они нужны при обучении bi-encoder?
  7. Почему в проде bi- и cross-encoder обычно сочетают в каскаде, а не выбирают один?
  8. Приведите пример запроса, на котором BM25 побьёт чистый векторный поиск, и объясните механизм.
Глава 10.2. Офлайн-эмбеддинги документа при индексации; ANN-поиск, HNSW, IVF/PQ (продвинутый)

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

После главы студент сможет:
  • Объяснить, как и когда документные эмбеддинги вычисляются и материализуются в индекс (связь с Модулем 4).
  • Сформулировать задачу поиска ближайших соседей (k-NN) и объяснить, почему точный перебор не масштабируется.
  • Описать идею приближённого поиска (ANN) и компромисс «полнота ↔ скорость ↔ память».
  • Объяснить устройство HNSW (графовый индекс) и роль параметров M и efSearch.
  • Объяснить устройство IVF (инвертированные ячейки) и PQ (product quantization), роль nlist, nprobe и сжатия.
Конспект

Документный эмбеддинг живёт в индексе

Из главы 10.1: vec(d) зависит только от документа. Поэтому его место — в этапе индексации (Модуль 4), рядом с обратным индексом. Конвейер документа дополняется шагом:

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

обход → нормализация/каноникализация → разбиение на токены/поля
      → построение постингов (обратный индекс, Модуль 4)
      → ЭНКОДЕР bi-encoder: текст документа → vec(d) ∈ R^d   ◄── НОВЫЙ ШАГ
      → запись vec(d) в векторный индекс (ANN-структуру)
Инженерная заметка. Документ часто длиннее окна энкодера. Стандартно его режут на пассажи (passages) — абзацы/окна по N токенов — и кодируют каждый. Тогда «единица поиска» — пассаж, а скор документа агрегируется по его пассажам (например, max по пассажам). Это удваивает важность разбиения: один документ → много векторов в индексе.
Внимание. Векторный индекс привязан к конкретной модели-энкодеру. Векторы разных версий модели несопоставимы (живут в разных пространствах). Поэтому смена модели = полная переиндексация всех документов (заново прогнать энкодер на всём корпусе) — дорогая операция, которую планируют заранее. Это прямое продолжение темы перестроения индекса из Модуля 4.
SEO-врезка. Поскольку индексируется именно текст пассажей, важно, чтобы каждый смысловой блок страницы был самодостаточен: пассаж, выдранный из контекста, должен оставаться понятным. Контент, смысл которого «размазан» по странице и зависит от соседних блоков, даёт слабые пассажные эмбеддинги.
Задача: ближайшие соседи и почему перебор не работает

Запрос закодирован в vec(q). Нужно найти k документов с наибольшим q·d (ближайших соседей, k-NN). Наивно — посчитать q·d для всех N векторов и взять топ-k. Стоимость — O(N·d) на запрос.
Пример. N = 10⁹ векторов, d = 768, float32. Один запрос — это ~7.7·10¹¹ умножений-сложений. Даже на быстром железе это сотни миллисекунд–секунды на запрос и терабайты памяти под векторы (10⁹·768·4 ≈ 3 ТБ). При тысячах запросов в секунду — невозможно. Нужен индекс по векторам.
ANN: приближённый поиск ближайших соседей

ANN (Approximate Nearest Neighbors) жертвует точностью ради скорости: возвращает «почти ближайших» соседей, не перебирая всё. Ключевая метрика качества — recall@k: какая доля истинных k ближайших соседей реально найдена. ANN — это треугольник компромиссов:

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

        скорость (QPS / латентность)
              /\
             /  \
            /    \
   полнота /______\ память
   (recall@k)      (размер индекса)
Параметрами структуры мы двигаемся внутри этого треугольника. Два главных семейства — графовые (HNSW) и на основе ячеек + квантизации (IVF/PQ).

HNSW — иерархический навигируемый граф малого мира

HNSW (Hierarchical Navigable Small World) строит над векторами многослойный граф: вершины — векторы документов, рёбра соединяют близкие вершины. Слоёв несколько: верхние — разреженные (дальние «магистральные» прыжки), нижние — плотные (точная навигация). Поиск — это жадный спуск:

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

  слой 2 (редкий):   o───────────o          вход сверху, большие прыжки
                      \          /
  слой 1:         o────o───o────o───o        прыжки поменьше
                  |    |   |    |   |
  слой 0 (все):  o─o─o─o─o─o─o─o─o─o─o        точная окрестность
Старт — с верхнего слоя; на каждом слое жадно переходим к соседу, наиболее близкому к q, пока не упрёмся в локальный минимум, затем спускаемся слоем ниже. На нижнем слое собираем кандидатов.

Параметры:
  • M — число рёбер на вершину (степень графа). Больше M → плотнее граф → выше recall, но больше памяти и дольше построение.
  • efConstruction — ширина поиска при построении графа (качество рёбер).
  • efSearch — ширина «фронта» поиска в рантайме (сколько кандидатов держим в очереди). Больше efSearch → выше recall, но медленнее. Это главный рантайм-рычаг «recall ↔ латентность».
Интуиция. HNSW — как авиаперелёт с пересадками: сначала дальний рейс между хабами (верхний слой), потом региональный, потом местный автобус (слой 0). Не объезжаешь все города — прыгаешь по уменьшающимся масштабам к цели.
Инженерная заметка. HNSW даёт отличный recall при низкой латентности, но хранит полные векторы в памяти (граф + float32-векторы) — это дорого по RAM на больших N. Вставка новых точек поддерживается, но массовое удаление/обновление графа неудобно — ещё один аргумент за периодическую полную переиндексацию.
IVF — инвертированные ячейки (грубая кластеризация)

IVF (Inverted File) сначала кластеризует все векторы на nlist ячеек (например, k-means; центр ячейки — центроид). Каждый документ приписан к ближайшему центроиду. Поиск:
  1. Сравнить q только с nlist центроидами (дёшево).
  2. Выбрать nprobe ближайших ячеек.
  3. Перебрать векторы только внутри этих ячеек.
Вместо N сравнений — примерно nlist + (nprobe/nlist)·N. Параметры:
  • nlist — число ячеек (грубость разбиения).
  • nprobe — сколько ячеек просматриваем на запрос. nprobe = 1 — быстро, но можно промахнуться мимо ячейки с истинным соседом (низкий recall); больше nprobe → выше recall, но медленнее.
Внимание. Главный риск IVF — граничный эффект: истинный сосед лежит в соседней ячейке, которую мы не просмотрели. Лечится ростом nprobe. Это прямой аналог компромисса efSearch в HNSW.
PQ — product quantization (сжатие векторов)

IVF сокращает число сравнений, но каждый вектор всё ещё d чисел по 4 байта. PQ (Product Quantization) сжимает сам вектор: делит его на m подвекторов, в каждом подпространстве обучает маленький кодбук (например, 256 центроидов = 1 байт) и заменяет подвектор номером ближайшего центроида.

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

исходный вектор (d=768, float32 = 3072 байт)
  │  делим на m=96 подвекторов по 8 чисел
  ▼
[c1][c2]...[c96]   каждый ci — 1 байт (номер из 256)  →  96 байт
сжатие ≈ в 32 раза
Скалярное произведение приближённо считают по предвычисленным таблицам расстояний до центроидов — быстро и без распаковки. PQ обычно ставят поверх IVF (схема IVF-PQ): IVF сужает зону поиска, PQ делает векторы компактными.
Инженерная заметка. IVF-PQ — выбор для очень больших корпусов, где полные векторы не влезают в RAM: сжатие в десятки раз делает индекс на диске/в памяти реалистичным ценой небольшой потери recall. HNSW — выбор, когда RAM позволяет и нужен максимальный recall при низкой латентности. Часто их комбинируют: HNSW поверх PQ-сжатых векторов.

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

                      |  HNSW                                |  IVF                          |  IVF-PQ
----------------------+--------------------------------------+-------------------------------+-----------------------------------
Идея                  |  граф близости                       |  кластеры-ячейки              |  ячейки + сжатие векторов
Что сокращает         |  число обходимых вершин              |  число сравниваемых векторов  |  + размер каждого вектора
Память                |  высокая (полные векторы в RAM)      |  средняя                      |  низкая (сжатие)
Главный рычаг recall  |  efSearch (M)                        |  nprobe (nlist)               |  nprobe + параметры PQ
Когда выбирать        |  RAM есть, нужен max recall/latency  |  большой корпус               |  гигантский корпус, RAM в дефиците
Частые заблуждения
Заблуждение. «ANN находит точно тех же соседей, что перебор, только быстрее.» Нет: ANN приближённый — он может пропустить истинного соседа. Качество меряют recall@k и сознательно крутят его параметрами против скорости/памяти.
Заблуждение. «Раз есть векторный индекс, обратный индекс (Модуль 4) больше не нужен.» Нет: они сосуществуют. Лексический (обратный) индекс нужен для гибрида, точных совпадений и фильтров; векторный — для семантики (глава 10.3).
Заблуждение. «Можно дообучить/заменить модель и индекс продолжит работать.» Нет: новые векторы несопоставимы со старыми. Смена энкодера требует полной переиндексации корпуса.
Лаба / практика

Цель: прочувствовать компромисс recall ↔ скорость в ANN. Время ~70 мин.
  1. Возьмите 50–100 тыс. эмбеддингов (готовый датасет или сгенерируйте энкодером из лабы 10.1).
  2. Постройте эталон: для 100 случайных запросов найдите истинных 10 ближайших соседей полным перебором (q·d по всем).
  3. Постройте HNSW-индекс. Прогоните те же запросы при efSearch ∈ {16, 64, 256}. Для каждого значения замерьте recall@10 (доля совпадения с эталоном) и среднюю латентность.
  4. Постройте IVF (или IVF-PQ) с фиксированным nlist, варьируйте nprobe ∈ {1, 8, 32}. Замерьте те же метрики.
  5. Постройте таблицу/график recall@10 vs латентность для обоих индексов.
Ожидаемый результат: монотонные кривые — рост efSearch/nprobe поднимает recall и латентность; IVF-PQ экономит память ценой recall.

Критерий «сделано»: для каждого индекса выбрана рабочая точка (recall@10 ≥ 0.95 при минимальной латентности) и объяснено, какой параметр за что отвечает.

Контрольные вопросы
  1. На каком этапе конвейера и почему именно там вычисляется vec(d)? Где он хранится?
  2. Зачем длинные документы режут на пассажи и как тогда считают скор документа?
  3. Почему смена модели-энкодера требует полной переиндексации?
  4. Оцените стоимость точного k-NN перебором для N=10⁹, d=768 и объясните, почему он нежизнеспособен.
  5. Что измеряет recall@k и почему он — главная метрика качества ANN?
  6. Опишите жадный спуск в HNSW. За что отвечают M и efSearch?
  7. Как работает IVF? Что такое граничный эффект и как nprobe на него влияет?
  8. Зачем нужен PQ поверх IVF и какой ресурс он экономит? Чем платим?
  9. Когда вы предпочтёте HNSW, а когда IVF-PQ? Сформулируйте через треугольник компромиссов.
Глава 10.3. Рантайм-близость query↔doc; дистилляция тяжёлых моделей в лёгкие (продвинутый)

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

После главы студент сможет:
  • Описать рантайм-путь запроса: кодирование q → ANN-поиск → (опц.) переранжирование cross-encoder’ом.
  • Объяснить, где в каскаде ранжирования (Модуль 12) живут векторный отбор и нейропереранжирование.
  • Спроектировать гибридный поиск: объединение лексического (BM25) и векторного списков (взвешивание скоров, RRF).
  • Объяснить дистилляцию (distillation): перенос знания тяжёлого cross-encoder-«учителя» в лёгкий bi-encoder-«ученика».
  • Обосновать, зачем нужна дистилляция: качество cross-encoder при стоимости bi-encoder.
Конспект

Рантайм-путь запроса

При индексации (глава 10.2) вся тяжёлая работа над документами уже сделана. В рантайме на запрос остаётся:

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

запрос q
  │  1. ЭНКОДЕР bi-encoder: q → vec(q)        (ОДИН прогон сети)
  ▼
  2. ANN-поиск по векторному индексу         (HNSW / IVF-PQ)
  │     → топ-K кандидатов по близости q·d
  ▼
  3. (параллельно) BM25 по обратному индексу → топ-K' лексических кандидатов
  ▼
  4. СЛИЯНИЕ списков (гибрид)                  → объединённые кандидаты
  ▼
  5. (опц.) ПЕРЕРАНЖИРОВАНИЕ cross-encoder’ом топ-K''  (точно, но дорого)
  ▼
  6. постранжирование, выдача (Модули 16, 12–13)
Инженерная заметка. Это и есть каскад ранжирования Модуля 12. Дешёвый и широкий векторный/лексический отбор — нижние уровни L0–L1 (тысячи кандидатов). Дорогой cross-encoder работает на L2–L3 только над десятками–сотнями выживших. Стоимость сети распределена: офлайн — документы (один раз), онлайн — только запрос (один прогон) + переранжирование горстки.
Гибридный поиск: лексика + вектора

Из глав 10.1–10.2: лексика точна на словах, вектора — на смысле. Гибридный поиск (hybrid search) объединяет оба сигнала, чтобы взять сильные стороны каждого. Два кандидата дают два списка; их надо слить. Два основных способа:

1. Линейная комбинация скоров. Нормируем оба скора и складываем с весом:

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

score_hybrid(d) = α · score_BM25(d) + (1 − α) · score_vec(d)
Проблема: BM25 и косинус живут в разных шкалах, их надо нормировать (min-max или z-score) перед сложением, иначе один сигнал задавит другой. Вес α подбирают по метрикам (Модуль 19).

2. Reciprocal Rank Fusion (RRF). Слияние по рангам, а не по скорам — устойчиво к несопоставимым шкалам:

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

score_RRF(d) = Σ_списки  1 / (k + rank_список(d)),   k ≈ 60
Документ, высоко стоящий в любом из списков, получает большой вклад; шкалы скоров вообще не участвуют. RRF прост и удивительно силён.
Интуиция. Гибрид — это «второе мнение». Если документ в топе и у лексики, и у векторов — он почти наверняка релевантен. Если только у одного — это либо точное совпадение по редкому слову (лексика), либо перефразировка (вектора); оба случая ценны, и RRF их не теряет.
Пример. Запрос «ошибка E-204 при оплате». BM25 точно цепляет страницу с кодом E-204 (вектор бы «размыл» код). Векторный поиск находит страницу «сбой транзакции на этапе платежа» без кода, но по смыслу. Гибрид (RRF) выдаёт обе наверх; чистый вектор потерял бы первую, чистая лексика — вторую.
SEO-врезка. Гибрид означает: побеждает контент, который и содержит точные термины запроса (для лексики), и связно раскрывает их смысл (для векторов). Ставка только на «нашпиговать ключи» проигрывает векторной половине; ставка только на «лить воду вокруг темы» без точных формулировок проигрывает лексической. Нужно и то, и другое.
Дистилляция: качество учителя при стоимости ученика

Дилемма модуля: cross-encoder точнее, bi-encoder дешевле и индексируем. Хочется качество первого при стоимости второго. Решение — дистилляция знаний (knowledge distillation).

Идея: тяжёлый, точный учитель (teacher) — обычно cross-encoder — размечает обучающие пары (q, d) своими оценками релевантности (мягкими, непрерывными). Лёгкий ученик (student) — bi-encoder — обучается воспроизводить оценки учителя, а не только бинарные метки «релевантно/нет».

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

   cross-encoder (учитель)  ──►  score_T(q,d)   ◄ богатый «мягкий» сигнал
                                   │
                                   ▼  ученик подгоняет q·d под score_T
   bi-encoder (ученик)      ──►  q·d ≈ score_T(q,d)
Интуиция. Бинарная метка говорит ученику только «да/нет». Учитель-cross-encoder говорит «этот релевантен на 0.9, тот на 0.6, а вон тот на 0.05» — градации, которые несут куда больше сигнала о том, что значит «более релевантно». Ученик впитывает эти градации и потому учится тоньше, чем на голых метках.
Эффект: дистиллированный bi-encoder заметно превосходит bi-encoder, обученный с нуля на бинарных метках, и приближается к учителю по качеству — сохраняя дешёвую офлайн-индексируемую архитектуру dual-tower. Поэтому дистилляция — стандартный приём прод-нейропоиска.
Инженерная заметка. Дистилляция часто идёт итеративно и в связке с майнингом жёстких негативов (глава 10.1): текущий ученик достаёт кандидатов → учитель их переоценивает → ученик дообучается на этих оценках → повторить. Каждый цикл подтягивает ученика ближе к учителю.
Заблуждение по ходу. «Дистилляция — это сжатие cross-encoder в меньший cross-encoder.» В контексте поиска ключевое — смена архитектуры: из неиндексируемого cross-encoder в индексируемый bi-encoder. Это не просто «уменьшить», а «переложить в форму, пригодную для офлайн-индекса».
Частые заблуждения
Заблуждение. «Гибрид — это просто запустить два поиска и показать оба.» Нет: суть в корректном слиянии. Складывать сырые BM25 и косинус нельзя (разные шкалы) — нужна нормировка или ранговое слияние (RRF).
Заблуждение. «Дистиллированный ученик так же хорош, как учитель.» Обычно нет — он приближается, но обычно чуть слабее. Ценность в том, что он дёшев и индексируем, тогда как учитель — нет.
Заблуждение. «Cross-encoder можно поставить первым уровнем, если железо мощное.» Нет: его стоимость растёт линейно с числом кандидатов, а первый уровень видит весь индекс. Cross-encoder — всегда переранжировщик горстки, не отборщик.
Лаба / практика

Цель: построить и оценить гибридный поиск. Время ~60 мин.
  1. На корпусе из лабы 10.1 получите для 10 запросов два ранжированных списка: BM25 (Модуль 6) и векторный (bi-encoder + поиск из 10.2).
  2. Слейте их RRF (k=60) и отдельно — линейной комбинацией с min-max-нормировкой при α ∈ {0.3, 0.5, 0.7}.
  3. Если есть размеченные релевантности (хотя бы вручную для 10 запросов) — посчитайте nDCG@10 (Модуль 19) для: чистого BM25, чистого вектора, RRF и линейного слияния.
  4. Найдите запросы, где гибрид строго лучше обоих одиночных методов, и объясните механизм (точный код vs перефразировка).
Ожидаемый результат: гибрид ≥ лучшего из одиночных на большинстве запросов; RRF устойчив без подбора шкалы; линейное слияние чувствительно к α и нормировке.

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

Контрольные вопросы
  1. Опишите рантайм-путь запроса по шагам. Сколько прогонов тяжёлой сети приходится на один запрос и почему так мало?
  2. Где в каскаде L0–L3 (Модуль 12) находятся векторный отбор и cross-encoder-переранжирование? Почему именно там?
  3. Почему нельзя просто сложить score_BM25 и cos(q,d)? Как это лечат?
  4. Объясните RRF. Почему он устойчив к разным шкалам скоров?
  5. Приведите запрос, на котором гибрид строго превосходит и чистую лексику, и чистый вектор.
  6. Что такое дистилляция в нейропоиске? Кто учитель, кто ученик и что именно перенимается?
  7. Почему «мягкие» оценки учителя информативнее бинарных меток релевантности?
  8. Почему в контексте поиска дистилляция — это смена архитектуры, а не просто уменьшение сети?
Глава 10.4. «Половина скалярного произведения»: что считать офлайн (документ), что онлайн (близость) (средний)

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

После главы студент сможет:
  • Сформулировать принцип «половины скалярного произведения»: документную часть — офлайн, запросную и само произведение — онлайн.
  • Объяснить, почему именно факторизуемость score = f(q) · g(d) делает нейропоиск масштабируемым.
  • Связать офлайн-часть с индексацией (Модуль 4), а онлайн-часть — с каскадом ранжирования (Модуль 12).
  • Распознавать, какие модели факторизуемы (bi-encoder), а какие нет (cross-encoder), и почему это определяет их место в системе.
Конспект

Это — концептуальный замок модуля, собирающий главы 10.1–10.3 в одну идею. Скалярное произведение score = vec(q) · vec(d) симметрично, но в инженерном смысле его две «половины» радикально разной стоимости и разного времени жизни.

Принцип факторизации

Релевантность bi-encoder факторизуется: её можно записать как произведение двух функций, каждая зависит только от своего аргумента:

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

score(q, d) = f(q) · g(d)
              └┬─┘   └┬─┘
          зависит    зависит
          только     только
          от запроса от документа
g(d) = vec(d) не содержит q — значит, считается до того, как любой запрос вообще появился, то есть при индексации, один раз на документ, на медленном «холодном» железе. f(q) = vec(q) не содержит d — значит, считается один раз на запрос, независимо от размера корпуса. Само произведение f(q)·g(d) — дешёвая арифметика, ускоренная ANN (глава 10.2).
Интуиция. Представьте магазин. Можно для каждого покупателя заново обмерять и описывать каждый товар (cross-encoder — пересчёт всего на каждый запрос). А можно один раз снабдить каждый товар «паспортом» — координатами на полке смыслов (g(d), офлайн), а когда приходит покупатель — описать только его потребность теми же координатами (f(q), онлайн) и подвести к ближайшей полке. Вторая схема и есть «половина скалярного произведения»: тяжёлую инвентаризацию делаем заранее, на запрос — лёгкое сопоставление.
Раскладка по времени и стоимости

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

Часть          |  Что это               |  Когда считается         |  Как часто          |  Стоимость на единицу      |  Модуль
---------------+------------------------+--------------------------+---------------------+----------------------------+--------
g(d) = vec(d)  |  вектор документа      |  офлайн, при индексации  |  1 раз на документ  |  дорого (тяжёлый энкодер)  |  4
хранение g(d)  |  векторный ANN-индекс  |  офлайн                  |  —                  |  память/диск               |  4
f(q) = vec(q)  |  вектор запроса        |  онлайн, на запрос       |  1 раз на запрос    |  дорого, но один прогон    |  12
f(q)·g(d)      |  близость              |  онлайн                  |  ANN по индексу     |  дёшево (+ANN)             |  12
Главная экономия — асимметрия частоты: документов миллиарды, и каждый кодируется единожды и заранее; запросов поток, но на каждый — ровно один прогон сети плюс ANN. Тяжёлая нейросеть никогда не запускается «корпус × запросы» раз.

Почему cross-encoder сюда не вписывается

У cross-encoder score(q,d) не факторизуется: [q‖d] идёт в сеть совместно, и q, d взаимодействуют на всех слоях. Нет такого g(d), которое можно посчитать без q. Поэтому:
  • его нельзя материализовать в индекс (нет офлайн-вектора документа);
  • его стоимость на запрос ∝ числу оцениваемых документов;
  • его место — только переранжирование уже отобранной горстки кандидатов (L2–L3).

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

ФАКТОРИЗУЕМ (bi-encoder):     score = f(q) · g(d)   → g(d) офлайн → индексируем → отбор по всему корпусу
НЕ ФАКТОРИЗУЕМ (cross-enc.):  score = h(q, d)        → нет g(d)    → не индексируем → только rerank топ-K
Внимание. Любой приём, который «подмешивает запрос в документную часть» (например, документный вектор, зависящий от запроса), ломает факторизацию и убивает офлайн-индексируемость. Если архитектуру тянет в сторону взаимодействия q⇄d на этапе документа — это уже cross-encoder со всеми его ограничениями на масштаб.
Инженерная заметка. Поздневзаимодействующие (late-interaction) модели — компромисс: документ хранят множеством токенных векторов (всё ещё офлайн, факторизация по токенам сохраняется), а взаимодействие с запросом — отложенное и дешёвое (max-sim по токенам в рантайме). Точнее одного-вектора bi-encoder, но дороже по памяти индекса. Это «полторы половины»: чуть больше онлайн-взаимодействия ценой большего офлайн-индекса.
SEO-врезка. Принцип объясняет, почему «обмануть на лету» нельзя: документная половина зафиксирована при индексации. Влиять можно только на то, что закодировано в g(d) — то есть на ясный, тематически сфокусированный смысл текста на момент индексации, а не на сиюминутную подгонку под конкретный запрос.
Частые заблуждения
Заблуждение. «Раз скалярное произведение симметрично, безразлично, что считать первым.» Математически — да; инженерно — нет. Документную половину считают офлайн один раз (её миллиарды), запросную — онлайн на каждый запрос. Асимметрия частоты и времени — весь смысл приёма.
Заблуждение. «Можно взять качество cross-encoder и просто закэшировать его выходы как векторы документов.» Нельзя: у cross-encoder нет документного вектора в отрыве от запроса — кэшировать нечего. Перенос его качества в индексируемую форму — это дистилляция в bi-encoder (глава 10.3), а не кэш.
Лаба / практика

Цель: измерить экономию от факторизации. Время ~40 мин.
  1. Возьмите корпус из 10 тыс. пассажей и 100 запросов. Реализуйте две схемы оценки близости.
  2. Схема A (факторизуемая, bi-encoder): один раз закодируйте все пассажи (g(d), засеките время — это «офлайн»). Затем на каждый запрос: один прогон f(q) + скалярные произведения. Засеките суммарное онлайн-время на 100 запросов и число прогонов сети.
  3. Схема B (имитация нефакторизуемой): запретите кэш g(d) — на каждый запрос пересчитывайте «совместное» представление каждой пары (можно сымитировать повторным прогоном энкодера на склейке для подвыборки пассажей, чтобы не ждать вечность). Экстраполируйте число прогонов на полный корпус.
  4. Сведите: число прогонов сети и время для A и B; во сколько раз A дешевле.
Ожидаемый результат: A — ≈ 10000 офлайн-прогонов + 100 онлайн; B — ≈ 100 × 10000 прогонов. Разница на порядки.

Критерий «сделано»: в отчёте явно показано, какая часть в A — офлайн, какая — онлайн, и сформулировано, почему B не масштабируется на реальный корпус.

Контрольные вопросы
  1. Запишите факторизацию score(q,d) = f(q)·g(d) и объясните, почему g(d) можно посчитать офлайн.
  2. Почему «половина скалярного произведения» даёт экономию именно за счёт асимметрии частоты документов и запросов?
  3. Заполните по памяти: что в нейропоиске считается офлайн (и в каком модуле живёт), что — онлайн (и в каком модуле).
  4. Почему cross-encoder не факторизуется и что из этого следует для его места в системе?
  5. Что произойдёт с масштабируемостью, если документный вектор сделать зависящим от запроса?
  6. Чем late-interaction-модели отличаются по балансу офлайн/онлайн от обычного bi-encoder?
  7. Почему нельзя «закэшировать» cross-encoder в виде документных векторов, и как тогда переносят его качество в индекс?
Итоги модуля
  1. Нейропоиск сопоставляет смыслы, а не строки — плотные эмбеддинги закрывают лексический разрыв (синонимия, перефразировки), где BM25 бессилен.
  2. Архитектура решает всё. Bi-encoder (dual-tower) кодирует запрос и документ раздельно и факторизуем → индексируем; cross-encoder кодирует их совместно, точнее, но не факторизуем → только переранжирование горстки кандидатов.
  3. Документные эмбеддинги материализуются в индекс при индексации (Модуль 4): vec(d) зависит только от документа, считается один раз офлайн; смена модели = полная переиндексация.
  4. Близость к запросу считается в рантайме (Модуль 12): на запрос — один прогон энкодера vec(q) + ANN-поиск; тяжёлая сеть никогда не гоняется «корпус × запросы» раз.
  5. Точный k-NN не масштабируется — нужен ANN. HNSW (графовый, max recall при наличии RAM; рычаг efSearch/M) и IVF/PQ (ячейки + сжатие, для гигантских корпусов; рычаг nprobe/nlist). Качество меряют recall@k в треугольнике «полнота ↔ скорость ↔ память».
  6. Гибридный поиск обязателен. Лексика точна на словах/кодах, вектора — на смысле; их сливают нормированной линейной комбинацией или ранговым RRF. Гибрид ≥ любого одиночного метода.
  7. Дистилляция даёт качество cross-encoder при стоимости bi-encoder: тяжёлый учитель размечает пары мягкими оценками, лёгкий индексируемый ученик их воспроизводит; часто итеративно с майнингом жёстких негативов.
  8. «Половина скалярного произведения» — стержень модуля: score = f(q)·g(d); документную половину g(d) считаем офлайн (Модуль 4), запросную f(q) и произведение — онлайн (Модуль 12). Вся масштабируемость нейропоиска — в этой факторизации.
Глоссарий модуля
  • Эмбеддинг (embedding) — плотный вектор фиксированной размерности, представляющий текст в пространстве смыслов; близкие по смыслу тексты дают близкие векторы.
  • Лексический разрыв (vocabulary mismatch) — несовпадение слов запроса и документа при совпадении смысла; главная проблема, которую решает нейропоиск.
  • Bi-encoder / dual-tower — архитектура с раздельным кодированием запроса и документа двумя башнями; релевантность = скалярное произведение векторов; факторизуема и индексируема.
  • Cross-encoder — архитектура с совместным кодированием склейки [q‖d]; точнее, но не факторизуема; применяется только для переранжирования.
  • Пулинг (pooling) — сведение токенных векторов в один вектор текста (CLS-пулинг, mean-пулинг).
  • Контрастная потеря (contrastive loss / InfoNCE) — функция обучения bi-encoder, тянущая релевантные пары ближе, нерелевантные — дальше.
  • Жёсткие негативы (hard negatives) — поверхностно похожие, но нерелевантные документы; учат модель тонким различиям.
  • k-NN / ANN — поиск k ближайших соседей; ANN (Approximate NN) — его приближённая, масштабируемая версия.
  • recall@k — доля истинных k ближайших соседей, найденных ANN; главная метрика качества ANN.
  • HNSW — иерархический навигируемый граф малого мира; графовый ANN-индекс; параметры M, efConstruction, efSearch.
  • IVF (inverted file) — ANN на кластерах-ячейках; параметры nlist (число ячеек), nprobe (просматриваемых ячеек).
  • PQ (product quantization) — сжатие вектора покусочным квантованием по кодбукам; экономит память; обычно поверх IVF (IVF-PQ).
  • Гибридный поиск (hybrid search) — объединение лексического (BM25) и векторного списков (нормированная линейная комбинация или RRF).
  • RRF (reciprocal rank fusion) — ранговое слияние списков, устойчивое к разным шкалам скоров.
  • Дистилляция (knowledge distillation) — перенос знания тяжёлого учителя (cross-encoder) в лёгкого ученика (bi-encoder) через мягкие оценки.
  • Факторизация score = f(q)·g(d) — представимость релевантности произведением функций запроса и документа порознь; основа офлайн-индексируемости.
  • Late interaction (позднее взаимодействие) — компромисс: документ хранится множеством токенных векторов (офлайн), взаимодействие с запросом отложено и дёшево (max-sim).
Связи с другими модулями
  • Опирается на: Модуль 1 (векторная модель, понятие близости и релевантности); Модуль 6 (BM25 как лексический базлайн и вторая половина гибрида); Модуль 9 (обучение ранжированию — связь с обучаемыми моделями релевантности).
  • Прямо продолжает: Модуль 4 (индексация) — документные эмбеддинги материализуются в векторный индекс рядом с обратным; переиндексация при смене модели.
  • Питает дальше: Модуль 12 (каскад ранжирования) — векторный/лексический отбор на L0–L1, cross-encoder-переранжирование на L2–L3; рантайм-кодирование запроса.
  • Тесно связан: Модуль 5 (понимание запроса — что именно кодировать в vec(q)); Модуль 16/13 (постранжирование и выдача — что происходит после нейроотбора); Модуль 19 (оценка качества: nDCG/recall@k, подбор α, efSearch, nprobe); Модуль 16 (антиспам — устойчивость векторных сигналов к манипуляциям); Модуль 20 (прикладное SEO под семантический и гибридный поиск).
Материалы для углубления
  • Классические работы по плотному поиску (dense retrieval) и архитектуре dual-tower / bi-encoder для первичного отбора.
  • Обзоры по cross-encoder-переранжированию и каскадным схемам «отбор → переранжирование».
  • Литература по приближённому поиску ближайших соседей: графовые методы (HNSW), инвертированные ячейки (IVF), квантизация векторов (PQ, IVF-PQ) — устройство, параметры, компромиссы recall/latency/memory.
  • Работы по обучению плотных энкодеров: контрастные функции потерь, майнинг жёстких негативов, дистилляция знания из cross-encoder в bi-encoder.
  • Исследования по гибридному поиску и слиянию ранжированных списков (нормировка скоров, reciprocal rank fusion).
  • Обзоры по late-interaction-моделям (многовекторное представление документа, max-sim) как компромиссу между bi- и cross-encoder.
👍3 ❤️5 🔥1 😄 🤔1
Аватара пользователя
petr3
Сообщения: 1
Зарегистрирован: 13 май 2026, 07:05

Re: Нейросетевой поиск (Neural IR)

Сообщение petr3 »

вопрос про пример с лечить простуду. dense retrieval через эмбеддинги ловит синонимы, но как у вас на практике с точными совпадениями типа номеров моделей и кодов ошибок? у меня чисто нейронный поиск как раз на таких запросах сливал bm25
👍2 ❤️ 🔥 😄 🤔1
Аватара пользователя
oralover
Сообщения: 1
Зарегистрирован: 13 май 2026, 16:53

Re: Нейросетевой поиск (Neural IR)

Сообщение oralover »

ага, вот почему гибрид bm25 плюс эмбеддинги работает лучше, чем каждый по отдельности. лексический ищет точное вхождение, а плотный добивает семантику, и их скоры потом сливаешь. по отдельности оба проседали на своих слабых местах
👍 ❤️ 🔥 😄 🤔
Аватара пользователя
esp32whale
Сообщения: 1
Зарегистрирован: 29 май 2026, 14:35

Re: Нейросетевой поиск (Neural IR)

Сообщение esp32whale »

мерил латентность: ann-индекс по эмбеддингам летает, но прогон кросс-энкодера на реранкинге топ-100 добавил под 200 мс. так что чистый сёрфейс-матч мы не выкинули, гоняем нейронку только на втором этапе
👍 ❤️2 🔥 😄 🤔
Ответить
← Предыдущая глава
Машинное обучение ранжированию (Learning-to-Rank)
Следующая глава →
Поведенческие сигналы и клик-модели

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

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

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

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

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