Back openDesk Edu for a sovereign, open-source education β every vote counts.
Vote nowBy mid-2026, GraphRAG has fragmented into specialised architectures, each optimised for a different slice of the retrieval space. "GraphRAG" no longer means one thing. This article profiles six notable variants β Deep GraphRAG, CatRAG, ParallaxRAG, TagRAG, LeanRAG, and the GraphRAG-Bench framework β and gives senior engineers a decision framework for picking among them.
Before comparing individual variants, understand how the field is being measured. GraphRAG-Bench, published at ICLR 2026, is the first benchmark purpose-built for GraphRAG evaluation. Earlier benchmarks like HotpotQA and MultiHop-RAG measure only shallow fact retrieval, missing the reasoning complexity graphs are supposed to unlock.
GraphRAG-Bench provides 1,018 college-level questions across 16 CS disciplines, covering five question types (multiple-choice, multi-select, true/false, fill-in-blank, open-ended) with end-to-end pipeline evaluation.
The headline finding: GraphRAG beats vanilla RAG only on complex multi-hop queries. For simple factual retrieval, graph traversal degrades both latency and accuracy. Variant choice must be driven by query complexity, not by graph enthusiasm.
| Query Type | GraphRAG Advantage | Variant Best Suited |
|---|---|---|
| Simple fact retrieval | None β vanilla RAG wins | None needed |
| Multi-hop (2-3 hops) | Moderate | CatRAG, ParallaxRAG |
| Deep multi-hop (4+ hops) | Strong | Deep GraphRAG, ParallaxRAG |
| Global summarisation | Strong | Deep GraphRAG, TagRAG |
| Domain-specific reasoning | Strong | TagRAG, LeanRAG |
Origin: Li et al., 2026. Not to be confused with Microsoft's original GraphRAG, though it builds on the same community-detection foundation.
Deep GraphRAG introduces a three-stage retrieval strategy that prunes the search space progressively: inter-community filtering (topological pruning), community-level refinement (entity-interaction analysis), and entity-level fine-grained search with beam-search re-ranking.
Its standout innovation is DW-GRPO (Dynamic Weighting Reward GRPO), which adaptively adjusts reward weights for relevance, faithfulness, and conciseness during RL training. The result: a 1.5B model achieves 94% of the performance of a 72B model on Natural Questions.
Best for: Global-to-local coverage when you cannot afford a frontier model for integration.
Tradeoff: Three-stage latency; non-trivial to reproduce DW-GRPO training; assumes stable hierarchical communities.
Origin: Lau et al., 2026, ACL 2026 Findings.
CatRAG targets the Static Graph Fallacy: methods like HippoRAG fix transition probabilities during indexing, ignoring query-dependent edge relevance. This causes semantic drift β random walks get sucked into high-degree hub nodes ("United States", "Nobel Prize") before reaching critical evidence.
CatRAG transforms the static KG into a query-adaptive navigation structure via three mechanisms:
On the HoVer dataset, CatRAG achieves an 18.7% relative gain in Joint Success Rate (full-chain retrieval) over HippoRAG2. The latency cost is approximately 2.6x the static baseline, adding roughly 4.8 seconds per query.
Best for: Multi-hop QA where reasoning completeness matters β legal document analysis, medical evidence chains, audit trails.
Tradeoff: Query-time LLM calls for edge weighting increase cost. The 2.6x latency premium may be unacceptable for real-time applications. The gains are concentrated on multi-hop queries; single-hop queries see no benefit.
Origin: Liu et al., 2026, ACL 2026.
ParallaxRAG is built on a compelling insight: transformer attention heads naturally specialise at different reasoning depths. Collapsing all hops into a single embedding suppresses this structure. ParallaxRAG decouples queries and KGs into head-specific semantic spaces β separate retrieval heads for entity-centric, relation-centric, and subgraph-centric views β enforced by Pairwise Similarity Regularisation (PSR) and consolidated via weakly supervised gating.
It achieves SOTA results on WebQSP (78.80 Macro-F1) and CWQ (62.31 Macro-F1), with zero-shot generalisation to biomedical BioASQ where it beats prior SOTA by 7.32 Macro-F1. Removing query-aware gating crashes performance by 15+ F1 points β it is not optional.
Best for: Complex, open-domain multi-hop QA with zero-shot domain transfer requirements. Biomedical and scientific literature QA are natural fits.
Tradeoff: Multi-head decoupling adds architectural complexity. Training requires careful tuning of the PSR regularisation strength. The framework is designed for KG-RAG (structured knowledge graphs like Freebase), not for document-derived graphs.
Origin: Tao et al., 2026, ACL 2026 Findings.
TagRAG takes a different approach to graph construction. Instead of extracting fine-grained entities and running community detection, it extracts object tags and organises them into hierarchical domain tag chains linked to predefined root tags.
This design yields two efficiency wins:
The performance is surprisingly strong: a 78.36% average win rate against NaiveRAG, GraphRAG, LightRAG, and MiniRAG across UltraDomain datasets (Agriculture, CS, Legal, cross-domain). Even more striking: TagRAG with a 1.7B model beats GraphRAG with a 4B model, demonstrating that the tag chain mechanism reduces reliance on LLM capability.
TagRAG also handles incremental updates cleanly β new documents insert tags into the existing DAG without full graph reconstruction.
Best for: Domain-specific RAG with structured taxonomies. Regulatory compliance, legal document management, and enterprise knowledge bases where domains are well-defined.
Tradeoff: Requires predefined root domain tags β not suitable for open-domain corpora where you cannot enumerate the hierarchy upfront. The tag chain abstraction discards fine-grained entity relationships that a full entity graph would capture.
Origin: Zhang et al., 2026, AAAI 2026.
LeanRAG addresses retrieval redundancy. Community-based methods retrieve entire communities, flooding the context window with overlapping information.
LeanRAG's solution has two parts. Semantic aggregation clusters entities into coherent groups and infers explicit relations between the cluster-level summaries, transforming disconnected "semantic islands" into a navigable network. Lowest Common Ancestor (LCA) traversal constructs a minimal subgraph from seed entities using their LCA in the hierarchy, producing a compact evidence set.
The headline result: 46% reduction in retrieval redundancy by token count, with no degradation in answer quality.
Best for: Resource-constrained deployments where context window pressure and API cost are primary concerns. High-throughput pipelines that process thousands of queries daily.
Tradeoff: The semantic aggregation step is itself an LLM call during indexing. The LCA strategy assumes a tree-like hierarchy β it may produce suboptimal subgraphs for graphs with dense cross-community connections.
While each variant demands its own research codebase, the underlying retrieval pattern β vector search for initial recall, graph traversal for structural precision β is shared across all six. The neo4j-graphrag Python library provides a unified retriever that maps directly onto these architectural choices.
pip install neo4j-graphrag neo4j sentence-transformers
The decision framework from this article compresses to a single function:
from dataclasses import dataclass
@dataclass
class QueryProfile:
hop_depth: int # Average relationship hops per query
domain_bounded: bool # Is the corpus domain-restricted?
latency_sensitive: bool # Must respond in < 2 seconds?
throughput: int # Queries per day
def select_variant(profile: QueryProfile) -> str:
"""Map pipeline characteristics to the optimal variant."""
if profile.hop_depth <= 1:
return "vanilla_rag" # Graph adds cost without benefit
if profile.domain_bounded:
return "TagRAG" # 14.6x faster construction
if profile.latency_sensitive:
return "LeanRAG" # Lowest query-time overhead
if profile.hop_depth >= 4:
return "Deep GraphRAG" # Hierarchical pruning for deep chains
return "CatRAG" # Best balance for 2-3 hop queries
# Example: regulatory compliance pipeline
cfg = select_variant(QueryProfile(
hop_depth=3, domain_bounded=True,
latency_sensitive=False, throughput=500,
))
print(cfg) # "TagRAG"
All six variants share a common architectural layer β hybrid vector-plus-graph retrieval. The HybridCypherRetriever from neo4j-graphrag configures this shared pattern. Variants differ in how the graph traversal query is structured:
from neo4j_graphrag.retrievers import HybridCypherRetriever
# Deep GraphRAG-style: community-aware traversal
retriever = HybridCypherRetriever(
driver=driver,
vector_index="entity_embeddings",
fulltext_index="entity_fts",
retrieval_query="""
WITH node AS chunk, score
OPTIONAL MATCH (chunk)-[:IN_COMMUNITY]->(c:Community)
OPTIONAL MATCH (c)<-[:IN_COMMUNITY]-(related)
WHERE c.modularity > 0.3
RETURN chunk.text, score,
collect(DISTINCT related.text) AS community_context
ORDER BY score DESC
LIMIT 10
"""
)
For TagRAG, the traversal switches from community detection to tag chain navigation; for CatRAG, it adds query-aware edge weighting at traversal time. The base retriever stays the same β only the Cypher query changes. This shared architecture means your initial investment in a hybrid retrieval pipeline transfers across variants as the field evolves.
| Variant | Approach | Key Innovation | Best Use Case | Tradeoff |
|---|---|---|---|---|
| Deep GraphRAG | Three-stage hierarchical retrieval + beam-search re-ranking | DW-GRPO: 1.5B model achieves 94% of 72B performance | Global-to-local QA with budget constraints | Multi-stage latency; complex training pipeline |
| CatRAG | Query-adaptive random walk on static KG | Dynamic edge weighting via LLM at query time | Multi-hop reasoning with complete evidence chains | 2.6x latency premium; query-time LLM cost |
| ParallaxRAG | Multi-head decoupling of queries and graph triples | Head-specific semantic spaces with PSR regularisation | Open-domain multi-hop QA; zero-shot domain transfer | Architectural complexity; requires structured KG |
| TagRAG | Tag-based hierarchical KG with domain chains | 14.6x construction efficiency via tag extraction | Domain-specific RAG with structured taxonomies | Requires predefined root tags; loses entity granularity |
| LeanRAG | Semantic aggregation + LCA-based traversal | 46% redundancy reduction via bundle-level grouping | High-throughput; resource-constrained deployments | Assumes tree hierarchy; aggregation adds indexing cost |
The prose above translates directly into a programmable decision function. This is useful if you're building an agentic pipeline that must self-select its retrieval strategy based on runtime query profiling:
from dataclasses import dataclass
@dataclass
class QueryProfile:
"""Describes the query load and deployment constraints for variant selection."""
avg_hops: float # Average reasoning depth required
domain_hierarchy_known: bool # Can root tags be predefined?
max_latency_ms: float # Tolerance for retrieval latency
throughput_qps: float # Queries per second target
budget_tier: str = "standard" # "economy", "standard", "unlimited"
def select_graphrag_variant(profile: QueryProfile) -> str:
\"\"\"Recommend a GraphRAG variant based on a query profile.\"\"\"
# Simple lookups: no GraphRAG needed
if profile.avg_hops < 1.5:
return "Vanilla RAG (no GraphRAG needed)"
# Domain-bounded with known taxonomy
if profile.domain_hierarchy_known:
if profile.budget_tier == "economy":
return "TagRAG (1.7B model)"
return "TagRAG"
# High-throughput, token-sensitive
if profile.throughput_qps > 50:
return "LeanRAG"
# Deep multi-hop reasoning
if profile.avg_hops >= 4:
if profile.max_latency_ms > 5000:
return "Deep GraphRAG"
return "ParallaxRAG"
# Moderate multi-hop (2β3 hops)
if 1.5 <= profile.avg_hops < 4:
if profile.max_latency_ms > 3000:
return "CatRAG"
return "ParallaxRAG"
return "Deep GraphRAG (default)"
Applying this to the domain-specific legal QA scenario from the TagRAG section:
legal_profile = QueryProfile(
avg_hops=2.5,
domain_hierarchy_known=True,
max_latency_ms=6000,
throughput_qps=5,
budget_tier="standard",
)
print(select_graphrag_variant(legal_profile))
# Output: "TagRAG"
For an open-domain research assistant deployed at scale:
research_profile = QueryProfile(
avg_hops=3.8,
domain_hierarchy_known=False,
max_latency_ms=4000,
throughput_qps=200,
budget_tier="unlimited",
)
print(select_graphrag_variant(research_profile))
# Output: "LeanRAG"
The decision function is intentionally simple β in production you would replace the if-chain with a learned classifier trained on offline benchmark data, but the same features (hop depth, domain structure, latency ceiling, throughput) remain the core predictors.
The comparison table above translates directly into code. Here is a minimal query router that selects the right variant based on your query profile:
from dataclasses import dataclass
from enum import Enum
class QueryComplexity(Enum):
SINGLE_HOP = 1
MULTI_HOP_SHORT = 2 # 2β3 hops
MULTI_HOP_DEEP = 3 # 4+ hops
GLOBAL = 4
DOMAIN = 5
@dataclass
class QueryProfile:
complexity: QueryComplexity
domain_bounded: bool = False
latency_sensitive: bool = False
throughput_critical: bool = False
def select_variant(p: QueryProfile) -> str:
match p.complexity:
case QueryComplexity.SINGLE_HOP:
return "Vanilla RAG β skip GraphRAG entirely"
case QueryComplexity.MULTI_HOP_SHORT:
return "CatRAG" if not p.latency_sensitive else "LeanRAG"
case QueryComplexity.MULTI_HOP_DEEP:
return "ParallaxRAG" if p.throughput_critical else "Deep GraphRAG"
case QueryComplexity.GLOBAL:
return "TagRAG" if p.domain_bounded else "Deep GraphRAG"
case QueryComplexity.DOMAIN:
return "TagRAG" if p.domain_bounded else "LeanRAG"
return "Deep GraphRAG" # safe fallback
Wire this router into your preprocessing pipeline to dispatch queries to the appropriate variant automatically. The only external input needed is a query classifier β a small LLM call or a rule-based heuristic that maps each query to a QueryComplexity.
Three questions to ask before picking a variant:
What kind of queries dominate your pipeline? If 80% are simple fact lookups, skip GraphRAG entirely β none of these variants beat vanilla RAG on that load. For multi-hop or global reasoning, match the variant to hop depth: CatRAG for 2-3 hops, ParallaxRAG or Deep GraphRAG for deeper chains.
Can you define your domain hierarchy upfront? TagRAG requires root domain tags. If you are building a legal document system with a known taxonomy (contract types, jurisdictions, practice areas), TagRAG is the most efficient choice. If your corpus is open-domain, ParallaxRAG or Deep GraphRAG are safer.
What are your latency and cost constraints? CatRAG's 2.6x latency multiplier is acceptable for offline document analysis but not for real-time chat. LeanRAG is the best choice for high-throughput pipelines where every token counts. Deep GraphRAG's distillation pathway saves on LLM cost but adds retrieval latency. TagRAG wins on both construction and retrieval efficiency, but only for domain-bounded corpora.
No single variant dominates. The 2026 GraphRAG landscape is a toolkit, not a monolith.
The decision framework above can be codified into a lightweight selection engine that routes queries to the optimal variant at runtime. The following Python implementation encapsulates the three decision dimensions β query depth, domain structure, and deployment constraints β into a reusable selector:
from enum import Enum
from dataclasses import dataclass
class QueryDepth(Enum):
SINGLE_HOP = "single_hop" # Simple fact lookup
MODERATE = "moderate" # 2-3 hop reasoning
DEEP = "deep" # 4+ hop or global reasoning
@dataclass
class DeploymentConstraints:
has_domain_hierarchy: bool # Predefined root tags available?
max_latency_ms: int # p99 latency budget
max_cost_per_query: float # USD per query (LLM calls)
queries_per_day: int # Daily throughput
class GraphRAGVariantSelector:
"""Selects the optimal GraphRAG variant for a given query context."""
def select(
self,
depth: QueryDepth,
constraints: DeploymentConstraints,
) -> str:
# Single-hop: GraphRAG adds latency without benefit
if depth == QueryDepth.SINGLE_HOP:
return "vanilla_rag"
# Domain hierarchy defined β TagRAG is most efficient
if constraints.has_domain_hierarchy:
return "tagrag"
# Tight latency budget or high throughput β LeanRAG
if constraints.max_latency_ms < 2000 or constraints.queries_per_day > 10_000:
return "leanrag"
# Deep multi-hop β ParallaxRAG for open-domain
if depth == QueryDepth.DEEP:
return "parallaxrag"
# Default: CatRAG for moderate multi-hop with evidence chains
return "catrag"
Usage in a retrieval pipeline:
selector = GraphRAGVariantSelector()
constraints = DeploymentConstraints(
has_domain_hierarchy=False,
max_latency_ms=3000,
max_cost_per_query=0.02,
queries_per_day=5000,
)
variant = selector.select(QueryDepth.DEEP, constraints)
# Returns "parallaxrag" β best for open-domain deep reasoning
# within a 3-second latency budget
This selector is deliberately simple β the decision logic fits in a single if chain because the three questions from the framework are mutually reinforcing. In production, the QueryDepth classifier can be driven by a small fine-tuned model or even an LLM call that analyses the question before routing. The key point is that variant selection should be automatic, not a manual decision made once at deployment time. A hard-coded variant will be optimal for some queries and suboptimal for others. Routing dynamically based on query characteristics is the difference between a toolkit and a monolith.