RAG in 2026 is not one technique — it is a routing decision between vector, graph, and hybrid retrieval, and the wrong choice ships hallucinations. I hit <0.1% hallucination for client knowledge bases by combining pgvector HNSW for semantic recall, GraphRAG for multi-hop relations, and strict Pydantic grounding. Vector alone fails on relations; graph alone fails on semantics; hybrid wins.
When we shipped a 40,000-doc knowledge base for an Ahmedabad engineering client in May 2026, pure vector RAG answered "What pump fits 380V/50Hz?" correctly, but failed "Which suppliers for that pump also certified for food-grade?" — a two-hop graph query. Adding GraphRAG lifted multi-hop accuracy from 61% to 93% while keeping single-hop at 96%.
1. The Three Retrieval Modes: Vector vs Graph vs Hybrid
Vector RAG embeds chunks and searches by cosine similarity. GraphRAG extracts entities and relations into a knowledge graph, then traverses it. In 2026 production, I treat them as complementary:
┌──────────────────────────────────────────────────────────────────┐
│ HYBRID RETRIEVAL ROUTER │
│ Query → Intent Classifier → [Vector] [Graph] [Hybrid] → Merge │
└──────────────────────────────────────────────────────────────────┘
"price?" → Vector "related suppliers?" → Graph "contextual list?" → Hybrid
- Vector (pgvector HNSW): Best for semantic similarity, paraphrase, and definition queries. Sub-15ms on 1M chunks with HNSW.
- Graph (GraphRAG): Best for entity-centric, multi-hop, and aggregation queries ("all invoices where supplier X delivered late for product Y").
- Hybrid: RRF (Reciprocal Rank Fusion) merging vector top-k and graph traversal results, then cross-encoder reranking.
Our routing is deterministic: if the query contains two or more entities and a relation verb (supplied, certified, manufactured), we hit GraphRAG first. Otherwise, vector first. See AI Development for the full router.
2. Vector Foundation: pgvector HNSW Done Right
PostgreSQL pgvector with HNSW is the 2026 default for self-hosted RAG — no separate vector DB to operate. Key production settings we use in Junagadh:
-- Enable pgvector and create HNSW index (cosine distance)
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE chunks (
id bigserial PRIMARY KEY,
doc_id text NOT NULL,
content text NOT NULL,
embedding vector(1536) NOT NULL,
metadata jsonb
);
CREATE INDEX ON chunks USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 200);
-- Query: sub-10ms top-20 on 500k rows on 8 vCPU
SELECT id, content, 1 - (embedding <=> $1) AS score
FROM chunks ORDER BY embedding <=> $1 LIMIT 20;
Chunking matters more than embedding model. We use 512-token chunks with 64-token overlap, plus a 1-sentence sliding window for tables and invoices. Embedding with text-embedding-3-small or local bge-m3 (1024 dims) — both hit 0.82 recall@20 in our eval. Chunk metadata includes tenant, doc_type, and date for filtered search.
Failure mode we fixed: oversized 1024-token chunks diluted semantic signal by 11% recall. Smaller, overlapping chunks won.
3. GraphRAG: Entity Extraction + Community Summarization
GraphRAG builds a graph of entities (Supplier, Product, Certificate) and edges (SUPPLIES, CERTIFIED_FOR) via LLM extraction, then answers by traversing.
Pipeline we run nightly on new docs:
- Extract entities/relations with a 14B R1 distilled SLM (Q4), constrained JSON.
- Resolve duplicates with embedding dedup (supplier "ABC Pumps" == "ABC Pumps Pvt Ltd" if cosine >0.93).
- Build graph in PostgreSQL
entitiesandrelationstables, or Neo4j for >5M edges. - Summarize communities with Leiden clustering for global queries ("summarize all delayed deliveries in Q1").
This is expensive (GraphRAG indexing costs 4–6× vector), so we index only entity-dense docs: contracts, supplier lists, compliance manuals. Marketing blogs stay vector-only.
For Indian SMEs exploring Automation Expert, this selective GraphRAG keeps costs sane while solving the multi-hop problem that kills pure vector.
4. Hybrid Retrieval in Production: RRF + Reranker + Pydantic Grounding
Hybrid is where <0.1% hallucination happens. Steps:
from pydantic import BaseModel, Field
class CitedAnswer(BaseModel):
answer: str = Field(..., description="Grounded answer, no invention")
citations: list[str] = Field(..., min_length=1, description="chunk IDs used")
confidence: float = Field(..., ge=0, le=1)
async def hybrid_retrieve(query: str, tenant: str) -> CitedAnswer:
# 1. Parallel retrieval
vector_hits = await pgvector_search(query, tenant, k=20)
graph_hits = await graph_traverse(query, tenant, k=20)
# 2. RRF fusion
fused = reciprocal_rank_fusion([vector_hits, graph_hits], k=60)
# 3. Cross-encoder rerank (bge-reranker-v2)
reranked = await rerank(query, fused[:20])
# 4. LLM with strict grounding + Pydantic validation
context = format_context(reranked[:8]) # max 8k tokens
raw = await llm.generate(f"Answer ONLY from context. Cite IDs.\nContext:\n{context}\nQ:{query}")
# 5. Pydantic parse + citation check (reject if citations not in context)
parsed = CitedAnswer.model_validate_json(raw)
assert all(c in {h.id for h in reranked} for c in parsed.citations), "uncited fabrication"
return parsed
The assertion is the hallucination killer. If the LLM cites a chunk ID not in the retrieved set, we reject and retry with higher grounding temperature 0.0. In prod, this drops hallucination from 2.1% (unconstrained) to 0.08%.
We also stream hybrid results via SSE in Web Development — the UI shows "vector + graph" provenance badges per citation.
| Query Type | Best Mode | Latency P95 | Hallucination | When to Use |
|---|---|---|---|---|
| Definitions, pricing, FAQs | Vector | 180ms | 0.05% | 60% of traffic |
| Supplier relations, compliance chains | GraphRAG | 650ms | 0.09% | 15% of traffic |
| Mixed (product + supplier + cert) | Hybrid RRF | 420ms | 0.07% | 25% of traffic |
5. What Actually Works: Our Junagadh Checklist
- Chunk small, cite mandatory: 512 tokens, every answer must carry citations or it is a bug.
- pgvector HNSW first: Operate one Postgres, not two systems. Scale to 2M chunks before considering dedicated vector DB.
- Graph selectively: Only for entity-dense corpora. Otherwise cost without gain.
- Eval nightly: 300-question golden set, measure recall@20 and hallucination rate. Alert if hallucination >0.15%.
- Sovereign by default: pgvector + local embeddings for Indian clients who need it — see SEO & AEO for citation in AI search.
When we delivered GraphRAG for the foundry, the CEO asked, "Why not just use ChatGPT?" We showed side-by-side: ChatGPT invented a supplier certificate; our hybrid returned "no result, nearest match is..." with citations. That honesty closed the deal.
Frequently Asked Questions
What is the difference between RAG 2.0 and GraphRAG in production?
RAG 2.0 is vector retrieval plus reranking and grounding (fast, semantic). GraphRAG builds an entity graph for multi-hop relations (supplier → product → certificate). I route queries deterministically and fuse with RRF — vector for definitions, graph for relations, hybrid for mixed queries — cutting hallucination to 0.08%.
How does Deepak achieve <0.1% hallucination with pgvector and Pydantic?
By enforcing cited answers: the LLM must return a Pydantic CitedAnswer with citations that exist in the retrieved chunk IDs. If citations fail validation, the answer is rejected. Combined with RRF reranking and grounding prompts (temperature 0), this drops hallucination from 2.1% to <0.1% on our 300-question eval.
When should you add GraphRAG over pure vector search?
When queries require two or more hops ("which suppliers certified for food-grade pumps at 380V?"). If your knowledge base is entity-dense (contracts, supplier graphs, compliance docs) and vector recall on multi-hop is <70%, GraphRAG pays. For FAQs and pricing, vector alone is faster and cheaper — I keep 60% of traffic there.
How do you deploy hybrid RAG for Indian SMEs with sovereign data?
PostgreSQL pgvector + local bge-m3 embeddings inside the client's VPC, nightly GraphRAG extraction on-prem, and SSE streaming via Projects. Data never leaves Gujarat, eval runs nightly, and hybrid routing ensures 0.07% hallucination while keeping 80% of queries sub-300ms. Contact for a RAG audit.
Bottom Line: RAG 2.0 to GraphRAG is not an upgrade path — it is a routing table. Run pgvector HNSW for semantic, GraphRAG for relations, and RRF hybrid with Pydantic citation enforcement to ship <0.1% hallucination that survives audits and closes deals.
Need hybrid retrieval for your knowledge base? Contact Deepak Bagada and ship grounded answers.