Гайд · TNWS AI

Как уменьшить векторный индекс Azure AI Search через scalar quantization

6 мин—

Настройка scalarQuantization int8 с preserveOriginals, oversampling и проверкой Recall@10 на отдельном индексе.

Задача и применимость

Актуальный русскоязычный запрос: «как уменьшить размер vector index Azure AI Search scalar quantization». Официальная документация Microsoft проверена 19 сентября 2026 года. REST API 2026-04-01; новый пустой индекс с float32/float16 embeddings, HNSW profile и фиксированным тестовым корпусом. Параметры сжатия задаются до загрузки данных.

Задача здесь — выполнить и проверить конкретную операцию в Azure AI Search. Образцовые значения вроде ru-kb, p1 и policy-2026-01 принадлежат тестовому корпусу, а не обязательным именам в вашем сервисе. У вас должны быть полномочия на указанную операцию; для теста можно использовать административный ключ на доверенном сервере, но в пользовательском браузере нужен защищённый серверный посредник. Сначала снимите baseline по контрольному запросу и набору документов, затем меняйте только одну настройку за раз.

Что подтверждает документация

vectorSearch.compressions поддерживает scalarQuantization и binaryQuantization; для scalar quantizedDataType указан int8. Сжатие уменьшает объём, но может изменить ранжирование. rescoringOptions enableRescoring, defaultOversampling и preserveOriginals позволяют повторно пересчитать кандидатов по исходным embeddings. Дополнительная копия для retrieval управляется stored отдельно.

Это не обещание одинакового ранжирования для любого русского корпуса. Результат embedding зависит от deployment, подготовки текста, chunking, обновлений модели и состава индекса. Доступность предварительных функций и ограничения сверяйте с документацией и настройками собственного сервиса; цена и длительность операций здесь намеренно не указаны, потому что они не следуют из поискового ответа. Отделяйте успешный HTTP-запрос от оценки полезности найденного фрагмента.

Пошаговое выполнение

  1. Зафиксируйте размер текущего индекса, Recall@10 и p95 на наборе русских вопросов.
  2. Создайте новый пустой индекс с отдельным именем compression sq1 и profile, ссылающимся на неё.
  3. Задайте scalarQuantization int8 и rescoringOptions с preserveOriginals; не удаляйте базовый индекс.
  4. Загрузите тот же корпус и выполните идентичные запросы для сравнения IDs.
  5. Переключайте приложение на новый индекс только при выполненных критериях качества, размера и задержки.

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

Готовый REST-шаблон

"vectorSearch":{"compressions":[{"name":"sq1","kind":"scalarQuantization",
 "scalarQuantizationParameters":{"quantizedDataType":"int8"},
 "rescoringOptions":{"enableRescoring":true,"defaultOversampling":10,
 "rescoreStorageMethod":"preserveOriginals"}}],
 "algorithms":[{"name":"h1","kind":"hnsw","hnswParameters":{"metric":"cosine"}}],
 "profiles":[{"name":"p1","algorithm":"h1","compression":"sq1"}]}
# Вставьте эту секцию в ПОЛНУЮ схему нового пустого индекса.

Подставьте своё имя сервиса в https://<service>.search.windows.net, передайте Content-Type: application/json и авторизацию выбранным поддерживаемым способом. Демонстрационный массив из трёх чисел или строка <embedding массива> — только описание формы; они не являются реальным embedding для поля с 1536 измерениями. Перед отправкой проверьте JSON, размерность и отсутствие ключа в клиентском коде.

Входные данные и ожидаемый результат

Вход: baseline index с document IDs policy-1, policy-2, shipping-1 и выборка из десяти русских вопросов; новый индекс содержит тот же корпус, тот же contentVector и int8 compression. Ожидается уменьшение vector footprint; точную экономию нельзя гарантировать без измерения. Если Recall@10 сильно падает, выпуск откладывают и меняют только одну настройку эксперимента.

Ожидаемый ID — проверяемая гипотеза на подготовленном тестовом наборе. При другом корпусе и другом embedding нельзя честно обещать конкретный score и порядок результатов. Сохраняйте как входное содержимое, так и текст возвращённого фрагмента: найденный ID без исходного подтверждения не годится для публикации ответа от имени компании.

Разбор и границы применения

Квантование и хранилище возвращаемых векторов — разные рычаги. stored:false снимает дополнительную копию для выдачи в API, а compression меняет представление поискового индекса; одно не заменяет другое. Если приложение использует embeddings из результата для дальнейшей обработки, сперва выясните, нужен ли retrievable:true. Для большинства RAG-приложений нужны текст и ссылка, а не сам vector; однако архитектурное предположение нужно проверить на конкретном клиенте. preserveOriginals требуется для повторной оценки близости оригинальными данными; discardOriginals меняет возможности рескоринга, поэтому копировать обе настройки без понимания нельзя. Oversampling расширяет число кандидатов до финального k и меняет нагрузку, так что сравнивайте не только качество, но и p95. Microsoft рекомендует задавать оптимизации на пустом индексе: попытка изменить структуру насыщенного корпуса не является безопасной in-place миграцией. Выборка должна включать короткие заголовки, длинные русские вопросы, близкие и почти одинаковые документы. Сохраняйте протокол теста с ID и датой: каждое последующее изменение модели embeddings требует нового baseline.

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

План перехода требует двух имен индексов: базового и сжатого. Загружайте оба из одного неизменяемого manifest, а не генерируйте embeddings заново между тестами; иначе обнаруженную разницу нельзя будет отнести к квантованию. Подсчитайте число документов и длину vectors в обоих индексах, затем замерьте vector index size, storage и p95 на одном наборе запросов. Для оценки качества используйте пары почти одинаковых документов, где различается важный срок: потеря таких деталей опаснее, чем обмен местами двух равно полезных страниц. При тестировании defaultOversampling=10 фиксируйте k, поскольку расширенный кандидатный пул зависит от k; не переносите измеренную задержку с k=5 на k=50 без новой проверки. Если сохранение originals противоречит заданному ограничению хранения, измерьте альтернативный вариант отдельно и явно отметьте ухудшение качества. Переключайте чтение постепенно и сохраняйте быстрый возврат к старому индексу; не удаляйте baseline до проверки производственных вопросов.

Критерии проверки

  • Новый индекс создан пустым и полностью загружен тем же корпусом.
  • Размер vector index измерен до и после.
  • Recall@10 и p95 выдерживают заранее выбранные пороги.
  • Приложение не зависит от отключённых retrievable vectors.

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

Типичные ошибки и что не делать

  • Обещать точную экономию без измерений.
  • Изменять compression в уже наполненном индексе без плана миграции.
  • Считать stored:false аналогом quantization.
  • Измерять только занимаемые гигабайты и не измерять качество.

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

FAQ

Какой тип для scalarQuantization?

В описанном API int8.

Зачем preserveOriginals?

Для повторного ранжирования по исходным векторам.

Когда сравнивать размеры?

После загрузки одного и того же корпуса в оба индекса.

Официальные источники

Частые вопросы

Какой тип для scalarQuantization?

В описанном API int8.

Зачем preserveOriginals?

Для повторного ранжирования по исходным векторам.

Когда сравнивать размеры?

После загрузки одного и того же корпуса в оба индекса.

Читайте также

Комментарии

Пока тихо. Скажите первое слово