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:
hajdul88 2025-03-12 14:31:19 +01:00 committed by GitHub
parent c1f7b667d1
commit 6fcfb3c398
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 1756 additions and 522 deletions

View file

@ -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,

View file

@ -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"]}

View file

@ -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"]}

View file

@ -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

View file

View 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

View 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)

View 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

View 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)

View file

@ -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"},
]

View 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

View 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 companys 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 peoples 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. Googles 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. Amazons 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 companys efforts signal a commitment to evolving digital interaction and building the metaversea 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())

View 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

File diff suppressed because it is too large Load diff

View file

@ -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]