Реализация RAG и поиска знаний на Python

В этой главе представлена технология RAG (Retrieval-Augmented Generation).

RAG — одна из ключевых технологий для создания агентов, интенсивно использующих знания.

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


Основы RAG

Основная идея RAG заключается в объединении двух этапов — «информационного поиска» и «генерации языка» — в полноценный конвейер ответов на вопросы.

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

Затем система передаёт извлечённое содержимое модели генерации в качестве контекста, помогая ей выдавать более точные и хорошо обоснованные ответы.

Зачем нужен RAG

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

Параметры модели конечны, и невозможно запомнить в них все знания мира.

Если модель полностью полагается на «припоминание» знаний из параметров, то, сталкиваясь с содержимым, которое не может точно вспомнить или никогда не изучала, она часто с невозмутимым видом выдумывает ответы. Это и есть то, что обычно называют «галлюцинацией».

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

Основная архитектура

Полноценная RAG-система обычно состоит из трёх основных компонентов:

Поисковик: Отвечает за поиск наиболее релевантных фрагментов информации в базе знаний.

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

Генератор: Генерирует итоговый ответ на естественном языке на основе найденного содержимого и исходного вопроса пользователя.

Взаимосвязь трёх компонентов можно понять так: поисковик отвечает за «поиск материалов», векторное хранилище — за «хранение материалов и быстрый поиск похожих материалов», а генератор — за «формирование ответа с опорой на материалы».

Рабочий процесс

Шаг 1:Этап индексации. Разделите исходные документы на несколько текстовых фрагментов, векторизуйте их по одному и сохраните в векторной базе данных. Этот шаг обычно выполняется офлайн и заранее.

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

Шаг 3:Этап дополнения. Объедините найденные релевантные текстовые фрагменты с исходным вопросом пользователя, чтобы построить более полный промпт.

Шаг 4:Этап генерации. Модель генерации создаёт итоговый ответ на основе этого дополненного контекста.

Из этих четырёх шагов только первый является офлайн-предобработкой; остальные три происходят в реальном времени, когда пользователь задаёт запрос. Поэтому скорость поиска и качество поиска напрямую определяют скорость ответа и качество ответа всей системы.

Реализация кода

Базовая реализация RAG

class SimpleRAG:
    """
Реализация упрощённой RAG-системы
Содержит три основных компонента: embedder, vector store, generator
    """


    def __init__(self, embedder, vector_store, generator):
        # Embedder: отвечает за преобразование текста в векторы
        self.embedder = embedder
        # Векторная база данных: отвечает за хранение векторов и поддержку поиска по сходству
        self.vector_store = vector_store
        # Generator: генерирует ответы на основе контекста
        self.generator = generator

    def add_documents(self, documents):
        """
Добавить документы в базу знаний
:param documents: исходный список документов (каждый элемент — цельный фрагмент текста)
        """

        # Шаг 1: Разделить длинные документы на более мелкие текстовые фрагменты для точного поиска
        chunks = self.chunk_documents(documents)

        # Шаг 2: Преобразовать все текстовые фрагменты в векторы
        embeddings = self.embedder.embed(chunks)

        # Шаг 3: Сохранить векторы вместе с соответствующим исходным текстом в векторной базе данных
        self.vector_store.add(embeddings, chunks)

    def chunk_documents(self, documents, chunk_size=500, overlap=50):
        """
Разбиение документов: разделить длинные документы на текстовые фрагменты фиксированной длины с некоторым перекрытием.

:param documents: список исходных документов
:param chunk_size: количество символов на текстовый фрагмент
:param overlap: количество перекрывающихся символов между соседними текстовыми фрагментами (чтобы семантика не обрывалась в точке разделения)
:return: список текстовых фрагментов после разбиения
        """

        chunks = []
        for doc in documents:
            # Скользящее разделение с шагом (chunk_size - overlap), сохраняющее определённую перекрывающуюся область
            for i in range(0, len(doc), chunk_size - overlap):
                chunk = doc[i:i + chunk_size]
                chunks.append(chunk)
        return chunks

    def query(self, question, top_k=5):
        """
Обработать запрос пользователя и вернуть сгенерированный ответ

:param question: вопрос, заданный пользователем
:param top_k: количество релевантных текстовых фрагментов, возвращаемых при извлечении
:return: итоговый ответ, выданный моделью генерации
        """

        # 1. Преобразовать вопрос в вектор, чтобы его можно было сравнить с векторами в базе знаний
        question_embedding = self.embedder.embed([question])[0]

        # 2. Извлеките top_k наиболее похожих текстовых фрагментов из векторной базы данных
        results = self.vector_store.search(question_embedding, top_k)

        # 3. Объедините извлечённые текстовые фрагменты в контекст
        context = "\n".join([doc for doc, _ in results])

        # 4. Организуйте контекст и исходный вопрос в промпт
        prompt = f"Ответьте на вопрос на основе следующего содержания:\n{context}\n\nВопрос: {question}"

        # 5. Передайте это модели генерации для создания финального ответа
        return self.generator.generate(prompt)

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


Продвинутый RAG

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

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

Переранжирование

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

Подход с переранжированием состоит в следующем: сначала с помощью векторного поиска быстро отобрать набор текстов-кандидатов (например, top-20), затем использовать более вычислительно затратный, но более точный кросс-энкодер (Cross-Encoder), чтобы оценить каждого кандидата по одному, переранжировать их и извлечь действительно наиболее релевантные несколько (например, top-5).

Этот двухэтапный подход — «сначала грубая фильтрация, затем точное ранжирование» — балансирует скорость поиска и точность поиска.

RAG с переранжированием

class AdvancedRAG:
    """
Продвинутая RAG-система
Добавьте шаг переранжирования поверх базового конвейера
    """


    def __init__(self, embedder, vector_store, reranker, generator):
        # Модель встраивания
        self.embedder = embedder
        # Векторная база данных
        self.vector_store = vector_store
        # Модель реранжирования (кросс-энкодер) для тонкого ранжирования
        self.reranker = reranker
        # Генератор
        self.generator = generator

    def query(self, question, initial_k=20, final_k=5):
        """
Обрабатывает запрос, включая двухэтапный поиск "грубая фильтрация + точное ранжирование"

: :param question: вопрос пользователя
: :param initial_k: Количество кандидатов, возвращаемых первым этапом векторного поиска.
:param final_k: Количество элементов, окончательно сохраняемых после реранжирования.
        """

        # ==================== Этап 1: Первоначальный поиск (грубая фильтрация) ====================
        Преобразует задачу в вектор.
        question_embedding = self.embedder.embed([question])[0]

        # Быстро извлечь партию текстов-кандидатов с помощью векторного сходства (быстро, средняя точность)
        initial_results = self.vector_store.search(
            question_embedding,
            initial_k
        )

        # ==================== Этап 2: Повторное ранжирование (точное ранжирование) ====================
        Сформируйте пары (вопрос, документ-кандидат) и подайте их в кросс-энкодер для поочерёдной оценки.
        doc_pairs = [(question, doc) for doc, _ in initial_results]

        Кросс-энкодеры кодируют вопрос и документ одновременно, что позволяет более точно судить об их релевантности.
        reranked = self.reranker.rerank(doc_pairs)

        # Возьмите действительно самые релевантные элементы final_k после повторного ранжирования.
        final_context = "\n".join([doc for doc, _ in reranked[:final_k]])

        # ==================== Этап 3: Генерация =====================
        prompt = fКонтекст: {final_context}\n\nВопрос: {question}
        return self.generator.generate(prompt)

Гибридный поиск

Гибридный поиск сочетает преимущества плотного и разреженного поиска.

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

Разреженный поиск (например, BM25) основан на статистике частоты ключевых слов, хорошо выполняет точное буквальное сопоставление и часто более надёжен, чем векторный поиск, в таких сценариях, как имена собственные, числа и фрагменты кода.

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

Гибридный поиск RAG

class HybridRAG:
    """
Гибридный поиск RAG
Объединение плотного поиска (векторного) и разреженного поиска (по ключевым словам)
    """


    def __init__(self, dense_retriever, sparse_retriever, fusion_fn):
        # Плотный ретривер: основан на векторном сходстве, хорошо справляется с семантическим сопоставлением.
        self.dense_retriever = dense_retriever
        # Разреженный ретривер: основан на статистике ключевых слов (например, BM25), хорошо справляется с точным сопоставлением.
        self.sparse_retriever = sparse_retriever
        # Функция слияния: используется для объединения двух результатов поиска, например RRF (см. реализацию ниже)
        self.fusion_fn = fusion_fn

    def query(self, question, top_k):
        """
Выполняет гибридный поиск и возвращает объединённые ранжированные результаты.

: :param question: вопрос пользователя
:param top_k: Итоговое количество результатов для возврата.
        """

        # ==================== Плотный поиск =====================
        # Извлечь больше кандидатов (top_k * 2), чтобы оставить запас для фильтрации во время слияния
        dense_results = self.dense_retriever.search(question, top_k * 2)

        # ==================== Разреженный поиск ====================
        # Поиск по ключевым словам, а также извлечение большего числа кандидатов
        sparse_results = self.sparse_retriever.search(question, top_k * 2)

        # ==================== Объединение результатов ====================
        # Используйте стратегии вроде Reciprocal Rank Fusion (RRF), чтобы объединить результаты ранжирования обоих каналов
        fused = self.fusion_fn(dense_results, sparse_results)

        # Взять top_k элементов с наивысшим объединённым ранжированием
        return fused[:top_k]


def reciprocal_rank_fusion(results_a, results_b, k=60):
    """
Алгоритм Reciprocal Rank Fusion (RRF)
Используется для объединения результатов ранжирования из двух (или нескольких) каналов поиска в единый ранжированный список

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

:param results_a: Результаты поиска A, в формате [(doc, score), ...]
:param results_b: Результаты поиска B, в формате [(doc, score), ...]
:param k: Константа сглаживания, используется для уменьшения разницы весов для документов с более низким рангом, обычно равна 60
:return: Список [(doc, score), ...], отсортированный по убыванию объединённой оценки
    """

    scores = {}

    # Обработка результатов A: чем выше ранг, тем больший вклад в оценку
    for rank, (doc, _) in enumerate(results_a):
        scores[doc] = scores.get(doc, 0) + 1 / (k + rank + 1)

    # Обработка результатов B, аналогично накапливаем оценки по рангу
    for rank, (doc, _) in enumerate(results_b):
        scores[doc] = scores.get(doc, 0) + 1 / (k + rank + 1)

    # Сортировать по суммарной объединенной оценке по убыванию
    sorted_docs = sorted(scores.items(), key=lambda x: -x[1])

    return sorted_docs

Другие стратегии оптимизации

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

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

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


Векторная база данных

Векторная база данных — это инфраструктура RAG-системы, отвечающая за хранение огромных высокоразмерных векторов и поддержку крупномасштабного поиска по сходству с низкой задержкой.

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

Эмбеддинг: процесс преобразования текста (или изображений, аудио и т. д.) в набор плотных числовых векторов, где семантически похожее содержимое находится ближе в векторном пространстве.

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

Мера сходства.: конкретный метод расчёта, используемый для измерения «сходства» или «расстояния» между двумя векторами. Разные метрики подходят для разных сценариев.

Общие метрики сходства

метод измерения формула Особенности Применимые сценарии
Косинусное сходство. cos(A,B) = A·B/(|A||B|) Измеряет только направленное сходство, не зависит от длины вектора, диапазон значений [-1,1] Сходство документов/текста
Евклидово расстояние d(A,B) = sqrt(sum((Ai-Bi)^2)) Измеряет абсолютное пространственное расстояние между векторами, диапазон значений [0,+∞) Сопоставление изображений
скалярное произведение A·B = sum(Ai*Bi) Зависит от направления и длины, обладает высокой вычислительной эффективностью система рекомендаций

Сравнение популярных векторных баз данных

база данных Type Особенности Применимые сценарии
Pinecone облачный сервис Полностью управляемый сервис, легко начать работу, автоматическое масштабирование, ручные операции не требуются Продакшен-среды, требующие быстрого запуска
Weaviate Открытый исходный код Нативно поддерживает гибридный поиск (векторный + по ключевым словам), обладает высокой модульностью Сценарии, требующие гибкой настройки логики извлечения
Milvus Открытый исходный код Высокая доступность, лёгкое горизонтальное масштабирование, поддержка миллиардов векторов и более Векторный поиск в сверхбольших масштабах
Chroma Открытый исходный код Лёгкий, простой API, можно запустить всего с несколькими строками кода Разработка прототипов, обучение и локальное тестирование
Qdrant Открытый исходный код Написан на Rust, отличная производительность, поддерживает расширенные условия фильтрации Сценарии, требующие высокой пропускной способности и сложной фильтрации

Примеры кода

Использование векторной базы данных Chroma

import chroma_client
from chroma_client import ChromaClient

# Создание клиента (можно подключиться к локальному экземпляру или удалённому сервису)
client = ChromaClient()

# Создание или получение коллекции — эквивалент 'таблицы' в реляционной базе данных
collection = client.get_or_create_collection("knowledge_base")

# Добавьте документы: ID, вектор, исходный текст и метаданные должны соответствовать один к одному
collection.add(
    ids=["doc1", "doc2", "doc3"],  # Уникальный идентификатор для каждого документа
    embeddings=[
        [0.1, 0.2, 0.3],  # Вектор, соответствующий документу 1 (фактическая размерность обычно намного выше 3 измерений)
        [0.4, 0.5, 0.6],  # Вектор, соответствующий документу 2
        [0.7, 0.8, 0.9],  # Вектор, соответствующий документу 3
    ],
    документы=[
        Искусственный интеллект — это раздел информатики.,
        "Машинное обучение — это подобласть искусственного интеллекта",
        "Глубокое обучение — это подобласть машинного обучения"
    ],
    metadatas=[
        {"source": “учебник”},  # Информация об источнике документа 1, может использоваться для последующей фильтрации
        {"source": Статья},
        {"source": Статья}
    ]
)

# Извлечение: передать вектор запроса, вернуть наиболее похожие n_results результатов
results = collection.query(
    query_embeddings=[[0.15, 0.25, 0.35]],  # Вектор, соответствующий запросу
    n_results=2  # Вернуть топ-2 наиболее похожих результатов
)

# Вывод результатов поиска
print(results["documents"])   # Совпавшее исходное текстовое содержимое
print(results["distances"])   # Соответствующий показатель расстояния/сходства; обычно чем меньше значение, тем выше сходство

При выборе векторной базы данных нужно всесторонне учитывать масштаб данных, требования к задержке запросов, способ развёртывания (облачное или собственное размещение) и возможности команды по эксплуатации. Для разработки небольших прототипов предпочтительнее Chroma; для готовой к использованию производственной среды выбирайте Pinecone; для сценариев сверхбольшого масштаба, требующих автономности и контроля, больше подходят Milvus или Qdrant.


GraphRAG

GraphRAG — это продвинутое решение, объединяющее граф знаний с RAG.

Он расширяет возможности поиска и рассуждения системы за счёт построения графовой структуры, состоящей из сущностей и отношений.

Почему GraphRAG — это

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

Традиционный RAG также с трудом явно улавливает семантические связи между сущностями, например структурированную информацию вроде «кто чей руководитель» или «какая компания приобрела какую компанию».

GraphRAG организует эти сущности и отношения в граф, позволяя системе рассуждать по путям отношений, а не просто «находить похожий текст».

Ключевые преимущества

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

Поддерживает рассуждения на основе путей и позволяет лучше отвечать на вопросы о связях.

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

Реализация кода

Реализация GraphRAG

class GraphRAG:
    """
Система GraphRAG
Сочетает поиск по графу знаний и векторный поиск, балансируя между рассуждениями на основе связей и семантическим сходством.
    """


    def __init__(self, kg_builder, embedder, vector_store, generator):
        # Построитель графа знаний: отвечает за извлечение сущностей/связей и запросы к графу
        self.kg_builder = kg_builder
        # Embedder: используется для преобразования документов и вопросов в векторы
        self.embedder = embedder
        # Векторная база данных: служит дополнительным каналом для поиска по графу знаний
        self.vector_store = vector_store
        # Генератор: генерирует итоговый ответ на основе объединённого контекста
        self.generator = generator

    def index_documents(self, documents):
        """
Индексировать документы как в графе знаний, так и в векторной базе данных
:param documents: список документов
        """

        for doc in documents:
            # Извлечь сущности из документов
            # Например, извлечь из "OpenAI была основана в 2015"
            # Сущность: OpenAI (организация), 2015 (время)
            entities = self.kg_builder.extract_entities(doc)

            # Извлечь связи между сущностями из документов
            # Например, извлечь триплет отношений: (OpenAI, основана в, 2015)
            relations = self.kg_builder.extract_relations(doc)

            # Записать сущности и связи в граф знаний
            self.kg_builder.add_entities(entities)
            self.kg_builder.add_relations(relations)

            # Одновременно векторизовать исходный текст и сохранить его в векторной базе данных для дополнения семантического поиска
            embedding = self.embedder.embed([doc])
            self.vector_store.add(embedding, [doc])

    def query(self, question):
        """
Обработка запросов: объединить рассуждение по графу знаний и векторный поиск
        """

        # ==================== Поиск по графу знаний ====================
        # Сначала определите релевантные сущности, упомянутые в вопросе
        # Например, "Кто основал OpenAI?" -> определить сущность "OpenAI"
        relevant_entities = self.kg_builder.query_entities(question)

        # На основе этих сущностей извлеките из графа подграф, непосредственно связанный с ними
        # Подграф содержит релевантные сущности, их смежные узлы и соединяющие рёбра
        subgraph = self.kg_builder.get_subgraph(relevant_entities)

        # ==================== Векторный поиск ====================
        # В качестве вспомогательного канала извлеките семантически похожее текстовое содержимое
        vector_results = self.vector_store.search(question, top_k=5)

        # ==================== Объединение результатов ====================
        # Объедините результаты графового рассуждения и результаты векторного поиска в единый контекст
        combined_context = self.fuse_results(subgraph, vector_results)

        # ==================== Генерация ====================
        return self.generator.generate(combined_context, question)

    def fuse_results(self, subgraph, vector_results):
        """
Объедините подграф графа знаний и результаты векторного поиска в текст контекста, читаемый генеративной моделью
        """

        # Преобразуйте подграф в описания на естественном языке (например, "OpenAI -founded in-> 2015")
        kg_text = subgraph.to_text()

        # Объединить исходные текстовые фрагменты, полученные с помощью векторного поиска
        vector_text = "\n".join([doc for doc, _ in vector_results])

        return f"{kg_text}\n{vector_text}"


class KnowledgeGraphBuilder:
    """Построитель графа знаний (иллюстративная реализация; в реальных проектах обычно вызываются специализированные модели NER/извлечения отношений)"""

    def extract_entities(self, text):
        """
# Извлечь именованные сущности из текста, обычно это делается с помощью моделей NER (распознавание именованных сущностей)
# Распространённые типы сущностей включают PERSON (человек), ORG (организация), TIME (время) и т. д.
        """

        entities = []
        return entities

    def extract_relations(self, text):
        """
# Извлечение связей между сущностями из текста, обычно выполняется с помощью моделей извлечения отношений
# Связи обычно представляются в виде триплетов: (головная сущность, тип связи, хвостовая сущность)
        """

        relations = []
        return relations

    def query_entities(self, question):
        """На основе вопроса пользователя определите сущности, участвующие в вопросе, для последующего извлечения подграфа"""
        return []

Сценарии применения

GraphRAG особенно подходит для следующих сценариев:

Вопросно-ответные системы, требующие понимания связей между сущностями, например: "Кто генеральный директор этой компании?"

Вопросы, требующие многошаговых рассуждений для получения ответа, например: "Кто научный руководитель научного руководителя Чжан Саня?"

Сценарии, требующие выявления неявных связей в базе знаний, которые не записаны явно.

Следует отметить, что построение и поддержание самого графа знаний сопряжено с определёнными инженерными затратами (точность извлечения сущностей/связей, обновление и поддержание графа и т.д.), поэтому он лучше подходит для сценариев с чёткими требованиями к рассуждениям о связях и не рекомендуется в качестве отправной точки по умолчанию для всех RAG-проектов.


Сравнение решений и рекомендации

Решение Основной подход Преимущества Ограничения Применимые сценарии
Базовый RAG Векторный поиск + прямая генерация Просто реализовать, низкая стоимость, быстрый старт Ограниченная точность поиска, склонность к извлечению недостаточно релевантного содержимого Простой Q&A, быстрая валидация прототипа
Продвинутый RAG (переранжирование) Грубая фильтрация векторами + точное ранжирование cross-encoder Значительно повышает точность ранжирования при поиске Добавляет дополнительный проход инференса модели, увеличивая задержку и стоимость Сценарии с высокими требованиями к точности ответов
Гибридный поиск Слияние векторного поиска и поиска по ключевым словам Балансирует семантическое сопоставление и точное сопоставление по ключевым словам Требует одновременного поддержания двух поисковых индексов Базы знаний с большим количеством имён собственных, кода и идентификаторов
GraphRAG Слияние графа знаний и векторного поиска Поддерживает рассуждения на основе связей и многошаговые вопросы и ответы Высокие затраты на построение и поддержание графа Сценарии с явными требованиями к рассуждениям на основе связей и многошаговым рассуждениям

Краткое содержание главы

В этой главе представлены основные технологии RAG и поиска знаний.

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

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

Векторная база данных: служит инфраструктурой RAG-систем, отвечая за эффективное хранение и извлечение векторных представлений документов; выбор решения следует делать исходя из масштаба данных и способа развёртывания.

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

Ключ к выбору подходящего RAG-решения — сначала понять реальные потребности бизнес-сценария: для простых сценариев вопросов-ответов базового RAG часто достаточно; когда требуется более высокая точность поиска, можно добавить reranking; когда база знаний содержит много имён собственных/ключевых слов, подходит гибридный поиск; когда задействовано большое количество реляционных рассуждений и многошаговых вопросов-ответов, стоит рассмотреть внедрение GraphRAG. Чем сложнее технология, тем выше затраты на инженерию и сопровождение, поэтому выбирать исходя из реальных потребностей важнее, чем слепо гнаться за «более продвинутыми решениями».

Другие расширения