Standard flat-vector RAG struggles when documents contain deeply interconnected entities. If you split a 50-page enterprise agreement, automotive catalog, warranty register, or CRM database into arbitrary 512-token chunks, the relational topology is broken. Vector similarity cannot easily perform a 4-hop walk: finding that a specific defective part was supplied by a Tier-1 vendor, fitted into a specific vehicle variant, sold through an authorized dealership, and replaced under a specific warranty claim.

To solve this, I designed and built an event-sourced Knowledge Compiler: a pipeline that processes raw unstructured documents, CSVs, JSON registries, and Markdown notes into a live 98,921-node context graph in Neo4j with explicit provenance tracking and deterministic graph traversal.


1. The 6-Stage Compilation Pipeline

Instead of relying on free-form prompting that produces disconnected entities, the compiler enforces a structured 6-stage lifecycle:

Stage 1 · AST Chunking & Content Hashing: Input files are parsed into semantic blocks (Markdown sections, table rows, JSON trees) with SHA-256 content hashes to support incremental re-indexing and idempotency.
Stage 2 · Ontology Discovery & Schema Gate: New predicates and node labels are validated against registered ontology classes to prevent schema drift.
Stage 3 · Two-Pass Entity Extraction: Pass 1 builds a global entity roster across the document. Pass 2 resolves subject-predicate-object triples with the roster present in the prompt context to eliminate dangling references.
Stage 4 · 5-Tier Entity Resolution: Mentions and aliases are normalized using exact primary-key lookups, FastRP topological similarity, and domain constraint checks.
Stage 5 · Bitemporal Patch Generation: Changes are emitted as atomic GraphPatch records containing asserted_at, valid_from, and supersedes references. Previous facts are marked superseded rather than destructively deleted.
Stage 6 · Batch Cypher Materialization: Mutations are committed via parameterized UNWIND transactions backed by Neo4j schema indexes.
# Conceptual: Bitemporal Mutation & Non-Destructive Superseding
function apply_assertion(graph, subject, predicate, object, document_source):
    existing_fact = graph.find_active_edge(subject, predicate)
    
    if existing_fact and existing_fact.target != object:
        # Supersede previous assertion without destructive deletion
        existing_fact.status = "superseded"
        existing_fact.valid_to = current_timestamp()
        
    # Insert new assertion with immutable provenance metadata
    graph.insert_edge(
        source = subject,
        relation = predicate,
        target = object,
        status = "current",
        asserted_at = current_timestamp(),
        source_doc = document_source
    )

2. Visualizing Scale: 500 to 100,000 Nodes

Visualizing massive graphs in a client browser quickly runs into performance bottlenecks. Running real-time force-directed physics simulations on 100,000 DOM elements easily exhausts browser memory and locks up the rendering loop.

Connected Subgraph Cluster with Semantic Edges
Figure 2: Zoomed-in view of core domain clusters showing active relationship edges ([:MANUFACTURES], [:SUPPLIES_PART], [:STOCKS_INVENTORY], [:CLAIM_ON_VEHICLE]) between OEMs, Dealerships, Parts, and Warranty records.

To make the UI responsive across scales, I added a multi-density rendering mode:


3. FastRP Topological Deduplication

Enterprise text often refers to the same real-world entity with slight variations—such as "Bombay Plant" versus "Mumbai Manufacturing Unit" or "GM" versus "General Manager". Calling an LLM to compare every pair of 100k entities is prohibitively slow and expensive.

To address this, I used Fast Random Projection (FastRP) graph embeddings. FastRP embeds node neighborhoods into 128-dimensional vectors based on graph topology. Candidate duplicates are identified using cosine similarity over structural neighbors and merged via atomic graph patches:

# Conceptual: Topological Graph Deduplication
function deduplicate_graph_entities(graph, similarity_threshold = 0.92):
    # 1. Project graph neighborhood into low-dimensional vector space
    embeddings = compute_fast_random_projection(graph.nodes, graph.edges, dim=128)
    
    # 2. Find candidate alias pairs via neighborhood cosine similarity
    candidate_pairs = find_high_similarity_pairs(embeddings, similarity_threshold)
    
    # 3. Validate schema compatibility and merge aliases
    for (entity_a, entity_b) in candidate_pairs:
        if validate_schema_compatibility(entity_a, entity_b):
            graph.merge_nodes(canonical = entity_a, alias = entity_b)

4. Grounded GraphRAG Agent & Traversal

When an end user asks complex multi-hop questions, the ReAct GraphRAG Agent does not guess. It executes targeted queries against the graph and traverses relationship pointers.

Example Query: "Which OEM manufactures the car inquired by customer LEAD-000010, and which dealership is assigned?"

Agent Execution Trace:
1. search_nodes("LEAD-000010") → Customer Lead Nisha Verma
2. Follow [:INQUIRED_ABOUT_MODEL] → Tata Harrier Adventure+ Diesel Automatic
3. Follow [:MANUFACTURES] → Tata Motors Passenger Vehicles Limited (org_tata)
4. Follow [:ASSIGNED_TO_DEALER] → Apex Automotive Madurai East (dealer_dl_mad_04)

Provenance: The response explicitly cites source assertions (assert_org_tata...) from leads.csv, car_catalog.csv, and dealership_master_network.md.

Handling Missing Data: A common failure mode in LLM RAG is inventing plausibly-sounding answers when an entity does not exist. If a user asks about LEAD-999999 or a non-existent dealership code, the graph lookup returns empty, and the agent explicitly reports that no assertion exists rather than guessing.


5. Comparison: Vector RAG vs Naive Graph vs Bitemporal Compiler

Dimension Flat Vector RAG Naive LLM Extraction Bitemporal Knowledge Compiler
Multi-Hop Traversal ❌ Lost across chunk boundaries 🟡 Fragile dangling IDs ✅ Indexed pointer hops
Temporal State & Auditing ❌ No bitemporal validity ❌ Destructive overwrites ✅ Immutable assertion IDs
Entity Disambiguation ❌ Embedding collision ❌ Entity duplication sprawl ✅ FastRP structural deduplication
Missing Entity Handling ❌ Frequent hallucination 🟡 Inconsistent grounding ✅ Explicit assertion check
100k Node Scale 🟡 High vector search latency ❌ Unindexed query bottlenecks ✅ B-Tree indexed batch UNWIND

Closing Takeaway

In complex domains like automotive supply chains, warranties, and multi-tier networks, relational topology matters as much as text semantics. Treating graph construction as a structured compiler problem—with deterministic AST chunking, bitemporal patches, and graph embeddings—gives LLM agents the precise, auditable ground truth they need to answer multi-hop questions reliably.