02/AI / DISTRIBUTED SEARCH · 2026

Production RAG System

Multi-Source Hybrid Retrieval Fusion and Cross-Encoder Reranking

TYPE
Distributed Retrieval Engine
ROLE
AI & Distributed Systems Engineer
DURATION
4 Weeks
TEAM
Solo Project
STATUS
Production Architecture
CORE STACK
Python / FastAPI / Qdrant
01 / SECTION

System Overview

The engine accepts complex technical queries across dense developer documentation and source code repositories. Rather than relying purely on vector cosine similarity—which notoriously fails on exact function signatures and alphanumeric IDs—the pipeline fuses sparse inverted index matches with dense semantic representations before passing candidates to a cross-encoder reranker.

EXECUTIVE SUMMARY

A production-grade retrieval engine designed for technical codebases and developer documentation, combining sparse lexical search, dense semantic embeddings, and joint cross-encoder reranking for zero-hallucination recall.

02 / SECTION

The Core Problem

Naive vector-based RAG architectures consistently break down in production software environments. Dense embeddings excel at high-level semantic intent, but fail on the exact strings that matter most to engineers.

01
Exact Alphanumeric Identifier Blindness

Embedding models compress text into dense vectors where exact symbol names like `checkpointer.put_writes()` or HTTP error `ERR_CONNECTION_REFUSED` blur into generic semantic neighbors.

02
Naive Fixed-Window Chunking

Splitting text every 512 tokens indiscriminately severs method signatures from their implementations, stripping code blocks of their scoping context.

03
Embedding Model Metric Distortion

Bi-encoder architectures encode query and document separately, failing to capture subtle fine-grained cross-attention relationships between technical questions and edge-case caveats.

04
Hallucinated Synthesis Without Chunk Attribution

Passing large unranked context windows causes the generator to cherry-pick plausible-sounding sentences that contradict the true source documentation.

NAIVE VECTOR-ONLY RAG PIPELINE (V0)FAILURE MODE
USER QUERYBI-ENCODER EMBEDDINGVECTOR DB COSINE KNNTOP-K PASSAGES TO LLMPLAUSIBLE HALLUCINATION
CRITIQUE:Dense vectors map 'how to checkpoint' and 'checkpointer interface implementation' to similar regions, but fail to differentiate between different library version semantics or exact parameter flags.
03 / SECTION

System Architecture

The system uses a multi-stage fusion pipeline. Sparse keyword matching and dense vector search run concurrently, fused via Reciprocal Rank Fusion (RRF), and refined using a cross-encoder model before reaching the LLM synthesis layer.

INTERACTIVE SYSTEM TOPOLOGYCLICK / HOVER NODE

QUERY NORMALIZER

HyDE & Keyword Extraction
COMPONENT ID: query-norm
INPUT
Raw user question
OUTPUT
Normalized query string + extracted technical symbols
CORE RESPONSIBILITIES
  • Extracts exact code tokens, package versions, and error identifiers
  • Expands acronyms and generates hypothetical query variations
  • Routes queries to appropriate sparse and dense index shards
04 / SECTION

Execution Walkthrough

Tracing a concrete request from ingestion through evaluation to final synthesis.

TEST INQUIRY
How does checkpoint persistence work in LangGraph?
STEP 01 · DUAL RETRIEVAL DISPATCHRETRIEVE

The query normalizer extracts `LangGraph` and `checkpoint persistence`. BM25 scans lexical inverted indexes for exact method signatures, while Qdrant searches 768-dimensional semantic space.

STEP 02 · CANDIDATE EXTRACTIONHARVEST

BM25 returns `checkpoint API docs` (0.86) and `BaseCheckpointSaver` (0.79). Qdrant returns `thread state persistence` (0.91) and `checkpoint memory model` (0.84).

STEP 03 · CROSS-ENCODER RERANKRERANK

The cross-encoder reranks the merged pool. It promotes `MemorySaver vs PostgresSaver` to #1 (score 0.96) because it specifically answers how state persists across invocation threads.

STEP 04 · GROUNDED ATTRIBUTION SYNTHESISSYNTHESIZE

The generator synthesizes an explanation strictly citing passages [1] and [2]. Any claim not verifiable within the top-5 reranked chunks is omitted.

RRF Fusion & Chunk Data Structure
typescript
export interface RetrievalChunk {
  chunkId: string;
  sourceDoc: string;
  section: string;
  codeBlock?: string;
  content: string;
  denseScore: number;
  bm25Score: number;
  rrfScore: number;
  crossEncoderScore?: number;
}

export function computeRRF(denseRank: number, bm25Rank: number, k: number = 60): number {
  return (1 / (k + denseRank)) + (1 / (k + bm25Rank));
}
ENGINEERING RATIONALEReciprocal Rank Fusion converts disjoint raw scores into normalized rank reciprocal weights, ensuring sparse exact matches and dense semantic matches combine harmoniously.
05 / SECTION

Key Technical Decisions

Engineering choices, alternatives evaluated, and deliberate tradeoffs made during system design.

DECISION 01

Why Hybrid Sparse + Dense Fusion?

DECISION

Combined BM25 lexical inverted index with Qdrant dense vector search.

ALTERNATIVE CONSIDERED

Using dense vectors exclusively with larger embedding models (e.g. OpenAI text-embedding-3-large).

WHY THIS WAS CHOSEN

Even state-of-the-art embedding models experience severe recall drops when queries contain specific symbols, CLI parameters, or version numbers. BM25 guarantees 100% recall on exact symbol tokens.

ENGINEERING TRADEOFF

Maintaining two separate index stores increases data ingestion pipeline complexity and disk storage.

DECISION 02

Why Cross-Encoder Over LLM Reranking?

DECISION

Deployed a local HuggingFace cross-encoder model (bge-reranker-base) for joint attention scoring.

ALTERNATIVE CONSIDERED

Prompting an LLM (e.g. GPT-4o-mini) to rerank passages via JSON output.

WHY THIS WAS CHOSEN

The cross-encoder evaluates the top-30 candidates in ~85ms on GPU, compared to 1,200ms+ for an LLM API roundtrip. It also eliminates non-deterministic parsing failures.

ENGINEERING TRADEOFF

Requires dedicated server memory for model weights (~1.2 GB VRAM).

DECISION 03

AST-Aware Parent-Child Document Chunking

DECISION

Split code documentation by markdown AST headers and function definitions rather than fixed character counts.

ALTERNATIVE CONSIDERED

Fixed 512-character sliding window with 50-character overlap.

WHY THIS WAS CHOSEN

Arbitrary character slicing regularly decapitated function signatures and severed parameter docstrings from their parent classes. AST-aware chunking maintains semantic cohesion.

ENGINEERING TRADEOFF

Variable chunk lengths require dynamic padding during batch vector embedding generation.

06 / SECTION

What Didn't Work

Development is an iterative discipline. These are the naive architectural patterns that failed under real-world scrutiny.

V1 FAILURE

Fixed 512-Token Windowing

WHAT HAPPENED

Code snippets were routinely sliced down the middle of function bodies. The retrieval engine frequently surfaced isolated lines of code with zero explanatory docstring context.

ROOT CAUSE

Character length is completely agnostic to code syntax and abstract syntax trees.

ARCHITECTURAL CHANGE

Built an AST-based parser that chunks by markdown headers, class definitions, and complete function signatures, linking children to parent overview chunks.

V2 FAILURE

Vector Search on SDK Version Numbers

WHAT HAPPENED

When developers searched for migration notes between v0.2 and v0.3, dense vector search returned generic v1.0 tutorials because cosine similarity favored overall topic similarity.

ROOT CAUSE

Vector embeddings treat version tags as tiny perturbations in semantic space.

ARCHITECTURAL CHANGE

Added regex metadata extraction during ingestion to tag chunks with explicit version flags, querying them as hard metadata filters alongside BM25.

07 / SECTION

Empirical Evaluation

Quantitative validation metrics measured against ground-truth benchmarks rather than subjective impressions.

EVALUATION DATASET

Evaluated across 50 technical queries containing exact API function calls, CLI parameters, and conceptual architecture questions against official developer documentation.

Hit Rate @ 5 (Hybrid + Rerank)
Top-5 candidates contained the exact verifiable ground-truth passage
88.4%
Hit Rate @ 5 (Dense Only Baseline)
Missed exact identifier matches in 14 out of 50 technical queries
72.1%
Mean Reciprocal Rank (MRR)
Ground-truth passage appeared in position #1 or #2 in 84% of queries
0.84
Answer Faithfulness Score
Synthesis answers strictly attributable to provided chunk citations
96.2%
MEDIAN LATENCY
420ms
P95 LATENCY
890ms
AVG TOKEN COST
$0.004 / query
08 / SECTION

System Tradeoffs

Every architectural choice gives up one property to prioritize another. Here is what this system sacrifices.

Cross-Encoder Reranking

+ SYSTEM ADVANTAGES
  • +Boosted Hit Rate @ 5 from 81% to 88.4%
  • +Filters out misleading chunks that scored high solely due to repetitive keyword stuffing
− CONSTRAINTS & COSTS
  • Adds ~85ms of neural inference latency per retrieval request
  • Increases infrastructure memory requirements

Dual-Index Synchronization

+ SYSTEM ADVANTAGES
  • +Flawless recall across both high-level semantic questions and exact code symbols
− CONSTRAINTS & COSTS
  • Requires dual writes to Qdrant and inverted index on document updates
  • Roughly 1.6x storage footprint compared to a single index
09 / SECTION

Future Iterations & Improvements

Concrete technical roadmap items if engineering development on this codebase continued.

  • 01Dynamic retrieval routing: automatically skip dense vector search when queries consist purely of alphanumeric hashes or exact CLI flags.
  • 02Contextual chunk compression: trim verbose boilerplate lines from retrieved passages before LLM injection to save context tokens.
  • 03Streaming citations: render citation footnotes in real time as the synthesis LLM streams tokens to the client.
  • 04Offline evaluation CI pipeline: automatically score PRs against a golden benchmark test suite before deploying new chunking strategies.
CORE TAKEAWAYS
Never rely solely on dense embeddings for technical software retrieval.
Reciprocal Rank Fusion is dramatically more robust than attempting to manually calibrate and sum disparate score distributions.
AST-aware chunking matters more for code RAG than switching between embedding models.
10 / SECTION

Comprehensive Tech Stack

Tools, frameworks, protocols, and libraries actively used across the system.

Vector & Search Indexes
  • Qdrant Vector DB
  • BM25 Okapi
  • HNSW Indexing
  • SQLite Metadata Store
Models & Embedding
  • text-embedding-3-small
  • bge-reranker-base (HuggingFace)
  • LlamaIndex Framework
Backend & API
  • Python 3.12
  • FastAPI
  • Redis Cache
  • Pydantic V2
Infrastructure
  • Docker
  • Gunicorn / Uvicorn Workers
  • GitHub Actions