Реалізація Graph RAG (вилучення з графу знань)

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1Усі 1566 послуг
Реалізація Graph RAG (вилучення з графу знань)
Складний
від 2 тижнів до 3 місяців
Часті запитання

Напрямки AI-розробки

Етапи розробки AI-рішення

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1284
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1196
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    901
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1119
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    586
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    853

Реалізація Graph RAG (видобування з графа знань)

Graph RAG — архітектура, що розширює стандартний векторний RAG структурою графа знань. Замість пошуку тільки за семантично близьким чанкам, система може перетинати граф: від сущности через зв'язки знаходити пов'язані концепції, які не містять ключових слів запиту, але семантично релевантні. Microsoft Research в 2024 році опублікувала GraphRAG — найвпливовішу реалізацію цього підходу.

Коли потрібен Graph RAG

Стандартний RAG не справляється з:

  • Запитаннями про відношення між сущностями ("Як пов'язані компанія X і контракт Y?")
  • Глобальними суммаризуючими запитаннями ("Які основні теми в корпусі документів?")
  • Multi-hop reasoning ("Хто є керівником відділу, відповідального за договір №123?")
  • Трекингом змін у часі

Архітектура Microsoft GraphRAG

Документи
    ↓
LLM видобуває сущності та зв'язки
    ↓
Граф знань (NetworkX/Neo4j)
    ↓
Ієрархічне виявлення спільнот (Leiden algorithm)
    ↓
Суммарі спільнот → Community reports
    ↓
Два режими пошуку:
├── Local search: вектор + graph-traversal від точки
└── Global search: суммаризація community reports

Видобування сущностей та зв'язків через LLM

from openai import OpenAI
import json

client = OpenAI()

ENTITY_EXTRACTION_PROMPT = """Видобути сущності та зв'язки з наступного тексту.
Верни JSON:
{{
  "entities": [
    {{"id": "1", "name": "...", "type": "PERSON|ORG|CONTRACT|REGULATION|CONCEPT", "description": "..."}}
  ],
  "relationships": [
    {{"source": "id1", "target": "id2", "relation": "SIGNED|MANAGES|REFERS_TO|PART_OF", "description": "..."}}
  ]
}}

Текст:
{text}"""

def extract_graph_elements(text: str) -> dict:
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": ENTITY_EXTRACTION_PROMPT.format(text=text)}],
        response_format={"type": "json_object"},
        temperature=0,
    )
    return json.loads(response.choices[0].message.content)

Побудова графа знань з NetworkX

import networkx as nx
from typing import List

class KnowledgeGraph:
    def __init__(self):
        self.graph = nx.DiGraph()
        self.entity_embeddings = {}

    def add_elements(self, elements: dict, source_doc: str):
        # Додаємо сущності
        for entity in elements["entities"]:
            self.graph.add_node(
                entity["id"],
                name=entity["name"],
                type=entity["type"],
                description=entity["description"],
                source=source_doc,
            )

        # Додаємо зв'язки
        for rel in elements["relationships"]:
            self.graph.add_edge(
                rel["source"],
                rel["target"],
                relation=rel["relation"],
                description=rel["description"],
            )

    def get_subgraph(self, entity_id: str, depth: int = 2) -> nx.DiGraph:
        """Повертає подграф навколо сущності"""
        nodes = {entity_id}
        for _ in range(depth):
            neighbors = set()
            for node in nodes:
                neighbors.update(self.graph.predecessors(node))
                neighbors.update(self.graph.successors(node))
            nodes.update(neighbors)
        return self.graph.subgraph(nodes)

    def serialize_subgraph(self, subgraph: nx.DiGraph) -> str:
        """Перетворює подграф на текст для контексту LLM"""
        lines = []
        for node in subgraph.nodes(data=True):
            lines.append(f"Сущність: {node[1].get('name')} ({node[1].get('type')})")
            lines.append(f"  Опис: {node[1].get('description', '')}")

        for edge in subgraph.edges(data=True):
            source_name = subgraph.nodes[edge[0]].get("name", edge[0])
            target_name = subgraph.nodes[edge[1]].get("name", edge[1])
            lines.append(f"Зв'язок: {source_name} → {target_name} ({edge[2].get('relation')})")
            lines.append(f"  {edge[2].get('description', '')}")

        return "\n".join(lines)

Local Search: GraphRAG запит

from langchain_openai import OpenAIEmbeddings
import numpy as np

class GraphRAGRetriever:
    def __init__(self, knowledge_graph: KnowledgeGraph, vectorstore, embeddings):
        self.kg = knowledge_graph
        self.vectorstore = vectorstore
        self.embeddings = embeddings

    def local_search(self, query: str, top_k: int = 5) -> str:
        """
        Local Search: комбінує векторний пошук
        з graph-traversal від знайдених сущностей
        """
        # 1. Векторний пошук чанків
        vector_docs = self.vectorstore.similarity_search(query, k=top_k)

        # 2. Видобування сущностей з знайдених чанків
        mentioned_entities = self._extract_entities_from_docs(vector_docs, query)

        # 3. Graph traversal: розширюємо контекст через пов'язані вузли
        graph_contexts = []
        for entity_id in mentioned_entities[:3]:
            subgraph = self.kg.get_subgraph(entity_id, depth=2)
            graph_context = self.kg.serialize_subgraph(subgraph)
            graph_contexts.append(graph_context)

        # 4. Об'єднуємо текстовий та граф-контекст
        vector_context = "\n\n".join([d.page_content for d in vector_docs])
        graph_context = "\n\n".join(graph_contexts)

        return f"## Текстовий контекст\n{vector_context}\n\n## Контекст з графа знань\n{graph_context}"

Практичний кейс: аналіз корпоративної документації

Задача: асистент юридичного відділу для аналізу відношень між контрагентами, договорами та співробітниками (6500 договорів, 12 років історії).

Запитання, які не вирішував стандартний RAG:

  • "Які постачальники брали участь в тендерах, де переможець пізніше був признаний банкротом?"
  • "Які договори станут затронути зміною керівництва в компанії X?"

Граф: 45 000 сущностей, 180 000 зв'язків (Neo4j).

Результати:

  • Multi-hop запитання (2+ переходи): вирішувалися у 12% стандартним RAG → 71% Graph RAG
  • Глобальні суммаризуючі запитання: 34% → 82%
  • Стандартні запитання (пошук факту): зопоставимо, незначний регрес (-3%)
  • Час побудови графа: 4 дні (GPT-4o для видобування, $240)

Інструменти для Graph RAG

  • Microsoft GraphRAG library: pip install graphrag — повна реалізація від Microsoft
  • Neo4j + LangChain: Neo4jGraph + GraphCypherQAChain для Cypher-запитів
  • LlamaIndex + Knowledge Graph: KnowledgeGraphIndex
  • NetworkX: легковесний граф в Python без зовнішніх залежностей

Графіки

  • Розроблення extraction pipeline (LLM → граф): 2–3 тижні
  • Побудова графа з існуючих документів: 1–4 тижні
  • Local/Global search реалізація: 2 тижні
  • Тестування та оцінка: 1–2 тижні
  • Всього: 6–11 тижнів