diff --git a/cookbook/advanced/10_Temporal_Knowledge_Graphs.ipynb b/cookbook/advanced/10_Temporal_Knowledge_Graphs.ipynb index 7289b337..7d5efd3d 100644 --- a/cookbook/advanced/10_Temporal_Knowledge_Graphs.ipynb +++ b/cookbook/advanced/10_Temporal_Knowledge_Graphs.ipynb @@ -6,35 +6,29 @@ "source": [ "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Hawksight-AI/semantica/blob/main/cookbook/advanced/10_Temporal_Knowledge_Graphs.ipynb)\n", "\n", - "# Temporal Knowledge Graphs\n", + "# Deep Dive: Temporal Knowledge Graphs\n", "\n", "## Overview\n", "\n", - "This notebook demonstrates advanced temporal knowledge graph capabilities using TemporalGraphQuery, TemporalPatternDetector, TemporalVersionManager, and TemporalVisualizer.\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", - "### Learning Objectives\n", - "\n", - "- Use TemporalGraphQuery for time-aware queries\n", - "- Use TemporalPatternDetector to detect temporal patterns\n", - "- Use TemporalVersionManager for temporal versioning and snapshots\n", - "- Use TemporalVisualizer to visualize temporal data\n", - "\n", - "## Installation\n", - "\n", - "Install Semantica from PyPI:\n", - "\n", - "```bash\n", - "pip install semantica\n", - "# Or with all optional dependencies:\n", - "pip install semantica[all]\n", - "```\n", - "\n", - "---\n", - "\n", - "## Workflow: Build Temporal KG \u2192 Time-Aware Queries \u2192 Pattern Detection \u2192 Version Management \u2192 Visualization\n" + "## Installation\n" ] }, { @@ -43,7 +37,7 @@ "metadata": {}, "outputs": [], "source": [ - "!pip install semantica\n" + "!pip install semantica[all]" ] }, { @@ -52,33 +46,112 @@ "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", - "from datetime import datetime\n", "\n", - "builder = GraphBuilder()\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", - " {\"id\": \"e1\", \"type\": \"Organization\", \"name\": \"Apple Inc.\", \"properties\": {\"founded\": \"1976\"}},\n", - " {\"id\": \"e2\", \"type\": \"Person\", \"name\": \"Steve Jobs\", \"properties\": {\"born\": \"1955\"}}\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", - " {\"source\": \"e2\", \"target\": \"e1\", \"type\": \"founded\", \"properties\": {\"timestamp\": \"1976-04-01\"}}\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", - "print(f\"Built temporal knowledge graph with {len(entities)} entities\")\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 2: Time-Aware Queries\n", + "## Step 3: Advanced Temporal Querying\n", "\n", - "Query the graph at specific time points.\n" + "We use `TemporalGraphQuery` to ask time-sensitive questions." ] }, { @@ -87,25 +160,48 @@ "metadata": {}, "outputs": [], "source": [ - "temporal_query = TemporalGraphQuery()\n", + "query_engine = TemporalGraphQuery()\n", "\n", - "query_result = temporal_query.query_time_range(\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", + " timestamp=\"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", + " timestamp=\"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", - " query=\"Find entities founded in 1976\",\n", - " start_time=\"1976-01-01\",\n", - " end_time=\"1976-12-31\"\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\"Time-aware query returned {len(query_result.get('entities', []))} entities\")\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 3: Temporal Pattern Detection\n", + "## Step 4: Graph Evolution Analysis\n", "\n", - "Detect temporal patterns in the graph.\n" + "We can analyze how the graph properties change over time using `analyze_evolution`." ] }, { @@ -114,24 +210,56 @@ "metadata": {}, "outputs": [], "source": [ - "pattern_detector = TemporalPatternDetector()\n", + "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", - "patterns = pattern_detector.detect_temporal_patterns(\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\"Detected {len(patterns)} temporal patterns\")\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 4: Version Management\n", + "## Step 6: Version Management & Comparisons\n", "\n", - "Manage temporal versions and snapshots.\n" + "In real-world scenarios, KGs are updated in batches. `TemporalVersionManager` handles these versions." ] }, { @@ -142,19 +270,25 @@ "source": [ "version_manager = TemporalVersionManager()\n", "\n", - "snapshot = version_manager.create_snapshot(temporal_kg, timestamp=datetime.now())\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", - "print(f\"Created temporal snapshot at {snapshot.get('timestamp', 'N/A')}\")\n", - "print(f\"Snapshot contains {len(snapshot.get('entities', []))} entities\")\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('added_entities_count', 0)}\")\n", + "print(f\"New Relationships: {diff.get('added_relationships_count', 0)}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Step 5: Temporal Visualization\n", + "## Step 7: Visualizing the Timeline\n", "\n", - "Visualize temporal data.\n" + "Finally, `TemporalVisualizer` brings the data to life. We will create an interactive timeline and a snapshot comparison." ] }, { @@ -163,9 +297,46 @@ "metadata": {}, "outputs": [], "source": [ - "temporal_visualizer = TemporalVisualizer()\n", + "visualizer = TemporalVisualizer()\n", "\n", - "visualization = temporal_visualizer.visualize_timeline(temporal_kg, output=\"interactive\")\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).\")" ] }, { @@ -174,66 +345,38 @@ "source": [ "## Summary\n", "\n", - "You've learned advanced temporal knowledge graph capabilities:\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", - "- **TemporalGraphQuery**: Time-aware graph querying\n", - "- **TemporalPatternDetector**: Temporal pattern detection\n", - "- **TemporalVersionManager**: Temporal versioning and snapshots\n", - "- **TemporalVisualizer**: Temporal data visualization\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Snapshot Comparison and Version History\n", - "\n", - "Compare graph snapshots across time and visualize version history." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Create multiple versions\n", - "version_manager = TemporalVersionManager()\n", - "version_2020 = version_manager.create_version(temporal_kg, timestamp=\"2020-01-01\", version_label=\"v2020\")\n", - "# Simulate changes for 2023\n", - "temporal_kg_updated = {\n", - " \"entities\": temporal_kg.get(\"entities\", []),\n", - " \"relationships\": temporal_kg.get(\"relationships\", []) + [\n", - " {\"source\": \"e1\", \"target\": \"e2\", \"type\": \"collaborated_with\", \"valid_from\": \"2023-01-01\"}\n", - " ]\n", - "}\n", - "version_2023 = version_manager.create_version(temporal_kg_updated, timestamp=\"2023-01-01\", version_label=\"v2023\")\n", - "\n", - "# Build snapshots dict for comparison\n", - "snapshots = {\n", - " version_2020[\"timestamp\"]: version_2020,\n", - " version_2023[\"timestamp\"]: version_2023\n", - "}\n", - "\n", - "# Visualize snapshot comparison\n", - "fig_snapshots = temporal_visualizer.visualize_snapshot_comparison(snapshots, output=\"interactive\")\n", - "\n", - "# Build version history list\n", - "version_history = [\n", - " {\"version\": version_2020.get(\"label\", \"v2020\"), \"timestamp\": version_2020.get(\"timestamp\"), \"changes\": f\"Entities: {len(version_2020.get('entities', []))}, Relationships: {len(version_2020.get('relationships', []))}\"},\n", - " {\"version\": version_2023.get(\"label\", \"v2023\"), \"timestamp\": version_2023.get(\"timestamp\"), \"changes\": f\"Entities: {len(version_2023.get('entities', []))}, Relationships: {len(version_2023.get('relationships', []))}\"}\n", - "]\n", - "\n", - "# Visualize version history\n", - "fig_versions = temporal_visualizer.visualize_version_history(version_history, output=\"interactive\")\n" + "This workflow forms the backbone of temporal intelligence applications in Semantica." ] } ], "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, "language_info": { - "name": "python" + "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": 2 -} \ No newline at end of file + "nbformat_minor": 4 +}