Деградация RAG при масштабировании: анализ HNSW и решения для production | AiManual
AiManual Logo Ai / Manual.
07 Янв 2026 Гайд

Когда RAG начинает врать: почему ваш поиск деградирует при росте базы и как это исправить

Почему RAG-система теряет качество при росте базы данных. Глубокий анализ алгоритма HNSW, метрика Recall@k и практические настройки для продакшена.

Тихий сбой: как RAG начинает врать без единой ошибки

Вы запустили RAG-систему. Все работает идеально. Ответы точные, релевантные, клиенты довольны. Проходит месяц, вы добавляете еще 100 тысяч документов. Еще месяц — еще полмиллиона. И вдруг замечаете: ответы стали странными. Нет, система не падает, ошибок в логах нет. Просто качество поиска незаметно просело на 15-20%. Контекст стал менее релевантным, LLM начинает генерировать ответы на основе не тех документов. Это не баг — это деградация.

Самый опасный сбой — тот, который не вызывает алертов. Система работает, но результаты становятся всё более бесполезными.

Почему это происходит? Математика против нас

Представьте, что у вас есть миллион точек в 768-мерном пространстве. Каждая точка — векторное представление документа. Когда вы ищете похожие векторы для запроса, вы ищете ближайших соседей. Точный поиск (exact nearest neighbors) требует сравнения запроса с КАЖДЫМ вектором в базе. При миллионе векторов это O(n) операций. Невыполнимо в реальном времени.

Поэтому мы используем приближенный поиск (ANN). Самый популярный алгоритм — HNSW (Hierarchical Navigable Small World). Он строит граф, где каждый вектор соединен с несколькими соседями. Поиск начинается с случайной вершины и прыгает по ребрам к всё более близким соседям. Быстро? Да. Точно? Не всегда.

💡
HNSW — это компромисс. Вы жертвуете точностью ради скорости. Проблема в том, что этот компромисс ухудшается с ростом данных.

Три главные причины деградации

  1. Плотность распределения: Чем больше векторов, тем плотнее они упакованы в пространстве. Различия между соседними точками становятся микроскопическими. Алгоритму сложнее найти «идеального» соседа.
  2. Качество эмбеддингов: Модели для создания векторных представлений тоже имеют пределы. При разнородных данных эмбеддинги становятся менее разделимыми.
  3. Параметры HNSW: Настройки, которые работали на 100k документов, перестают работать на 1M. Особенно критичны два параметра: M (количество связей) и ef_search (размер кандидатов при поиске).

Как измерить проблему: Recall@k — ваш новый лучший друг

Вы не можете управлять тем, что не измеряете. Стандартные метрики вроде точности (precision) или времени ответа не покажут деградацию поиска. Нужна Recall@k.

Recall@k показывает, насколько часто ваш приближенный поиск находит те же векторы, что и точный поиск. Формула простая: (количество найденных правильных векторов) / (общее количество правильных векторов). Если Recall@10 = 0.95 — значит, в 95% случаев ваш ANN находит все нужные векторы среди топ-10 результатов.

Размер базы Recall@10 (ef_search=200) Время поиска (мс)
100k векторов 0.98 12
500k векторов 0.91 28
1M векторов 0.83 45
5M векторов 0.67 120

Видите тренд? С ростом базы качество поиска падает, даже если параметры те же. Это не ваша вина — это математика. Но вы можете с ней бороться.

Практические решения: настройка HNSW для продакшена

Теперь перейдем к конкретике. Вот что нужно сделать, чтобы ваш RAG не деградировал при масштабировании.

1 Измеряйте Recall@k регулярно

Создайте тестовый набор запросов с известными правильными ответами. Для каждого запроса запускайте два поиска: точный (brute force) и приближенный через HNSW. Сравните результаты. Делайте это еженедельно при активном росте базы.

Если вы используете векторные БД вроде Qdrant или Weaviate, они часто имеют встроенные инструменты для оценки. Если нет — пишите скрипт сами. Не экономьте на этом времени. Одна неделя с Recall@10=0.7 может испортить все доверие пользователей.

2 Настройте ef_search динамически

Параметр ef_search определяет, сколько кандидатов алгоритм рассматривает на каждом слое графа. Больше кандидатов — точнее поиск, но медленнее. Мало кандидатов — быстро, но неточно.

Ошибка номер один: установить фиксированное значение. Ошибка номер два: установить слишком маленькое значение для экономии ресурсов.

ef_search=32 — это стандартная настройка для демо. Для продакшена с миллионом векторов нужно минимум 200-400. Да, это в 10 раз медленнее, но и в 3 раза точнее.

Решение: настройте ef_search в зависимости от размера базы и требований к задержке. Формула эмпирическая: ef_search = base_value * log10(N/100000), где base_value — значение для 100k векторов.

3 Увеличьте параметр M (количество связей)

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

Для 100k векторов M=16 достаточно. Для 1M нужно M=32-48. Для 10M — M=64 и выше. Проблема в том, что увеличить M постфактум нельзя — нужно перестраивать индекс. Поэтому планируйте заранее.

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

4 Добавьте гибридный поиск

Векторный поиск — не панацея. Когда плотность векторов становится слишком высокой, спасает старый добрый ключевой поиск. Комбинируйте результаты векторного поиска (по эмбеддингам) с полнотекстовым поиском (по ключевым словам).

Как это работает? Вы запускаете оба поиска параллельно, получаете два списка результатов, затем ранжируете их с помощью reranker модели или простого взвешенного голосования. Это повышает recall на 20-40% без увеличения ef_search.

В статье про гибридный поиск для RAG я подробно разбирал эту технику. На дешёвом CPU-сервере можно получить прирост точности почти в 50%.

5 Пересмотрите эмбеддинг-модель

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

Для больших баз (1M+) стоит рассматривать модели с размерностью 768 или даже 1024. Они занимают больше памяти и медленнее, но обеспечивают лучшее разделение векторов.

Также обращайте внимание на нормализацию векторов. Большинство векторных БД ожидают нормализованные векторы (длина = 1). Если ваша модель не нормализует выходные векторы — делайте это сами. Косинусное расстояние для ненормализованных векторов работает плохо.

Архитектурные хитрости для production

Параметры HNSW — это только половина дела. Вторая половина — как вы организуете поиск в продакшене.

Шардирование по смыслам

Если у вас 10 миллионов документов, не храните их все в одном индексе. Разделите по тематикам, языкам, типам контента. Для запроса ищите только в релевантных шардах. Это уменьшает N для каждого поиска в разы.

Многоуровневый поиск

Сначала быстрый приближенный поиск с низким ef_search, чтобы отсеять 90% неподходящих документов. Затем точный поиск по сокращенному набору кандидатов. Это компромисс между скоростью и точностью.

Кэширование частых запросов

20% запросов составляют 80% трафика. Кэшируйте результаты поиска для популярных запросов. Не только конечный ответ LLM, но и результаты векторного поиска. Это снижает нагрузку на HNSW.

💡
Кэширование эмбеддингов запросов — самая недооцененная оптимизация. Генерация эмбеддинга для одного запроса может занимать 50-100мс. При 1000 RPS это 50-100 секунд чистого CPU времени.

Что делать, если уже всё плохо

Допустим, вы уже в ситуации: база выросла до 2 миллионов документов, Recall@10 упал до 0.65, пользователи жалуются. План действий:

  1. Остановите добавление новых документов. Темп роста ухудшает ситуацию.
  2. Измерьте текущий Recall@k для разных ef_search значений. Найдите точку, где recall достигает приемлемого уровня (0.9+).
  3. Увеличьте ef_search в продакшене, даже если это увеличит задержку. Лучше медленный правильный ответ, чем быстрый неправильный.
  4. Запланируйте перестройку индекса с увеличенным M. Делайте это постепенно: создавайте новый индекс параллельно со старым, затем переключите трафик.
  5. Добавьте гибридный поиск как временное решение. Это даст немедленное улучшение качества.

Чеклист для production-ready RAG

  • Измеряйте Recall@k еженедельно при активном росте базы
  • Настройте мониторинг качества ответов (человеческая оценка выборочных запросов)
  • Используйте ef_search не менее 200 для баз >500k документов
  • Заложите M с запасом при создании индекса (M = 16 + log10(N/100000)*8)
  • Реализуйте гибридный поиск с BM25 или другими ключевыми методами
  • Кэшируйте эмбеддинги частых запросов
  • Шардируйте индекс по тематикам при >1M документов
  • Используйте reranker модели для финального ранжирования

Неочевидный совет: иногда проблема не в HNSW

Бывает, что вы всё настроили правильно, но качество всё равно падает. Возможно, проблема не в алгоритме поиска, а в данных или эмбеддингах.

Проверьте:

  • Дубликаты в базе: они размывают пространство поиска
  • Качество чанков: слишком мелкие или слишком крупные фрагменты
  • Дрейф эмбеддингов: если вы обновили эмбеддинг-модель, старые векторы стали несовместимы с новыми
  • Проблемы с нормализацией: векторы разной длины дают некорректное расстояние

Иногда решение лежит не в настройках HNSW, а в архитектуре всей RAG-системы. Или даже в подходе к подготовке данных, как в случае с обучением нейросети физике дефектов.

Главное — не игнорировать проблему. Деградация поиска в RAG — это не баг, это системная характеристика. Её нельзя пофиксить раз и навсегда, но можно контролировать. Измеряйте, настраивайте, перестраивайте. И ваш RAG будет масштабироваться не только количественно, но и качественно.

P.S. Если вы думаете, что эта проблема касается только огромных баз — вы ошибаетесь. Деградация начинается уже на 200-300k документах. Просто вы её ещё не заметили.