Skip to content

Hybrid Graph-Vector RAG — Architecture Guide ​

POST /rag/hybrid-query · MCP tool: rag.hybrid_query


What is Hybrid Graph-Vector RAG? ​

Hybrid Graph-Vector RAG is the capstone retrieval architecture in Purple8 Hyper Graph. It fuses vector similarity and graph structural signals at every stage of the retrieval pipeline — not just at seed selection. The result is a retriever that understands both semantic meaning and relational structure simultaneously.

At a high level:

User Query
    │
    ▼
[Stage 1] Dual-Signal Seed Fusion
    ├── Vector branch: HNSW top-2k → rank by cosine similarity
    ├── Graph branch:  vector seeds → degree centrality probe
    └── Weighted RRF fusion (alpha controls graph vs vector weight)
    │
    ▼
[Stage 2] Vector-Guided BFS Expansion
    ├── BFS from fused seed nodes (configurable depth 1–5)
    ├── Each candidate neighbour re-scored by cosine(query, neighbour)
    └── Low-similarity neighbours pruned (threshold 0.25 default)
    │
    ▼
[Stage 3] Semantic Path Scoring
    ├── Every graph path from seeds to retrieved nodes is scored
    ├── Score = keyword overlap + edge-type bonus
    └── Paths ranked; top paths surface to LLM context
    │
    ▼
[Stage 4] Dual-Provenance Context Assembly + LLM Generation
    ├── Each context node annotated with:
    │     seed#N  vec=0.XX  deg=N  hub  hop=N
    ├── LLM prompt includes provenance annotations
    └── LLM generates grounded answer + optional inferred edges

Pipeline Stages in Detail ​

Retrieval contracts ​

  • label_filter is passed to ANN seed selection before top-k ranking, rather than discarding other labels afterward.
  • Graph expansion consumes the engine's actual traversal nodes and paths. Context edges are collected from the selected nodes' adjacency, not from a global, truncated edge listing.
  • Storage, traversal, and edge-read failures stop retrieval and propagate to the caller. The REST endpoint returns a non-2xx error and does not invoke answer generation for a failed retrieval.
  • max_nodes limits assembled context and bounds discovered nodes in each expansion traversal, including its seed. It is not a global work/deadline budget: multiple seeds can each initiate a traversal, and reading a large adjacency list can still require additional work and memory.

Stage 1 — Dual-Signal Seed Fusion ​

python
# Pseudocode
vector_hits   = embed(query) |> hnsw_search(k=2×seed_k)  # wide net
degree_probes = vector_hits  |> count_edges()             # structural signal
fused_seeds   = weighted_rrf(vector_hits, degree_probes, alpha=fusion_alpha)

Two independent signals rank the same candidate pool:

  • Vector rank: cosine similarity to the query embedding. Captures semantic proximity.
  • Degree rank: number of edges on each node. Captures structural importance (hubs that connect many entities are high-value traversal starting points).

The two ranked lists are combined with Weighted Reciprocal Rank Fusion (W-RRF):

$$\text{score}(d) = (1 - \alpha) \cdot \frac{1}{k + r_v} + \alpha \cdot \frac{1}{k + r_g}$$

where $r_v$ is the vector rank, $r_g$ is the degree rank, $k=60$ (standard RRF constant), and $\alpha \in [0, 1]$ controls graph vs vector emphasis.

Fusion ModeαBest For
vector_first0.2Semantic similarity queries
balanced0.5General-purpose (recommended default)
graph_first0.8Dense relationship / deep traversal queries

Stage 2 — Vector-Guided BFS Expansion ​

python
# Pseudocode
for seed in fused_seeds:
    for neighbour in bfs_neighbours(seed, depth=max_hops):
        sim = cosine(embed(query), embed(neighbour))
        if sim >= vector_expansion_threshold:    # default 0.25
            include(neighbour)

Standard Graph RAG expands BFS unconditionally — every reachable neighbour enters the subgraph. Hybrid RAG filters each candidate neighbour by its embedding similarity to the query. This prevents irrelevant structural expansion from contaminating the LLM context, which is the primary reason multi-hop accuracy improves from 0.79 (Graph RAG) to 0.91 (Hybrid RAG).


Stage 3 — Semantic Path Scoring ​

Every path connecting a seed node to a retrieved node is scored:

$$\text{path_score}(p) = \text{keyword_overlap}(p, q) + \sum_{e \in p} \text{edge_bonus}(e)$$

Where:

  • keyword_overlap counts query terms appearing in node property text along the path
  • edge_bonus is a small additive bonus for "strong" edge types (e.g. OWNS, CONTROLS, FOUNDED)

Paths are sorted by score and the top paths are surfaced in the LLM context, giving the model explicit reasoning chains rather than a flat node dump.


Stage 4 — Dual-Provenance Context Assembly ​

Each node in the final context receives human-readable provenance annotations:

[seed#1] Acme Corp  (vec=0.92, deg=47, hub)
[hop=1]  Beta Inc   (vec=0.71, deg=12)
[hop=2]  VC Fund A  (vec=0.63, deg=31, hub)
AnnotationMeaning
seed#NThis node was selected as the N-th fusion seed
vec=0.XXCosine similarity to the query embedding
deg=NNumber of graph edges (structural importance)
hubNode is in the top 10% by degree centrality
hop=NBFS distance from nearest seed node

These annotations allow the LLM to:

  1. Weight high-similarity nodes more heavily in its answer
  2. Explain relationships using the path structure
  3. Generate more faithful, relationship-grounded answers

Configuration Reference ​

REST Endpoint ​

POST /rag/hybrid-query

json
{
  "question":             "string (required)",
  "mode":                 "balanced | graph_first | vector_first  (default: balanced)",
  "fusion_alpha":         0.5,
  "max_hops":             2,
  "seed_k":               5,
  "max_nodes":            50,
  "write_inferred":       false,
  "vector_expansion":     true,
  "semantic_path_scoring": true,
  "label_filter":         ["Company", "Person"],
  "max_tokens":           1024,
  "temperature":          0.0
}

MCP Tool ​

json
{
  "tool": "rag.hybrid_query",
  "arguments": {
    "question":              "How does Acme Corp's investor network connect to Beta Inc?",
    "mode":                  "balanced",
    "max_hops":              3,
    "seed_k":                8,
    "write_inferred":        true
  }
}

Use rag.profile_collection to inspect graph topology and receive recommended fusion_alpha, max_hops, and seed_k values for your corpus, or rag.tune_collection to run an autonomous retrieval grid search and persist a named CollectionProfile.

Parameter Cheat Sheet ​

ParameterDefaultRangeEffect
modebalanced—Preset fusion alpha
fusion_alpha0.50.0–1.0Override mode weight
max_hops21–5BFS depth; ↑ = more context, ↑ latency
seed_k51–20Seeds per signal; ↑ = broader search
max_nodes505–200Subgraph budget; ↑ = richer context
vector_expansiontrueboolCosine-filter BFS neighbours
semantic_path_scoringtrueboolRank paths semantically
write_inferredfalseboolPersist LLM edges to graph

Response Schema ​

json
{
  "answer":        "LLM-generated answer string",
  "subgraph": {
    "nodes":       [...],
    "paths":       [...]
  },
  "retrieval_provenance": [
    {
      "node_id":     "acme-corp",
      "vector_score": 0.92,
      "graph_degree": 47,
      "seed_rank":    1,
      "hop_distance": 0,
      "fused_score":  0.87,
      "signals":      ["vector", "degree"]
    }
  ],
  "path_relevance_scores": [
    {
      "path_index":     0,
      "relevance_score": 0.83,
      "matching_terms": ["investor", "portfolio"],
      "path_description": "Acme Corp → INVESTED_BY → VC Fund A → PORTFOLIO → Beta Inc"
    }
  ],
  "retrieval_mode":     "balanced",
  "fusion_alpha":       0.5,
  "seed_fusion_stats":  { "vector_seeds": 5, "degree_seeds": 5, "fused_seeds": 5 },
  "inferred_edges":     [...],
  "query_time_ms":      237
}

When to Use Each RAG Type ​

Decision tree
─────────────────────────────────────────────────────────────────────
Is latency < 100 ms critical?
  → YES: Use rag.query (Flat Vector RAG)
  → NO:
      Does the question involve relationships or traversal?
        → YES: Use rag.hybrid_query
            Are the relationships very dense / deep?
              → YES: mode=graph_first, max_hops=3–4
              → NO:  mode=balanced (default)
        → NO:
            Is the question pure semantic similarity?
              → YES: rag.hybrid_query, mode=vector_first
                     (or rag.query if latency matters)
              → NO:  rag.hybrid_query, mode=balanced

Empirical Accuracy ​

MetricFlat Vector RAGGraph RAGHybrid RAG
Precision@50.610.740.83
Recall@50.580.710.79
MRR0.640.760.85
Multi-hop Accuracy0.420.790.91
Context Quality (1–10)5.27.89.1
Mean Latency (ms)45180240

→ Full benchmark methodology and per-question-type breakdown: RAG Benchmark


Advanced Use Cases ​

Temporal Hybrid RAG ​

When your graph has temporal edges (valid_from / valid_to), the hybrid pipeline automatically respects the time dimension:

python
# Query the knowledge graph as it existed on a specific date
result = await pipeline.query(
    "Who were Acme Corp's key investors in Q3 2024?",
    temporal_at="2024-09-30T23:59:59Z",  # point-in-time filter
)

BFS expansion in Stage 2 skips edges whose validity window does not contain the query timestamp — your RAG context reflects the historical state of the graph, not the current state. Combine with dynamic PageRank for authoritative retrieval at a point in time.

Industry Algorithm Augmentation ​

The hybrid pipeline can be seeded with outputs from industry-specific algorithms for precision retrieval in vertical domains:

python
# Fraud investigation: seed hybrid RAG from fraud-ring detection output
fraud_rings = engine.algorithms.fraud_ring_detection(
    entity_type="Account", min_ring_size=3
)
suspicious_nodes = [m for ring in fraud_rings for m in ring.members]

result = await pipeline.query(
    "Summarise the transaction patterns in this fraud ring",
    seed_node_ids=suspicious_nodes,  # pre-seed BFS from algorithm output
    mode="graph_first",
    max_hops=3,
)

Similarly, A* pathfinding results, attack path analysis outputs, and recommendation engine candidates can all be used as BFS seeds for targeted hybrid retrieval.


See Also ​

Purple8 Hyper Graph v0.72.0 · AI-Native Execution Infrastructure · NVIDIA Inception Member · Red Hat Technology Partner.