Files
semantica/cookbook/advanced/10_Temporal_Knowledge_Graphs.ipynb
T
KaifAhmad1 7a6f1d0417 docs: add citation section and fix stale org references
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.
2026-08-24 16:07:22 +05:30

15 KiB

Open In Colab

Deep Dive: Temporal Knowledge Graphs

Overview

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:

  • Corporate History Analysis: Tracking mergers, acquisitions, and leadership changes.
  • Supply Chain Monitoring: Tracing product movement and status changes.
  • Financial Fraud Detection: Analyzing sequences of transactions.

We will build a rich scenario modeling the history of a tech ecosystem, covering 40 years of evolution.

Key Components Covered

  1. GraphBuilder (Temporal Mode): Constructing KGs with time-aware properties.
  2. TemporalGraphQuery: Performing point-in-time, interval, and path queries.
  3. TemporalPatternDetector: Identifying sequences and cyclic patterns.
  4. TemporalVersionManager: Managing snapshots and comparing graph states.
  5. TemporalVisualizer: Interactive timelines and evolution plots.

Documentation: API Reference

Installation

In [ ]:
# !pip install semantica[all]
In [ ]:
import json
from datetime import datetime
from semantica.kg import GraphBuilder, TemporalGraphQuery, TemporalPatternDetector, TemporalVersionManager
from semantica.visualization import TemporalVisualizer
import plotly.offline as pyo
pyo.init_notebook_mode(connected=True)

# Ensure consistent output for reproducibility
import random
random.seed(42)

Step 1: Scenario Definition & Data Preparation

We define a dataset representing the history of "TechCorp" and "InnovateInc", including their founders, products, and eventual merger.

Temporal Properties:

  • Entities have founded, born, released dates.
  • Relationships have timestamp (point event) or valid_from/valid_to (intervals).
In [ ]:
# 1. Define Entities with Temporal Metadata
entities = [
    # Organizations
    {"id": "org_1", "type": "Organization", "name": "TechCorp", "properties": {"founded": "1980-01-01", "industry": "Hardware"}},
    {"id": "org_2", "type": "Organization", "name": "InnovateInc", "properties": {"founded": "1995-06-15", "industry": "Software"}},
    {"id": "org_3", "type": "Organization", "name": "FutureSystems", "properties": {"founded": "2010-03-10", "industry": "AI"}},
    
    # People
    {"id": "per_1", "type": "Person", "name": "Alice Founder", "properties": {"born": "1955-05-20"}},
    {"id": "per_2", "type": "Person", "name": "Bob Coder", "properties": {"born": "1970-08-12"}},
    {"id": "per_3", "type": "Person", "name": "Charlie CEO", "properties": {"born": "1980-02-28"}},
    
    # Products
    {"id": "prod_1", "type": "Product", "name": "HomePC", "properties": {"released": "1985-11-20"}},
    {"id": "prod_2", "type": "Product", "name": "SoftOS", "properties": {"released": "1998-07-25"}},
    {"id": "prod_3", "type": "Product", "name": "SmartAI", "properties": {"released": "2015-01-10"}}
]

# 2. Define Temporal Relationships
relationships = [
    # Founding Events (Point in time)
    {"source": "per_1", "target": "org_1", "type": "founded", "timestamp": "1980-01-01", "properties": {"timestamp": "1980-01-01"}},
    {"source": "per_2", "target": "org_2", "type": "founded", "timestamp": "1995-06-15", "properties": {"timestamp": "1995-06-15"}},
    
    # Employment (Intervals)
    {"source": "per_1", "target": "org_1", "type": "ceo_of", "valid_from": "1980-01-01", "valid_to": "2000-01-01", "properties": {"role": "CEO"}},
    {"source": "per_3", "target": "org_1", "type": "ceo_of", "valid_from": "2000-01-02", "valid_to": "2023-01-01", "properties": {"role": "CEO"}},
    {"source": "per_2", "target": "org_2", "type": "cto_of", "valid_from": "1995-06-15", "valid_to": "2010-05-01", "properties": {"role": "CTO"}},
    
    # Product Launches
    {"source": "org_1", "target": "prod_1", "type": "launched", "timestamp": "1985-11-20", "properties": {"timestamp": "1985-11-20"}},
    {"source": "org_2", "target": "prod_2", "type": "launched", "timestamp": "1998-07-25", "properties": {"timestamp": "1998-07-25"}},
    {"source": "org_3", "target": "prod_3", "type": "launched", "timestamp": "2015-01-10", "properties": {"timestamp": "2015-01-10"}},
    
    # Corporate Actions
    {"source": "org_1", "target": "org_2", "type": "acquired", "timestamp": "2010-05-01", "properties": {"amount": "$5B", "timestamp": "2010-05-01"}},
    {"source": "org_1", "target": "org_3", "type": "invested_in", "timestamp": "2012-08-15", "properties": {"amount": "$100M", "timestamp": "2012-08-15"}}
]

print(f"Defined {len(entities)} entities and {len(relationships)} temporal relationships.")

Step 2: Building the Temporal Graph

We use GraphBuilder with enable_temporal=True. This instructs the builder to index temporal properties like timestamp, valid_from, and valid_to.

In [ ]:
builder = GraphBuilder(
    enable_temporal=True,
    temporal_granularity="day"  # Can be 'year', 'month', 'day', 'hour'
)

temporal_kg = builder.build(entities, relationships)

# The graph object now contains temporal indices
print("Graph built successfully.")
print(f"Nodes: {len(temporal_kg['entities'])}")
print(f"Edges: {len(temporal_kg['relationships'])}")

Step 3: Advanced Temporal Querying

We use TemporalGraphQuery to ask time-sensitive questions.

In [ ]:
query_engine = TemporalGraphQuery()

# 1. Point-in-Time Query
# "Who was the CEO of TechCorp in 1990?"
ceo_1990 = query_engine.query_at_time(
    temporal_kg,
    query="Find the CEO of TechCorp",
    at_time="1990-06-01"
)
print("CEO in 1990:", [e['id'] for e in ceo_1990.get('entities', [])])

# "Who was the CEO of TechCorp in 2015?"
ceo_2015 = query_engine.query_at_time(
    temporal_kg,
    query="Find the CEO of TechCorp",
    at_time="2015-06-01"
)
print("CEO in 2015:", [e['id'] for e in ceo_2015.get('entities', [])])

# 2. Temporal Path Finding
# "How did Alice (Founder) connect to SmartAI (Product released in 2015)?"
# This requires traversing through time: Alice -> founded TechCorp -> invested in FutureSystems -> launched SmartAI
paths = query_engine.find_temporal_paths(
    graph=temporal_kg,
    source="per_1", # Alice
    target="prod_3", # SmartAI
    start_time="1980-01-01",
    end_time="2020-01-01"
)

print(f"\nFound {len(paths)} temporal paths from Alice to SmartAI.")
for i, path in enumerate(paths):
    print(f"Path {i+1}: {path}")

Step 4: Graph Evolution Analysis

We can analyze how the graph properties change over time using analyze_evolution.

In [ ]:
evolution_stats = query_engine.analyze_evolution(
    temporal_kg,
    start_time="1980-01-01",
    end_time="2025-01-01",
    metrics=["count", "diversity", "stability"]
)

print("\nEvolution Statistics (1980-2025):")
print(f"Total Relationships: {evolution_stats.get('count', 'N/A')}")
print(f"Relationship Diversity: {evolution_stats.get('diversity', 'N/A')}")
print(f"Graph Stability: {evolution_stats.get('stability', 'N/A')}")

Step 5: Temporal Pattern Detection

We use TemporalPatternDetector to automatically find recurring structures, such as sequences (A -> B -> C) or cycles.

In [ ]:
detector = TemporalPatternDetector()

# Detect sequential patterns (e.g., Founded -> Launched -> Acquired)
sequences = detector.detect_temporal_patterns(
    temporal_kg,
    pattern_type="sequence",
    min_frequency=1
)

print(f"\nDetected {len(sequences)} sequential patterns.")
for seq in sequences[:3]: # Show top 3
    print(f"Pattern: {seq.get('pattern')}")
    print(f"Support: {seq.get('support')}")

Step 6: Version Management & Comparisons

In real-world scenarios, KGs are updated in batches. TemporalVersionManager handles these versions.

In [ ]:
version_manager = TemporalVersionManager()

# Create explicit versions
v1_1990 = version_manager.create_version(temporal_kg, timestamp="1990-01-01", version_label="v1.0 (Early Days)")
v2_2010 = version_manager.create_version(temporal_kg, timestamp="2010-01-01", version_label="v2.0 (Post-Merger)")

# Compare versions
diff = version_manager.compare_versions(v1_1990, v2_2010)

print(f"\nComparing {v1_1990['label']} vs {v2_2010['label']}:")
print(f"New Entities: {diff.get('entities_added', 0)}")
print(f"New Relationships: {diff.get('relationships_added', 0)}")

Step 7: Visualizing the Timeline

Finally, TemporalVisualizer brings the data to life. We will create an interactive timeline and a snapshot comparison.

In [ ]:
visualizer = TemporalVisualizer()

# 1. Interactive Timeline
# Prepare events for visualization (extract from KG)
def extract_events(graph):
    events = []
    for rel in graph['relationships']:
        # Point events
        if rel.get('timestamp'):
            events.append({
                'timestamp': rel['timestamp'],
                'type': rel['type'],
                'label': f"{rel['source']} -> {rel['target']}",
                'entity': rel['source']
            })
        # Interval events (start)
        if rel.get('valid_from'):
             events.append({
                'timestamp': rel['valid_from'],
                'type': f"{rel['type']} (start)",
                'label': f"{rel['source']} -> {rel['target']}",
                'entity': rel['source']
            })
    return {'events': events}

temporal_data = extract_events(temporal_kg)
timeline_fig = visualizer.visualize_timeline(temporal_data, output="interactive")
# In a notebook, this would render a Plotly figure. 
timeline_fig.show()

# 2. Version History Visualization
history = [
    {"version": "v1.0", "timestamp": "1990-01-01", "changes": "Founding Era"},
    {"version": "v2.0", "timestamp": "2010-01-01", "changes": "Expansion Era"},
    {"version": "v3.0", "timestamp": "2020-01-01", "changes": "AI Era"}
]
history_fig = visualizer.visualize_version_history(history, output="interactive")
history_fig.show()

print("Visualizations generated (render requires Jupyter environment).")

Summary

In this deep dive, we:

  1. modeled a complex corporate history with temporal metadata.
  2. Built a time-aware knowledge graph using GraphBuilder.
  3. Queried specific time slices and intervals to reconstruct history.
  4. Traced temporal paths to understand indirect connections.
  5. Analyzed the graph's evolution metrics.
  6. Managed versions and visualized the timeline.
  7. Visualized the data with TemporalVisualizer.

This workflow forms the backbone of temporal intelligence applications in Semantica.