Векторный поиск - это круто. Вы загружаете документы, режете их на чанки, получаете эмбеддинги, и ваш AI-ассистент бодро находит ответы. Но есть одна беда: он слеп. Не в смысле "не видит текст" - с этим как раз порядок. Он не видит связи между сущностями. Спрашиваете: "Какие документы нужны для ипотеки в Сбере?" - он находит текст про ипотеку. Спрашиваете: "А если у меня плохая кредитная история?" - он снова лезет в ту же кучу чанков, не понимая, что ответ зависит от пересечения двух понятий. Это не вина эмбеддингов. Это архитектурное ограничение чистого векторного поиска.
И тут на сцену выходит GraphRAG. Комбинация графа знаний и RAG, которая разрывает шаблон. Сбер, например, для своего ГигаЧата (на базе GigaChat API) уже использует этот подход. Давайте разберем, как именно и почему это работает, а главное - как внедрить такую систему самому.
💡 Мысль вслух: Если ваша RAG-система начала "врать" при росте базы - вы не одиноки. Я уже писал об этом в статье "Когда RAG начинает врать" - рекомендую прочитать для погружения в контекст.
Почему векторный поиск слеп?
Эмбеддинги хороши в одном: найти семантически похожий текст. Но они не строят логических цепочек. Запрос: "Какие лимиты по кредитной карте для клиента с высокой зарплатой?" - векторная модель найдет куски про "лимит кредитной карты" и отдельно про "высокая зарплата", но не соединит их. Результат: половина ответов нерелевантна, а LLM начинает галлюцинировать, пытаясь склеить разрозненные факты.
Это называется lack of relational context. И именно здесь граф знаний становится палочкой-выручалочкой. Если вы еще не знакомы с основами построения графов - советую глянуть статью "Knowledge Graph на практике" - там разжевано, зачем они нужны и как их строить.
GraphRAG - спаситель контекста
GraphRAG (Graph-based Retrieval-Augmented Generation) - это архитектура, в которой классический векторный поиск дополняется графовым ретривалом. Вы не просто ищете похожие чанки, а перемещаетесь по графу сущностей: от "клиент" к "кредитная карта", от "кредитная карта" к "лимит", от "лимит" к "условия по зарплате". Этот процесс называется traversal. В результате LLM получает не кучу разрозненных текстов, а связный контекст с явными отношениями.
⚠️ Важно: GraphRAG не заменяет векторный поиск - он дополняет его. Гибридная схема (вектора + граф + реранкер) дает наилучший результат. Подробнее о гибридном поиске читайте в материале "Гибридный поиск в Agentic RAG".
Кейс Сбера: как ГигаЧат получил суперсилу
Сбер внедрил GraphRAG для своего корпоративного ассистента ГигаЧат. Вместо того чтобы искать просто по эмбеддингам, они построили граф сущностей: продукты (кредиты, карты, вклады), условия (ставки, лимиты, сроки), клиенты (возраст, доход, история) и отношения между ними. Когда пользователь задает вопрос, система сначала находит релевантные узлы в графе через векторный поиск эмбеддингов узлов, затем выполняет traversal по связям (например, "клиент -> продукт -> условие") и подтягивает текстовые чанки, привязанные к этим узлам.
Результаты впечатляют: по внутренним тестам Сбера (2025 г.), точность ответов выросла на 33%, а количество галлюцинаций снизилось в 2.5 раза. Время ответа при этом увеличилось незначительно (на 150-300 мс) за счет параллельного выполнения graph-walk и векторного поиска.
Как построить GraphRAG: пошаговый план
1 Извлечение графа из документов
Скармливаете каждый документ LLM с промптом для извлечения триплетов: (субъект, отношение, объект). Пример промпта:
prompt = """Извлеки все сущности и отношения из текста.
Формат: сущность1 | отношение | сущность2
Текст: {chunk}"""
response = llm.invoke(prompt)
triplets = parse_triplets(response.text)
Сохраняем триплеты в графовую БД. Для быстрых экспериментов подойдет Neo4j, для продакшена - ArangoDB или даже Rust-графы для AI, где эмбеддинги и связи хранятся в одном движке.
2 Генерация эмбеддингов для узлов
Для каждого узла (сущности) генерируем эмбеддинг на основе его имени и связанных текстов. Храним их в векторной базе (FAISS, Qdrant, или прямо в Elasticsearch). Это позволяет быстро находить стартовые узлы по запросу.
3 Гибридный retrieval
При получении запроса:
- Векторный поиск находит top-K узлов (эмбеддинги запроса vs эмбеддинги узлов).
- Для каждого узла выполняем traversal по графу на глубину 1-2 (получаем соседние узлы и связи).
- Собираем текстовые чанки, привязанные к найденным узлам и связям.
- Подаем их LLM вместе с вопросом.
Схему такого пайплайна можно реализовать на LangGraph или свежих фреймворках вроде LightRAG - кстати, о сравнении с векторным поиском писал в статье "Как графы знаний решают проблему RAG в юриспруденции".
4 Реранкер для финального отбора
Даже с графом в результат может попасть мусор. Ставим реранкер (например, cross-encoder от Cohere или BAAI) на выходе, который заново оценит релевантность каждого чанка к запросу. Это отсекает шум на 15-20%.
Сравнение результатов: чистый Vector Search vs GraphRAG
| Метрика | Vector Search | GraphRAG |
|---|---|---|
| Точность (Precision@5) | 67% | 89% |
| Полнота (Recall@10) | 54% | 78% |
| Доля галлюцинаций | 22% | 8% |
| Время ответа (p95) | 1.2 сек | 1.6 сек |
📊 Данные приведены для тестовой коллекции из 50 000 документов (внутренняя база Сбера + синтетика). Время ответа увеличено, но падение галлюцинаций того стоит.
Типичные ошибки при внедрении GraphRAG
🚫 Ошибка 1: Слишком глубокий граф. Не пытайтесь извлечь все связи. Достаточно 2-3 уровней. Глубокий traversal убивает производительность и зашумляет контекст.
🚫 Ошибка 2: Игнорирование конфликта источников. Если у вас есть свежие SQL-данные и старые вектора - граф может их смешать, дав неверный ответ. Как с этим бороться - разобрано в статье "Когда свежие SQL-данные проигрывают старым векторам".
🚫 Ошибка 3: Отсутствие реранкера. Граф находит много, но не все релевантно. Без реранкера точность падает на 10-15%. Ставьте cross-encoder на выход.
FAQ по GraphRAG
Когда GraphRAG оправдан?
Если ваши документы содержат много связанных сущностей (продукты, условия, клиенты), а запросы пользователей требуют сопоставления сразу нескольких концепций. Для простых FAQ проще остаться на чистом векторном поиске.
Сколько документов нужно для старта?
Минимум 5000-10000, иначе граф будет слишком разреженным. Если у вас меньше - попробуйте гибридный поиск с BM25, он часто достаточен (см. оптимизацию RAG через OpenSearch).
Какую графовую БД выбрать?
Для прототипа - Neo4j (простой Cypher). Для продакшена - NebulaGraph или Rust-граф (быстрее и дешевле). В обзоре свежих исследований RAG есть сравнение фреймворков.
И последнее. Неочевидный совет: не пытайтесь заменить векторный поиск графом. Сделайте пайплайн: vector search -> graph traversal -> reranker. И не забывайте про кеширование traversal-результатов для частых запросов. Именно так Сбер получил 33% прироста без просадки по UX. А если вы используете Elasticsearch или OpenSearch - в них уже есть встроенная поддержка графовых запросов через joins и nested-объекты, что описано в статье "Оптимизация RAG для LLM с Elasticsearch/OpenSearch". Пробуйте, ошибайтесь, но стройте графы - оно того стоит.