Один документ занял весь top-k в RAG: как вернуть разнообразие источников

База знаний хранит договоры и приложения к ним. Вы спрашиваете, какие условия возврата действуют для нового тарифа. Поиск отдаёт десять ближайших фрагментов, но восемь из них — соседние абзацы одного старого договора. Новый регламент, где указано исключение, не попадает в контекст ответа. Поднять limit с 10 до 30 можно, но тогда в модель уходит больше повторяющегося текста, а нужный источник всё ещё может стоять ниже.

Что именно надо разнообразить

Сначала откройте результаты поиска до LLM и посчитайте уникальные document_id. Если десять кандидатов представляют два файла, проблема находится в выдаче, а не в формулировке ответа. Сохраните для каждого кандидата его chunk_id, document_id, версию документа, расстояние или score и позицию. Так видно, не заполнила ли выдачу пачка почти одинаковых чанков одного файла. Отдельно проверьте, что нужный регламент вообще есть в индексе и доступен этому пользователю: группировка не создаст отсутствующий источник.

Политика выдачи может звучать так: сначала получить до четырёх разных документов, затем из каждого взять не больше двух лучших фрагментов. Это сознательно меняет задачу. Теперь первый этап обеспечивает широту источников, второй даёт локальный контекст внутри каждого. Если вопрос требует нескольких пунктов одного большого документа, group_size=1 будет слишком жёстким; оставьте два или три чанка и проверяйте ответы на разных типах вопросов.

Группировка в Qdrant

У Qdrant есть запрос POST /collections/{collection_name}/points/query/groups. Он группирует результаты по payload-полю, поэтому при индексации у каждого чанка должен быть стабильный document_id. Пример тела запроса для коллекции с векторами размерности 3:

{
  "query": [0.12, 0.34, 0.56],
  "group_by": "document_id",
  "limit": 4,
  "group_size": 2,
  "with_payload": true
}

Здесь limit — максимальное число групп, group_size — максимальное число точек в каждой. Фактическое число групп может быть меньше. Индекс payload по document_id нужен для эффективной группировки; у Qdrant Cloud строгий режим может отклонить запрос без такого индекса. В реальной коллекции длина query должна совпадать с размерностью векторов, а права доступа и фильтры клиента надо применять до группировки.

Простая дедупликация уже полученного top-10 не эквивалентна групповому поиску. Если top-10 содержит только два документа, удаление лишних восьми оставит два результата. Групповой запрос ищет группы как единицы выдачи и может найти следующие документы. При многоступенчатом поиске следите за размером предварительного набора кандидатов: если нужный документ не дошёл до этапа группировки, API не сможет его восстановить.

Сохраните старый и новый результат для нескольких запросов рядом: список document_id, лучший chunk_id внутри каждого документа и score. Это позволит увидеть цену разнообразия. Например, четвёртый документ может оказаться заметно менее близким, чем третий фрагмент первого. Такой результат не надо автоматически отправлять модели. Отсейте группы ниже согласованного порога качества или передайте результаты реранкеру, который читает полный текст кандидатов. Порог подбирайте на вопросах с известным источником, а не по одному примеру.

Проверка результата

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

В платном курсе Vector DB & RAG Developer вы строите поиск на Qdrant, Weaviate и FAISS, оцениваете Recall@K и nDCG и собираете RAG-бота с цитатами. Группировка полезна как конкретный эксперимент: она меняет состав контекста, а метрики показывают, помогло ли это пользователю найти ответ. Откройте программу курса и посмотрите практику индексации и оценки выдачи.

Продолжить на практике

  • Vector DB & RAG Developer ↗

    Практический курс по векторным базам данных и семантическому поиску. Вы развернёте Qdrant, Weaviate и FAISS, научитесь индексировать миллионы эмбеддингов, строить k-NN-поиск с фильтрами, объединять его с BM-25 и создавать RAG-ботов, которые отвечают на вопросы на основе ваших данных.