Реализация построения графа знаний из текстов (Knowledge Graph Construction)
Граф знаний — это структурированное представление знаний в виде троек (субъект, предикат, объект), хранящихся как граф. Автоматическое построение из текстов позволяет превратить неструктурированные корпусы в навигируемую, запрашиваемую базу знаний.
Что такое граф знаний и когда он нужен
В отличие от реляционной БД, граф знаний гибко представляет многосвязные отношения: «Иван Петров → работает_в → Газпром → расположен_в → Москва → является_столицей → Россия». Запросы по графу («Найди всех сотрудников компаний, расположенных в Москве») невозможны или неудобны в SQL.
Граф знаний нужен когда:
- Данные сильно связные, много типов отношений
- Нужны многоуровневые запросы (граф-обход)
- Планируется объединение данных из разных источников
- Требуется объяснимость: «почему система так решила» — потому что A связан с B через C
Архитектура автоматического построения
Три ключевых компонента работают последовательно:
Entity Extraction — NER расширенным набором типов. Для корпоративных графов: PERSON, ORGANIZATION, LOCATION, PRODUCT, EVENT, DATE, MONEY, ROLE.
Relation Extraction — определение типа связи между парами сущностей в одном предложении или параграфе. REBEL (Babelscape) — лучший открытый инструмент для end-to-end извлечения троек.
Coreference Resolution — разрешение кореференций: «Газпром... Компания... Она...» — все указывают на одну сущность. Используется NeuralCoref или spaCy-experimental.
Entity Linking — привязка упомянутых сущностей к каноническим записям в базе (Wikidata, DBpedia): «ВТБ», «Банк ВТБ», «VTB Bank» → один узел графа.
Технический стек
# REBEL для извлечения троек
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("Babelscape/rebel-large")
model = AutoModelForSeq2SeqLM.from_pretrained("Babelscape/rebel-large")
def extract_triplets(text: str) -> list[tuple]:
inputs = tokenizer(text, return_tensors="pt", max_length=512, truncation=True)
outputs = model.generate(**inputs, max_length=256)
decoded = tokenizer.batch_decode(outputs, skip_special_tokens=False)[0]
# Парсинг специального формата REBEL: <triplet> <subj> <rel> <obj>
return parse_rebel_output(decoded)
Хранилище графа
Neo4j — стандарт де-факто для графовых БД:
from neo4j import GraphDatabase
driver = GraphDatabase.driver("bolt://localhost:7687", auth=("neo4j", "password"))
def add_triplet(tx, subject, predicate, obj, source_doc):
tx.run("""
MERGE (s:Entity {name: $subject})
MERGE (o:Entity {name: $obj})
MERGE (s)-[r:RELATION {type: $predicate, source: $source_doc}]->(o)
""", subject=subject, predicate=predicate, obj=obj, source_doc=source_doc)
Запросы на Cypher:
// Найти всех коллег человека (работающих в той же компании)
MATCH (p:Entity {name: "Иван Петров"})-[:RELATION {type: "работает_в"}]->
(org:Entity)<-[:RELATION {type: "работает_в"}]-(colleague:Entity)
WHERE colleague <> p
RETURN colleague.name
Интеграция с LLM (GraphRAG)
Граф знаний + LLM = GraphRAG: вместо семантического поиска по чанкам, LLM получает контекст из связного подграфа. Microsoft GraphRAG (LangChain реализация) показывает значительно лучшие результаты для вопросов о связях между сущностями по сравнению с классическим RAG.
Workflow:
- Вопрос пользователя → извлечение сущностей
- Обход графа от этих сущностей (2–3 уровня)
- Подграф → текстовое представление → LLM контекст
- LLM генерирует ответ
Поддержание актуальности
Граф знаний устаревает: компании меняют владельцев, люди меняют должности. Инкрементальное обновление:
- Обнаружение противоречий: новая тройка «А работает_в Б» vs существующая «А работает_в В»
- Версионирование рёбер с датами актуальности
- Автоматическая деактивация устаревших связей
Оценка качества
- Precision/Recall/F1 по тройкам (стандарт: CoDEx, KELM датасеты)
- Graph Completeness: процент заполненных атрибутов относительно эталонной базы знаний
- Downstream task quality: улучшение Q&A или рекомендаций — конечная метрика
Сроки реализации
Месяц 1: Определение онтологии (типы сущностей и отношений), настройка pipeline извлечения
Месяц 2–3: Построение графа на историческом корпусе, entity linking к Wikidata
Месяц 4: Neo4j + GraphRAG интерфейс, первые запросы
Месяц 5–6: Инкрементальное обновление, мониторинг качества, интеграция с продуктом







