Привет, Хабр! В этом посте мы поговорим подробно про RAG на каждом его этапе, его текущее развитие на момент написания статьи и про другие модификации. В прошлой статье я писал про промптинг, советую глянуть ?
Интро
Генерация ответов LLM происходит исключительно на основе информации и шаблонов, усвоенной в ходе обучения (то, что знает сама модель). Однако такие модели ограничены теми данными, на которых они были обучены, что приводит к известной проблеме галлюцинаций — созданию ложных ответов с точки зрения фактологии или логики.
Пример работы LLM без использования RAG или внешних данных
В декабре 2024 я задал вопрос одной LLM про топ игр 2024, на тот момент уже прошел Game Awards 2024, а значит было понимание, чего ожидать по играм. Однако, получил следующее:
Во‑первых, модель сама говорит, что у нее нет актуальной информации на 2024 — значит не используется внешняя информация, только знания LLM.
Во‑вторых, посмотрев на первые два топа — уже есть вопросы: первая игра вызвала неоднозначные мнения, вторая вообще вышла в 2023 году.
Вывод: такой ИИ не будет практичным и полезным
Тренировочные данные быстро могут стать out‑of‑date — за день могут появится новые термины и тренды, о которых LLM не знает, а сама LLM не может выйти в БД и в Интернет. Поэтому на сегодняшний день мы знаем, как дать актуальные знания генеративным моделям, используя RAG — Retrieval Augmented Generation.
Обсудим поэтапно RAG или RrrAG и как его можно улучшать:
Retrieval — как извлекаются нужные данные
Re‑rank — как полученные данные отсортировать по релевантности
Augmentation — как извлеченные данные подаются в LLM
Generation — как генерируются ответы и как их можно оценивать
Гайд основан на открытых источниках и на моем личном опыте.
RAG
RAG (Retrieval Augmented Generation) — метод, который комбинирует генеративные модели с поисковыми системами или базой данных для генерации ответов, обогащёнными внешними данными. Классическая схема выглядит так:
Подаем текстовый запрос в пайплайн
Векторизируем текстовый запрос с помощью методов векторизации
По вектору запроса ищем в БД N текстовых документов с близким векторным расстоянием (чем ближе вектора, тем схожи запрос и документ с ответом)
Полученные документы можем реранжировать для улучшения релевантности
Полученные документы вместе с запросом интегрируем в промпт
Генерируем ответ по сформированному промпту
Такую RAG систему со всеми этапами, которые проговорим ниже, можно быстро развернуть на примерах с Llama Index или Langchain.
Теперь рассмотрим поэтапно.
Retrieval
На этапе Retrieval происходит поиск и извлечение информации в базе данных или документах. Retrieval состоит из ретривера (способа поиска и извлечения), базы данных и эмбеддера (для векторного поиска).
Ретривер
Есть три типа retrieval‑систем:
Sparse Retrieval — используется для полнотекстового или лексического поиска с помощью TF‑IDF или BM25.
Dense Retrieval — используется для векторного поиска с помощью эмбеддингов, полученных от нейронных моделей (word2vec, rubert, e5-multilingual и др.)
Hybrid Retrieval — используется для комбинации из разных типов поиска
Для финальных решений обычно RAG строят на гибридном подходе, так он сочетает преимущества каждого из типов поиска.
Выбор базы данных
Под каждый тип поиска подойдут следующие БД:
Sparse Retrieval: PostgreSQL, Apache Solr, Whoosh
Dense Retrieval: ChromaDB, FAISS, Pinecone, Qdrant, RediSearch, Milvus
Hybrid Retrieval: ElasticSearch, Qdrant, PostgreSQL (c плагином pgvector)
За последнее время набирают популярность графовые базы данных, так как в них реализованы алгоритмы графового поиска, которые могут быть совместимы с другими типами поиска. Из плюсов графовых БД — хранение связей (отношениями) между объектами. Вот пример таких БД:
Graph Databases: Neo4j, TigerGraph, Weaviate, ArangoDB
Какую БД выбрать знает опытный DE или DS, так как выбор зависит от решаемой задачи, наличия вычислительных ресурсов и требованиям по скорости работы, масштабированию и нагрузке приложения. Для простого решения можно выбрать ChromaDB, FAISS или PostgreSQL — их легко можно развернуть у себя (другие БД возможно тоже, лично не пробовал).
Подготовка и запись данных
Сбор. Собираем датасет с данными (включая текстовые) и определяем колонку, по которой будет идти поиск. Например, пусть это будет таблица с отзывами о фильмах с колонками: текст отзыва, id, дата отзыва, id пользователя. В этом случае, поиск будет проводится по тексту отзыва.
Разбитие по чанкам. Далее текст отзыва стоит разделить на фрагменты (чанки). Имхо, здесь есть два аргумента:
В одном документе может присутствовать множество тематик, между которыми будет неоднородный контекст, что делает вектор более расплывчатым и менее информативным.
В том же отзыве о фильме можно писать положительно об актерском составе, отрицательно о сюжете, хорошо отзываться о спецэффектах и т. д. В идеальном варианте мы бы не хотели терять эту информацию, записывая все под один вектор.Эмбеддерные модели имеют ограничение входного контекстного окна — 512, 1024, 2048 токенов. Это значит, если текст превышает контекстное окно — часть вне контекстного окна теряется. Есть модели, у которых длина больше 2048 — но тут можно вернуться к первому аргументу.
Классическое разбиение по чанкам происходит по ограничению кол‑ва символов или токенов (второе используется для контроля кол‑ва токенов под контекстное окно).
Важно помнить: кол‑во токенов не равно кол‑ву символов. Для первого разбиения можно взять 400–500 символов. Далее стоит провести свои эксперименты с разным кол‑вом символов для разбиения и провалидировать подбор документов. Финальная цифра зависит от результатов поиска, кол‑ва тематик в документе и необходимости их разделения.
Также можно разбивать рекурсивными сплитерами:
По спец‑символам \n, \t и др. (если текст подобным образом структурирован)
Учитывая перекрытие соседних чанков (чтобы не терять контекст прошлого и следующего фрагмента)
Векторизация. Для выбора эмбеддера можно отслеживать лидерборд на бенчмарке MTEB, включая отдельный лидерборд для русского языка.
Конечно, это все только бенчмарк, на вашей реальной задаче рейтинг моделей, скорее всего, изменится — поэтому финальной моделью будет та, что лучше покажет на вашем эксперименте. В качестве первой модели для русского домена можно взять e5_multilingual_base и e5_multilingual_large — эти модели известны в RU DS сообществе, также сам использую из‑за хороших эмбеддингов. Однако, на выборе модели все не заканчивается — если домен вашей задачи специфичен, рекомендуется дообучить модель на ваших данных через contrastive learning.
Как улучшить Retrieval
Семантическое чанкирование. Вместо обычного разделения используем LLM для разделения документа на чанки по контексту тематик. Идет от задачи Text Segmentation
Использовать мультимодальные данные. Одна модальность хорошо — две еще лучше
Мультиплицирование (перефраз/перевод) запроса. Перефразируем изначальный запрос с помощью LLM или иными способами — говорим модели перефразировать запрос, меняем формальность запроса или перевести запрос на другой язык, таким образом получаем выборку больше и разнообразнее.
HyDE (Hypothetical Document Embedding). В поиске используем используем как исходный запрос, так и гипотетический ответ (сгенерированный LLM).
1. Запрос — какие лучшие блюда в McDonalds?
2. LLM генерирует пример такого документа — «Лучшие блюда в McDonald's включают Биг Мак, Чизбургер и картошку фри. Биг Мак известен своим уникальным соусом и двумя котлетами, а Чизбургер предлагает классический вкус с плавленым сыром.»
3. Этот документ отправляем как запрос в Retriever для нахождения реальных документовКонтекстуализация запроса. Добавляем к запросу дополнительный бекграунд: предыдущие запросы клиента, информация о домене
Декомпозиция сложных запросов. Если есть возможность, лучше разбить запрос на подзадачи запроса (через LLM)
Контекстуализация чанков (Contextual Retrieval). Здесь идея обогащения контекстом не запроса, а самих чанков. Например:
1. Документы дробим на мелкие чанки (1 предложение или 1 тезис):
«Компания увеличила доход на 3% по сравнению с предыдущим кварталом.»
2. Строим контекстуализированные фрагменты с помощью ИИ на основе оригинального документа.
«Этот фрагмент взят из отчета SEC о финансовых результатах компании ACME за второй квартал 2023 года; доход за предыдущий квартал составил 314 миллионов долларов. Компания увеличила доход на 3% по сравнению с предыдущим кварталом.»
3. Обогащаем БД контекстуализированными чанками
Re-rank
После того, как были получены первые N документов из ретривера, можно их финально реранжировать для улучшения релевантности выдачи. Например, если был использован один тип ретривера, можно реранжировать через другой тип.
Для этого используются BM25 (Sparse Retrieval) или эмбеддер (Dense Retrieval). Эмбеддер можно использовать как Bi‑encoder (запрос и ответ векторизируем отдельно, после измеряем их близость) и Cross‑encoder (запрос и ответ подаем вместе в одно контекстное окно — на выходе получаем скор близости)
В некоторых БД есть уже встроенные эмбеддеры для реранжирования: ColBert, Cohere (embed‑english‑v3.0, embed‑multilingual‑v3.0); а также встроенные LLM: RankGPT. При этом реранжирование можно строить на открытых эмбеддерах или LLM (в 2 случае задаем промпт в духе «отранжируй эти документы по близости к данному запросу». На практике DS используют свои методы/модели для реранжирования. Если брать открытые модели, то лучше брать размером больше, чем эмбеддер в поиске.
Augmentation
Теперь можно приступить к внедрению документов в промпт. Здесь уже заранее можно представить структуру шаблона документов, как будет описана эта информация для модели. Обычно в промпте после вводной информации, ниже указывается место для документов и после этого целевая задача для LLM. Помимо этого, кроме самого текстового документа можно интегрировать и его мета‑данные, так как на выходе ретривера извлекаются строки со всеми включенными колонками.
Дополнительные действия перед аугментацией
Валидация или фильтрация документов к исходному запросу через LLM. Если ответы нерелевантные — идем обратно в Retriever или останавливаем пайплайн
Суммаризация чанков. Можно сократить документы, агрегируя информацию в один документ (через модель суммаризации или LLM) — тем самым оптимизировать промпт.
Generation
Здесь в целом ничего нового, аналогично генерируется ответ через LLM теперь с актуальной информацией с помощью RAG.
Пример работы LLM с внешними данными/с RAG
Вывод: такой ИИ мы используем.
Развитие RAG
К началу 2025 года RAG активно развивается, предлагая новые оптимизации и улучшения: переход в мультимодальность, обогащение чанков контекстом, использование графов знаний и т.д.
В этом посте я бы выделил две интересные темы: валидация и автоматизация RAG
Валидация RAGa
Оценивать выдачу документов и генерацию можно классическими метриками:
Mean Reciprocal Rank (MRR) оценивает, насколько быстро система находит первый релевантный документ в ответ на запрос.
Mean Average Precision (MAP) учитывает как точность извлечения, так и порядок документов в списке результатов, рассчитывается как среднее значение точности для нескольких запросов.
BLEU и ROUGE - используются для оценки качества текста на основе сравнения с эталонными ответами.
Или другими метриками ранжирования и качества ответа
За последнее время начинает набирать популярность Триада метрик. Каждая из них оценивается с помощью LLM и заранее заданного промпта.
1. Релевантность ответа (Answer Relevance) - оценивает, насколько хорошо сгенерированный ответ соответствует заданному вопросу. Высокая релевантность ответа означает, что информация, предоставленная в ответе, полезна и отвечает на конкретный запрос.
2. Верность (Groundedness) - измеряет, насколько точно сгенерированный ответ соответствует фактам, содержащимся в извлеченных документах. Нужно для предотвращения "галлюцинаций". Высокая верность указывает на то, что модель использует извлеченный контекст для формирования обоснованных ответов.
3. Релевантность контекста (Contextual Relevance) - оценивает, насколько хорошо извлеченные документы соответствуют запросу.
Похожие и классические метрики реализованы в библиотеке RAGAS.
Это быстрый способ оценки RAG системы, если вы доверяете оценку LLM.
Подробно о нем можно посмотреть их документацию, есть статья с подробным описанием и его хороший перевод на Хабре.
AutoRAG - Автоматизация RAG
Наверное, для меня AutoRAG (repo) - это первый рабочий автоматизированный RAG фреймворк. По-хорошему, здесь нужен отдельный пост, чтобы подробно рассказать. Ниже прикрепил схему этапов работы пайплайна с их включенными методами. Наверное, из минусов - хотелось бы иметь возможность использовать открытые модели, и думаю это скоро будет.
Заключение
И это не все про RAG, о чем еще хотел бы рассказать. Поисследовать другие модификации можно тут.
Спасибо за внимание! Пишите в комментариях про ваш опыт с RAG.
Andriljo
Хороший гайд,лайк, закладка
mrcoolinhabr Автор
Благодарю!