mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-08-29 04:26:20 +00:00
Add a Cite Us section to the README with BibTeX citation info, and align it with docs/citation.md (author/organization: Semantica, 2026). Update LICENSE and docs/project-license.md copyright holder to Semantica, and replace the stale Hawksight-AI GitHub org slug with semantica-agi across READMEs, plugin manifests, cookbook notebooks, and GitHub templates.
385 lines
15 KiB
Plaintext
385 lines
15 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"[](https://colab.research.google.com/github/semantica-agi/semantica/blob/main/cookbook/advanced/10_Temporal_Knowledge_Graphs.ipynb)\n",
|
|
"\n",
|
|
"# Deep Dive: Temporal Knowledge Graphs\n",
|
|
"\n",
|
|
"## Overview\n",
|
|
"\n",
|
|
"This notebook provides a comprehensive deep dive into **Temporal Knowledge Graphs (TKGs)** using Semantica. Unlike static KGs, TKGs capture the evolution of facts, relationships, and entities over time. This capability is crucial for applications like:\n",
|
|
"\n",
|
|
"- **Corporate History Analysis**: Tracking mergers, acquisitions, and leadership changes.\n",
|
|
"- **Supply Chain Monitoring**: Tracing product movement and status changes.\n",
|
|
"- **Financial Fraud Detection**: Analyzing sequences of transactions.\n",
|
|
"\n",
|
|
"We will build a rich scenario modeling the history of a tech ecosystem, covering 40 years of evolution.\n",
|
|
"\n",
|
|
"### Key Components Covered\n",
|
|
"\n",
|
|
"1. **`GraphBuilder` (Temporal Mode)**: Constructing KGs with time-aware properties.\n",
|
|
"2. **`TemporalGraphQuery`**: Performing point-in-time, interval, and path queries.\n",
|
|
"3. **`TemporalPatternDetector`**: Identifying sequences and cyclic patterns.\n",
|
|
"4. **`TemporalVersionManager`**: Managing snapshots and comparing graph states.\n",
|
|
"5. **`TemporalVisualizer`**: Interactive timelines and evolution plots.\n",
|
|
"\n",
|
|
"**Documentation**: [API Reference](https://semantica.readthedocs.io/reference/kg/)\n",
|
|
"\n",
|
|
"## Installation\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# !pip install semantica[all]"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import json\n",
|
|
"from datetime import datetime\n",
|
|
"from semantica.kg import GraphBuilder, TemporalGraphQuery, TemporalPatternDetector, TemporalVersionManager\n",
|
|
"from semantica.visualization import TemporalVisualizer\n",
|
|
"import plotly.offline as pyo\n",
|
|
"pyo.init_notebook_mode(connected=True)\n",
|
|
"\n",
|
|
"# Ensure consistent output for reproducibility\n",
|
|
"import random\n",
|
|
"random.seed(42)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Step 1: Scenario Definition & Data Preparation\n",
|
|
"\n",
|
|
"We define a dataset representing the history of \"TechCorp\" and \"InnovateInc\", including their founders, products, and eventual merger.\n",
|
|
"\n",
|
|
"**Temporal Properties**:\n",
|
|
"- Entities have `founded`, `born`, `released` dates.\n",
|
|
"- Relationships have `timestamp` (point event) or `valid_from`/`valid_to` (intervals).\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# 1. Define Entities with Temporal Metadata\n",
|
|
"entities = [\n",
|
|
" # Organizations\n",
|
|
" {\"id\": \"org_1\", \"type\": \"Organization\", \"name\": \"TechCorp\", \"properties\": {\"founded\": \"1980-01-01\", \"industry\": \"Hardware\"}},\n",
|
|
" {\"id\": \"org_2\", \"type\": \"Organization\", \"name\": \"InnovateInc\", \"properties\": {\"founded\": \"1995-06-15\", \"industry\": \"Software\"}},\n",
|
|
" {\"id\": \"org_3\", \"type\": \"Organization\", \"name\": \"FutureSystems\", \"properties\": {\"founded\": \"2010-03-10\", \"industry\": \"AI\"}},\n",
|
|
" \n",
|
|
" # People\n",
|
|
" {\"id\": \"per_1\", \"type\": \"Person\", \"name\": \"Alice Founder\", \"properties\": {\"born\": \"1955-05-20\"}},\n",
|
|
" {\"id\": \"per_2\", \"type\": \"Person\", \"name\": \"Bob Coder\", \"properties\": {\"born\": \"1970-08-12\"}},\n",
|
|
" {\"id\": \"per_3\", \"type\": \"Person\", \"name\": \"Charlie CEO\", \"properties\": {\"born\": \"1980-02-28\"}},\n",
|
|
" \n",
|
|
" # Products\n",
|
|
" {\"id\": \"prod_1\", \"type\": \"Product\", \"name\": \"HomePC\", \"properties\": {\"released\": \"1985-11-20\"}},\n",
|
|
" {\"id\": \"prod_2\", \"type\": \"Product\", \"name\": \"SoftOS\", \"properties\": {\"released\": \"1998-07-25\"}},\n",
|
|
" {\"id\": \"prod_3\", \"type\": \"Product\", \"name\": \"SmartAI\", \"properties\": {\"released\": \"2015-01-10\"}}\n",
|
|
"]\n",
|
|
"\n",
|
|
"# 2. Define Temporal Relationships\n",
|
|
"relationships = [\n",
|
|
" # Founding Events (Point in time)\n",
|
|
" {\"source\": \"per_1\", \"target\": \"org_1\", \"type\": \"founded\", \"timestamp\": \"1980-01-01\", \"properties\": {\"timestamp\": \"1980-01-01\"}},\n",
|
|
" {\"source\": \"per_2\", \"target\": \"org_2\", \"type\": \"founded\", \"timestamp\": \"1995-06-15\", \"properties\": {\"timestamp\": \"1995-06-15\"}},\n",
|
|
" \n",
|
|
" # Employment (Intervals)\n",
|
|
" {\"source\": \"per_1\", \"target\": \"org_1\", \"type\": \"ceo_of\", \"valid_from\": \"1980-01-01\", \"valid_to\": \"2000-01-01\", \"properties\": {\"role\": \"CEO\"}},\n",
|
|
" {\"source\": \"per_3\", \"target\": \"org_1\", \"type\": \"ceo_of\", \"valid_from\": \"2000-01-02\", \"valid_to\": \"2023-01-01\", \"properties\": {\"role\": \"CEO\"}},\n",
|
|
" {\"source\": \"per_2\", \"target\": \"org_2\", \"type\": \"cto_of\", \"valid_from\": \"1995-06-15\", \"valid_to\": \"2010-05-01\", \"properties\": {\"role\": \"CTO\"}},\n",
|
|
" \n",
|
|
" # Product Launches\n",
|
|
" {\"source\": \"org_1\", \"target\": \"prod_1\", \"type\": \"launched\", \"timestamp\": \"1985-11-20\", \"properties\": {\"timestamp\": \"1985-11-20\"}},\n",
|
|
" {\"source\": \"org_2\", \"target\": \"prod_2\", \"type\": \"launched\", \"timestamp\": \"1998-07-25\", \"properties\": {\"timestamp\": \"1998-07-25\"}},\n",
|
|
" {\"source\": \"org_3\", \"target\": \"prod_3\", \"type\": \"launched\", \"timestamp\": \"2015-01-10\", \"properties\": {\"timestamp\": \"2015-01-10\"}},\n",
|
|
" \n",
|
|
" # Corporate Actions\n",
|
|
" {\"source\": \"org_1\", \"target\": \"org_2\", \"type\": \"acquired\", \"timestamp\": \"2010-05-01\", \"properties\": {\"amount\": \"$5B\", \"timestamp\": \"2010-05-01\"}},\n",
|
|
" {\"source\": \"org_1\", \"target\": \"org_3\", \"type\": \"invested_in\", \"timestamp\": \"2012-08-15\", \"properties\": {\"amount\": \"$100M\", \"timestamp\": \"2012-08-15\"}}\n",
|
|
"]\n",
|
|
"\n",
|
|
"print(f\"Defined {len(entities)} entities and {len(relationships)} temporal relationships.\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Step 2: Building the Temporal Graph\n",
|
|
"\n",
|
|
"We use `GraphBuilder` with `enable_temporal=True`. This instructs the builder to index temporal properties like `timestamp`, `valid_from`, and `valid_to`."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"builder = GraphBuilder(\n",
|
|
" enable_temporal=True,\n",
|
|
" temporal_granularity=\"day\" # Can be 'year', 'month', 'day', 'hour'\n",
|
|
")\n",
|
|
"\n",
|
|
"temporal_kg = builder.build(entities, relationships)\n",
|
|
"\n",
|
|
"# The graph object now contains temporal indices\n",
|
|
"print(\"Graph built successfully.\")\n",
|
|
"print(f\"Nodes: {len(temporal_kg['entities'])}\")\n",
|
|
"print(f\"Edges: {len(temporal_kg['relationships'])}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Step 3: Advanced Temporal Querying\n",
|
|
"\n",
|
|
"We use `TemporalGraphQuery` to ask time-sensitive questions."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"query_engine = TemporalGraphQuery()\n",
|
|
"\n",
|
|
"# 1. Point-in-Time Query\n",
|
|
"# \"Who was the CEO of TechCorp in 1990?\"\n",
|
|
"ceo_1990 = query_engine.query_at_time(\n",
|
|
" temporal_kg,\n",
|
|
" query=\"Find the CEO of TechCorp\",\n",
|
|
" at_time=\"1990-06-01\"\n",
|
|
")\n",
|
|
"print(\"CEO in 1990:\", [e['id'] for e in ceo_1990.get('entities', [])])\n",
|
|
"\n",
|
|
"# \"Who was the CEO of TechCorp in 2015?\"\n",
|
|
"ceo_2015 = query_engine.query_at_time(\n",
|
|
" temporal_kg,\n",
|
|
" query=\"Find the CEO of TechCorp\",\n",
|
|
" at_time=\"2015-06-01\"\n",
|
|
")\n",
|
|
"print(\"CEO in 2015:\", [e['id'] for e in ceo_2015.get('entities', [])])\n",
|
|
"\n",
|
|
"# 2. Temporal Path Finding\n",
|
|
"# \"How did Alice (Founder) connect to SmartAI (Product released in 2015)?\"\n",
|
|
"# This requires traversing through time: Alice -> founded TechCorp -> invested in FutureSystems -> launched SmartAI\n",
|
|
"paths = query_engine.find_temporal_paths(\n",
|
|
" graph=temporal_kg,\n",
|
|
" source=\"per_1\", # Alice\n",
|
|
" target=\"prod_3\", # SmartAI\n",
|
|
" start_time=\"1980-01-01\",\n",
|
|
" end_time=\"2020-01-01\"\n",
|
|
")\n",
|
|
"\n",
|
|
"print(f\"\\nFound {len(paths)} temporal paths from Alice to SmartAI.\")\n",
|
|
"for i, path in enumerate(paths):\n",
|
|
" print(f\"Path {i+1}: {path}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Step 4: Graph Evolution Analysis\n",
|
|
"\n",
|
|
"We can analyze how the graph properties change over time using `analyze_evolution`."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"evolution_stats = query_engine.analyze_evolution(\n",
|
|
" temporal_kg,\n",
|
|
" start_time=\"1980-01-01\",\n",
|
|
" end_time=\"2025-01-01\",\n",
|
|
" metrics=[\"count\", \"diversity\", \"stability\"]\n",
|
|
")\n",
|
|
"\n",
|
|
"print(\"\\nEvolution Statistics (1980-2025):\")\n",
|
|
"print(f\"Total Relationships: {evolution_stats.get('count', 'N/A')}\")\n",
|
|
"print(f\"Relationship Diversity: {evolution_stats.get('diversity', 'N/A')}\")\n",
|
|
"print(f\"Graph Stability: {evolution_stats.get('stability', 'N/A')}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Step 5: Temporal Pattern Detection\n",
|
|
"\n",
|
|
"We use `TemporalPatternDetector` to automatically find recurring structures, such as sequences (A -> B -> C) or cycles."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"detector = TemporalPatternDetector()\n",
|
|
"\n",
|
|
"# Detect sequential patterns (e.g., Founded -> Launched -> Acquired)\n",
|
|
"sequences = detector.detect_temporal_patterns(\n",
|
|
" temporal_kg,\n",
|
|
" pattern_type=\"sequence\",\n",
|
|
" min_frequency=1\n",
|
|
")\n",
|
|
"\n",
|
|
"print(f\"\\nDetected {len(sequences)} sequential patterns.\")\n",
|
|
"for seq in sequences[:3]: # Show top 3\n",
|
|
" print(f\"Pattern: {seq.get('pattern')}\")\n",
|
|
" print(f\"Support: {seq.get('support')}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Step 6: Version Management & Comparisons\n",
|
|
"\n",
|
|
"In real-world scenarios, KGs are updated in batches. `TemporalVersionManager` handles these versions."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"version_manager = TemporalVersionManager()\n",
|
|
"\n",
|
|
"# Create explicit versions\n",
|
|
"v1_1990 = version_manager.create_version(temporal_kg, timestamp=\"1990-01-01\", version_label=\"v1.0 (Early Days)\")\n",
|
|
"v2_2010 = version_manager.create_version(temporal_kg, timestamp=\"2010-01-01\", version_label=\"v2.0 (Post-Merger)\")\n",
|
|
"\n",
|
|
"# Compare versions\n",
|
|
"diff = version_manager.compare_versions(v1_1990, v2_2010)\n",
|
|
"\n",
|
|
"print(f\"\\nComparing {v1_1990['label']} vs {v2_2010['label']}:\")\n",
|
|
"print(f\"New Entities: {diff.get('entities_added', 0)}\")\n",
|
|
"print(f\"New Relationships: {diff.get('relationships_added', 0)}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Step 7: Visualizing the Timeline\n",
|
|
"\n",
|
|
"Finally, `TemporalVisualizer` brings the data to life. We will create an interactive timeline and a snapshot comparison."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"visualizer = TemporalVisualizer()\n",
|
|
"\n",
|
|
"# 1. Interactive Timeline\n",
|
|
"# Prepare events for visualization (extract from KG)\n",
|
|
"def extract_events(graph):\n",
|
|
" events = []\n",
|
|
" for rel in graph['relationships']:\n",
|
|
" # Point events\n",
|
|
" if rel.get('timestamp'):\n",
|
|
" events.append({\n",
|
|
" 'timestamp': rel['timestamp'],\n",
|
|
" 'type': rel['type'],\n",
|
|
" 'label': f\"{rel['source']} -> {rel['target']}\",\n",
|
|
" 'entity': rel['source']\n",
|
|
" })\n",
|
|
" # Interval events (start)\n",
|
|
" if rel.get('valid_from'):\n",
|
|
" events.append({\n",
|
|
" 'timestamp': rel['valid_from'],\n",
|
|
" 'type': f\"{rel['type']} (start)\",\n",
|
|
" 'label': f\"{rel['source']} -> {rel['target']}\",\n",
|
|
" 'entity': rel['source']\n",
|
|
" })\n",
|
|
" return {'events': events}\n",
|
|
"\n",
|
|
"temporal_data = extract_events(temporal_kg)\n",
|
|
"timeline_fig = visualizer.visualize_timeline(temporal_data, output=\"interactive\")\n",
|
|
"# In a notebook, this would render a Plotly figure. \n",
|
|
"timeline_fig.show()\n",
|
|
"\n",
|
|
"# 2. Version History Visualization\n",
|
|
"history = [\n",
|
|
" {\"version\": \"v1.0\", \"timestamp\": \"1990-01-01\", \"changes\": \"Founding Era\"},\n",
|
|
" {\"version\": \"v2.0\", \"timestamp\": \"2010-01-01\", \"changes\": \"Expansion Era\"},\n",
|
|
" {\"version\": \"v3.0\", \"timestamp\": \"2020-01-01\", \"changes\": \"AI Era\"}\n",
|
|
"]\n",
|
|
"history_fig = visualizer.visualize_version_history(history, output=\"interactive\")\n",
|
|
"history_fig.show()\n",
|
|
"\n",
|
|
"print(\"Visualizations generated (render requires Jupyter environment).\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Summary\n",
|
|
"\n",
|
|
"In this deep dive, we:\n",
|
|
"1. **modeled** a complex corporate history with temporal metadata.\n",
|
|
"2. **Built** a time-aware knowledge graph using `GraphBuilder`.\n",
|
|
"3. **Queried** specific time slices and intervals to reconstruct history.\n",
|
|
"4. **Traced** temporal paths to understand indirect connections.\n",
|
|
"5. **Analyzed** the graph's evolution metrics.\n",
|
|
"6. **Managed** versions and visualized the timeline.\n",
|
|
"7. **Visualized** the data with `TemporalVisualizer`.\n",
|
|
"\n",
|
|
"This workflow forms the backbone of temporal intelligence applications in Semantica."
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.11.9"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
}
|