Как преобразовать любой текст в граф понятий
Мастерство преобразования текста в озаряющий граф понятий
Несколько месяцев назад основанный на знаниях вопросно-ответный сервис (KBQA) был новинкой. Теперь KBQA с Retrieval Augmented Generation (RAG) является игрушкой для любого энтузиаста искусственного интеллекта. Удивительно наблюдать, как область возможностей в компьютерной лингвистике так быстро расширяется благодаря мощности языковых моделей. И она становится все лучше с каждым днем.
В моей последней статье я рассказал о рекурсивном подходе RAG для реализации QnA с многошаговым рассуждением для ответов на сложные запросы на основе большого корпуса текста.
Исследовательский агент: решение проблемы ответов на вопросы на основе большого корпуса текста
Я создал автономного исследовательского агента искусственного интеллекта, способного отвечать на сложные вопросы с использованием глубокого многошагового рассуждения
towardsdatascience.com
- Исследователи из NVIDIA и Университета Техаса в Остине представили MimicGen автономную систему генерации данных для робототехники.
- Простота точной кластеризации руководство kscorer по автоматическому выбору оптимальных кластеров K-means
- OpenAI объявляет о своей новейшей модели GPT-4 Турбо
Множество людей испробовали его и отправили обратную связь. Благодарю всех за обратную связь. Затем я собрал эти вклады и внес несколько улучшений в код, чтобы исправить некоторые проблемы с исходной реализацией. В планах написать отдельную статью об этом.
В этой статье я хочу поделиться другой идеей, которая, в комбинации с рекурсивным RAG, может помочь создать супер-исследовательского агента. Идея возникла в результате моих экспериментов с рекурсивным RAG с более маленькими языковыми моделями и несколькими другими идеями, которые я прочитал на VoAGI, а именно — Knowledge-Graph Augmented Generation.
Аннотация
Граф Знаний (Knowledge Graph), или любой другой граф, состоит из узлов и ребер. Каждый узел графа представляет собой концепцию, а каждое ребро — отношение между двумя такими концепциями. В этой статье я поделюсь методом преобразования любого текстового корпуса в граф концепций. Я использую термин “граф концепций” (Graph of Concept, GC) взаимозаменяемо с термином “граф знаний” для более точного описания того, что я демонстрирую здесь.
Все компоненты, которые я использовал в этой реализации, можно установить локально, поэтому этот проект легко запускается на персональном компьютере. Здесь я не использую модели GPT, потому что я верю в использование более маленьких открытых моделей. Я использую фантастические модели Mistral 7B Openorca instruct и Zephyr. Эти модели можно локально установить с Ollama.
Базы данных, такие как Neo4j, упрощают хранение и извлечение графовых данных. Здесь я использую Dataframes в памяти Pandas и библиотеку NetworkX для простоты.
Наша цель здесь — преобразовать любой текстовый корпус в граф концепций (GC) и визуализировать его, как красивое баннерное изображение этой статьи. Мы сможем взаимодействовать с графом с помощью перемещения узлов и ребер, масштабирования изображения, а также изменения физики графа по своему усмотрению. Вот ссылка на страницу Github, которая показывает результат того, что мы строим.
https://rahulnyk.github.io/knowledge_graph/
Но давайте сначала погрузимся в основную идею графов знаний и почему они нам нужны. Если вы уже знакомы с этой концепцией, не стесняйтесь пропустить следующий раздел.
Граф Знаний
Рассмотрим следующий текст.
Мэри имела маленькую овечку,Вы уже слышали эту сказку раньше;Но знаете ли вы, что она подала свою тарелку,И ела еще чуть-чуть!
(Надеюсь, здесь нет детей, читающих это 😝)
Вот одно из возможных представлений текста в виде графа знаний.
В следующей статье от IBM наглядно объясняется фундаментальное понятие графов знаний.
Что такое граф знаний? | IBM
Узнайте о графах знаний, сетях семантической метаданных, представляющих собой коллекцию связанных сущностей.
www.ibm.com
Цитируя отрывок из статьи для краткого изложения идеи:
Граф знаний, также известный как семантическая сеть, представляет собой сеть реальных мировых сущностей – объектов, событий, ситуаций или понятий – и показывает связь между ними. Эта информация обычно хранится в графовой базе данных и визуализируется в виде графической структуры, что объясняет термин “граф знаний”.
Почему граф знаний?
Графы знаний полезны в различных отношениях. Мы можем запускать графовые алгоритмы и вычислять центральности любого узла, чтобы понять, насколько важно понятие (узел) для данной работы. Мы можем анализировать связанные и несвязанные группы концепций или вычислять сообщества концепций для глубокого понимания предметной области. Мы можем понять связи между кажущимися несвязанными концепциями.
Мы также можем использовать графы знаний для реализации Усиленной генерации с использованием графического поиска (GRAG или GAG) и взаимодействовать с нашими документами. Это может дать нам гораздо лучшие результаты, чем простая старая версия RAG, которая имеет несколько недостатков. Например, поиск контекста, наиболее релевантного для запроса с помощью обычного семантического поиска сходства, не всегда эффективен. Особенно когда запрос не предоставляет достаточно контекста о своем истинном намерении или когда контекст разбросан по большому корпусу текста.
Например, рассмотрим такой запрос —
Расскажи мне о генеалогическом древе Хосе Аркадио Буэндии в книге “Сто лет одиночества”.
В книге описано 7 поколений Хосе Аркадио Буэндии, причем половина персонажей названа Хосе Аркадио Буэндия. Будет довольно сложно, если вообще возможно, ответить на этот запрос с помощью простого конвейера RAG.
Еще одним недостатком RAG является то, что он не может сказать вам, что спросить. Очень часто задавать правильные вопросы важнее, чем получить ответы.
Усиленная генерация с использованием графа (GAG) может частично устранить эти недостатки RAG. Что еще лучше, мы можем сочетать и соединять и создавать конвейер Усиленной генерации с использованием графа, чтобы получить лучшее из обоих миров.
Теперь мы знаем, что графы интересны, они могут быть чрезвычайно полезными и выглядеть красиво.
Создание графа концепций
Если бы вы спросили GPT, как создать граф знаний из заданного текста, он мог бы предложить процесс, похожий на следующий.
- Извлекайте концепции и сущности из текстового материала. Они являются узлами.
- Извлечь отношения между концепциями. Они являются связями.
- Заполните узлы (концепции) и ребра (связи) в графической структуре или базе данных графов.
- Визуализируйте для художественного наслаждения, если не для чего-то еще.
Шаги 3 и 4 звучат понятно. Но как достичь шагов 1 и 2?
Вот схема метода, который я разработал для извлечения графа концепций из любого данного текстового корпуса. Она похожа на вышеописанный метод, но с некоторыми незначительными различиями.
- Разделите текстовый корпус на фрагменты. Назначьте каждому из этих фрагментов идентификатор.
- Для каждого фрагмента текста извлекайте концепции и их семантические отношения с помощью LLM. Давайте присвоим этому отношению вес W1. Между одной и той же парой концепций может быть несколько отношений. Каждое такое отношение является связью между парой концепций.
- Учтите, что концепции, которые встречаются в одном фрагменте текста, также связаны своей контекстуальной близостью. Давайте присвоим этому отношению вес W2. Обратите внимание, что одна и та же пара концепций может встречаться в нескольких фрагментах.
- Группируйте подобные пары, суммируйте их веса и соединяйте их отношения. Таким образом, у нас теперь есть только одна связь между любой отдельной парой концепций. Связь имеет определенный вес и список отношений в качестве своего имени.
Вы можете увидеть реализацию этого метода в виде кода Python в репозитории GitHub, который я делюсь в этой статье. Давайте кратко рассмотрим основные идеи реализации в следующих нескольких разделах.
Для демонстрации метода здесь я использую следующую обзорную статью, опубликованную в PubMed/Cureus на условиях лицензии Creative Commons Attribution. Заслуги авторов в конце этой статьи.
Повышение кадрового потенциала Индии в здравоохранении
Здоровье Индии за последнее время улучшилось, но все еще отстает от показателей своих ровесников….
www.cureus.com
Мистраль и Первоочередное
Шаг 1 в приведенной выше схеме выполнения прост. Langchain предоставляет множество разделителей текста, которые мы можем использовать для разделения нашего текста на фрагменты.
Шаг 2 – это там начинается настоящее веселье. Чтобы извлечь понятия и их взаимосвязи, я использую модель Mistral 7B. До того, как я сделал выбор варианта модели, наиболее подходящего для наших целей, я экспериментировал со следующими:
Mistral Instruct, Mistral OpenOrca и Zephyr (версия Hugging Face, производная от Mistral)
Я использовал 4-битную квантованную версию этих моделей – чтобы мой Mac не начал меня ненавидеть – запущенных локально с Ollama.
Ollama
Быстрый старт с большими языковыми моделями локально.
ollama.ai
Все эти модели – это настроенные на инструкцию модели с системным приглашением и пользовательским приглашением. Все они хорошо выполняют инструкции и аккуратно форматируют ответ в JSON, если мы попросим об этом.
После нескольких раундов проб и ошибок, я наконец сделал выбор в пользу модели Zephyr с использованием следующих приглашений.
SYS_PROMPT = ( "Вы - создатель сетевого графа, который извлекает термины и их взаимосвязи из заданного контекста. " "Вам предоставлен фрагмент контекста (ограниченный «```»). Ваша задача - извлечь онтологию " "терминов, упомянутых в заданном контексте. Эти термины должны представлять ключевые концепции в соответствии с контекстом. \n" "Мысль 1: Перебирая каждое предложение, подумайте о ключевых терминах, упомянутых в нем.\n" "\tТермины могут включать объект, сущность, местоположение, организацию, человека, \n" "\tсостояние, акроним, документы, услугу, концепцию и т. д.\n" "\tТермины должны быть как можно более атомарными\n\n" "Мысль 2: Подумайте, как эти термины могут иметь однозначное отношение к другим терминам.\n" "\tТермины, упомянутые в одном предложении или одном абзаце, обычно связаны между собой.\n" "\tТермины могут быть связаны с многими другими терминами\n\n" "Мысль 3: Определите отношение между каждой такой связанной парой терминов. \n\n" "Отформатируйте вывод в виде списка json. Каждый элемент списка содержит пару терминов" "и отношение между ними, как показано ниже: \n" "[\n" " {\n" ' "node_1": "Концепция извлеченной онтологии",\n' ' "node_2": "Связанная концепция извлеченной онтологии",\n' ' "edge": "отношение между двумя концепциями, node_1 и node_2 в одном или двух предложениях"\n' " }, {...}\n" "]")USER_PROMPT = f"контекст: ```{input}``` \n\n вывод: "
Если мы передадим нашу (не подходящую) детскую песенку с таким приглашением, вот результат.
[ { "node_1": "Мэри", "node_2": "ягненок", "edge": "владеется" }, { "node_1": "тарелка", "node_2": "пища", "edge": "содержится" }, . . .]
Заметьте, что он даже угадал ‘пища’ как понятие, которое не было явно упомянуто в текстовом фрагменте. Это прекрасно!
Если мы прогоним это через каждый текстовый фрагмент нашей примерной статьи и преобразуем json в таблицу данных Pandas, то она будет выглядеть так.
Каждая строка здесь представляет отношение между парой понятий. Каждая строка представляет собой ребро между двумя узлами в нашем графе, и может быть несколько ребер или отношений между одной и той же парой понятий. Счетчик в таблице данных выше я задал произвольно равным 4.
Контекстуальная близость
Я предполагаю, что понятия, которые встречаются близко друг к другу в корпусе текста, связаны. Назовем это отношение “контекстуальная близость”.
Чтобы вычислить ребра контекстуальной близости, мы преобразуем таблицу данных таким образом, чтобы node_1 и node_2 объединились в одну колонку. Затем мы создаем самосоединение этой таблицы данных с использованием идентификатора фрагмента в качестве ключа. Таким образом, узлы с одинаковыми идентификаторами фрагментов будут объединяться друг с другом, чтобы образовать строку.
Но это также означает, что каждое понятие также будет объединено с самим собой. Это называется самопетлей, когда ребро начинается и заканчивается на одном и том же узле. Чтобы убрать эти самопетли, мы удалим каждую строку, где node_1 равно node_2, из таблицы данных.
В итоге мы получаем таблицу данных, очень похожую на нашу исходную таблицу данных.
Колонка count здесь – это количество фрагментов, где node_1 и node_2 встречаются вместе. Колонка chunk_id – это список всех этих фрагментов.
Итак, у нас теперь есть две таблицы данных, одна с семантическим отношением, а другая с контекстуальной близостью между понятиями, упомянутыми в тексте. Мы можем объединить их, чтобы сформировать нашу таблицу данных графа сети.
Построение графа концепций для нашего текста завершено. Но остановиться на этом этапе будет не очень приятным упражнением. Наша цель – визуализировать граф так же, как на изображении в начале этой статьи, и мы не так далеки от этой цели.
Создание сети понятий
NetworkX – это библиотека Python, которая значительно облегчает работу с графами. Если вы еще не знакомы с библиотекой, нажмите на их логотип ниже для получения дополнительной информации.
Добавление нашей таблицы данных в граф NetworkX – это всего лишь несколько строк кода.
G = nx.Graph()## Добавим узлы в графfor node in nodes: G.add_node(str(node))## Добавим ребра в графfor index, row in dfg.iterrows(): G.add_edge( str(row["node_1"]), str(row["node_2"]), title=row["edge"], weight=row['count'] )
Здесь мы можем начать использовать возможности графа NetworkX. NetworkX предоставляет нам множество алгоритмов для работы с графами. Вот ссылка на список алгоритмов, которые мы можем запустить на нашем графе.
Алгоритмы – документация NetworkX 3.2.1
Изменить описание
networkx.org
Здесь я использую алгоритм обнаружения сообществ, чтобы добавить цвета к узлам. Сообщества – это группы узлов, которые более тесно связаны друг с другом, чем с остальным графом. Сообщества понятий могут дать нам хорошее представление о широких темах, обсуждаемых в тексте.
Алгоритм Girvan Newman обнаружил 17 сообществ понятий в нашей обзорной статье, с которой мы работаем. Вот одно такое сообщество.
['цифровая технология', 'EVIN', 'медицинские приборы', 'системы управления онлайн-обучением', 'носимая, отслеживаемая технология']
Это сразу дает нам представление о широкой теме обсуждаемых в обзорной статье технологий здравоохранения и позволяет нам задавать вопросы, на которые мы затем можем ответить с помощью нашего RAG Pipeline. Не здорово ли это?
Давайте также рассчитаем степень каждого концепта в нашем графе. Степень узла – это общее количество ребер, с которыми он соединен. Так что в нашем случае, чем выше степень концепта, тем более центральным он является для нашего текста. Мы будем использовать степень в качестве размера узла в нашей визуализации.
Визуализация графа
Визуализация – это самая интересная часть этого упражнения. Она имеет определенную качественность, которая дарит вам художественное удовлетворение.
Я использую библиотеку PiVis для создания интерактивных графов. Pyvis – это библиотека Python для визуализации сетей. Вот статья VoAGI, которая демонстрирует простоту и мощь библиотеки.
Pyvis: Визуализация интерактивных сетевых графов на Python
Все, что нужно, это несколько строк кода
towardsdatascience.com
Pyvis имеет встроенный помощник NetworkX для преобразования нашего графа NetworkX в объекты PyVis. Так что нам больше не нужно писать код… Ура!!
Помните, что мы уже рассчитали вес каждого ребра для толщины ребра, сообщества узлов для их цвета и степень каждого узла в качестве их размера.
Так что, со всеми этими дополнительными возможностями, вот наш граф.
Ссылка на интерактивный граф: https://rahulnyk.github.io/knowledge_graph/
Мы можем увеличивать и уменьшать масштаб, перемещать узлы и ребра по своему усмотрению. У нас также есть панель слайдеров внизу страницы для изменения физики графа. Посмотрите, как граф может помочь нам задавать правильные вопросы и лучше понимать предметную область!
Мы также можем обсудить, как наш граф может помочь нам построить Graph Augmented Retrieval и как это может помочь нам создать более эффективный RAG Pipeline. Но я думаю, что лучше оставить это на другой день. Мы уже достигли нашей цели для этой статьи!
Github Repo
GitHub – rahulnyk/knowledge_graph: Преобразование любого текста в граф знаний. Это можно использовать для…
Преобразование любого текста в граф знаний. Это можно использовать для графового расширения и основанных на графах вопросов и ответов…
github.com
Приветствуются вклады и предложения
Я использовал следующую статью для демонстрации своего кода.
Saxena S G, Godfrey T (11 июня 2023 г.) Возможности Индии в решении проблем кадрового обеспечения в здравоохранении. Cureus 15(6): e40274. DOI 10.7759/cureus.40274
Я благодарен авторам за замечательную работу и за ее выпуск на условиях лицензии Creative Commons Attribution.
Обо мне
Я учусь архитектуре (не строениям… технической). Ранее я работал с моделированием полупроводников, проектированием цифровых схем, моделированием электронных интерфейсов и Интернетом вещей. В настоящее время я работаю с интероперабельностью данных и архитектурами хранилищ данных для здоровья и благополучия в Walmart Health and Wellness.