mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-08-29 04:26:20 +00:00
Merge pull request #685 from Sameer6305/docs/improve-ontology-guide
docs: improve ontology guide onboarding and practical guidance
This commit is contained in:
+111
-1
@@ -5,15 +5,115 @@ description: "Generate OWL ontologies from your knowledge graph, validate class
|
||||
|
||||
`OntologyGenerator` derives a formal OWL ontology directly from the entities and relationships already in your knowledge graph — no schema design upfront. Use it to produce a machine-readable contract for your graph's classes and properties, then export to Turtle, OWL/XML, or JSON-LD for SHACL validation, reasoning engines, and STIX/TAXII toolchains.
|
||||
|
||||
## What Is an Ontology?
|
||||
|
||||
An ontology is a formal specification of the concepts and relationships in a domain. It defines a shared vocabulary for your knowledge graph by declaring:
|
||||
|
||||
**Classes** — Types of entities in your domain. For example, `ThreatActor`, `Vulnerability`, or `Software` in cybersecurity. Classes describe what kinds of things exist.
|
||||
|
||||
**Object Properties** — Relationships between entities. Examples: `exploits` (Threat Actor exploits Vulnerability), `targets` (Malware targets Organization), or `uses` (Actor uses Tool).
|
||||
|
||||
**Datatype Properties** — Attributes with literal values. Examples: `name` (text), `severity_score` (decimal), `published_date` (date), or `ip_address` (string).
|
||||
|
||||
An ontology makes your knowledge graph machine-readable by specifying which relationships are valid, what types of values each property can hold, and how concepts relate to each other hierarchically.
|
||||
|
||||
## Why Use Ontologies?
|
||||
|
||||
**Consistency.** Without an ontology, one team might use "Threat_Actor" while another uses "ThreatActor" for the same concept. Ontologies enforce a single naming convention.
|
||||
|
||||
**Validation.** Ontologies enable automatic checking — does this relationship make sense? Should a Vulnerability have a CVSS score as text or number?
|
||||
|
||||
**Reasoning.** Exporting to OWL/Turtle lets external reasoning engines (HermiT, Pellet, ELK) infer new facts. If Malware subclasses Software and HAMMERTOSS is Malware, an OWL reasoner concludes HAMMERTOSS is also Software. Semantica exports the ontology; reasoning itself runs in the external tool.
|
||||
|
||||
**Knowledge Graph Quality.** Structured schemas catch errors early and ensure new data integrates cleanly with existing entities.
|
||||
|
||||
## When To Use / When Not To Use
|
||||
|
||||
**Use ontologies for:**
|
||||
- Formal knowledge graphs with complex entity relationships
|
||||
- Data integration across multiple teams or organizations
|
||||
- Automated reasoning and rule-based systems
|
||||
- Long-term knowledge bases that need consistency over time
|
||||
- Integration with external tools that expect OWL/RDF schemas
|
||||
|
||||
**Don't use ontologies for:**
|
||||
- Simple semantic search over text documents
|
||||
- Lightweight RAG where vector similarity is sufficient
|
||||
- Prototype development where the schema changes rapidly
|
||||
- Single-use data analysis that doesn't need reusability
|
||||
- Cases where the overhead exceeds the complexity of your domain
|
||||
|
||||
<Info>
|
||||
Semantica's ontology module derives formal OWL ontologies directly from entities and relationships already in your knowledge graph — no schema design upfront. A 6-stage pipeline infers classes, builds hierarchies, maps OWL types, and serialises to Turtle. The pipeline runs in memory; you do not need a running triple store.
|
||||
</Info>
|
||||
|
||||
---
|
||||
|
||||
## A Simple Example
|
||||
|
||||
Start with a familiar business domain to understand the mechanics before diving into cybersecurity:
|
||||
|
||||
```python
|
||||
from semantica.ontology import OntologyGenerator
|
||||
|
||||
# Build a simple organizational graph directly
|
||||
data = {
|
||||
"entities": [
|
||||
{"id": "e-1", "name": "Alice", "type": "Person"},
|
||||
{"id": "e-2", "name": "Bob", "type": "Person"},
|
||||
{"id": "e-3", "name": "Carol", "type": "Person"},
|
||||
{"id": "e-4", "name": "Acme Corporation", "type": "Company"},
|
||||
{"id": "e-5", "name": "San Francisco", "type": "Location"},
|
||||
],
|
||||
"relationships": [
|
||||
{"source_id": "e-1", "target_id": "e-4", "type": "works_for"},
|
||||
{"source_id": "e-2", "target_id": "e-4", "type": "works_for"},
|
||||
{"source_id": "e-1", "target_id": "e-3", "type": "reports_to"},
|
||||
{"source_id": "e-4", "target_id": "e-5", "type": "headquartered_in"},
|
||||
],
|
||||
}
|
||||
|
||||
generator = OntologyGenerator(
|
||||
base_uri="https://company.example.org/ontology/",
|
||||
min_occurrences=1,
|
||||
)
|
||||
|
||||
ontology = generator.generate_ontology(
|
||||
data,
|
||||
name="OrganizationOntology",
|
||||
build_hierarchy=True,
|
||||
)
|
||||
|
||||
# Inspect what was generated
|
||||
print(f"Classes: {len(ontology.get('classes', []))}")
|
||||
# Classes: 3
|
||||
|
||||
print("Object Properties:")
|
||||
for prop in ontology.get('properties', []):
|
||||
if prop.get('type') == 'object':
|
||||
domain = ', '.join(prop.get('domain', []))
|
||||
range_ = ', '.join(prop.get('range', []))
|
||||
print(f" {prop['name']} ({domain} → {range_})")
|
||||
# works_for (Person → Company)
|
||||
# reports_to (Person → Person)
|
||||
# headquartered_in (Company → Location)
|
||||
|
||||
print("Datatype Properties:")
|
||||
for prop in ontology.get('properties', []):
|
||||
if prop.get('type') == 'data':
|
||||
print(f" {prop['name']} ({prop.get('range')})")
|
||||
# name (string)
|
||||
```
|
||||
|
||||
The **base_uri** (`https://company.example.org/ontology/`) becomes the namespace prefix for all classes and properties. `Person` becomes `<https://company.example.org/ontology/Person>` in the exported RDF.
|
||||
|
||||
**Object properties** connect entities to other entities (`works_for`, `reports_to`). **Datatype properties** connect entities to literal values (`name`).
|
||||
|
||||
---
|
||||
|
||||
## The graph that has no schema
|
||||
|
||||
Populate a knowledge graph with CTI data to make the pipeline mechanics visible.
|
||||
Now with a schema understanding, populate a knowledge graph with CTI data to make the pipeline mechanics visible.
|
||||
|
||||
```python
|
||||
from semantica.context import AgentContext, ContextGraph
|
||||
@@ -201,6 +301,16 @@ The exported Turtle file is the input to Semantica's SHACL validation pipeline.
|
||||
|
||||
---
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
**Over-modeling.** Don't create 50 classes when 10 would suffice. Start simple and add complexity only when you need formal distinctions for reasoning or validation. Having separate classes for `MaliciousEmail` and `PhishingEmail` is only useful if they have different properties or relationships.
|
||||
|
||||
**Ontology drift.** When new entity types appear in your graph, the ontology becomes stale unless you regenerate or incrementally update it. Set up monitoring to detect when new entity types appear that aren't covered by your current ontology.
|
||||
|
||||
**Inconsistent class naming.** Pick a convention (CamelCase, snake_case, or kebab-case) and stick to it. Mixing `ThreatActor`, `threat_actor`, and `threat-actor` in the same ontology creates confusion and breaks tooling that expects consistent naming patterns.
|
||||
|
||||
---
|
||||
|
||||
## Domain Examples
|
||||
|
||||
<Tabs>
|
||||
|
||||
Reference in New Issue
Block a user