
Исторически в Яндекс Картинках релевантность документа оценивалась по двум сигналам: насколько запросу подходит само изображение и насколько — текст, связанный с этим изображением. Такой подход позволяет учесть контент картинки и не провалиться на визуально трудноотличимых объектах, однако он же порождает проблему: в «серой зоне», когда текстовая релевантность не сонаправлена с картиночной, становится неочевидно, как именно агрегировать сигналы в финальный скор релевантности.
Привет! Я Константин Николаев, занимаюсь внедрением нейротехнологий в Поиске по картинкам. В этой статье я расскажу, как наша команда научила модели смотреть на картинку и читать текст документа одновременно: начали с тяжёлой мультимодальной VLM ради максимального качества, а затем дистиллировали её в набор лёгких моделей — по одной под каждую стадию пайплайна. Что из этого удалось довести до realtime‑поиска с десятками тысяч запросов в секунду и как совместный анализ двух модальностей добавил 5% релевантных картинок в топ выдачи — под катом.
Стартовая точка: как устроено ранжирование картинок
Проводить dense‑поиск по всей базе для каждого запроса — слишком затратно. Поэтому наш пайплайн ранжирования устроен многоступенчато: на каждой стадии остаётся всё меньше документов, а модели и факторы, по которым работает ранжирование, становятся всё тяжелее:
Обратный индекс — из миллиардов документов отбираются сотни тысяч кандидатов.
Кандидатогенерация — лёгкие модели сужают выборку до нескольких тысяч документов.
Черновое ранжирование — модели среднего размера оценивают порядка тысячи документов.
Реранкинг — самая точная и самая дорогая стадия, на которой формируется финальная выдача (как правило, это около сотни изображений).
До недавнего времени релевантность на каждой из стадий оценивалась двумя типами факторов: «картинка — запрос» (i2t, image‑to‑text) и «текст документа — запрос» (t2t, text‑to‑text) (рассчитывается по текстам, атрибуцированным картинке, например прикартиночному тексту). Оба фактора были устроены как clip‑подобные модели: энкодер запроса, энкодер картинки или текста и скалярное произведение эмбеддингов между ними. Итоговая релевантность документа складывалась из этих и других факторов в общем ансамбле (бустинге). Может быть неочевидно, для чего именно нужен скор по текстовым полям. Но в ряде запросов необходимо учитывать текстовую модальность. Например, при поиске артикулов, моделей автомобилей или просто при поиске среди объектов, визуально очень похожих друг на друга.
Однако такая схема обработки запроса порождала ряд проблем. Например, мы хотим найти картинку с лемуром.

Как видно из примера, каждая комбинация модальностей приводит к разным, независимым друг от друга ошибкам. Ансамбль с трудом различает релевантные объекты в «серой зоне» — в случаях, когда предсказания t2t и i2t расходятся.
Для точного поиска на сложных примерах необходимо учитывать обе документные модальности — текстовую и картиночную. Далее расскажу, как именно мы этого достигли.
Архитектуры: от точной модели к продакшен‑варианту
В своих поисках мы шли от точности к скорости: сначала получили модель с максимально возможным качеством, а затем дистиллировали её в более лёгкие варианты для разных стадий ранжирования.
VLM — совместная модель
Первый вариант — и, возможно, самый очевидный — мультимодальная модель на основе VLM. Напомним, что устроена она так: изображение проходит через визуальный энкодер, а LLaVA‑адаптер переводит его в токены, понятные языковой модели. Эти токены объединяются с текстовыми полями документа и подаются в трансформерный декодер. На выходе вместо привычного для декодера текста мы снимаем одно число — скор релевантности.
Декодер здесь работает с каузальной маской: каждый токен видит только те токены, что идут до него. Для генерации текста это стандартный режим, и в первом варианте мы его не трогали.

Дальше попробовали приём, который часто встречается в статьях, — Chain‑of‑Thought, когда модель сначала «рассуждает» текстом и только потом выдаёт ответ. Обычно его комбинируют с дообучением на предпочтениях, вроде GRPO или DPO. Для нашей задачи рассуждения ничего не дали: качество предсказания релевантности не улучшилось. Так что в финальном варианте мы обошлись без них, но в другой задаче этот приём вполне может выстрелить.
vBERT — та же идея, но быстрее
VLM — это, по сути, генеративный декодер: каузальная (верхнетреугольная) маска запрещает каждому токену заглядывать в те токены, что идут после него. Для генерации текста это необходимо, но наша задача другая — предсказать один скор релевантности. Здесь токенам нечего «генерировать по порядку», и ограничивать их обзор незачем: пусть каждый видит сразу и картинку, и весь текст документа. Поэтому маску мы убрали и перешли к двунаправленному вниманию, как в энкодере. Такой подход применялся в целом ряде опенсорс‑работ: Llama‑Embed‑Nemotron, Qwen‑Embedding и многих других.
Заодно уменьшили и размер: параметров, типичных для VLM, для дискриминативной задачи (где на выходе всего одно число, а не текст) обычно избыточно много. Так получилась следующая модель:

В итоге vBERT показал хорошую точность. Однако несмотря на размеры (около миллиарда параметров), эта модель была всё ещё слишком медленной для realtime‑ранжирования. Так что мы продолжили поиски решения.
Лёгкие модели для продакшена
Следующим шагом стала дистилляция vBERT в несколько специализированных архитектур — каждая для своей стадии пайплайна.
Bi‑encoder — классическая двухбашенная модель. Документная башня обрабатывает изображение и текст документа совместно и сворачивает их в один эмбеддинг документа. Башня запроса независимо от этого строит эмбеддинг запроса.
Далее эти эмбеддинги агрегируются в финальный скор через небольшую MLP‑голову. В нашем случае в MLP попадает N dot‑product‑скоров между запросными эмбеддами и одним документным.
Идею смешивать скалярное произведение с явными признаками пары мы отчасти позаимствовали у моделей семейства DCN.

Embedder — упрощённый вариант bi‑encoder без дополнительных признаков и MLP‑головы. Здесь релевантность определяется чистым скалярным произведением эмбеддингов.

Такая простота — наше осознанное решение. Эмбеддинги можно заранее сложить в ANN‑индекс (HNSW) и искать по нему кандидатов почти мгновенно. А это то, что нужно для самой чувствительной к скорости стадии — кандидатогенерации.
Cross‑Encoder / Light Cross‑Encoder (LCE) — модель для финальной стадии, где документов уже немного, но требования к точности максимальны. В основе лежит идея «раннего связывания» (early binding): эмбеддинги документа и запроса вычисляются раздельно и кешируются, как в bi‑encoder, а затем поверх них работает лёгкий совместный трансформерный энкодер, который дополнительно учитывает текстовые признаки пары «запрос — документ» и формирует единый скор.

По качеству такая схема почти догоняет полноценный совместный энкодер, а на рантайме считается заметно дешевле. В момент запроса остаётся только лёгкое совместное дообъединение, поэтому и качество близко к совместному энкодеру, и стоимость почти как у bi‑encoder.
Режим обучения моделей
Большинство моделей — VLM, vBERT, bi‑encoder и Cross‑Encoder — мы обучали в pointwise‑режиме: где каждая пара «запрос — документ» размечается и оценивается сама по себе, без оглядки на остальные документы в батче.
Пробовали и pairwise‑режим, где модель учится не на отдельной паре, а на сравнении двух документов между собой. Однако значимого прироста он не дал.
Embedder — исключение, и это его главное отличие от bi‑encoder при почти одинаковой архитектуре. Его мы обучали на двух лоссах сразу: контрастивном и лоссе с hard negatives — намеренно подобранными «почти подходящими» документами, которые модель должна отличить от по‑настоящему релевантных.
В наших экспериментах оказалось, что такое обучение с явным противопоставлением негативам критично именно для Embedder.
Инференс в продакшене
Общий принцип для всех лёгких моделей один: документную часть рассчитываем в офлайне, остальное — в рантайме.

Офлайн. Эмбеддинги документов (изображение + текст) вычисляются заранее, независимо от запросов, и складываются в хранилище.
Рантайм с кешем. Эмбеддинг запроса считается один раз на запрос и кешируется — так мы не пересчитываем его для каждого документа.
Рантайм. Агрегация готовых эмбеддингов документа и запроса с небольшим набором дополнительных признаков. Это единственная часть вычислений, которая выполняется напрямую при обработке запроса, так что требования к её размеру намного строже.
Встраивание в существующий пайплайн
Новые модели не заменили старое ранжирование — они вошли в общий ансамбль как ещё один фактор, рядом с уже работающими i2t, t2t и другими сигналами.

В итоговой конфигурации модели распределились по стадиям пайплайна: чем раньше стадия и чем больше на ней документов, тем легче и быстрее модель, а чем ближе к финалу, тем она точнее и дороже.
Embedder — на кандидатогенерации. Векторы этой модели используются для построения HNSW‑индекса.
Bi‑encoder — на черновом ранжировании. Документов уже заметно меньше, но счёт всё ещё идёт на тысячи.
Light Cross Encoder (LCE) — на реранкинге. Финальная стадия, где решается судьба примерно сотни документов и точность важнее всего.

Результаты и выводы
Bi‑encoder на нижних стадиях ранжирования и Cross‑Encoder на финальной вместе добавили 4% релевантных изображений в топ выдачи. А с учётом всех внедрений, включая Embedder на кандидатогенерации, суммарный прирост релевантности в топе составил 5%.
Вернёмся к примеру с лемуром. Именно этого мы и добивались: модель смотрит на изображение и текст вместе и не принимает похожего зверька за настоящего лемура только потому, что в подписи есть нужное слово.
К каким выводам мы пришли:
Тяжёлые модели работают в realtime. Если аккуратно разделить вычисления на офлайн и онлайн и грамотно дистиллировать, даже сложную совместную архитектуру можно довести до продакшена с десятками тысяч запросов в секунду.
Открытые подходы — опорная точка, а не готовое решение. Индустриальные архитектуры удобно брать за основу, но почти всегда их приходится дообучать и упрощать под ограничения своей системы.
Непопулярность подхода не означает его неработоспособность. То, что архитектура непопулярна для конкретной задачи, не мешает ей давать прирост качества — если правильно её адаптировать.
Главное в этой работе — не новый фактор, а смена принципа. Раньше мы считали релевантность по изображению и по тексту порознь, а потом сводили оценки в ансамбле. Теперь модель анализирует обе модальности сразу — и именно это закрывает «серую зону», с которой мы начинали.
Путь от тяжёлой VLM до набора лёгких продакшен‑моделей, разведённых по стадиям ранжирования, показал, что совместную мультимодальную архитектуру реально довести до realtime без потери скорости. Остаётся только правильно разложить вычисления между офлайном и рантаймом — и высокое качество тяжёлой модели становится доступным на каждом запросе.

