О чём статья: описание простого подхода к построению системы знаний через синтаксис (NLP) и семантику (LLM).
Под онтологией в общем виде понимается некое представление о структуре мира, о сущностях и их взаимосвязях. В информатике тоже прижилось это понятие — как формальное описание области знаний, позволяющее ее структурировать и систематизировать. Где это может пригодиться? Везде, где было бы удобно представить разрозненные сведения в единую систему для поиска и обработки — документы организаций, обращения пользователей, экспертные системы и т. д. В прошлом веке были попытки делать такие системы, прописывая все возможные запросы и ответы на на них — понятно, что такой способ не сильно взлетел. Небольшое изменение запроса — и ответ не найден, чтобы что‑то найти — нужно точно знать, как именно разработчик обозвал те или иные сущности. В наши дни, кажется, появился инструмент для преодоления этих трудностей — языковые модели (LLM). Да, к ним предъявляют претензии по поводу галлюцинаций и прочего, но это уже хорошее приближение к тому, чтобы формализовать такую вроде бы неформализуемую штуку, как человеческая речь.
Итак, попробуем программно выделить смысловую структуру из текста. Инструментарий пусть будет такой:
Основное приложение (Java, Spring)
SpaCy — библиотека для выделения синтаксических связей (написана почему‑то не на джаве, а на другом языке, кажется, он называется «Piton». Запустим в отдельном контейнере, будем обращаться по API.) Модель — «en_core_web_lg». Если что, для русского языка может подойти «ru_core_news_sm».
LM Studio — платформа для загрузки языковых моделей, предоставляет API. Модель — малютка qwen3–8b_Q4 (для русского языка иногда советуют Сайгу). Корявый код и примеры промптов — на гитхабе.
Возьмём где‑нибудь кусок текста, пусть это будет что‑то про атомы: An atom is a basic unit of matter that consists of a central nucleus surrounded by negatively charged electrons. The nucleus contains protons and neutrons. Electrons revolve around the nucleus in different orbits.
Сначала нужно определить, о ком идёт речь в тексте. Далее такие сущности будем называть «cубъектами». Попросим SpaCy синтаксически разобрать связи и получим список существительных (подлежащих). Иногда субъекты могут скрываться под словами‑заменителями — например, «этот», но, если у нас достаточно цельный фрагмент, то все субъекты в итоге попадут в список.
Вот наши участники:
atom, unit, matter, nucleus, electron(s), proton(s), neutron(s), orbit(s)
Как видно, слова по своей смысловой роли очень разные — какие‑то важны для описания именно атома (nucleus, ядро), а у каких‑то общий или служебный смысл (unit, единица).
Будем пытаться вытаскивать сущностные связи через LLM.
В системном промпте задаём правила вывода (json) и общую цель — выделить для субъектов короткие связи с другими субъектами или понятиями. В шаблон юзер‑промпта закидываем субъектов из нашего списка (по одному на запрос) и исходный фрагмент текста, предлагаем примеры связей. Пока, для простоты, ограничимся тремя типами отношений — структура (вида A состоит из Б), свойство (А имеет свойство Б) и действие (например, А обращается вокруг Б). Прогнав весь список, получаем пару десятков разнообразных связей, типа «nucleus is_surrounded_by electrons» или «electron has_property negatively charged».
Связи, поверьте на слово, вышли очень разношёрстные. Если у нас будет достаточно большой объем текста, из него выжмется огромное количество самых разных соотношений, причем иногда означающих одно и то же, но названных моделью по‑разному (например, «A includes B», «A has_part B»). С отношениями всякого взаимодействия при таком подходе получится множество самых разных глаголов, связывающих субъекты, без учёта их смысла.
Онтологии обычно предполагают возможность поиска нужной информации в структурированных данных. Поэтому наш зоопарк тоже надо как‑то причесать. При анализе полученных отношений возникает логичная мысль их обобщить — пусть у нас будет ещё один уровень связей, уже абстрактных. Если мы разложим много конкретных связей на несколько общих смысловых групп, получится более понятная структура. Что это нам даст в плане использования? Например, можно будет позже (не сейчас) реализовать такую схему: пользователь задаёт вопрос в свободной форме, LLM выделяет подходящую по смыслу абстрактную группу, по этой группе из базы данных вынимаются конкретные связанные понятия, из них LLM обратно создаёт красивый ответ пользователю (да, это похоже на RAG, но не RAG). Разумеется, в продуктовых системах нужен более серьёзный подход, чем изложенный здесь, с максимальной валидацией на всех этапах.
Продолжим. Итак, нужно как‑то составить список общих связей, чтобы потом сгруппировать по ним конкретные. Придумывать этот список лень, поэтому попросим LLM для каждой конкретной связи написать абстрактную (пример: «A contains B» → «A has_part B», has_part будет общим определением для подобных случаев). При каждом следующем запросе пихаем в шаблон промпта предложенные ранее абстрактные отношения и предлагаем выбрать для конкретной связи подходящую, если не получается — пусть придумывает новую. В итоге получаем список. В нём, разумеется, будут попадаться всякие несуразности, убираем их вручную и снова прогоняем через промпт. Через несколько итераций модель уже перестаёт предлагать новые связи, её устраивают те, что есть. Получается более‑менее стройный список абстрактных соотношений, с сопоставленными им наборами конкретных. Можно сделать ещё один уровень — совсем общие группы. В начале мы предлагали в промпте три главных типа, в процессе придумались такие: структурные, классификационные (это про всякие классы и типы/подтипы субъектов), пространственные (про взаимное расположение), а также свойства и действия. Structural, taxonomic, spatial, property, process — такой список можно показывать LLM в промптах, пусть заодно раскидает всё и по этим группам тоже.
Полученную систему понятий можно далее завернуть в красивый граф, и в целом всячески программно обрабатывать. Конечно, здесь обрисована совсем простая схема, на дому
и из подручных материалов. Мечтается же об мощной системе, неутомимо поедающей тексты и аккуратно раскладывающей их в удобную структуру, на которой можно построить, например, механического эксперта по какой‑нибудь реальной области знаний. Будем копать в этом направлении.
Телеграм‑канала нет, поэтому просто — всем бобра, критика и предложения приветствуются.