Перейти к содержимому
09 окт. 2025 г.·8 мин чтения

Миграция на новую модель эмбеддингов: что проверить

Миграция на новую модель эмбеддингов требует проверки размерности, качества поиска, скорости, памяти и совместимости старых векторов.

Миграция на новую модель эмбеддингов: что проверить

Почему слепой реиндекс ломает результат

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

Пользователь ищет "условия возврата товара". Раньше в первых строках были правила возврата и сроки. После реиндекса первыми вдруг идут общие FAQ, потому что новая модель иначе оценивает близость фраз. Формально поиск работает. Для пользователя он стал хуже.

С порогами похожести та же история. Если раньше score выше 0.82 часто давал хороший матч, после смены модели этот порог уже ничего не гарантирует. Новая модель может давать более плотное или, наоборот, более разреженное распределение расстояний. В результате система либо пропускает лишние документы, либо отсекает полезные.

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

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

Обычно слепой реиндекс ломает результат по четырем причинам:

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

Поэтому переход на новую модель эмбеддингов - это не просто "пересчитать векторы и поехать дальше". Сначала проверьте, как новая модель меняет ранжирование, пороги и размер индекса именно на ваших данных. Иначе проблема всплывет уже в продакшене, когда пользователи начнут видеть странные ответы.

Что меняется вместе с моделью

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

Сначала проверьте размерность. Если старая модель давала 768 чисел, а новая 1024 или 3072, индекс, кэш и сетевой трафик вырастут. Даже при том же числе документов разница по памяти может быть заметной. Формат тоже важен: float32, float16, иногда квантизованный вариант. Это влияет и на цену хранения, и на скорость.

Метрика и нормализация

Дальше посмотрите на нормализацию. Одни модели выдают векторы, уже нормированные по длине, другие нет. Поэтому cosine и dot product могут давать разный порядок результатов на одном и том же наборе документов. Если база рассчитана под cosine, а новая модель лучше работает с dot, качество поиска может просесть без единой ошибки в коде.

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

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

Русский, казахский и смешанные данные

Если у вас база на русском, проверяйте русский отдельно, а не только общий средний балл. То же касается смешанных фрагментов вроде "доставка заказа", "refund", "SKU" и названий продуктов латиницей. Некоторые модели хорошо держат английский, но хуже понимают бытовой код-свитч.

Старые векторы почти никогда не стоит считать совместимыми по умолчанию. Даже если размерность совпала, пространство может быть другим. Тогда запрос, закодированный новой моделью, начнет хуже находить документы, закодированные старой.

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

Какие данные взять для проверки

Тестовый набор решает почти все. Если взять только чистые учебные примеры, новая модель покажет красивую среднюю оценку и провалится на живом трафике в первый же день.

Для проверки лучше собирать запросы из реального поиска, чата поддержки, RAG-логов и внутренних ассистентов. Часто хватает 100-300 запросов, если это настоящие случаи, а не фразы из презентации. Перед работой уберите персональные данные или замаскируйте их.

Хороший набор всегда немного неудобный. В нем должны быть не только аккуратные запросы вроде "условия возврата", но и короткие, шумные и редкие формулировки: "возврат", "не нашел акт", "тариф b2b архив", запросы с опечатками, аббревиатурами и смешением языков.

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

Такой разрез особенно полезен там, где в одном потоке живут бытовые вопросы и строгие формулировки из политики или договора. Для банков, телекома и госсектора это обычная ситуация.

До первого теста зафиксируйте эталон. Для каждого запроса отметьте, какие документы, чанки или ответы вы считаете правильными. Не обязательно выбирать один идеальный кусок текста. Часто честнее задать 2-3 допустимых результата, если они одинаково решают задачу.

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

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

Как проверить качество до реиндекса

До реиндекса сравните старую и новую модель на одном и том же замороженном наборе запросов и документов. Если одновременно менять корпус, чанки или фильтры, тест теряет смысл.

Сначала смотрите на попадания в top-k и MRR. Если релевантный документ чаще оказывается в top-3 или top-10, это хороший знак. MRR покажет, насколько высоко ответ поднимается в выдаче, а не просто попадает ли он туда вообще.

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

Полезно вручную разобрать 20-30 провалов. Обычно причина становится понятна быстро: модель хуже связывает синонимы и аббревиатуры, новый вектор тянет слишком общие тексты, фильтр по полю режет правильный результат, проблема сидит не в модели, а в чанкинге или метаданных, либо старая логика порога похожести больше не подходит.

Такой разбор часто полезнее, чем еще одна средняя метрика. Если 8 из 20 провалов связаны с одним типом документов, уже ясно, где править пайплайн.

Отдельно проверьте поиск с фильтрами и гибридным ранжированием. В чистом векторном поиске новая модель может выигрывать, а после фильтра по продукту, региону или дате терять нужные документы. То же касается схемы, где вы смешиваете BM25, векторы и rerank. Сравнивайте не только в лабораторных условиях, а в режиме, близком к боевому.

Для задач с порогом похожести нужны свои тесты. Дедупликация, матчинг карточек и алерты на похожие инциденты зависят не от места в top-k, а от конкретного порога. Если раньше дубликаты уверенно отсекались на 0.82, новая модель может сместить рабочую зону к 0.74 или 0.89. Тогда поиск выглядит нормальным, а бизнес-правила начинают ошибаться.

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

Как посчитать размер индекса и память

Проверьте миграцию на живом трафике
Меняйте модель и провайдера, не трогая SDK, код и промпты.

Начните с самой простой оценки: число векторов x размерность эмбеддингов x размер одного числа. Для float32 это 4 байта, для float16 - 2 байта, для int8 - 1 байт, если ваш движок вообще умеет хранить векторы в таком виде.

Пример: 10 млн векторов по 1024 измерения в float32 дадут 10 000 000 x 1024 x 4 = 40,96 ГБ сырого векторного слоя. Если новая модель увеличивает размерность с 768 до 1536, этот слой почти удвоится еще до учета накладных расходов.

На этом расчеты не заканчиваются. Индекс держит в памяти не только сами векторы. Поисковый граф, служебные поля, ID документов, фильтры и внутренние структуры часто добавляют еще 20-60% сверху. При агрессивных настройках HNSW может быть и больше.

Полезно считать отдельно четыре слоя:

  • сырые векторы;
  • память на структуру индекса;
  • метаданные и служебные поля;
  • реплики и запас под сборку.

Реплики меняют картину сильнее, чем кажется. Если один индекс занимает 55 ГБ, то с одной репликой это уже около 110 ГБ, без учета фоновых процессов, кэшей и памяти самого сервиса. Во время пересборки часто нужен еще один временный индекс, значит пиковое потребление может вырасти почти вдвое.

Потом сравните не только RAM, но и SSD. Часть движков активно читает индекс с диска, часть держит почти все в памяти, но в обоих случаях рост размерности обычно тянет за собой более долгую сборку и больше трафика между узлами. Если индекс раньше строился 3 часа, после смены модели он может собираться 6-8 часов просто из-за объема данных.

Финальная проверка очень простая: влезает ли новый индекс в текущие узлы без swap. Если память подходит только на бумаге, система начнет тормозить в самый неудобный момент. Лучше оставить запас хотя бы 20-30% под пики нагрузки, фоновые задачи и откат на старые векторы во время миграции.

Как замерить скорость на своей нагрузке

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

Сначала снимите p50 и p95 для двух случаев: один текст за запрос и пакетная отправка. Один запрос показывает базовую задержку. Пакеты показывают, что случится при ночной загрузке каталога, базы знаний или архива тикетов. Иногда модель быстро отвечает по одному документу, но резко проседает на батчах по 64 или 128 записей.

Обычно достаточно зафиксировать четыре цифры:

  • p50 и p95 для одиночного эмбеддинга;
  • p50 и p95 для пакетного эмбеддинга;
  • время полного реиндекса на всем объеме;
  • задержку поиска на холодном и теплом кэше.

Полный реиндекс лучше мерить не на выборке из 10 тысяч строк, а на полном массиве или хотя бы на крупном куске, где уже видны очереди, нагрузка на диск и лимиты провайдера. Маленький тест часто врет. На 1 миллионе документов вы можете уложиться в час, а на 40 миллионах внезапно упретесь в пропускную способность хранилища, а не в саму модель.

Поиск тоже проверяйте в двух режимах. Холодный кэш показывает, что увидит первый пользователь утром или после перезапуска. Теплый кэш показывает обычную рабочую картину. Разница между ними иногда больше, чем разница между двумя моделями.

Если вы сравниваете несколько моделей через один OpenAI-совместимый контур, проще оставить один и тот же клиентский код и честно менять только модель и провайдера. Для таких тестов удобно использовать единый шлюз вроде AI Router: вы не переписываете SDK и не смешиваете оценку модели с изменениями во всей обвязке.

Смотрите на скорость вместе с качеством поиска. Если новая модель дает ответ на 80 мс быстрее, но теряет 6 из 20 релевантных документов в топе, такой переход вряд ли окупится.

Что делать со старыми векторами

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

Нормальный путь - держать старый и новый индекс рядом хотя бы на время проверки. Тогда приложение может читать из нового индекса для части трафика, а старый оставить как страховку. Такой режим проще отладить, чем один большой реиндекс за ночь с надеждой, что утром все будет работать.

Если команда тестирует новую модель через AI Router, провайдера или модель удобно переключать на уровне API. Но для векторной базы это ничего не меняет: старые и новые векторы все равно нужно хранить отдельно, пока вы не увидите стабильную выдачу на реальных запросах.

С архивом и редко используемыми данными спешить не стоит. Часто хватает такого порядка:

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

Так вы не тратите дни на данные, которые почти никто не ищет, и быстрее получаете сигнал по качеству на живом трафике.

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

Я бы не закрывал откат, пока не выполняются два условия: метрики поиска держатся ровно и поддержка не видит новых жалоб от пользователей. Для многих команд это не 2 часа, а 1-2 недели.

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

Как провести миграцию по шагам

Сравните 500+ моделей
Проверяйте эмбеддинги от 68+ провайдеров на одном наборе запросов.

Полный переход редко начинается с полного реиндекса. Безопаснее взять небольшой, но живой срез данных: свежие документы, частые запросы, сложные формулировки, дубли и короткие тексты. Такой набор быстрее пересчитать и проще проверить вручную.

Рабочий порядок обычно такой:

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

Лучше всего работает параллельный прогон. Один и тот же запрос идет в оба индекса, а команда смотрит, какой документ попал выше, сколько времени занял поиск и не выросли ли расходы. Если новая модель чаще находит нужный фрагмент, но индекс стал вдвое больше, это уже не выглядит как автоматическая победа.

На практике удобно начать с 5% трафика, потом подняться до 20%, а затем до 50%. Порог отката стоит определить заранее. Например, если задержка выросла больше чем на 120 мс или доля удачных попаданий просела хотя бы на 2%, вы возвращаете старый маршрут без споров и срочных созвонов.

Для базы знаний это выглядит просто: у вас есть 10 000 статей, 300 частых запросов поддержки и старая схема чанкинга по 500 токенов. Вы строите второй индекс, гоняете на него те же запросы и сверяете top-5 результатов. Часто проблема сидит не в самой модели, а в том, что новый эмбеддинг лучше работает только при другом размере чанка или другой очистке текста.

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

Простой сценарий для базы знаний

У службы поддержки есть база из 50 тысяч статей на русском и казахском. Старый поиск честно цепляется за совпадения слов, но часто мимо смысла. Запрос вроде "не пришел код после смены номера" может поднять статьи про "код" и "номер", а не инструкцию по восстановлению доступа.

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

Как команда проверяет это без лишнего риска

Сначала команда берет 500 живых запросов из логов. Туда входят частые вопросы, редкие формулировки, русские и казахские запросы, а еще несколько тем, где пользователи чаще всего не находят ответ с первого раза.

Потом для каждого запроса смотрят top-5 результатов в старом и новом варианте. Оценка простая: ответ найден сразу, полезная статья есть, но не на первом месте, выдача уводит в сторону, или в первых пяти вообще нет нужного ответа.

Такой ручной просмотр занимает время, зато быстро показывает реальное качество поиска. На этом этапе сразу видно, помогает ли новая модель в живой базе, а не на аккуратном демо-наборе.

После проверки команда сводит три вещи: насколько выросло качество, сколько RAM съедает новый индекс и сколько времени займет пересчет. Если новая модель заметно поднимает сложные запросы, а рост памяти остается терпимым, полный реиндекс оправдан. Если выигрыш виден только на малой части запросов, а индекс сильно тяжелеет, лучше не спешить.

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

Частые ошибки перед запуском

Оставьте данные в Казахстане
Тестируйте 20+ open-weight моделей на локальной GPU-инфраструктуре в Казахстане.

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

Еще одна типичная проблема - менять не только модель, но и окружение вокруг нее. У новой модели может быть другая размерность, а вместе с ней часто меняются метрика поиска и настройки индекса. Если раньше у вас работал cosine, это не значит, что те же параметры дадут нормальное качество после перехода. HNSW, IVF и лимиты на кандидатов тоже стоит пересчитать, иначе вы сравните не модели, а случайный набор настроек.

Хуже всего выпускать в один релиз сразу две перемены: новую модель и новый чанкинг. После этого никто не понимает, что именно улучшило поиск, а что его испортило. Если качество просело на длинных документах, причина может быть не в модели, а в том, что вы порезали текст на слишком мелкие куски.

Одно среднее число тоже легко обманывает. Recall@10 или nDCG по всему набору полезны, но они прячут провалы. Смотрите хотя бы на короткие и длинные запросы, запросы с опечатками, смешанный язык, редкие термины и коды товаров, а также на новые документы против старых.

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

Короткий чек-лист и следующие шаги

Перед запуском зафиксируйте не только новую модель, но и весь контракт вокруг нее. Если меняется размерность, метрика поиска, схема чанкинга или лимит входного текста, меняется и поведение поиска. Даже хорошая модель даст плохой результат, если один из этих параметров ушел в сторону.

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

Перед запуском полезно пройтись по короткому списку:

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

Если вы сравниваете нескольких провайдеров, прогоняйте тесты через один OpenAI-совместимый шлюз. Для команд в Казахстане и Центральной Азии это удобно делать через AI Router: можно менять base_url на api.airouter.kz и сравнивать модели в одном и том же клиентском контуре, не переписывая SDK, код и промпты.

Не смешивайте сразу две задачи: смену модели и смену поставщика. Если менять все вместе, потом сложно понять, что именно испортило качество поиска или замедлило систему. Один и тот же тестовый контур экономит много времени.

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

Если пилот прошел нормально, не переводите весь трафик сразу. Дайте новой модели часть нагрузки, соберите метрики за несколько дней и только потом принимайте финальное решение. Подход скучный, но почти всегда самый дешевый и безопасный.

Часто задаваемые вопросы

Можно ли держать старые и новые векторы в одном индексе?

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

Какой тестовый набор нужен перед миграцией?

Минимум возьмите живые запросы из поиска, поддержки или RAG-логов. Обычно хватает 100–300 примеров, если в наборе есть короткие запросы, опечатки, редкие формулировки и смешение русского, казахского и английских терминов.

Какие метрики лучше проверить до реиндекса?

Смотрите не только на среднюю метрику. Полезнее сравнить top-k, MRR и затем вручную разобрать 20–30 худших запросов, чтобы понять, где новая модель реально теряет релевантные документы.

Почему старый порог похожести перестает работать?

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

Как заранее понять, влезет ли новый индекс в память?

Посчитайте сырой объем по формуле: число векторов умножить на размерность и на размер числа. Потом добавьте запас на структуру индекса, метаданные, реплики и временный индекс на время пересборки.

Достаточно ли сравнить скорость на маленькой выборке?

Не совсем. Проверьте p50 и p95 для одиночных запросов и батчей, а еще время полного реиндекса на объеме, близком к боевому. На малой выборке модель часто выглядит быстрее, чем под реальной нагрузкой.

Стоит ли вместе с моделью менять чанкинг и метрику поиска?

Нет, лучше менять что-то одно. Если вы одновременно меняете модель, чанкинг, метрику и настройки индекса, потом трудно понять, что дало рост, а что сломало поиск.

Нужно ли тестировать поиск с фильтрами и гибридным ранжированием?

Проверьте это отдельно на тех же фильтрах и в том же пайплайне, что работают в проде. Новая модель может выиграть в чистом векторном поиске, но просесть после фильтра по продукту, дате или региону.

Как безопасно запускать новую модель в проде?

Рабочий вариант — держать два индекса рядом и переводить трафик частями. Так вы быстро сравните выдачу на живых запросах и сможете откатиться без ночного пересчета.

Когда можно удалять старый индекс после миграции?

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