feat: productionizing ontology solution [COG-1401] (#623)
<!-- .github/pull_request_template.md --> ## Description This PR contains the ontology feature integrated into cognify ## DCO Affirmation I affirm that all code in every commit of this pull request conforms to the terms of the Topoteretes Developer Certificate of Origin <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Enhanced ontology management with the introduction of the `OntologyResolver` class for improved data handling and querying. - Expanded ontology framework now provides enriched coverage of technology and automotive domains, including new entities and relationships. - Updated entity models now include a validation flag to support improved data integrity. - Added support for specifying an ontology file path in relevant functions to enhance flexibility. - **Refactor** - Streamlined integration of ontology processing across data extraction and workflow routines. - **Chores** - Updated project dependencies to include `owlready2` for advanced ontology functionality. - **Tests** - Introduced a new test suite for the `OntologyResolver` class to validate its functionality under various conditions. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
c1f7b667d1
commit
6fcfb3c398
16 changed files with 1756 additions and 522 deletions
|
|
@ -1,10 +1,11 @@
|
|||
import asyncio
|
||||
import logging
|
||||
from typing import Union
|
||||
from typing import Union, Optional
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from cognee.infrastructure.llm import get_max_chunk_tokens
|
||||
from cognee.modules.ontology.rdf_xml.OntologyResolver import OntologyResolver
|
||||
from cognee.modules.cognify.config import get_cognify_config
|
||||
from cognee.modules.data.methods import get_datasets, get_datasets_by_name
|
||||
from cognee.modules.data.methods.get_dataset_data import get_dataset_data
|
||||
|
|
@ -37,6 +38,7 @@ async def cognify(
|
|||
user: User = None,
|
||||
graph_model: BaseModel = KnowledgeGraph,
|
||||
tasks: list[Task] = None,
|
||||
ontology_file_path: Optional[str] = None,
|
||||
):
|
||||
if user is None:
|
||||
user = await get_default_user()
|
||||
|
|
@ -57,7 +59,7 @@ async def cognify(
|
|||
awaitables = []
|
||||
|
||||
if tasks is None:
|
||||
tasks = await get_default_tasks(user, graph_model)
|
||||
tasks = await get_default_tasks(user, graph_model, ontology_file_path=ontology_file_path)
|
||||
|
||||
for dataset in datasets:
|
||||
dataset_name = generate_dataset_name(dataset.name)
|
||||
|
|
@ -113,13 +115,17 @@ def generate_dataset_name(dataset_name: str) -> str:
|
|||
|
||||
|
||||
async def get_default_tasks( # TODO: Find out a better way to do this (Boris's comment)
|
||||
user: User = None, graph_model: BaseModel = KnowledgeGraph, chunker=TextChunker
|
||||
user: User = None,
|
||||
graph_model: BaseModel = KnowledgeGraph,
|
||||
chunker=TextChunker,
|
||||
ontology_file_path: Optional[str] = None,
|
||||
) -> list[Task]:
|
||||
if user is None:
|
||||
user = await get_default_user()
|
||||
|
||||
try:
|
||||
cognee_config = get_cognify_config()
|
||||
ontology_adapter = OntologyResolver(ontology_file=ontology_file_path)
|
||||
default_tasks = [
|
||||
Task(classify_documents),
|
||||
Task(check_permissions_on_documents, user=user, permissions=["write"]),
|
||||
|
|
@ -129,7 +135,10 @@ async def get_default_tasks( # TODO: Find out a better way to do this (Boris's
|
|||
chunker=chunker,
|
||||
), # Extract text chunks based on the document type.
|
||||
Task(
|
||||
extract_graph_from_data, graph_model=graph_model, task_config={"batch_size": 10}
|
||||
extract_graph_from_data,
|
||||
graph_model=graph_model,
|
||||
ontology_adapter=ontology_adapter,
|
||||
task_config={"batch_size": 10},
|
||||
), # Generate knowledge graphs from the document chunks.
|
||||
Task(
|
||||
summarize_text,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
from cognee.infrastructure.engine import DataPoint
|
||||
from cognee.modules.engine.models.EntityType import EntityType
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class Entity(DataPoint):
|
||||
name: str
|
||||
is_a: EntityType
|
||||
is_a: Optional[EntityType] = None
|
||||
description: str
|
||||
ontology_valid: bool = False
|
||||
|
||||
metadata: dict = {"index_fields": ["name"]}
|
||||
|
|
|
|||
|
|
@ -4,5 +4,6 @@ from cognee.infrastructure.engine import DataPoint
|
|||
class EntityType(DataPoint):
|
||||
name: str
|
||||
description: str
|
||||
ontology_valid: bool = False
|
||||
|
||||
metadata: dict = {"index_fields": ["name"]}
|
||||
|
|
|
|||
|
|
@ -7,83 +7,234 @@ from cognee.modules.engine.utils import (
|
|||
generate_node_id,
|
||||
generate_node_name,
|
||||
)
|
||||
from owlready2 import Thing, ThingClass
|
||||
from cognee.shared.data_models import KnowledgeGraph
|
||||
from cognee.modules.ontology.rdf_xml.OntologyResolver import OntologyResolver
|
||||
|
||||
|
||||
def expand_with_nodes_and_edges(
|
||||
data_chunks: list[DocumentChunk],
|
||||
chunk_graphs: list[KnowledgeGraph],
|
||||
ontology_resolver: OntologyResolver = OntologyResolver(),
|
||||
existing_edges_map: Optional[dict[str, bool]] = None,
|
||||
):
|
||||
if existing_edges_map is None:
|
||||
existing_edges_map = {}
|
||||
|
||||
added_nodes_map = {}
|
||||
|
||||
added_ontology_nodes_map = {}
|
||||
relationships = []
|
||||
ontology_relationships = []
|
||||
|
||||
for index, data_chunk in enumerate(data_chunks):
|
||||
graph = chunk_graphs[index]
|
||||
name_mapping = {}
|
||||
key_mapping = {}
|
||||
|
||||
if graph is None:
|
||||
for data_chunk, graph in zip(data_chunks, chunk_graphs):
|
||||
if not graph:
|
||||
continue
|
||||
|
||||
for node in graph.nodes:
|
||||
node_id = generate_node_id(node.id)
|
||||
node_name = generate_node_name(node.name)
|
||||
|
||||
type_node_id = generate_node_id(node.type)
|
||||
type_node_name = generate_node_name(node.type)
|
||||
|
||||
if f"{str(type_node_id)}_type" not in added_nodes_map:
|
||||
ontology_validated_source_type = False
|
||||
ontology_validated_source_ent = False
|
||||
|
||||
type_node_key = f"{type_node_id}_type"
|
||||
|
||||
if type_node_key not in added_nodes_map and type_node_key not in key_mapping:
|
||||
(
|
||||
ontology_entity_type_nodes,
|
||||
ontology_entity_type_edges,
|
||||
ontology_closest_class_node,
|
||||
) = ontology_resolver.get_subgraph(node_name=type_node_name, node_type="classes")
|
||||
|
||||
if ontology_closest_class_node:
|
||||
name_mapping[type_node_name] = ontology_closest_class_node.name
|
||||
ontology_validated_source_type = True
|
||||
old_key = type_node_key
|
||||
type_node_id = generate_node_id(ontology_closest_class_node.name)
|
||||
type_node_key = f"{type_node_id}_type"
|
||||
type_node_name = generate_node_name(ontology_closest_class_node.name)
|
||||
key_mapping[old_key] = type_node_key
|
||||
|
||||
type_node = EntityType(
|
||||
id=type_node_id,
|
||||
name=type_node_name,
|
||||
type=type_node_name,
|
||||
description=type_node_name,
|
||||
ontology_valid=ontology_validated_source_type,
|
||||
)
|
||||
added_nodes_map[f"{str(type_node_id)}_type"] = type_node
|
||||
else:
|
||||
type_node = added_nodes_map[f"{str(type_node_id)}_type"]
|
||||
added_nodes_map[type_node_key] = type_node
|
||||
|
||||
for ontology_node_to_store in ontology_entity_type_nodes:
|
||||
ont_node_id = generate_node_id(ontology_node_to_store.name)
|
||||
ont_node_name = generate_node_name(ontology_node_to_store.name)
|
||||
|
||||
if isinstance(ontology_node_to_store, ThingClass):
|
||||
ont_node_key = f"{ont_node_id}_type"
|
||||
if (ont_node_key not in added_nodes_map) and (
|
||||
ont_node_key not in added_ontology_nodes_map
|
||||
):
|
||||
added_ontology_nodes_map[ont_node_key] = EntityType(
|
||||
id=ont_node_id,
|
||||
name=ont_node_name,
|
||||
description=ont_node_name,
|
||||
ontology_valid=True,
|
||||
)
|
||||
|
||||
elif isinstance(ontology_node_to_store, Thing):
|
||||
ont_node_key = f"{ont_node_id}_entity"
|
||||
if (ont_node_key not in added_nodes_map) and (
|
||||
ont_node_key not in added_ontology_nodes_map
|
||||
):
|
||||
added_ontology_nodes_map[ont_node_key] = Entity(
|
||||
id=ont_node_id,
|
||||
name=ont_node_name,
|
||||
description=ont_node_name,
|
||||
ontology_valid=True,
|
||||
)
|
||||
|
||||
for source, relation, target in ontology_entity_type_edges:
|
||||
source_node_id = generate_node_id(source)
|
||||
target_node_id = generate_node_id(target)
|
||||
relationship_name = generate_edge_name(relation)
|
||||
edge_key = f"{source_node_id}_{target_node_id}_{relationship_name}"
|
||||
|
||||
if edge_key not in existing_edges_map:
|
||||
ontology_relationships.append(
|
||||
(
|
||||
source_node_id,
|
||||
target_node_id,
|
||||
relationship_name,
|
||||
dict(
|
||||
relationship_name=relationship_name,
|
||||
source_node_id=source_node_id,
|
||||
target_node_id=target_node_id,
|
||||
),
|
||||
)
|
||||
)
|
||||
existing_edges_map[edge_key] = True
|
||||
else:
|
||||
type_node = added_nodes_map.get(type_node_key) or added_nodes_map.get(
|
||||
key_mapping.get(type_node_key)
|
||||
)
|
||||
|
||||
entity_node_key = f"{node_id}_entity"
|
||||
|
||||
if entity_node_key not in added_nodes_map and entity_node_key not in key_mapping:
|
||||
ontology_entity_nodes, ontology_entity_edges, start_ent_ont = (
|
||||
ontology_resolver.get_subgraph(node_name=node_name, node_type="individuals")
|
||||
)
|
||||
|
||||
if start_ent_ont:
|
||||
name_mapping[node_name] = start_ent_ont.name
|
||||
ontology_validated_source_ent = True
|
||||
old_key = entity_node_key
|
||||
node_id = generate_node_id(start_ent_ont.name)
|
||||
entity_node_key = f"{node_id}_entity"
|
||||
node_name = generate_node_name(start_ent_ont.name)
|
||||
key_mapping[old_key] = entity_node_key
|
||||
|
||||
if f"{str(node_id)}_entity" not in added_nodes_map:
|
||||
entity_node = Entity(
|
||||
id=node_id,
|
||||
name=node_name,
|
||||
is_a=type_node,
|
||||
description=node.description,
|
||||
ontology_valid=ontology_validated_source_ent,
|
||||
)
|
||||
|
||||
added_nodes_map[f"{str(node_id)}_entity"] = entity_node
|
||||
added_nodes_map[entity_node_key] = entity_node
|
||||
|
||||
for ontology_node_to_store in ontology_entity_nodes:
|
||||
ont_node_id = generate_node_id(ontology_node_to_store.name)
|
||||
ont_node_name = generate_node_name(ontology_node_to_store.name)
|
||||
|
||||
if isinstance(ontology_node_to_store, ThingClass):
|
||||
ont_node_key = f"{ont_node_id}_type"
|
||||
if (ont_node_key not in added_nodes_map) and (
|
||||
ont_node_key not in added_ontology_nodes_map
|
||||
):
|
||||
added_ontology_nodes_map[ont_node_key] = EntityType(
|
||||
id=ont_node_id,
|
||||
name=ont_node_name,
|
||||
description=ont_node_name,
|
||||
ontology_valid=True,
|
||||
)
|
||||
|
||||
elif isinstance(ontology_node_to_store, Thing):
|
||||
ont_node_key = f"{ont_node_id}_entity"
|
||||
if (ont_node_key not in added_nodes_map) and (
|
||||
ont_node_key not in added_ontology_nodes_map
|
||||
):
|
||||
added_ontology_nodes_map[ont_node_key] = Entity(
|
||||
id=ont_node_id,
|
||||
name=ont_node_name,
|
||||
description=ont_node_name,
|
||||
ontology_valid=True,
|
||||
)
|
||||
|
||||
for source, relation, target in ontology_entity_edges:
|
||||
source_node_id = generate_node_id(source)
|
||||
target_node_id = generate_node_id(target)
|
||||
relationship_name = generate_edge_name(relation)
|
||||
edge_key = f"{source_node_id}_{target_node_id}_{relationship_name}"
|
||||
|
||||
if edge_key not in existing_edges_map:
|
||||
ontology_relationships.append(
|
||||
(
|
||||
source_node_id,
|
||||
target_node_id,
|
||||
relationship_name,
|
||||
dict(
|
||||
relationship_name=relationship_name,
|
||||
source_node_id=source_node_id,
|
||||
target_node_id=target_node_id,
|
||||
ontology_valid=True,
|
||||
),
|
||||
)
|
||||
)
|
||||
existing_edges_map[edge_key] = True
|
||||
|
||||
else:
|
||||
entity_node = added_nodes_map[f"{str(node_id)}_entity"]
|
||||
entity_node = added_nodes_map.get(entity_node_key) or added_nodes_map.get(
|
||||
key_mapping.get(entity_node_key)
|
||||
)
|
||||
|
||||
if data_chunk.contains is None:
|
||||
data_chunk.contains = []
|
||||
|
||||
data_chunk.contains.append(entity_node)
|
||||
|
||||
# Add relationship that came from graphs.
|
||||
for edge in graph.edges:
|
||||
source_node_id = generate_node_id(edge.source_node_id)
|
||||
target_node_id = generate_node_id(edge.target_node_id)
|
||||
source_node_id = generate_node_id(
|
||||
name_mapping.get(edge.source_node_id, edge.source_node_id)
|
||||
)
|
||||
target_node_id = generate_node_id(
|
||||
name_mapping.get(edge.target_node_id, edge.target_node_id)
|
||||
)
|
||||
relationship_name = generate_edge_name(edge.relationship_name)
|
||||
|
||||
edge_key = str(source_node_id) + str(target_node_id) + relationship_name
|
||||
edge_key = f"{source_node_id}_{target_node_id}_{relationship_name}"
|
||||
|
||||
if edge_key not in existing_edges_map:
|
||||
relationships.append(
|
||||
(
|
||||
source_node_id,
|
||||
target_node_id,
|
||||
edge.relationship_name,
|
||||
relationship_name,
|
||||
dict(
|
||||
relationship_name=generate_edge_name(edge.relationship_name),
|
||||
relationship_name=relationship_name,
|
||||
source_node_id=source_node_id,
|
||||
target_node_id=target_node_id,
|
||||
ontology_valid=False,
|
||||
),
|
||||
)
|
||||
)
|
||||
existing_edges_map[edge_key] = True
|
||||
|
||||
return (data_chunks, relationships)
|
||||
graph_nodes = data_chunks + list(added_ontology_nodes_map.values())
|
||||
graph_edges = relationships + ontology_relationships
|
||||
|
||||
return graph_nodes, graph_edges
|
||||
|
|
|
|||
0
cognee/modules/ontology/__init__.py
Normal file
0
cognee/modules/ontology/__init__.py
Normal file
7
cognee/modules/ontology/exceptions/__init__.py
Normal file
7
cognee/modules/ontology/exceptions/__init__.py
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
"""
|
||||
Custom exceptions for the Cognee API.
|
||||
|
||||
This module defines a set of exceptions for handling various data errors
|
||||
"""
|
||||
|
||||
from .exceptions import OntologyInitializationError, FindClosestMatchError, GetSubgraphError
|
||||
32
cognee/modules/ontology/exceptions/exceptions.py
Normal file
32
cognee/modules/ontology/exceptions/exceptions.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
from cognee.exceptions import CogneeApiError
|
||||
from fastapi import status
|
||||
|
||||
|
||||
class OntologyInitializationError(CogneeApiError):
|
||||
def __init__(
|
||||
self,
|
||||
message: str = "Ontology initialization failed",
|
||||
name: str = "OntologyInitializationError",
|
||||
status_code: int = status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
):
|
||||
super().__init__(message, name, status_code)
|
||||
|
||||
|
||||
class FindClosestMatchError(CogneeApiError):
|
||||
def __init__(
|
||||
self,
|
||||
message: str = "Error in find_closest_match",
|
||||
name: str = "FindClosestMatchError",
|
||||
status_code: int = status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
):
|
||||
super().__init__(message, name, status_code)
|
||||
|
||||
|
||||
class GetSubgraphError(CogneeApiError):
|
||||
def __init__(
|
||||
self,
|
||||
message: str = "Failed to retrieve subgraph",
|
||||
name: str = "GetSubgraphError",
|
||||
status_code: int = status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
):
|
||||
super().__init__(message, name, status_code)
|
||||
140
cognee/modules/ontology/rdf_xml/OntologyResolver.py
Normal file
140
cognee/modules/ontology/rdf_xml/OntologyResolver.py
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
import os
|
||||
import difflib
|
||||
import logging
|
||||
from collections import deque
|
||||
from typing import List, Tuple, Dict, Optional, Any
|
||||
from owlready2 import get_ontology, ClassConstruct, Ontology, Thing
|
||||
|
||||
from cognee.modules.ontology.exceptions import (
|
||||
OntologyInitializationError,
|
||||
FindClosestMatchError,
|
||||
GetSubgraphError,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("OntologyAdapter")
|
||||
|
||||
|
||||
class OntologyResolver:
|
||||
def __init__(
|
||||
self,
|
||||
ontology_file: Optional[str] = None,
|
||||
fallback_url: str = "http://example.org/empty_ontology",
|
||||
):
|
||||
self.ontology_file = ontology_file
|
||||
try:
|
||||
if ontology_file and os.path.exists(ontology_file):
|
||||
self.ontology: Ontology = get_ontology(ontology_file).load()
|
||||
logger.info("Ontology loaded successfully from file: %s", ontology_file)
|
||||
else:
|
||||
logger.warning(
|
||||
"Ontology file '%s' not found. Using fallback ontology at %s",
|
||||
ontology_file,
|
||||
fallback_url,
|
||||
)
|
||||
self.ontology = get_ontology(fallback_url)
|
||||
self.build_lookup()
|
||||
except Exception as e:
|
||||
logger.error("Failed to load ontology: %s", str(e))
|
||||
raise OntologyInitializationError() from e
|
||||
|
||||
def build_lookup(self):
|
||||
try:
|
||||
self.lookup: Dict[str, Dict[str, Thing]] = {
|
||||
"classes": {
|
||||
cls.name.lower().replace(" ", "_").strip(): cls
|
||||
for cls in self.ontology.classes()
|
||||
},
|
||||
"individuals": {
|
||||
ind.name.lower().replace(" ", "_").strip(): ind
|
||||
for ind in self.ontology.individuals()
|
||||
},
|
||||
}
|
||||
logger.info(
|
||||
"Lookup built: %d classes, %d individuals",
|
||||
len(self.lookup["classes"]),
|
||||
len(self.lookup["individuals"]),
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error("Failed to build lookup dictionary: %s", str(e))
|
||||
raise RuntimeError("Lookup build failed") from e
|
||||
|
||||
def refresh_lookup(self):
|
||||
self.build_lookup()
|
||||
logger.info("Ontology lookup refreshed.")
|
||||
|
||||
def find_closest_match(self, name: str, category: str) -> Optional[str]:
|
||||
try:
|
||||
normalized_name = name.lower().replace(" ", "_").strip()
|
||||
possible_matches = list(self.lookup.get(category, {}).keys())
|
||||
if normalized_name in possible_matches:
|
||||
return normalized_name
|
||||
|
||||
best_match = difflib.get_close_matches(
|
||||
normalized_name, possible_matches, n=1, cutoff=0.8
|
||||
)
|
||||
return best_match[0] if best_match else None
|
||||
except Exception as e:
|
||||
logger.error("Error in find_closest_match: %s", str(e))
|
||||
raise FindClosestMatchError() from e
|
||||
|
||||
def get_subgraph(
|
||||
self, node_name: str, node_type: str = "individuals"
|
||||
) -> Tuple[List[Any], List[Tuple[str, str, str]], Optional[Any]]:
|
||||
nodes_set = set()
|
||||
edges: List[Tuple[str, str, str]] = []
|
||||
visited_nodes = set()
|
||||
queue = deque()
|
||||
|
||||
try:
|
||||
closest_match = self.find_closest_match(name=node_name, category=node_type)
|
||||
if not closest_match:
|
||||
logger.info("No close match found for '%s' in category '%s'", node_name, node_type)
|
||||
return list(nodes_set), edges, None
|
||||
|
||||
node = self.lookup[node_type].get(closest_match)
|
||||
if node is None:
|
||||
logger.info("Node '%s' not found in lookup.", closest_match)
|
||||
return list(nodes_set), edges, None
|
||||
|
||||
logger.info("%s match was found for found for '%s' node", node.name, node_name)
|
||||
|
||||
queue.append(node)
|
||||
visited_nodes.add(node)
|
||||
nodes_set.add(node)
|
||||
|
||||
while queue:
|
||||
current_node = queue.popleft()
|
||||
|
||||
if hasattr(current_node, "is_a"):
|
||||
for parent in current_node.is_a:
|
||||
if isinstance(parent, ClassConstruct):
|
||||
if hasattr(parent, "value") and hasattr(parent.value, "name"):
|
||||
parent = parent.value
|
||||
else:
|
||||
continue
|
||||
edges.append((current_node.name, "is_a", parent.name))
|
||||
nodes_set.add(parent)
|
||||
if parent not in visited_nodes:
|
||||
visited_nodes.add(parent)
|
||||
queue.append(parent)
|
||||
|
||||
for prop in self.ontology.object_properties():
|
||||
for target in prop[current_node]:
|
||||
edges.append((current_node.name, prop.name, target.name))
|
||||
nodes_set.add(target)
|
||||
if target not in visited_nodes:
|
||||
visited_nodes.add(target)
|
||||
queue.append(target)
|
||||
|
||||
for source in prop.range:
|
||||
if current_node in prop[source]:
|
||||
edges.append((source.name, prop.name, current_node.name))
|
||||
nodes_set.add(source)
|
||||
if source not in visited_nodes:
|
||||
visited_nodes.add(source)
|
||||
queue.append(source)
|
||||
|
||||
return list(nodes_set), edges, node
|
||||
except Exception as e:
|
||||
logger.error("Error in get_subgraph: %s", str(e))
|
||||
raise GetSubgraphError() from e
|
||||
0
cognee/modules/ontology/rdf_xml/__init__.py
Normal file
0
cognee/modules/ontology/rdf_xml/__init__.py
Normal file
|
|
@ -4,6 +4,7 @@ from typing import Type, List
|
|||
from pydantic import BaseModel
|
||||
|
||||
from cognee.infrastructure.databases.graph import get_graph_engine
|
||||
from cognee.modules.ontology.rdf_xml.OntologyResolver import OntologyResolver
|
||||
from cognee.modules.chunking.models.DocumentChunk import DocumentChunk
|
||||
from cognee.modules.data.extraction.knowledge_graph import extract_content_graph
|
||||
from cognee.modules.graph.utils import (
|
||||
|
|
@ -15,7 +16,10 @@ from cognee.tasks.storage import add_data_points
|
|||
|
||||
|
||||
async def integrate_chunk_graphs(
|
||||
data_chunks: list[DocumentChunk], chunk_graphs: list, graph_model: Type[BaseModel]
|
||||
data_chunks: list[DocumentChunk],
|
||||
chunk_graphs: list,
|
||||
graph_model: Type[BaseModel],
|
||||
ontology_adapter: OntologyResolver,
|
||||
) -> List[DocumentChunk]:
|
||||
"""Updates DocumentChunk objects, integrates data points and edges into databases."""
|
||||
graph_engine = await get_graph_engine()
|
||||
|
|
@ -34,9 +38,7 @@ async def integrate_chunk_graphs(
|
|||
)
|
||||
|
||||
graph_nodes, graph_edges = expand_with_nodes_and_edges(
|
||||
data_chunks,
|
||||
chunk_graphs,
|
||||
existing_edges_map,
|
||||
data_chunks, chunk_graphs, ontology_adapter, existing_edges_map
|
||||
)
|
||||
|
||||
if len(graph_nodes) > 0:
|
||||
|
|
@ -49,10 +51,12 @@ async def integrate_chunk_graphs(
|
|||
|
||||
|
||||
async def extract_graph_from_data(
|
||||
data_chunks: list[DocumentChunk], graph_model: Type[BaseModel]
|
||||
data_chunks: list[DocumentChunk],
|
||||
graph_model: Type[BaseModel],
|
||||
ontology_adapter: OntologyResolver = OntologyResolver(),
|
||||
) -> List[DocumentChunk]:
|
||||
"""Extracts and integrates a knowledge graph from the text content of document chunks using a specified graph model."""
|
||||
chunk_graphs = await asyncio.gather(
|
||||
*[extract_content_graph(chunk.text, graph_model) for chunk in data_chunks]
|
||||
)
|
||||
return await integrate_chunk_graphs(data_chunks, chunk_graphs, graph_model)
|
||||
return await integrate_chunk_graphs(data_chunks, chunk_graphs, graph_model, ontology_adapter)
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ chunk_by_sentence_module = sys.modules.get("cognee.tasks.chunks.chunk_by_sentenc
|
|||
|
||||
|
||||
GROUND_TRUTH = [
|
||||
{"word_count": 879, "len_text": 5607, "cut_type": "sentence_end"},
|
||||
{"word_count": 953, "len_text": 6363, "cut_type": "sentence_end"},
|
||||
{"word_count": 879, "len_text": 5697, "cut_type": "sentence_end"},
|
||||
{"word_count": 953, "len_text": 6473, "cut_type": "sentence_end"},
|
||||
]
|
||||
|
||||
|
||||
|
|
|
|||
161
cognee/tests/unit/modules/ontology/test_ontology_adapter.py
Normal file
161
cognee/tests/unit/modules/ontology/test_ontology_adapter.py
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
import pytest
|
||||
from owlready2 import get_ontology, Thing
|
||||
from cognee.modules.ontology.rdf_xml.OntologyResolver import OntologyResolver
|
||||
|
||||
|
||||
def test_ontology_adapter_initialization_success():
|
||||
"""Test successful initialization of OntologyAdapter."""
|
||||
ontology = get_ontology("http://example.org/test_ontology")
|
||||
|
||||
adapter = OntologyResolver()
|
||||
adapter.ontology = ontology
|
||||
adapter.build_lookup()
|
||||
|
||||
assert adapter.ontology is not None
|
||||
assert isinstance(adapter.lookup, dict)
|
||||
|
||||
|
||||
def test_ontology_adapter_initialization_file_not_found():
|
||||
"""Test OntologyAdapter initialization with nonexistent file."""
|
||||
adapter = OntologyResolver(ontology_file="nonexistent.owl")
|
||||
assert adapter.ontology.base_iri == "http://example.org/empty_ontology#"
|
||||
|
||||
|
||||
def test_build_lookup():
|
||||
"""Test the lookup dictionary is correctly built."""
|
||||
ontology = get_ontology("http://example.org/test_ontology")
|
||||
|
||||
with ontology:
|
||||
|
||||
class Car(Thing):
|
||||
pass
|
||||
|
||||
Car("Audi")
|
||||
|
||||
adapter = OntologyResolver()
|
||||
adapter.ontology = ontology
|
||||
adapter.build_lookup()
|
||||
|
||||
assert isinstance(adapter.lookup, dict)
|
||||
assert "car" in adapter.lookup["classes"]
|
||||
assert "audi" in adapter.lookup["individuals"]
|
||||
|
||||
|
||||
def test_find_closest_match_exact():
|
||||
"""Test finding exact match in lookup."""
|
||||
ontology = get_ontology("http://example.org/test_ontology")
|
||||
|
||||
with ontology:
|
||||
|
||||
class Car(Thing):
|
||||
pass
|
||||
|
||||
Car("Audi")
|
||||
|
||||
adapter = OntologyResolver()
|
||||
adapter.ontology = ontology
|
||||
adapter.build_lookup()
|
||||
|
||||
result = adapter.find_closest_match("Audi", "individuals")
|
||||
|
||||
assert result is not None
|
||||
assert result == "audi"
|
||||
|
||||
|
||||
def test_find_closest_match_fuzzy():
|
||||
"""Test fuzzy matching for lookup."""
|
||||
ontology = get_ontology("http://example.org/test_ontology")
|
||||
|
||||
with ontology:
|
||||
|
||||
class Car(Thing):
|
||||
pass
|
||||
|
||||
Car("Audi")
|
||||
Car("BMW")
|
||||
|
||||
adapter = OntologyResolver()
|
||||
adapter.ontology = ontology
|
||||
adapter.build_lookup()
|
||||
|
||||
result = adapter.find_closest_match("Audii", "individuals")
|
||||
|
||||
assert result == "audi"
|
||||
|
||||
|
||||
def test_find_closest_match_no_match():
|
||||
"""Test no match found in lookup."""
|
||||
ontology = get_ontology("http://example.org/test_ontology")
|
||||
|
||||
adapter = OntologyResolver()
|
||||
adapter.ontology = ontology
|
||||
adapter.build_lookup()
|
||||
|
||||
result = adapter.find_closest_match("Nonexistent", "individuals")
|
||||
|
||||
assert result is None
|
||||
|
||||
|
||||
def test_get_subgraph_no_match():
|
||||
"""Test get_subgraph with no matching node."""
|
||||
ontology = get_ontology("http://example.org/test_ontology")
|
||||
|
||||
adapter = OntologyResolver()
|
||||
adapter.ontology = ontology
|
||||
adapter.build_lookup()
|
||||
|
||||
nodes, relationships, start_node = adapter.get_subgraph("Nonexistent", "individuals")
|
||||
|
||||
assert nodes == []
|
||||
assert relationships == []
|
||||
assert start_node is None
|
||||
|
||||
|
||||
def test_get_subgraph_success():
|
||||
"""Test successful retrieval of subgraph."""
|
||||
ontology = get_ontology("http://example.org/test_ontology")
|
||||
|
||||
with ontology:
|
||||
|
||||
class Company(Thing):
|
||||
pass
|
||||
|
||||
class Vehicle(Thing):
|
||||
pass
|
||||
|
||||
class Car(Vehicle):
|
||||
pass
|
||||
|
||||
audi = Car("Audi")
|
||||
porsche = Car("Porsche")
|
||||
vw = Company("VW")
|
||||
|
||||
vw.owns = [audi, porsche]
|
||||
|
||||
adapter = OntologyResolver()
|
||||
adapter.ontology = ontology
|
||||
adapter.build_lookup()
|
||||
|
||||
nodes, relationships, start_node = adapter.get_subgraph("Audi", "individuals")
|
||||
|
||||
assert audi in nodes
|
||||
assert Car in nodes
|
||||
assert Vehicle in nodes
|
||||
assert Thing in nodes
|
||||
assert ("Audi", "is_a", "Car") in relationships
|
||||
assert ("Car", "is_a", "Vehicle") in relationships
|
||||
assert ("Vehicle", "is_a", "Thing") in relationships
|
||||
|
||||
|
||||
def test_refresh_lookup():
|
||||
"""Test refreshing lookup rebuilds the dictionary."""
|
||||
ontology = get_ontology("http://example.org/test_ontology")
|
||||
|
||||
adapter = OntologyResolver()
|
||||
adapter.ontology = ontology
|
||||
adapter.build_lookup()
|
||||
|
||||
original_lookup = adapter.lookup.copy()
|
||||
adapter.refresh_lookup()
|
||||
|
||||
assert adapter.lookup is not original_lookup
|
||||
89
examples/python/ontology_demo_example.py
Normal file
89
examples/python/ontology_demo_example.py
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import cognee
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
|
||||
from cognee.api.v1.search import SearchType
|
||||
from cognee.api.v1.visualize.visualize import visualize_graph
|
||||
from cognee.shared.utils import setup_logging
|
||||
|
||||
text_1 = """
|
||||
1. Audi
|
||||
Audi is known for its modern designs and advanced technology. Founded in the early 1900s, the brand has earned a reputation for precision engineering and innovation. With features like the Quattro all-wheel-drive system, Audi offers a range of vehicles from stylish sedans to high-performance sports cars.
|
||||
|
||||
2. BMW
|
||||
BMW, short for Bayerische Motoren Werke, is celebrated for its focus on performance and driving pleasure. The company’s vehicles are designed to provide a dynamic and engaging driving experience, and their slogan, "The Ultimate Driving Machine," reflects that commitment. BMW produces a variety of cars that combine luxury with sporty performance.
|
||||
|
||||
3. Mercedes-Benz
|
||||
Mercedes-Benz is synonymous with luxury and quality. With a history dating back to the early 20th century, the brand is known for its elegant designs, innovative safety features, and high-quality engineering. Mercedes-Benz manufactures not only luxury sedans but also SUVs, sports cars, and commercial vehicles, catering to a wide range of needs.
|
||||
|
||||
4. Porsche
|
||||
Porsche is a name that stands for high-performance sports cars. Founded in 1931, the brand has become famous for models like the iconic Porsche 911. Porsche cars are celebrated for their speed, precision, and distinctive design, appealing to car enthusiasts who value both performance and style.
|
||||
|
||||
5. Volkswagen
|
||||
Volkswagen, which means “people’s car” in German, was established with the idea of making affordable and reliable vehicles accessible to everyone. Over the years, Volkswagen has produced several iconic models, such as the Beetle and the Golf. Today, it remains one of the largest car manufacturers in the world, offering a wide range of vehicles that balance practicality with quality.
|
||||
|
||||
Each of these car manufacturer contributes to Germany's reputation as a leader in the global automotive industry, showcasing a blend of innovation, performance, and design excellence.
|
||||
"""
|
||||
|
||||
text_2 = """
|
||||
1. Apple
|
||||
Apple is renowned for its innovative consumer electronics and software. Its product lineup includes the iPhone, iPad, Mac computers, and wearables like the Apple Watch. Known for its emphasis on sleek design and user-friendly interfaces, Apple has built a loyal customer base and created a seamless ecosystem that integrates hardware, software, and services.
|
||||
|
||||
2. Google
|
||||
Founded in 1998, Google started as a search engine and quickly became the go-to resource for finding information online. Over the years, the company has diversified its offerings to include digital advertising, cloud computing, mobile operating systems (Android), and various web services like Gmail and Google Maps. Google’s innovations have played a major role in shaping the internet landscape.
|
||||
|
||||
3. Microsoft
|
||||
Microsoft Corporation has been a dominant force in software for decades. Its Windows operating system and Microsoft Office suite are staples in both business and personal computing. In recent years, Microsoft has expanded into cloud computing with Azure, gaming with the Xbox platform, and even hardware through products like the Surface line. This evolution has helped the company maintain its relevance in a rapidly changing tech world.
|
||||
|
||||
4. Amazon
|
||||
What began as an online bookstore has grown into one of the largest e-commerce platforms globally. Amazon is known for its vast online marketplace, but its influence extends far beyond retail. With Amazon Web Services (AWS), the company has become a leader in cloud computing, offering robust solutions that power websites, applications, and businesses around the world. Amazon’s constant drive for innovation continues to reshape both retail and technology sectors.
|
||||
|
||||
5. Meta
|
||||
Meta, originally known as Facebook, revolutionized social media by connecting billions of people worldwide. Beyond its core social networking service, Meta is investing in the next generation of digital experiences through virtual and augmented reality technologies, with projects like Oculus. The company’s efforts signal a commitment to evolving digital interaction and building the metaverse—a shared virtual space where users can connect and collaborate.
|
||||
|
||||
Each of these companies has significantly impacted the technology landscape, driving innovation and transforming everyday life through their groundbreaking products and services.
|
||||
"""
|
||||
|
||||
|
||||
async def main():
|
||||
# Step 1: Reset data and system state
|
||||
await cognee.prune.prune_data()
|
||||
await cognee.prune.prune_system(metadata=True)
|
||||
|
||||
# Step 2: Add text
|
||||
text_list = [text_1, text_2]
|
||||
await cognee.add(text_list)
|
||||
|
||||
# Step 3: Create knowledge graph
|
||||
|
||||
ontology_path = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)), "ontology_input_example/basic_ontology.owl"
|
||||
)
|
||||
|
||||
pipeline_run = await cognee.cognify(ontology_file_path=ontology_path)
|
||||
print("Knowledge with ontology created.")
|
||||
|
||||
# Step 4: Calculate descriptive metrics
|
||||
await cognee.get_pipeline_run_metrics(pipeline_run, include_optional=True)
|
||||
print("Descriptive graph metrics saved to database.")
|
||||
|
||||
# Step 5: Query insights
|
||||
search_results = await cognee.search(
|
||||
query_type=SearchType.GRAPH_COMPLETION,
|
||||
query_text="What are the exact cars and their types produced by Audi?",
|
||||
)
|
||||
print(search_results)
|
||||
|
||||
await visualize_graph()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
setup_logging(logging.INFO)
|
||||
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
try:
|
||||
loop.run_until_complete(main())
|
||||
finally:
|
||||
loop.run_until_complete(loop.shutdown_asyncgens())
|
||||
290
examples/python/ontology_input_example/basic_ontology.owl
Normal file
290
examples/python/ontology_input_example/basic_ontology.owl
Normal file
|
|
@ -0,0 +1,290 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rdf:RDF
|
||||
xmlns:ns1="http://example.org/ontology#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
|
||||
>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Volkswagen">
|
||||
<rdfs:comment>Created for making cars accessible to everyone.</rdfs:comment>
|
||||
<ns1:produces rdf:resource="http://example.org/ontology#VW_Golf"/>
|
||||
<ns1:produces rdf:resource="http://example.org/ontology#VW_ID4"/>
|
||||
<ns1:produces rdf:resource="http://example.org/ontology#VW_Touareg"/>
|
||||
<rdf:type rdf:resource="http://example.org/ontology#CarManufacturer"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Azure">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#CloudServiceProvider"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Porsche">
|
||||
<ns1:produces rdf:resource="http://example.org/ontology#Porsche_Cayenne"/>
|
||||
<ns1:produces rdf:resource="http://example.org/ontology#Porsche_Taycan"/>
|
||||
<ns1:produces rdf:resource="http://example.org/ontology#Porsche_911"/>
|
||||
<rdf:type rdf:resource="http://example.org/ontology#CarManufacturer"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
<rdfs:comment>Famous for high-performance sports cars.</rdfs:comment>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Meta">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#TechnologyCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#Instagram"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#Facebook"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#Oculus"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#WhatsApp"/>
|
||||
<rdfs:comment>Pioneering social media and virtual reality technology.</rdfs:comment>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#TechnologyCompany">
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Apple">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#TechnologyCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
<rdfs:comment>Known for its innovative consumer electronics and software.</rdfs:comment>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#iPad"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#iPhone"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#AppleWatch"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#MacBook"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Audi">
|
||||
<ns1:produces rdf:resource="http://example.org/ontology#Audi_eTron"/>
|
||||
<ns1:produces rdf:resource="http://example.org/ontology#Audi_R8"/>
|
||||
<ns1:produces rdf:resource="http://example.org/ontology#Audi_A8"/>
|
||||
<rdf:type rdf:resource="http://example.org/ontology#CarManufacturer"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
<rdfs:comment>Known for its modern designs and technology.</rdfs:comment>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#AmazonEcho">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#HardwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Porsche_Taycan">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#ElectricCar"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#BMW">
|
||||
<ns1:produces rdf:resource="http://example.org/ontology#BMW_7Series"/>
|
||||
<ns1:produces rdf:resource="http://example.org/ontology#BMW_M4"/>
|
||||
<ns1:produces rdf:resource="http://example.org/ontology#BMW_iX"/>
|
||||
<rdf:type rdf:resource="http://example.org/ontology#CarManufacturer"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
<rdfs:comment>Focused on performance and driving pleasure.</rdfs:comment>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#VW_Touareg">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#SUV"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#SportsCar">
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
|
||||
<rdfs:subClassOf rdf:resource="http://example.org/ontology#Car"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#ElectricCar">
|
||||
<rdfs:subClassOf rdf:resource="http://example.org/ontology#Car"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Google">
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#GooglePixel"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#GoogleCloud"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#Android"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#GoogleSearch"/>
|
||||
<rdf:type rdf:resource="http://example.org/ontology#TechnologyCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
<rdfs:comment>Started as a search engine and expanded into cloud computing and AI.</rdfs:comment>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#AmazonPrime">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#SoftwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Car">
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#WindowsOS">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#SoftwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Android">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#SoftwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Oculus">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#HardwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#GoogleCloud">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#CloudServiceProvider"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Microsoft">
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#Surface"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#WindowsOS"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#Azure"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#Xbox"/>
|
||||
<rdf:type rdf:resource="http://example.org/ontology#TechnologyCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
<rdfs:comment>Dominant in software, cloud computing, and gaming.</rdfs:comment>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#GoogleSearch">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#SoftwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Mercedes_SClass">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#LuxuryCar"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Audi_A8">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#LuxuryCar"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Sedan">
|
||||
<rdfs:subClassOf rdf:resource="http://example.org/ontology#Car"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#VW_Golf">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#Sedan"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Facebook">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#SoftwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#WhatsApp">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#SoftwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#produces">
|
||||
<rdfs:domain rdf:resource="http://example.org/ontology#CarManufacturer"/>
|
||||
<rdfs:range rdf:resource="http://example.org/ontology#Car"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#BMW_7Series">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#LuxuryCar"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#BMW_M4">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#SportsCar"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Audi_eTron">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#ElectricCar"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Kindle">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#HardwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#BMW_iX">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#ElectricCar"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#SoftwareCompany">
|
||||
<rdfs:subClassOf rdf:resource="http://example.org/ontology#TechnologyCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Audi_R8">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#SportsCar"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Xbox">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#HardwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Technology">
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Mercedes_EQS">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#ElectricCar"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Porsche_911">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#SportsCar"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#HardwareCompany">
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
|
||||
<rdfs:subClassOf rdf:resource="http://example.org/ontology#TechnologyCompany"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#MercedesBenz">
|
||||
<ns1:produces rdf:resource="http://example.org/ontology#Mercedes_SClass"/>
|
||||
<ns1:produces rdf:resource="http://example.org/ontology#Mercedes_EQS"/>
|
||||
<ns1:produces rdf:resource="http://example.org/ontology#Mercedes_AMG_GT"/>
|
||||
<rdfs:comment>Synonymous with luxury and quality.</rdfs:comment>
|
||||
<rdf:type rdf:resource="http://example.org/ontology#CarManufacturer"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Amazon">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#TechnologyCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#Kindle"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#AmazonEcho"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#AWS"/>
|
||||
<ns1:develops rdf:resource="http://example.org/ontology#AmazonPrime"/>
|
||||
<rdfs:comment>From e-commerce to cloud computing giant with AWS.</rdfs:comment>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Instagram">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#SoftwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#AWS">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#CloudServiceProvider"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#SUV">
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
|
||||
<rdfs:subClassOf rdf:resource="http://example.org/ontology#Car"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#VW_ID4">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#ElectricCar"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#CloudServiceProvider">
|
||||
<rdfs:subClassOf rdf:resource="http://example.org/ontology#TechnologyCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Surface">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#HardwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#iPad">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#HardwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#iPhone">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#HardwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Mercedes_AMG_GT">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#SportsCar"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#MacBook">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#HardwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#develops">
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
|
||||
<rdfs:range rdf:resource="http://example.org/ontology#Technology"/>
|
||||
<rdfs:domain rdf:resource="http://example.org/ontology#TechnologyCompany"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#LuxuryCar">
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
|
||||
<rdfs:subClassOf rdf:resource="http://example.org/ontology#Car"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#AppleWatch">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#HardwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Porsche_Cayenne">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#SUV"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#GooglePixel">
|
||||
<rdf:type rdf:resource="http://example.org/ontology#HardwareCompany"/>
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#Company">
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
|
||||
</rdf:Description>
|
||||
<rdf:Description rdf:about="http://example.org/ontology#CarManufacturer">
|
||||
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
|
||||
<rdfs:subClassOf rdf:resource="http://example.org/ontology#Company"/>
|
||||
</rdf:Description>
|
||||
</rdf:RDF>
|
||||
1325
poetry.lock
generated
1325
poetry.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -87,6 +87,7 @@ gdown = {version = "^5.2.0", optional = true}
|
|||
pyside6 = {version = "^6.8.2.1", optional = true}
|
||||
qasync = {version = "^0.27.1", optional = true}
|
||||
graphiti-core = {version = "^0.7.0", optional = true}
|
||||
owlready2 = "^0.47"
|
||||
|
||||
|
||||
[tool.poetry.extras]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue