Главная / Статьи / Ontology-Aware GraphRAG: когда векторам нужны типизированные связи

Ontology-Aware GraphRAG: когда векторам нужны типизированные связи

Как анкоры идентификаторов, контракты онтологии, слияние рангов и механизмы «цитируй или отклони» устраняют сбои RAG при работе с CVE, проблемами многократного владения и негласными фактами графа.

2819 слов

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

Часть 1 — Как именно работает RAG

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

question: "path traversal apache httpd"

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

VECTOR (cosine)                       LEXICAL (keyword overlap)
1. CVE-2021-41773  0.746  ← correct   1. CVE-2021-28544  6.60
2. CVE-2021-23797  0.735              2. CVE-2021-40525  6.47
3. CVE-2021-32643  0.728              5. CVE-2021-41773  5.57  ← correct, buried

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

Часть 2 — С которыми препятствиями сталкивается RAG, и как они измеряются

Ошибка 1 — точные идентификаторы

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

[S1] "Rejected reason: This vulnerability does not meet the criteria for a
      security vulnerability…"

Затем генерация отражает неверного соседа.

Неудача 2 — полнота связей

На вопрос «Какие продукты затронуты?» требуются рёбра, а не просто ближайший параграф. Алгоритмы нахождения сходства возвращают связанные CVE, но не проходят по ссылкам типа AFFECTS.

Неудача 3 — факты, которые никто не записал

Некоторые ответы существуют только в виде пересечений между объектами — никогда в виде отдельного предложения. Ни один фрагмент текста не содержит такого соединения; только граф может его представить.

Часть 3 — Что добавляет граф знаний

Узлы и рёбра с указанным типом делают идентификаторы и связи первостепенными элементами:

(:Vulnerability {cve_id: 'CVE-2021-41773', cvss_base_score: 9.8, cvss_severity: 'CRITICAL'})
   -[:AFFECTS {version: '2.4.49'}]-> (:Product {key: 'apache:http_server'})
   -[:HAS_WEAKNESS]->                (:Weakness {cwe_id: 'CWE-22'})

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

Онтология против графа знаний — операционное различие

Онтология представляет собой контракт, определяющий, какие типы сущностей, какие типы связей и какие свойства необходимы. Граф знаний — это реализация этого контракта с заполненными данными. Без онтологии процесс извлечения информации становится нестабильным, а операции объединения данных теряют надежность. С онтологией пайплайны могут проверять и отклонять некорректные тройки данных до того, как они повлияют на результаты поиска.

Три значения понятия «GraphRAG»

  1. Граф в качестве индекса — хранение фрагментов текста, но поиск осуществляется через соседние узлы графа.
  2. Граф в качестве памяти — сущности и связи являются основным хранилищем данных; текст служит доказательством.
  3. Граф в качестве планировщика — агент планирует последовательность действий, затем запрашивает текст.

Дизайны, учитывающие онтологию, обычно сочетают подходы (2) и (1): структурированные данные для точности и исходный текст для цитирования.

Часть 4 — Архитектура, слой за слоем

Процесс обработки извлекает сущности/связи из онтологии, записывает факты графа, сохраняет исходные участки текста и при этом создает векторный/лексикальный индекс текста. Во время запроса используются анкоры-идентификаторы, расширяются соседние узлы графа, выполняется плотное/лексикальное поисковое восстановление, сливаются рейтинги, и формируется запрос с отдельными разделами ФАКТЫ и ДОКАЗЫ, а также правила цитирования.

Три решения, навязанные данными

  1. Анкоры-идентификаторы превосходят метод нечеткого совпадения, когда присутствует токен CVE/продукта.
  2. Взвешенное слияние должно повышать рейтинги узлов графа для запросов на идентификаторы, не маскируя при этом прозаический текст для запросов на повествование.
  3. Проверки точности должны отклонять ответы, в которых упоминаются отсутствующие теги или противоречат свойствам графа.

Часть 5 — Один вопрос, от начала до конца

Вопрос:

Q: "which products are affected by CVE-2021-41773"

Разрешение анкоров:

ANCHOR  Vulnerability  CVE-2021-41773  method=identifier  conf=1.00

Веса фьюжн при использовании идентификатора в качестве ориентира:

weights = {graph: 2.0, vector: 1.0}     # identifier match
# a lexical product match would be 1.2; no anchor at all, 0.0

Конкурирующие списки:

VECTOR  1. CVE-2021-21022 (Magento IDOR)   2. CVE-2021-27385  …
GRAPH   1. CVE-2021-41773 (anchor)         2. CVE-2021-25216 (shares netapp:cloud_backup)

Оценки фьюжн на основе взаимных рангов:

CVE-2021-41773   2.0/(60+1) = 0.03279   ← graph, rank 1
CVE-2021-21022   1.0/(60+1) = 0.01639   ← vector, rank 1

Факты графа, компрессированные для модели:

FACTS (from the knowledge graph):
[G1] CVE-2021-41773 | CRITICAL 9.8 (CVSS 3.1) | CWE: CWE-22
     affects: apache:http_server 2.4.49, fedoraproject:fedora 34,
              fedoraproject:fedora 35, netapp:cloud_backup,
              oracle:instantis_enterprisetrack 17.1 / 17.2 / 17.3
     source: https://nvd.nist.gov/vuln/detail/CVE-2021-41773

Источники доказательств:

EVIDENCE (source text):
[S1] "A flaw was found in a change made to path normalization in Apache
      HTTP Server 2.4.49. An attacker could use a path traversal attack…"

Структурированный ответ с цитатами:

{"answer": "CVE-2021-41773 is CRITICAL with a CVSS base score of 9.8 [G1].
            It affects apache:http_server 2.4.49, fedoraproject:fedora 34,
            fedoraproject:fedora 35 [G1].",
 "sources": ["G1"],
 "entities": [{"label": "Vulnerability", "key": "CVE-2021-41773"}],
 "confidence": "high"}

Фильтры после генерации:

✓ every cited tag exists in the context
✓ the answer cites something at all
✓ every CVE id in the answer appears in the context
✓ entity labels are real ontology classes
✓ numbers that look like CVSS scores match the graph facts
→ ACCEPTED

Плохой ответ, не прошедший фильтры:

{"answer": "CVE-2021-41773 scores 4.3 and affects nginx [G1]."}

Причины отклонения:

✗ states 4.3 but the graph facts say [9.8]
✗ entity Product nginx:nginx is not in the context
→ REJECTED → one repair attempt → still bad → REFUSAL

Та же самая система, но на один шаг дальше

Объединение данных из инвентаря преобразует «пострадавшие продукты» в «пострадавшие приложения первого уровня и соответствующие команды»:

application        criticality  team            library  pinned    match_precision
checkout-web       tier1        payments        httpd    2.4.49    version-exact
log-aggregator     tier2        infrastructure  httpd    2.4.49    version-exact
api-gateway        tier1        platform-core   httpd    1.15.17   product-level

Та же самая система ориентиров и фьюжн; ещё один шаг через связи между приложениями.

Часть 6 — Результаты, затраты и ошибки

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

Баги, потому что они и являются основным содержанием

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

Часть 7 — Когда создавать это, а когда нет

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

Пять неизменных принципов, важных на любом уровне

  1. Сначала онтология — типы перед тройками данных.
  2. Якоря для идентификаторов — точное совпадение перед использованием коэффициента косинуса.
  3. Разделяйте факты и доказательства в запросе.
  4. Проверка через цитирование или отклонение после генерации ответа.
  5. Оценивайте на основе собственных вопросов — а не только по публичным статистикам успеха.

Эти инварианты остаются полезными как при демонстрации на ноутбуке, так и в системах обеспечения безопасности с множественными арендаторами. Расширение охвата должно подразумевать расширение онтологии и фикстур, а не добавление ещё одного указания к неконтролируемому набору фрагментов данных. Сохраняйте показатели извлечения (точность/покрытие для сущностей и связей) наряду с показателями ответов; в противном случае «лучшая» модель может тайно создавать отношения, которые кажутся логичными, но проваливают аудиты. Версионируйте онтологию как API: добавление изменений происходит легко, переименование требует операций миграции, а удаление — создания «надгробий», чтобы старые копии не восстанавливали удалённые связи. Для круглосуточного мониторинга устанавливайте оповещения при резком увеличении отказов на шлюзе и при высоких показателях ошибок извлекателя, а не только при задержках шлюза — эти сигналы позволяют обнаружить сбои в системе знаний до того, как пользователи заметят неверную степень серьёзности CVE. Наконец, в первые месяцы выделите бюджет на очередь для ручного рассмотрения спорных CVE и сопоставлений продуктов; метки со временем становятся ненадёжными.

Тесты слияния, которые обеспечивают точность весов слияния по мере роста каталога.

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

Рассматривайте веса слияния как параметры конфигурации, подлежащие тестированию: храните их рядом с фиксами, которые зафиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания pull-реквеста для обновления этих фиксов, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в коллективных знаниях.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в традиционных знаниях команды.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в традиционных знаниях команды.

Рассматривайте веса фьюжн как конфигурацию, находящуюся на тестировании: храните их рядом с фикстчерами, которые фиксируют вопрос, списки кандидатов и ожидаемый ID лучшего результата. Когда кто-то «настраивает» веса в ноутбуке, требуйте создания PR для обновления этих фикстчеров, чтобы регрессии не оставались скрытыми в традиционных знаниях команды.

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

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