Dhruvpandey1476's picture
GraphRAG Hackathon Round 2 Submission - 54.7% token reduction
cb4c15b
|
Raw History Blame Contribute Delete
11.5 kB

Architecture Deep Dive β€” GraphRAG Inference System

System Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         GraphRAG Inference System                          β”‚
β”‚                                                                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                    React Dashboard (Port 5173)                       β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚  β”‚
β”‚  β”‚  β”‚  Query Input   β”‚  β”‚ Token BarChart  β”‚  β”‚   Accuracy RadarChart  β”‚ β”‚  β”‚
β”‚  β”‚  β”‚  Sample Q's    β”‚  β”‚ (Recharts)      β”‚  β”‚   (LLM-as-Judge)       β”‚ β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚  β”‚
β”‚  β”‚          β”‚ POST /query/compare                                        β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚             β”‚                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                    FastAPI Server (Port 8000)                         β”‚  β”‚
β”‚  β”‚                                                                      β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚
β”‚  β”‚  β”‚  Pipeline 1  β”‚  β”‚   Pipeline 2      β”‚  β”‚     Pipeline 3       β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  LLM Only    β”‚  β”‚   Basic RAG       β”‚  β”‚     GraphRAG         β”‚  β”‚  β”‚
β”‚  β”‚  β”‚              β”‚  β”‚                   β”‚  β”‚                      β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  β€’ sys promptβ”‚  β”‚  β€’ embed query    β”‚  β”‚  β€’ extract entities  β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  β€’ question  β”‚  β”‚  β€’ FAISS search   β”‚  β”‚  β€’ TG traversal      β”‚  β”‚  β”‚
β”‚  β”‚  β”‚  β€’ LLM call  β”‚  β”‚  β€’ top-K chunks   β”‚  β”‚  β€’ serialize graph   β”‚  β”‚  β”‚
β”‚  β”‚  β”‚              β”‚  β”‚  β€’ LLM call       β”‚  β”‚  β€’ LLM call          β”‚  β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚  β”‚
β”‚  β”‚         β”‚                  β”‚                          β”‚              β”‚  β”‚
β”‚  β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚  β”‚
β”‚  β”‚                            β”‚                                          β”‚  β”‚
β”‚  β”‚                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”                                β”‚  β”‚
β”‚  β”‚                   β”‚  LLM-as-Judge   β”‚                                β”‚  β”‚
β”‚  β”‚                   β”‚  + Metrics Agg  β”‚                                β”‚  β”‚
β”‚  β”‚                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                               β”‚                                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚                                   β”‚
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚   FAISS Vector DB   β”‚             β”‚   TigerGraph Savanna β”‚
   β”‚   (in-memory/pkl)   β”‚             β”‚   Knowledge Graph    β”‚
   β”‚                     β”‚             β”‚                      β”‚
   β”‚  chunks[]           β”‚             β”‚  Entity vertices     β”‚
   β”‚  embeddings[]       β”‚             β”‚  RELATED_TO edges    β”‚
   β”‚  IndexFlatIP        β”‚             β”‚  MENTIONED_IN edges  β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                β”‚
                                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                     β”‚   OpenAI API         β”‚
                                     β”‚   (LLM + Embeddings) β”‚
                                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Component Details

1. Ingestion Pipeline (backend/graph/ingestion.py)

Converts raw documents into the knowledge graph:

Raw Docs (.txt/.md)
    β”‚
    β–Ό  chunk_text() β€” token-aware, 512 tokens + 64 overlap
Document Chunks
    β”‚
    β–Ό  extract_entities_and_relations() β€” GPT-4o-mini JSON extraction
Entities + Relationships
    β”‚
    β”œβ”€β–Ά get_embeddings_batch() β€” text-embedding-3-small
    β”‚       β”‚
    β”‚       β–Ό
    β”‚   Entity embeddings (for future vector-on-graph hybrid)
    β”‚
    β”œβ”€β–Ά tg.upsert_entity() β€” Entity vertex in TigerGraph
    β”œβ”€β–Ά tg.upsert_document() β€” Document vertex in TigerGraph
    β”œβ”€β–Ά tg.upsert_relationship() β€” RELATED_TO edge
    └─▢ tg.link_entity_to_document() β€” MENTIONED_IN edge

Simultaneously, all raw chunks are added to FAISS for Pipeline 2.

2. Basic RAG Pipeline (backend/rag/basic_rag.py)

User Query
    β”‚
    β–Ό  openai.embeddings.create() β†’ 1536-dim vector
Query Vector
    β”‚
    β–Ό  faiss.IndexFlatIP.search() β€” cosine similarity
Top-K Chunk Indices (K=5)
    β”‚
    β–Ό  Concatenate chunk texts
Context String (~3,000 tokens)
    β”‚
    β–Ό  openai.chat.completions.create()
Answer + Token Usage

Token overhead: system prompt (50) + context (3,000) + question (~50) = ~3,100 prompt tokens

3. GraphRAG Pipeline (backend/rag/graph_rag.py)

User Query
    β”‚
    β–Ό  extract_query_entities() β€” LLM β†’ ["Entity A", "Entity B"]
Seed Entities
    β”‚
    β–Ό  tg.get_entity_subgraph() β€” GSQL multi-hop traversal
Subgraph {entities[], relationships[], documents[]}
    β”‚
    β–Ό  serialize_subgraph() β€” compact structured text
Graph Context (~400-800 tokens)
    β”‚
    β–Ό  openai.chat.completions.create()
Answer + Token Usage

Token overhead: system prompt (60) + graph context (600) + question (~50) = ~710 prompt tokens

Token reduction: ~77%

4. LLM-as-a-Judge (backend/llm/judge.py)

Question + Answer + Ground Truth
    β”‚
    β–Ό  GPT-4o-mini with JSON response format
{
  "score": 8,
  "correctness": 9,
  "completeness": 7,
  "clarity": 8,
  "relevance": 8,
  "reasoning": "..."
}

Run for both Basic RAG and GraphRAG answers. Used for per-query comparison and aggregate pass rate.

5. BERTScore Evaluation (evaluation/benchmark.py)

from bert_score import score as bert_score_fn
P, R, F1 = bert_score_fn(
    predictions=[graph_answers],
    references=[ground_truths],
    lang="en",
    model_type="distilbert-base-uncased"
)

Target: F1 rescaled β‰₯ 0.55 (raw β‰₯ 0.88) for bonus points.


Knowledge Graph Schema

Vertices

Type Key Attributes Purpose
Entity name, entity_type, description, embedding Core knowledge nodes
Document title, content, chunk_index, token_count Source text chunks
Concept name, category, importance_score High-level topics

Edges

Type Direction Attributes Purpose
RELATED_TO Entity ↔ Entity relation_type, confidence, context Core relationships
MENTIONED_IN Entity β†’ Document frequency, relevance_score Entity-source links
HAS_CONCEPT Document β†’ Concept weight Topic tagging
CO_OCCURS_WITH Entity ↔ Entity co_occurrence_count Statistical co-occurrence

Subgraph Serialization Format

The key to token efficiency is our compact serialization format:

## ENTITIES
β€’ [Entity Name] [TYPE]: description text

## RELATIONSHIPS
β€’ Entity A β€”[RELATION_TYPE]β†’ Entity B (conf: 0.95) | context snippet

## SUPPORTING TEXT (top-1 doc, max 300 chars)
[Document Title]: first 300 characters of relevant chunk...

This format is:

  • Hierarchically structured (LLM can parse with zero instruction)
  • Non-redundant (each fact stated once)
  • Confidence-weighted (LLM can trust high-confidence facts more)
  • Bounded (caps prevent runaway token usage)

API Endpoints

Method Path Description
GET /health Server health + TG connection status
POST /query/compare Run all 3 pipelines, return full metrics
GET /stats/session Cumulative session token savings
GET /graph/stats TigerGraph vertex/edge counts
POST /ingest/text Quick-ingest a document

Performance Characteristics

Operation Typical Latency
Query embedding (OpenAI) 150–300ms
FAISS search (100K chunks) <10ms
Entity extraction (LLM) 300–600ms
TigerGraph GSQL traversal 50–200ms
LLM generation (gpt-4o-mini) 800–2000ms
LLM Judge evaluation 300–600ms
Total: Basic RAG ~1,500–2,500ms
Total: GraphRAG ~1,000–1,800ms

GraphRAG's latency advantage comes from:

  1. No FAISS search needed (graph traversal replaces it)
  2. Smaller context = faster LLM generation
  3. No chunk deduplication step needed

Scaling Considerations (Round 2)

For 50-100M token datasets:

  • TigerGraph Savanna handles billions of edges natively β€” no schema changes needed
  • FAISS upgrades to IndexIVFFlat or HNSW for ANN search at scale
  • Ingestion parallelized with async batch processing
  • Entity extraction cached β€” same entities aren't re-extracted across document runs
  • Community detection (TigerGraph built-in) adds global context layer for broad queries