Продвинутый RAG: объяснение LongRAG, Self-RAG и GraphRAG

LongRAG, Self-RAG, GraphRAG — технологии следующего поколения

Содержимое страницы

Генерация с дополнением извлечения (RAG) развилась далеко за пределы простого поиска по векторной схожести. LongRAG, Self-RAG и GraphRAG представляют собой передовой край этих возможностей.

Современные системы RAG должны уметь обрабатывать огромные документы, понимать сложные взаимосвязи между сущностями и многое другое.

a-pirate-captain Это красивое изображение сгенерировано с помощью модели ИИ Flux 1 dev.

Эволюция за пределами базового RAG

Традиционные системы RAG следуют простой схеме: разбивают документы на фрагменты (чанки), преобразуют их в векторы, извлекают похожие фрагменты с помощью косинусной схожести и передают их в LLM. Хотя этот подход эффективен для многих сценариев, он сталкивается с трудностями в трех критических ситуациях:

Понимание различий между поиском (search), углубленным поиском (deepsearch) и углубленными исследованиями (deep research) помогает прояснить, почему для сложных задач извлечения информации необходимы продвинутые варианты RAG. Для более глубокого погружения в эти концепции см. Поиск vs Углубленный поиск vs Углубленные исследования.

  1. Дальнодействующие зависимости: Важный контекст может охватывать тысячи токенов в нескольких фрагментах
  2. Уверенность в извлечении: Система не имеет возможности оценить, действительно ли извлеченный контент релевантен
  3. Сложность взаимосвязей: Векторная схожесть не может уловить тонкие связи между сущностями

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

LongRAG: Покорение расширенного контекста

Обзор архитектуры

LongRAG фундаментально пересматривает стратегию разбивки на фрагменты, используя LLM с расширенными окнами контекста (32K, 100K или даже 1M токенов). Вместо того чтобы разбивать документы на маленькие фрагменты по 512 токенов, LongRAG использует иерархический подход:

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

Минимальная фрагментация: Когда разбивка на фрагменты необходима, LongRAG использует гораздо большие фрагменты (4K-8K токенов) со значительным перекрытием (20-30%). Это сохраняет нарративный поток и снижает фрагментацию контекста.

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

Стратегия реализации

Вот концептуальная реализация на Python с использованием современных моделей встраивания:

from typing import List, Dict
import numpy as np

class LongRAGRetriever:
    def __init__(self, model, chunk_size=8000, overlap=1600):
        self.model = model
        self.chunk_size = chunk_size
        self.overlap = overlap
        self.doc_embeddings = []
        self.documents = []
    
    def create_long_chunks(self, text: str) -> List[str]:
        """Создание больших перекрывающихся фрагментов"""
        chunks = []
        start = 0
        while start < len(text):
            end = start + self.chunk_size
            chunk = text[start:end]
            chunks.append(chunk)
            start += (self.chunk_size - self.overlap)
        return chunks
    
    def index_document(self, doc: str, metadata: Dict):
        """Индексация документа с иерархическим встраиванием"""
        # Встраивание всего документа
        doc_embedding = self.model.embed(doc)
        
        # Создание больших фрагментов с перекрытием
        chunks = self.create_long_chunks(doc)
        chunk_embeddings = [self.model.embed(c) for c in chunks]
        
        self.doc_embeddings.append({
            'doc_id': len(self.documents),
            'doc_embedding': doc_embedding,
            'chunk_embeddings': chunk_embeddings,
            'chunks': chunks,
            'full_text': doc,
            'metadata': metadata
        })
        self.documents.append(doc)
    
    def retrieve(self, query: str, top_k: int = 3) -> List[Dict]:
        """Извлечение релевантного контента в длинном формате"""
        query_embedding = self.model.embed(query)
        
        # Оценивание на уровне документа в первую очередь
        doc_scores = [
            np.dot(query_embedding, doc['doc_embedding'])
            for doc in self.doc_embeddings
        ]
        
        # Получение лучших документов
        top_doc_indices = np.argsort(doc_scores)[-top_k:][::-1]
        
        results = []
        for idx in top_doc_indices:
            doc_data = self.doc_embeddings[idx]
            
            # Для каждого документа находим лучшие фрагменты
            chunk_scores = [
                np.dot(query_embedding, emb)
                for emb in doc_data['chunk_embeddings']
            ]
            best_chunk_idx = np.argmax(chunk_scores)
            
            # Возврат расширенного контекста вокруг лучшего фрагмента
            context_chunks = self._get_extended_context(
                doc_data['chunks'], 
                best_chunk_idx
            )
            
            results.append({
                'text': ''.join(context_chunks),
                'score': doc_scores[idx],
                'metadata': doc_data['metadata']
            })
        
        return results
    
    def _get_extended_context(self, chunks: List[str], 
                             center_idx: int) -> List[str]:
        """Получение расширенного контекста вокруг релевантного фрагмента"""
        start = max(0, center_idx - 1)
        end = min(len(chunks), center_idx + 2)
        return chunks[start:end]

Сценарии использования и производительность

LongRAG преуспевает в сценариях, где важен контекст:

  • Анализ юридических документов: Контракты и юридические резюме часто имеют зависимости, охватывающие десятки страниц
  • Извлечение научных статей: Понимание методологии требует связных разделов, а не изолированных абзацев
  • Репозитории кода: Функции и классы должны быть поняты в контексте их модуля

Характеристики производительности:

  • Задержка: Выше из-за обработки больших фрагментов (в 2-5 раз медленнее стандартного RAG)
  • Точность: Улучшение на 15-25% в бенчмарках QA для длинных текстов
  • Память: Требуется в 3-4 раза больше памяти для окон контекста

Self-RAG: Рефлексивное извлечение

Основные принципы

Self-RAG вводит метакогнитивный слой в системы RAG. Вместо слепого извлечения и генерации система активно размышляет о своих собственных процессах с помощью специальных токенов размышления:

Токен извлечения: Решает, необходимо ли извлечение для данного запроса Токен релевантности: Оценивает, являются ли извлеченные документы действительно релевантными Токен поддержки: Проверяет, поддерживается ли сгенерированный ответ извлеченным контентом Токен критики: Оценивает общее качество сгенерированного ответа

Архитектурные компоненты

Архитектура Self-RAG состоит из трех переплетающихся фаз:

class SelfRAGSystem:
    def __init__(self, retriever, generator, critic):
        self.retriever = retriever
        self.generator = generator
        self.critic = critic
    
    def generate_with_reflection(self, query: str, 
                                 max_iterations: int = 3):
        """Генерация ответа с самоанализом"""
        
        # Фаза 1: Решение о необходимости извлечения
        retrieve_decision = self.critic.should_retrieve(query)
        
        if not retrieve_decision:
            # Прямая генерация без извлечения
            return self.generator.generate(query)
        
        # Фаза 2: Извлечение и оценка релевантности
        retrieved_docs = self.retriever.retrieve(query)
        relevant_docs = []
        
        for doc in retrieved_docs:
            relevance_score = self.critic.assess_relevance(
                query, doc
            )
            if relevance_score > 0.7:  # Порог
                relevant_docs.append(doc)
        
        if not relevant_docs:
            # Откат к генерации без извлечения
            return self.generator.generate(query)
        
        # Фаза 3: Генерация и проверка поддержки
        best_answer = None
        best_score = -1
        
        for _ in range(max_iterations):
            # Генерация кандидата на ответ
            answer = self.generator.generate(
                query, context=relevant_docs
            )
            
            # Оценка поддержки и качества
            support_score = self.critic.check_support(
                answer, relevant_docs
            )
            quality_score = self.critic.assess_quality(answer)
            
            total_score = 0.6 * support_score + 0.4 * quality_score
            
            if total_score > best_score:
                best_score = total_score
                best_answer = answer
            
            # Ранняя остановка при достижении высокого качества
            if total_score > 0.9:
                break
        
        return {
            'answer': best_answer,
            'confidence': best_score,
            'sources': relevant_docs,
            'reflections': {
                'retrieved': retrieve_decision,
                'relevance': len(relevant_docs),
                'support': support_score
            }
        }

Обучение механизмов рефлексии

Self-RAG требует обучения компонента критика для принятия надежных решений. Обычно это включает:

  1. Обучение с учителем на датасетах, аннотированных суждениями о релевантности
  2. Обучение с подкреплением с наградами за точные предсказания
  3. Контрастивное обучение для различения подтвержденных и неподтвержденных утверждений

Токены рефлексии могут быть реализованы как:

  • Специальные токены в словаре (например, [RETRIEVE], [RELEVANT])
  • Отдельные классифицирующие головы на модели
  • Внешние модели-критики (ансамблевый подход)

Соображения для внедрения в производство

При развертывании Self-RAG в производственных системах:

Компромиссы задержки: Каждый шаг рефлексии добавляет 20-40% накладных расходов на инференс. Балансируйте тщательность с требованиями к времени отклика.

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

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

GraphRAG: Извлечение с усилением графов знаний

Концептуальная основа

GraphRAG трансформирует проблему извлечения из векторной схожести в обход графа. Вместо поиска семантически схожих текстовых фрагментов, GraphRAG идентифицирует релевантные подграфы связанных сущностей и отношений.

Извлечение сущностей: Идентификация именованных сущностей, концепций и их типов Картирование отношений: Извлечение отношений между сущностями (временные, причинно-следственные, иерархические) Построение графа: Создание графа знаний, где сущности являются узлами, а отношения — ребрами Извлечение подграфа: По запросу найти релевантные связанные подграфы

Конвейер построения графа

Построение графа знаний из неструктурированного текста включает несколько этапов:

class GraphRAGBuilder:
    def __init__(self, entity_extractor, relation_extractor):
        self.entity_extractor = entity_extractor
        self.relation_extractor = relation_extractor
        self.graph = NetworkGraph()
    
    def build_graph(self, documents: List[str]):
        """Построение графа знаний из документов"""
        for doc in documents:
            # Извлечение сущностей
            entities = self.entity_extractor.extract(doc)
            
            # Добавление сущностей как узлов
            for entity in entities:
                self.graph.add_node(
                    entity['text'],
                    entity_type=entity['type'],
                    context=entity['surrounding_text']
                )
            
            # Извлечение отношений
            relations = self.relation_extractor.extract(
                doc, entities
            )
            
            # Добавление отношений как ребер
            for rel in relations:
                self.graph.add_edge(
                    rel['source'],
                    rel['target'],
                    relation_type=rel['type'],
                    confidence=rel['score'],
                    evidence=rel['text_span']
                )
    
    def enrich_graph(self):
        """Добавление производных отношений и метаданных"""
        # Вычисление важности узлов (PageRank и т.д.)
        self.graph.compute_centrality()
        
        # Идентификация сообществ/кластеров
        self.graph.detect_communities()
        
        # Добавление временного упорядочивания, если доступны временные метки
        self.graph.add_temporal_edges()

Обработка запросов с графами

Запросы в GraphRAG включают многошаговое рассуждение по графу знаний:

class GraphRAGRetriever:
    def __init__(self, graph, embedder):
        self.graph = graph
        self.embedder = embedder
    
    def retrieve_subgraph(self, query: str, 
                         max_hops: int = 2,
                         max_nodes: int = 50):
        """Извлечение релевантного подграфа для запроса"""
        
        # Идентификация начальных сущностей в запросе
        query_entities = self.entity_extractor.extract(query)
        
        # Поиск совпадающих узлов в графе
        seed_nodes = []
        for entity in query_entities:
            matches = self.graph.find_similar_nodes(
                entity['text'],
                similarity_threshold=0.85
            )
            seed_nodes.extend(matches)
        
        # Расширение подграфа путем обхода
        subgraph = self.graph.create_subgraph()
        visited = set()
        
        for seed in seed_nodes:
            self._expand_from_node(
                seed, 
                subgraph, 
                visited,
                current_hop=0,
                max_hops=max_hops
            )
        
        # Ранжирование узлов по релевантности
        ranked_nodes = self._rank_subgraph_nodes(
            subgraph, query
        )
        
        # Извлечение и форматирование контекста
        context = self._format_graph_context(
            ranked_nodes[:max_nodes],
            subgraph
        )
        
        return context
    
    def _expand_from_node(self, node, subgraph, visited,
                         current_hop, max_hops):
        """Рекурсивное расширение подграфа"""
        if current_hop >= max_hops or node in visited:
            return
        
        visited.add(node)
        subgraph.add_node(node)
        
        # Получение соседей
        neighbors = self.graph.get_neighbors(node)
        
        for neighbor, edge_data in neighbors:
            # Добавление ребра в подграф
            subgraph.add_edge(node, neighbor, edge_data)
            
            # Рекурсивное расширение
            self._expand_from_node(
                neighbor,
                subgraph,
                visited,
                current_hop + 1,
                max_hops
            )
    
    def _format_graph_context(self, nodes, subgraph):
        """Преобразование подграфа в текстовый контекст"""
        context_parts = []
        
        for node in nodes:
            # Добавление контекста узла
            context_parts.append(f"Entity: {node.text}")
            context_parts.append(f"Type: {node.entity_type}")
            
            # Добавление информации об отношениях
            edges = subgraph.get_edges(node)
            for edge in edges:
                context_parts.append(
                    f"- {edge.relation_type} -> {edge.target.text}"
                )
        
        return "\n".join(context_parts)

Реализация GraphRAG от Microsoft

Графический RAG от Microsoft использует уникальный подход, генерируя сводки сообществ:

  1. Построение начального графа из документов с использованием извлечения сущностей/отношений на базе LLM
  2. Обнаружение сообществ с использованием алгоритма Лейдена или аналогичных
  3. Генерация сводок для каждого сообщества с использованием LLM
  4. Иерархическая структура: Построение нескольких уровней абстракции сообществ
  5. Время запроса: Извлечение релевантных сообществ и обход к конкретным сущностям

Этот подход особенно эффективен для:

  • Исследовательских запросов («Каковы основные темы в этом корпусе?»)
  • Многошагового рассуждения («Как A связано с C через B?»)
  • Временного анализа («Как эволюционировали отношения этой сущности?»)

Сравнительный анализ

Когда использовать каждый вариант

Используйте LongRAG, когда:

  • Документы имеют сильную внутреннюю связность
  • Окна контекста вашего LLM поддерживают большие входы (32K+)
  • Ответы на запросы требуют понимания дальнодействующих зависимостей
  • Вы работаете со структурированными документами (отчеты, статьи, книги)

Используйте Self-RAG, когда:

  • Точность и доверие критически важны
  • Вам нужны объяснимые решения по извлечению
  • Ложные срабатывания от нерелевантного извлечения стоят дорого
  • Сложность запросов сильно варьируется (некоторые требуют извлечения, другие нет)

Используйте GraphRAG, когда:

  • Ваша область имеет богатые отношения между сущностями
  • Запросы требуют многошагового рассуждения
  • Важны временные или иерархические отношения
  • Вам нужно понимать связи между сущностями

Сравнение метрик производительности

Метрика Стандартный RAG LongRAG Self-RAG GraphRAG
Время индексации 1x 0.8x 1.1x 3-5x
Задержка запроса 1x 2-3x 1.4x 1.5-2x
Использование памяти 1x 3-4x 1.2x 2-3x
Точность (QA) базовая +15-25% +20-30% +25-40%*
Интерпретируемость Низкая Средняя Высокая Высокая

*Улучшения GraphRAG сильно зависят от предметной области

Гибридные подходы

Самые мощные производственные системы часто комбинируют несколько техник:

LongRAG + GraphRAG: Используйте структуру графа для идентификации релевантных кластеров документов, затем извлекайте полные документы, а не фрагменты

Self-RAG + GraphRAG: Применяйте механизмы рефлексии к решениям обхода графа (какие пути следовать, когда остановиться)

Трехэтапный конвейер: Используйте GraphRAG для начального извлечения на основе сущностей → Self-RAG для фильтрации релевантности → LongRAG для сборки контекста

Соображения реализации

Модели встраивания

Различные варианты RAG имеют разные требования к встраиванию:

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

Self-RAG: Выигрывает от встраиваний, которые захватывают семантические нюансы для тонкой оценки релевантности.

GraphRAG: Требует встраиваний, осознающих сущности. Модели, дообученные на задачах связывания сущностей, работают лучше.

Выбор модели встраивания значительно влияет на производительность. При работе с локальными моделями инструменты вроде Ollama предоставляют простой способ экспериментировать с различными моделями встраивания перед переходом к производному развертыванию.

Стратегии разбивки на фрагменты: пересмотр

Традиционная разбивка на фрагменты фиксированного размера недостаточна для продвинутого RAG:

Семантическая разбивка: Разбивка на естественных границах (абзацы, разделы, смены тем) Рекурсивная разбивка: Создание иерархических фрагментов с отношениями родитель-потомок Скользящее окно: Использование перекрывающихся фрагментов для сохранения контекста на границах Осознание структуры: Уважение структуры документа (заголовки markdown, XML-теги, блоки кода)

Для реализаций на Python библиотеки вроде LangChain и LlamaIndex предоставляют встроенную поддержку этих стратегий разбивки.

Интеграция переранжирования

Переранжирование dramatically улучшает качество извлечения во всех вариантах RAG. После начального извлечения специализированная модель переранжирования переоценивает результаты на основе признаков взаимодействия запрос-документ. Это обеспечивает значительный прирост точности (10-20%) с минимальным влиянием на задержку при продуманной интеграции.

Масштабирование до производства

Конвейер индексации:

  • Используйте распределенную обработку (Ray, Dask) для больших корпусов документов
  • Реализуйте инкрементальную индексацию для обновлений в реальном времени
  • Храните встраивания в оптимизированных векторных базах данных (Pinecone, Weaviate, Qdrant)

Оптимизация запросов:

  • Кэшируйте частые запросы и их результаты
  • Реализуйте маршрутизацию запросов (различные варианты RAG для разных типов запросов)
  • Используйте поиск приближенных ближайших соседей для сублинейного масштабирования

Мониторинг:

  • Отслеживайте оценки релевантности извлечения
  • Мониторьте решения рефлексии в Self-RAG
  • Измеряйте пути и глубины обхода графа
  • Логируйте оценки уверенности и отзывы пользователей

Реальные применения

Поиск по технической документации

Крупный облачный провайдер внедрил GraphRAG для своей документации:

  • Сущности: конечные точки API, параметры, коды ошибок, названия сервисов
  • Отношения: зависимости, совместимость версий, пути миграции
  • Результат: 35% сокращение обращений в службу поддержки, 45% ускорение времени решения проблем

Компания в сфере юридического технологий объединила Self-RAG и LongRAG:

  • Self-RAG отсекает нерелевантные документы на ранних этапах
  • LongRAG сохраняет контекст в сохраненных документах
  • Юристы просматривают на 60% меньше ложных срабатываний
  • Сохранение критического контекста улучшилось с 71% до 94%

Обзор научной литературы

Академический поисковик с гибридным подходом:

  • GraphRAG идентифицирует сети цитирований и научные сообщества
  • LongRAG извлекает полные разделы, сохраняя контекст методологии
  • 40% улучшение в обнаружении релевантных статей
  • Сокращение времени обзора литературы с недель до дней

Продвинутые темы

Мультимодальный RAG

Расширение этих вариантов для обработки изображений, таблиц и кода:

  • Визуальное заземление: Связывание текстовых сущностей с изображениями в документах
  • Понимание таблиц: Парсинг структурированных данных в формат графа
  • Анализ кода: Построение графов зависимостей из кодовых баз

Адаптивный RAG

Динамический выбор стратегии RAG на основе характеристик запроса:

  • Классификатор сложности запроса
  • Детектор типа документа
  • Оптимизатор выгоды/затрат для выбора стратегии

RAG с сохранением приватности

Реализация этих вариантов с ограничениями конфиденциальности:

  • Федеративное извлечение через изолированные хранилища данных
  • Дифференциальная приватность в встраиваниях
  • Зашифрованный поиск по схожести

Начало работы

Быстрый старт на Python

Для тех, кто хочет реализовать эти техники, начало с прочной базы Python является обязательным. Богатая экосистема Python для машинного обучения делает его естественным выбором для разработки RAG.

Вот простая отправная точка для экспериментов:

# Установка зависимостей
# pip install sentence-transformers faiss-cpu langchain

from sentence_transformers import SentenceTransformer
import faiss
import numpy as np

# Базовая настройка для экспериментов с длинными фрагментами
model = SentenceTransformer('all-MiniLM-L6-v2')

documents = [
    # Ваши длинные документы здесь
]

# Создание встраиваний
embeddings = model.encode(documents)

# Построение индекса FAISS
dimension = embeddings.shape[1]
index = faiss.IndexFlatL2(dimension)
index.add(embeddings.astype('float32'))

# Запрос
query = "Ваш вопрос здесь"
query_embedding = model.encode([query])
distances, indices = index.search(
    query_embedding.astype('float32'), k=3
)

Выбор фреймворка

LangChain: Лучший для быстрого прототипирования, обширные интеграции LlamaIndex: Оптимизирован для индексации и извлечения документов Haystack: Готов к производству, сильные абстракции конвейеров Кастомный: Когда вам нужен полный контроль и оптимизация

Фреймворк оценки

Реализуйте строгую оценку перед развертыванием в производство:

Метрики извлечения:

  • Precision@K, Recall@K, MRR (Mean Reciprocal Rank)
  • NDCG (Normalized Discounted Cumulative Gain)

Метрики генерации:

  • ROUGE, BLEU для текстовой схожести
  • BERTScore для семантической схожести
  • Человеческая оценка для оценки качества

Метрики end-to-end:

  • Успешность выполнения задачи
  • Оценки удовлетворенности пользователей
  • Процентили задержки (p50, p95, p99)

Заключение

Ландшафт систем RAG значительно зрел за пределы базового поиска по векторной схожести. LongRAG, Self-RAG и GraphRAG каждый решает конкретные ограничения традиционных подходов:

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

Self-RAG добавляет критическое самосознание в системы извлечения. Размышляя о своих собственных решениях, он снижает ложные срабатывания и повышает доверие — это необходимо для приложений с высокими ставками, где точность важнее скорости.

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

Будущее RAG, вероятно, будет включать гибридные подходы, сочетающие сильные стороны этих вариантов. Производственная система может использовать GraphRAG для идентификации релевантных кластеров сущностей, Self-RAG для фильтрации и валидации извлечений, а LongRAG для сборки связного контекста для LLM.

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

Экосистема инструментов быстро развивается, и фреймворки вроде LangChain, LlamaIndex и Haystack предоставляют все более изощренную поддержку для этих продвинутых паттернов. В сочетании с мощными локальными runtime для LLM и моделями встраивания, никогда еще не было так легко экспериментировать и развертывать системы RAG производственного уровня.

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

Полезные ссылки

Внешние ссылки