Главная / Статьи

За пределами косинусной похожести: сравнение пяти техник поиска для RAG

Косинус, BM25, гибридный RRF, переранжирование с использованием кросс-энкодера и MMR — объяснение с примерами кода, компромиссы и подход, основанный на запросе, для выбора техники поиска, необходимой вашему RAG.

Издатель: REACTAPP.TOP10 мин чтения2236 слов

Источники: **Beyond Cosine Similarity: The 5 RAG Retrieval Techniques That Actually Move the Needle**

Две фразы — «кошка сидела на коврике» и «кошка отдыхала на ковре» — совершенно не содержат общих слов, однако модель на основе эмбеддингов оценивает их сходство примерно в 0,85. Именно так формируется репутация косинусного сходства, и именно на этом большинство учебников по RAG останавливаются: показывают косинусный коэффициент, вставляют фрагмент текста и переходят дальше.

collection.query(query_embeddings=embedding, n_results=5)

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

Что измеряет косинус

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

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

Типичные оценки выглядят так:

Пара Оценка
"Кошка сидела на коврике" и "Котенок отдыхал на ковре" 0.85
"Как работает внимание?" и "Объясните механизм трансформера" 0.79
"Язык программирования Python" и "Вид змей Python" 0.38
"Я обожаю утренний кофе" и ">Теория квантовой сверхсвязи" 0.03

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

Почему не евклидова расстояние

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

Предупреждение о рейтингах

Косинусовые рейтинги не являются универсальными. Значение 0,7 от модели all-MiniLM-L6-v2 — это другой показатель, чем значение 0,7 от модели text-embedding-3-large, поскольку у каждой модели есть свое пространство вкладок с собственной плотностью. Настройте пороги оценки на собственном наборе данных для тестирования и не копируйте числа из учебника, в котором использовалась другая модель.

Аналогия с фестивалем для тех, кто не инженер

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

  • По направлению (косинус). Вы оба соглашаетесь повернуться к сцене. Одно и то же направление означает одного и того же человека, независимо от расстояния между вами. Важен угол, в котором вы указываете, а расстояние между вами — нет.
  • По именной табличке (поиск по ключевым словам, BM25). Вы кричите: «Есть ли здесь Алекс?» Этот метод работает идеально, если имена совпадают полностью, но он не учитывает таких людей, как Алексис, Эл или Сэнди, которые на самом деле являются одним и тем же человеком с другим именем.
  • По лицу и именной табличке (гибридный метод). Вы проверяете оба критерия. Тот, кто соответствует обоим, выделяется в верхней части списка, а тот, кто соответствует только одному, всё равно привлекает внимание. Этот метод обеспечивает наиболее полный охват.

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

Пять методов, по одному

1. Похожесть косинуса, стандартный вариант

Что она делает. Сравнивает семантическое направление векторов запроса и документа.

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

В чём слабости. Буквальные строки. Код продукта, номер счёта-фактуры или имя человека, которое почти не встречалось в данных обучения, могут полностью сорвать работу метода косинуса. Векторы «GPT-4o» и «GPT-4» могут находиться достаточно близко друг к другу, что приводит к появлению шума вместо значимых сигналов.

В коде:

collection.query(
    query_embeddings=query_embedding,
    n_results=5
)

Компромисс. Значение важнее точного формулирования. Этот метод быстр, достаточно точен и не требует дополнительной настройки.

2. Поиск по ключевым словам BM25 — инструмент точности

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

Когда использовать его. Когда запрос основан на точном идентификаторе, который должен совпадать буква в букву, например номер счета-фактуры, название модели с датой выпуска или ссылка CVE.

Чего он не учитывает. Любого смысла. Слово «Feline» не будет соответствовать документам, в которых используется слово «cat». Синонимы и парафразы для него невидимы.

Информативный результат. В одном небольшом проекте с нуля добавление алгоритма BM25 вместе с методом косинуса повысило показатель воспроизведения с 0,25 до 0,75. Причиной стало то, что реальные запросы пользователей содержали точные названия продуктов, которые метод косинуса преобразовывал в почти совпадающие результаты вместо того, чтобы находить их напрямую. Считайте это одной точкой данных, а не универсальным показателем.

Компромисс. Точность поиска по точному совпадению ценой полного отсутствия семантической генерализации.

3. Гибридный поиск — стандарт в производстве

Как это работает. Методы косинуса и BM25 применяются одновременно, а два полученных ранжированных списка объединяются с помощью техники Reciprocal Rank Fusion (RRF). Ни один из методов в отдельности не покрывает все типы запросов.

Когда использовать его. Запросы сочетают естественный язык с конкретными терминами, что характерно практически для любой производственной системы. Пользователь, задающий вопрос «Какова политика возврата средств для заказа №8821?», использует как семантический элемент (политика возврата средств), так и точное совпадение (№8821).

Этап слияния. Каждая техника возвращает свой собственный ранжированный список. Метод RRF присваивает каждому документу оценку на основе его позиции в каждом списке — 1 делено на (k плюс ранг), где k — константа, обычно равная 60, после чего суммируются оценки от всех методов. Документы, занимающие высокие позиции в обоих списках, поднимаются вверх.

# Pseudocode for RRF merge
def rrf_score(rank, k=60):
    return 1 / (k + rank)
def merge_results(cosine_results, bm25_results):
    scores = {}
    for rank, doc in enumerate(cosine_results):
        scores[doc.id] = scores.get(doc.id, 0) + rrf_score(rank)
    for rank, doc in enumerate(bm25_results):
        scores[doc.id] = scores.get(doc.id, 0) + rrf_score(rank)
    return sorted(scores.items(), key=lambda x: x[1], reverse=True)

В AWS OpenSearch поддерживает это из коробки: вы настраиваете гибридный поиск с параметром веса, и сервис самостоятельно обрабатывает объединение результатов.

Компромисс. Максимальная точность восстановления данных при примерно вдвое больших затратах на поиск, что обычно оправдано.

4. Переупорядочивание с использованием кросс-кодера

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

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

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

from sentence_transformers import CrossEncoder
reranker = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')# Stage 1: retrieve candidates
candidates = collection.query(query_embeddings=embedding, n_results=20)# Stage 2: rerank
pairs = [(query, chunk) for chunk in candidates['documents'][0]]
scores = reranker.predict(pairs)
top_5 = sorted(zip(scores, candidates['documents'][0]), reverse=True)[:5]

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

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

5. Максимальная граничная релевантность (MMR) для разнообразия

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

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

Параметр лямбда.

  • lambda = 1.0 означает чистую релевантность, то же самое, что и стандартный косинусный коэффициент
  • lambda = 0.0 означает чистое разнообразие, при котором полностью игнорируется релевантность
  • lambda = 0.5 — сбалансированная отправная точка для дальнейшей настройки
  • def mmr_select(query_embedding, candidates, lambda_param=0.5, k=5):
        selected = []
        remaining = list(candidates)
    
        while len(selected) < k and remaining:
            mmr_scores = []
            for doc in remaining:
                relevance = cosine_similarity(query_embedding, doc.embedding)
                if selected:
                    redundancy = max(cosine_similarity(doc.embedding, s.embedding)
                                    for s in selected)
                else:
                    redundancy = 0
                mmr_scores.append(lambda_param * relevance - (1 - lambda_param) * redundancy)
    
            best = remaining[mmr_scores.index(max(mmr_scores))]
            selected.append(best)
            remaining.remove(best)
    
        return selected
    

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

    Компромисс. Этот метод устраняет избыточность, но требует настройки параметров алгоритма lambda.

    Выбор: пусть решают ваши запросы

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

    • 80% или более запросов — это обычный естественный язык. Коэффициент косинуса — ваш стандартный выбор. Начните с него, поскольку он быстрый, точный и не требует дополнительной инфраструктуры.
    • 30% или более запросов содержат точные термины, коды, идентификаторы или собственные имена. Добавьте алгоритм BM25. Как только вы заметите такую закономерность, гибридный поиск становится стандартом для производственных задач, поэтому реализуйте метод слияния RRF. Повышение точности восстановления результатов обычно происходит быстро и значительно.
  • Ведущие результаты релевантны, но первый из них слабый. Используйте ранжер с кросс-кодером на втором этапе: выберите 20 кандидатов и оставьте лучшие 5, а также проверьте увеличившуюся задержку перед запуском.
  • Все ведущие результаты избыточны. Добавьте MMR с параметром lambda 0.5: значение ближе к 0 обеспечит большее разнообразие, а ближе к 1 — большую релевантность. Это критически важно для кратких ответов и вопросов исследовательского типа.
  • Пользователи задают расплывчатые вопросы, в которых едва описывается их цель. Сначала попробуйте метод HyDE (Hypothetical Document Embeddings). Сгенерируйте вымышленный ответ на вопрос, включите его в формат эмбеддингов и используйте для поиска вместо исходного запроса. Вымышленный ответ находится ближе к идеальному документу, чем сам вопрос.
  • Создание системы RAG в производственных целях на AWS. OpenSearch с встроенным гибридным механизмом поиска (BM25 плюс плотные векторы, объединение с помощью RRF) в сочетании с Cohere Rerank в качестве второго этапа — это решение, которое выбирают многие команды.
  • Чего не упоминают учебники

    Техники могут вступать в противоречие друг с другом, а не просто дополнять друг друга. В одном эксперименте использование метода расширения запроса, который генерирует несколько вариантов запроса и выполняет поиск для каждого из них, поверх гибридного механизма поиска казалось безупречным решением. Более широкий охват должен был привести к лучшим результатам. Однако оценки снизились с 0,807 до 0,702. Увеличение количества сигналов поиска усиливает как полезные сигналы, так и шум, а дополнительные варианты запроса приводят к включению соседних, но неверных фрагментов информации. Гибридный механизм поиска и так работал хорошо, а метод расширения запроса только усугублял ситуацию. Необходимо добавлять техники по одной, измерять их эффективность по отдельности перед совместным использованием, помня, что порядок имеет значение, поскольку то, что полезно по отдельности, может навредить при совместном применении.

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

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

    Полная цепочка обработки

    Вот многоуровневая структура, к которой в итоге приходят многие производственные системы RAG:

    User Query
        ↓
    [Optional: HyDE — if query is vague]
        ↓
    Stage 1 Retrieval: Hybrid (Cosine + BM25 → RRF merge)
        → Top 20 candidates
        ↓
    [Optional: Cross-encoder reranking — if precision matters]
        → Top 5 candidates
        ↓
    [Optional: MMR — if results are redundant]
        → Final k candidates
        ↓
    LLM Context Assembly + Generation
    

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

    Важное число

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