trustgraph/docs/tech-specs/ontology-extract-phase-2.ru.md
Alex Jenkins 8954fa3ad7 Feat: TrustGraph i18n & Documentation Translation Updates (#781)
Native CLI i18n: The TrustGraph CLI has built-in translation support
that dynamically loads language strings. You can test and use
different languages by simply passing the --lang flag (e.g., --lang
es for Spanish, --lang ru for Russian) or by configuring your
environment's LANG variable.

Automated Docs Translations: This PR introduces autonomously
translated Markdown documentation into several target languages,
including Spanish, Swahili, Portuguese, Turkish, Hindi, Hebrew,
Arabic, Simplified Chinese, and Russian.
2026-04-14 12:08:32 +01:00

32 KiB
Raw Blame History

layout title parent
default Извлечение знаний из онтологий - Фаза 2, рефакторинг Russian (Beta)

Извлечение знаний из онтологий - Фаза 2, рефакторинг

Beta Translation: This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.

Статус: Черновик Автор: Аналитическая сессия 2025-12-03 Связанные: ontology.md, ontorag.md

Обзор

Этот документ выявляет несоответствия в текущей системе извлечения знаний на основе онтологий и предлагает рефакторинг для повышения производительности LLM и снижения потери информации.

Текущая реализация

Как это работает сейчас

  1. Загрузка онтологии (ontology_loader.py) Загружает JSON-файл онтологии с ключами, такими как "fo/Recipe", "fo/Food", "fo/produces" Идентификаторы классов включают префикс пространства имен в самом ключе Пример из food.ontology:

    "classes": {
      "fo/Recipe": {
        "uri": "http://purl.org/ontology/fo/Recipe",
        "rdfs:comment": "A Recipe is a combination..."
      }
    }
    
  2. Построение запроса (extract.py:299-307, ontology-prompt.md) Шаблон получает словари classes, object_properties, datatype_properties Шаблон выполняет итерацию: {% for class_id, class_def in classes.items() %} LLM видит: **fo/Recipe**: A Recipe is a combination... Пример формата вывода показывает:

    {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"}
    {"subject": "recipe:cornish-pasty", "predicate": "has_ingredient", "object": "ingredient:flour"}
    
  3. Разбор ответа (extract.py:382-428) Ожидается массив JSON: [{"subject": "...", "predicate": "...", "object": "..."}] Проверка на соответствие подмножеству онтологии Расширение URI с помощью expand_uri() (extract.py:473-521)

  4. Расширение URI (extract.py:473-521) Проверяет, присутствует ли значение в словаре ontology_subset.classes Если найдено, извлекает URI из определения класса Если не найдено, создает URI: f"https://trustgraph.ai/ontology/{ontology_id}#{value}"

Пример потока данных

JSON онтологии → Загрузчик → Запрос:

"fo/Recipe" → classes["fo/Recipe"] → LLM sees "**fo/Recipe**"

Большая языковая модель → Парсер → Вывод:

"Recipe" → not in classes["fo/Recipe"] → constructs URI → LOSES original URI
"fo/Recipe" → found in classes → uses original URI → PRESERVES URI

Выявленные проблемы

1. Несоответствие примеров в запросе

Проблема: Шаблон запроса показывает идентификаторы классов с префиксами (fo/Recipe), но пример вывода использует имена классов без префиксов (Recipe).

Местоположение: ontology-prompt.md:5-52

## Ontology Classes:
- **fo/Recipe**: A Recipe is...

## Example Output:
{"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "Recipe"}

Влияние: LLM получает противоречивые сигналы о том, какой формат использовать.

2. Потеря информации при расширении URI

Проблема: Когда LLM возвращает имена классов без префикса, следуя примеру, expand_uri() не может найти их в словаре онтологии и создает резервные URI, теряя исходные правильные URI.

Местоположение: extract.py:494-500

if value in ontology_subset.classes:  # Looks for "Recipe"
    class_def = ontology_subset.classes[value]  # But key is "fo/Recipe"
    if isinstance(class_def, dict) and 'uri' in class_def:
        return class_def['uri']  # Never reached!
return f"https://trustgraph.ai/ontology/{ontology_id}#{value}"  # Fallback

Влияние: Исходный URI: http://purl.org/ontology/fo/Recipe Сформированный URI: https://trustgraph.ai/ontology/food#Recipe Семантическое значение потеряно, нарушается совместимость.

3. Неоднозначный формат экземпляра сущности

Проблема: Отсутствуют четкие указания относительно формата URI экземпляра сущности.

Примеры в запросе: "recipe:cornish-pasty" (префикс, похожий на пространство имен) "ingredient:flour" (другой префикс)

Фактическое поведение (extract.py:517-520):

# Treat as entity instance - construct unique URI
normalized = value.replace(" ", "-").lower()
return f"https://trustgraph.ai/{ontology_id}/{normalized}"

Влияние: LLM должна угадать соглашение о префиксах без контекста онтологии.

4. Отсутствие рекомендаций по префиксам пространств имен

Проблема: JSON-файл онтологии содержит определения пространств имен (строки 10-25 в food.ontology):

"namespaces": {
  "fo": "http://purl.org/ontology/fo/",
  "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
  ...
}

Но эти данные никогда не передаются в языковую модель. Языковая модель не знает: Что означает "fo" Какой префикс использовать для сущностей К каким элементам относится какое пространство имен

5. Метки, не используемые в запросе

Проблема: У каждого класса есть поля rdfs:label (например, {"value": "Recipe", "lang": "en-gb"}), но шаблон запроса их не использует.

Текущая ситуация: Отображаются только class_id и comment

- **{{class_id}}**{% if class_def.comment %}: {{class_def.comment}}{% endif %}

Доступно, но не используется:

"rdfs:label": [{"value": "Recipe", "lang": "en-gb"}]

Влияние: Может предоставить удобочитаемые имена наряду с техническими идентификаторами.

Предлагаемые решения

Вариант A: Нормализация до идентификаторов без префиксов

Подход: Удалять префиксы из идентификаторов классов перед отображением LLM.

Изменения:

  1. Изменить build_extraction_variables() для преобразования ключей:

    classes_for_prompt = {
        k.split('/')[-1]: v  # "fo/Recipe" → "Recipe"
        for k, v in ontology_subset.classes.items()
    }
    
  2. Обновить пример запроса, чтобы он соответствовал (уже использует имена без префиксов).

  3. Изменить expand_uri() для обработки обоих форматов:

    # Try exact match first
    if value in ontology_subset.classes:
        return ontology_subset.classes[value]['uri']
    
    # Try with prefix
    for prefix in ['fo/', 'rdf:', 'rdfs:']:
        prefixed = f"{prefix}{value}"
        if prefixed in ontology_subset.classes:
            return ontology_subset.classes[prefixed]['uri']
    

Преимущества: Более понятный и читаемый для человека. Соответствует существующим примерам запросов. Большие языковые модели (LLM) лучше работают с более простыми токенами.

Недостатки: Конфликты имен классов, если несколько онтологий имеют одинаковое имя класса. Потеря информации о пространстве имен. Требуется логика обработки исключений для поиска.

Вариант B: Использовать полные префиксные идентификаторы последовательно

Подход: Обновить примеры для использования префиксных идентификаторов, соответствующих тем, которые показаны в списке классов.

Изменения:

  1. Обновить пример запроса (ontology-prompt.md:46-52):

    [
      {"subject": "recipe:cornish-pasty", "predicate": "rdf:type", "object": "fo/Recipe"},
      {"subject": "recipe:cornish-pasty", "predicate": "rdfs:label", "object": "Cornish Pasty"},
      {"subject": "recipe:cornish-pasty", "predicate": "fo/produces", "object": "food:cornish-pasty"},
      {"subject": "food:cornish-pasty", "predicate": "rdf:type", "object": "fo/Food"}
    ]
    
  2. Добавьте объяснение пространства имен в запрос:

    ## Namespace Prefixes:
    - **fo/**: Food Ontology (http://purl.org/ontology/fo/)
    - **rdf:**: RDF Schema
    - **rdfs:**: RDF Schema
    
    Use these prefixes exactly as shown when referencing classes and properties.
    
  3. Оставьте expand_uri() без изменений (это работает правильно, когда найдены совпадения).

Преимущества: Согласованность входных и выходных данных. Отсутствие потери информации. Сохраняет семантику пространства имен. Работает с несколькими онтологиями.

Недостатки: Более многословные токены для LLM. Требует от LLM отслеживания префиксов.

Вариант C: Гибридный - Отображать и метку, и идентификатор.

Подход: Улучшить запрос, чтобы отображать как читаемые человеком метки, так и технические идентификаторы.

Изменения:

  1. Обновить шаблон запроса:

    {% for class_id, class_def in classes.items() %}
    - **{{class_id}}** (label: "{{class_def.labels[0].value if class_def.labels else class_id}}"){% if class_def.comment %}: {{class_def.comment}}{% endif %}
    {% endfor %}
    

    Пример вывода:

    - **fo/Recipe** (label: "Recipe"): A Recipe is a combination...
    
  2. Инструкции по обновлению:

    When referencing classes:
    - Use the full prefixed ID (e.g., "fo/Recipe") in JSON output
    - The label (e.g., "Recipe") is for human understanding only
    

Преимущества: Наиболее понятный формат для больших языковых моделей (LLM). Сохраняет всю информацию. Явно указывает, что использовать.

Недостатки: Более длинный запрос. Более сложный шаблон.

Реализованный подход

Упрощенный формат "Сущность-Отношение-Атрибут" - полностью заменяет старый формат на основе троек.

Новый подход был выбран, потому что:

  1. Отсутствие потери информации: Оригинальные URI сохраняются корректно.
  2. Более простая логика: Не требуется преобразование, прямые запросы к словарям работают.
  3. Безопасность пространств имен: Обрабатывает несколько онтологий без конфликтов.
  4. Семантическая корректность: Сохраняет семантику RDF/OWL.

Реализация завершена

Что было создано:

  1. Новый шаблон запроса (prompts/ontology-extract-v2.txt) Четкие разделы: Типы сущностей, Отношения, Атрибуты. Пример использования полных идентификаторов типов (fo/Recipe, fo/has_ingredient). Инструкции по использованию точных идентификаторов из схемы. Новый формат JSON с массивами сущностей/отношений/атрибутов.

  2. Нормализация сущностей (entity_normalizer.py) normalize_entity_name() - Преобразует имена в формат, безопасный для URI. normalize_type_identifier() - Обрабатывает слеши в типах (fo/Recipefo-recipe). build_entity_uri() - Создает уникальные URI, используя кортеж (имя, тип). EntityRegistry - Отслеживает сущности для исключения дубликатов.

  3. JSON-парсер (simplified_parser.py) Парсит новый формат: {entities: [...], relationships: [...], attributes: [...]} Поддерживает имена полей в формате kebab-case и snake_case. Возвращает структурированные классы данных. Корректная обработка ошибок с ведением журнала.

  4. Тройной преобразователь (triple_converter.py) convert_entity() - Автоматически генерирует тройки типа + метки. convert_relationship() - Соединяет URI сущностей через свойства. convert_attribute() - Добавляет литеральные значения. Выполняет поиск полных URI из определений онтологии.

  5. Обновленный основной процессор (extract.py) Удален старый код извлечения на основе троек. Добавлен метод extract_with_simplified_format(). Теперь использует только новый упрощенный формат. Вызывает запрос с идентификатором extract-with-ontologies-v2.

Тестовые примеры

Тест 1: Сохранение URI

# Given ontology class
classes = {"fo/Recipe": {"uri": "http://purl.org/ontology/fo/Recipe", ...}}

# When LLM returns
llm_output = {"subject": "x", "predicate": "rdf:type", "object": "fo/Recipe"}

# Then expanded URI should be
assert expanded == "http://purl.org/ontology/fo/Recipe"
# Not: "https://trustgraph.ai/ontology/food#Recipe"

Тест 2: Конфликт между несколькими онтологиями

# Given two ontologies
ont1 = {"fo/Recipe": {...}}
ont2 = {"cooking/Recipe": {...}}

# LLM should use full prefix to disambiguate
llm_output = {"object": "fo/Recipe"}  # Not just "Recipe"

Тест 3: Формат экземпляра сущности

# Given prompt with food ontology
# LLM should create instances like
{"subject": "recipe:cornish-pasty"}  # Namespace-style
{"subject": "food:beef"}              # Consistent prefix

Открытые вопросы

  1. Следует ли экземплярам сущностей использовать префиксы пространств имен? Сейчас: "recipe:cornish-pasty" (произвольно) Альтернатива: Использовать префикс онтологии "fo:cornish-pasty"? Альтернатива: Без префикса, расширить в URI "cornish-pasty" → полный URI?

  2. Как обрабатывать область определения/область значений в запросе? В настоящее время отображается: (Recipe → Food) Должно ли быть: (fo/Recipe → fo/Food)?

  3. Следует ли нам проверять ограничения области определения/области значений? TODO комментарий в extract.py:470 Это позволило бы выявлять больше ошибок, но было бы сложнее.

  4. Что касается обратных свойств и эквивалентностей? В онтологии есть owl:inverseOf, owl:equivalentClass В настоящее время не используются при извлечении. Следует ли их использовать?

Показатели успеха

Отсутствие потери информации об URI (100% сохранение исходных URI). Формат вывода LLM соответствует формату входных данных. Отсутствие неоднозначных примеров в запросе. Тесты проходят с использованием нескольких онтологий. Улучшенное качество извлечения (измеряется процентом допустимых троек).

Альтернативный подход: Упрощенный формат извлечения

Философия

Вместо того, чтобы просить LLM понимать семантику RDF/OWL, попросите его делать то, что он умеет хорошо: находить сущности и отношения в тексте.

Пусть код занимается построением URI, преобразованием в RDF и формальностями семантической паутины.

Пример: Классификация сущностей

Исходный текст:

Cornish pasty is a traditional British pastry filled with meat and vegetables.

Схема онтологии (показана LLM):

## Entity Types:
- Recipe: A recipe is a combination of ingredients and a method
- Food: A food is something that can be eaten
- Ingredient: An ingredient combines a quantity and a food

Что возвращает большая языковая модель (простой JSON):

{
  "entities": [
    {
      "entity": "Cornish pasty",
      "type": "Recipe"
    }
  ]
}

Что генерирует код (тройки RDF):

# 1. Normalize entity name + type to ID (type prevents collisions)
entity_id = "recipe-cornish-pasty"  # normalize("Cornish pasty", "Recipe")
entity_uri = "https://trustgraph.ai/food/recipe-cornish-pasty"

# Note: Same name, different type = different URI
# "Cornish pasty" (Recipe) → recipe-cornish-pasty
# "Cornish pasty" (Food) → food-cornish-pasty

# 2. Generate triples
triples = [
    # Type triple
    Triple(
        s=Value(value=entity_uri, is_uri=True),
        p=Value(value="http://www.w3.org/1999/02/22-rdf-syntax-ns#type", is_uri=True),
        o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True)
    ),
    # Label triple (automatic)
    Triple(
        s=Value(value=entity_uri, is_uri=True),
        p=Value(value="http://www.w3.org/2000/01/rdf-schema#label", is_uri=True),
        o=Value(value="Cornish pasty", is_uri=False)
    )
]

Преимущества

  1. LLM (большая языковая модель) не должна: Понимать синтаксис URI Придумывать префиксы идентификаторов (recipe:, ingredient:) Знать о rdf:type или rdfs:label Конструировать идентификаторы семантической паутины

  2. LLM просто должна: Находить сущности в тексте Сопоставлять их с классами онтологии Извлекать отношения и атрибуты

  3. Код обрабатывает: Нормализацию и построение URI Генерацию триплетов RDF Автоматическое присвоение меток Управление пространствами имен

Почему это работает лучше

Более простой запрос = меньше путаницы = меньше ошибок Согласованные идентификаторы = код контролирует правила нормализации Автоматически сгенерированные метки = нет отсутствующих триплетов rdfs:label LLM фокусируется на извлечении = на том, что она действительно хороша

Пример: Отношения между сущностями

Исходный текст:

Cornish pasty is a traditional British pastry filled with beef and potatoes.

Схема онтологии (показана LLM):

## Entity Types:
- Recipe: A recipe is a combination of ingredients and a method
- Food: A food is something that can be eaten
- Ingredient: An ingredient combines a quantity and a food

## Relationships:
- has_ingredient: Relates a recipe to an ingredient it uses (Recipe → Ingredient)
- food: Relates an ingredient to the food that is required (Ingredient → Food)

Что возвращает большая языковая модель (простой JSON):

{
  "entities": [
    {
      "entity": "Cornish pasty",
      "type": "Recipe"
    },
    {
      "entity": "beef",
      "type": "Food"
    },
    {
      "entity": "potatoes",
      "type": "Food"
    }
  ],
  "relationships": [
    {
      "subject": "Cornish pasty",
      "subject-type": "Recipe",
      "relation": "has_ingredient",
      "object": "beef",
      "object-type": "Food"
    },
    {
      "subject": "Cornish pasty",
      "subject-type": "Recipe",
      "relation": "has_ingredient",
      "object": "potatoes",
      "object-type": "Food"
    }
  ]
}

Что генерирует код (тройки RDF):

# Normalize entity names to URIs
cornish_pasty_uri = "https://trustgraph.ai/food/cornish-pasty"
beef_uri = "https://trustgraph.ai/food/beef"
potatoes_uri = "https://trustgraph.ai/food/potatoes"

# Look up relation URI from ontology
has_ingredient_uri = "http://purl.org/ontology/fo/ingredients"  # from fo/has_ingredient

triples = [
    # Entity type triples (as before)
    Triple(s=cornish_pasty_uri, p=rdf_type, o="http://purl.org/ontology/fo/Recipe"),
    Triple(s=cornish_pasty_uri, p=rdfs_label, o="Cornish pasty"),

    Triple(s=beef_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"),
    Triple(s=beef_uri, p=rdfs_label, o="beef"),

    Triple(s=potatoes_uri, p=rdf_type, o="http://purl.org/ontology/fo/Food"),
    Triple(s=potatoes_uri, p=rdfs_label, o="potatoes"),

    # Relationship triples
    Triple(
        s=Value(value=cornish_pasty_uri, is_uri=True),
        p=Value(value=has_ingredient_uri, is_uri=True),
        o=Value(value=beef_uri, is_uri=True)
    ),
    Triple(
        s=Value(value=cornish_pasty_uri, is_uri=True),
        p=Value(value=has_ingredient_uri, is_uri=True),
        o=Value(value=potatoes_uri, is_uri=True)
    )
]

Основные моменты: LLM возвращает имена сущностей на естественном языке: "Cornish pasty", "beef", "potatoes" LLM включает типы для устранения неоднозначности: subject-type, object-type LLM использует имя отношения из схемы: "has_ingredient" Код генерирует согласованные идентификаторы, используя (имя, тип): ("Cornish pasty", "Recipe")recipe-cornish-pasty Код ищет URI отношения в онтологии: fo/has_ingredient → полный URI Одна и та же (имя, тип) всегда получает один и тот же URI (дедупликация)

Пример: Разрешение неоднозначности имени сущности

Проблема: Одно и то же имя может относиться к разным типам сущностей.

Реальный пример:

"Cornish pasty" can be:
- A Recipe (instructions for making it)
- A Food (the dish itself)

Как это обрабатывается:

LLM возвращает оба элемента как отдельные сущности:

{
  "entities": [
    {"entity": "Cornish pasty", "type": "Recipe"},
    {"entity": "Cornish pasty", "type": "Food"}
  ],
  "relationships": [
    {
      "subject": "Cornish pasty",
      "subject-type": "Recipe",
      "relation": "produces",
      "object": "Cornish pasty",
      "object-type": "Food"
    }
  ]
}

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

# Different types → different URIs
recipe_uri = normalize("Cornish pasty", "Recipe")
# → "https://trustgraph.ai/food/recipe-cornish-pasty"

food_uri = normalize("Cornish pasty", "Food")
# → "https://trustgraph.ai/food/food-cornish-pasty"

# Relationship connects them correctly
triple = Triple(
    s=recipe_uri,  # The Recipe
    p="http://purl.org/ontology/fo/produces",
    o=food_uri     # The Food
)

Почему это работает: Тип включен во ВСЕ ссылки (сущности, отношения, атрибуты). Код использует кортеж (name, type) в качестве ключа поиска. Отсутствие неоднозначности, отсутствие конфликтов.

Пример: Атрибуты сущности

Исходный текст:

This Cornish pasty recipe serves 4-6 people and takes 45 minutes to prepare.

Схема онтологии (показана LLM):

## Entity Types:
- Recipe: A recipe is a combination of ingredients and a method

## Attributes:
- serves: Indicates what the recipe is intended to serve (Recipe → text)
- preparation_time: Time needed to prepare the recipe (Recipe → text)

Что возвращает большая языковая модель (простой JSON):

{
  "entities": [
    {
      "entity": "Cornish pasty recipe",
      "type": "Recipe"
    }
  ],
  "attributes": [
    {
      "entity": "Cornish pasty recipe",
      "entity-type": "Recipe",
      "attribute": "serves",
      "value": "4-6 people"
    },
    {
      "entity": "Cornish pasty recipe",
      "entity-type": "Recipe",
      "attribute": "preparation_time",
      "value": "45 minutes"
    }
  ]
}

Что генерирует код (тройки RDF):

# Normalize entity name to URI
recipe_uri = "https://trustgraph.ai/food/cornish-pasty-recipe"

# Look up attribute URIs from ontology
serves_uri = "http://purl.org/ontology/fo/serves"  # from fo/serves
prep_time_uri = "http://purl.org/ontology/fo/preparation_time"  # from fo/preparation_time

triples = [
    # Entity type triple
    Triple(
        s=Value(value=recipe_uri, is_uri=True),
        p=Value(value=rdf_type, is_uri=True),
        o=Value(value="http://purl.org/ontology/fo/Recipe", is_uri=True)
    ),

    # Label triple (automatic)
    Triple(
        s=Value(value=recipe_uri, is_uri=True),
        p=Value(value=rdfs_label, is_uri=True),
        o=Value(value="Cornish pasty recipe", is_uri=False)
    ),

    # Attribute triples (objects are literals, not URIs)
    Triple(
        s=Value(value=recipe_uri, is_uri=True),
        p=Value(value=serves_uri, is_uri=True),
        o=Value(value="4-6 people", is_uri=False)  # Literal value!
    ),
    Triple(
        s=Value(value=recipe_uri, is_uri=True),
        p=Value(value=prep_time_uri, is_uri=True),
        o=Value(value="45 minutes", is_uri=False)  # Literal value!
    )
]

Основные моменты: LLM извлекает строковые значения: "4-6 people", "45 minutes" LLM включает тип сущности для устранения неоднозначности: entity-type LLM использует имя атрибута из схемы: "serves", "preparation_time" Код ищет URI атрибута из свойств типа данных онтологии Объект является строковым значением (is_uri=False), а не ссылкой URI Значения остаются в виде обычного текста, нормализация не требуется

Различия с отношениями: Отношения: и субъект, и объект являются сущностями (URI) Атрибуты: субъект является сущностью (URI), объект является строковым значением (строка/число)

Полный пример: Сущности + Отношения + Атрибуты

Исходный текст:

Cornish pasty is a savory pastry filled with beef and potatoes.
This recipe serves 4 people.

Что возвращает большая языковая модель:

{
  "entities": [
    {
      "entity": "Cornish pasty",
      "type": "Recipe"
    },
    {
      "entity": "beef",
      "type": "Food"
    },
    {
      "entity": "potatoes",
      "type": "Food"
    }
  ],
  "relationships": [
    {
      "subject": "Cornish pasty",
      "subject-type": "Recipe",
      "relation": "has_ingredient",
      "object": "beef",
      "object-type": "Food"
    },
    {
      "subject": "Cornish pasty",
      "subject-type": "Recipe",
      "relation": "has_ingredient",
      "object": "potatoes",
      "object-type": "Food"
    }
  ],
  "attributes": [
    {
      "entity": "Cornish pasty",
      "entity-type": "Recipe",
      "attribute": "serves",
      "value": "4 people"
    }
  ]
}

Результат: Сгенерировано 11 тройных наборов RDF: 3 тройных набора, определяющих тип сущности (rdf:type) 3 тройных набора, определяющих метку сущности (rdfs:label) - автоматически 2 тройных набора, описывающих отношения (has_ingredient) 1 тройной набор, описывающий атрибут (serves)

Все это получено из простых, естественных текстовых извлечений с помощью LLM!

Ссылки

Текущая реализация: trustgraph-flow/trustgraph/extract/kg/ontology/extract.py Шаблон запроса: ontology-prompt.md Тестовые примеры: tests/unit/test_extract/test_ontology/ Пример онтологии: e2e/test-data/food.ontology