ASIM ANSARI // PROJECTS
PROJECT CASE STUDY // PROGRESSIVE RETRIEVAL CURRICULUM & VECTOR SEARCH

GEMINI-RAG

A progressive, branch-by-branch retrieval engineering curriculum dissecting the limitations of naive vector search. Evolves from raw ChromaDB similarity queries into Maximal Marginal Relevance (MMR) diversity, dynamic SelfQueryRetriever AST query decomposition, and mathematical embedding compression filters.

LangChain ChromaDB Google Gemini MMR Diversity SelfQueryRetriever Contextual Compression EmbeddingsFilter 6 Git Branches
SIGNAL // RETRIEVAL LAB & BENCHMARK HARNESS
Subdomain Research Lab: gemini-rag.asimansari.com functions as an architectural deep-dive into production retrieval techniques, isolating each mechanism on a dedicated Git branch to enable direct algorithmic diffing without framework bloat.
[01] CONTEXT & EVOLUTION

WHY NAIVE RAG BREAKS IN PRODUCTION

THE FRICTION // THE RETRIEVAL PITFALLS

Semantic Clustering & Context Pollution

Most introductory RAG tutorials rely exclusively on naive cosine similarity: embed query, fetch top-K nearest neighbors, and dump them into an LLM prompt. In real production datasets, this creates severe failure modes:

1. Semantic Redundancy: All top 5 chunks often contain virtually identical sentences repeated across document sections.
2. Lost in the Middle: Long uncompressed context windows degrade the LLM's attention heads.
3. Unfiltered Noise: Asking "What happened in 2023?" still pulls 2022 documents if the lexical similarity is slightly higher.

THE ARCHITECTURE // PROGRESSIVE LAB

Isolating Techniques on Dedicated Branches

Rather than building a monolith where architectural trade-offs are obscured, I structured Gemini-RAG as an educational, branch-based laboratory.

Each Git branch isolates a single retrieval primitive with working test scripts, State of the Union corpora, and comparative engineering notes—allowing developers to step through the evolution from raw vector search to autonomous query decomposition.

[02] THE 6-STAGE BRANCH MATRIX

STEP-BY-STEP RETRIEVAL PROGRESSION

STAGE 01 origin/similarity-search

Cosine Similarity Search

The foundational baseline. Generates 768-dim embeddings via Google Generative AI and queries ChromaDB via collection.query(). Demonstrates raw semantic retrieval and documents clustering traps.

STAGE 02 origin/mmr

Maximal Marginal Relevance

Solves semantic redundancy. Fetches a wide candidate pool (fetch_k=20) and iteratively penalizes chunks similar to already selected results, balancing query relevance with information diversity.

STAGE 03 origin/metadata-filtering

Hard Metadata Scoping

Applies categorical partition gates (e.g. where={"filename": "2023.txt"}) prior to vector calculations. Ensures queries targeting specific source documents never waste compute on irrelevant corpora.

STAGE 04 origin/self-query

LLM Self-Query Retriever

Employs an LLM query constructor with typed AttributeInfo schemas. Translates natural language questions into structured query ASTs that automatically extract both the search phrase and dynamic metadata filters.

STAGE 05 origin/compression

Contextual Compression

Deploys LLMChainExtractor over candidate passages. Discards sentences unrelated to the prompt before injecting context into the answering model, drastically reducing prompt tokens and context pollution.

STAGE 06 origin/compression-filter

Mathematical Embedding Filters

High-speed gatekeeper. Replaces the costly secondary LLM compression pass with an EmbeddingsFilter using mathematical similarity thresholds, pruning low-relevance chunks with zero extra LLM API latency.

[03] ARCHITECTURAL PHILOSOPHY

SEPARATION OF CONCERNS: CHROMADB VS. LANGCHAIN

DATABASE LAYER // THE ENGINE

ChromaDB: Pure Index Execution

ChromaDB is purposefully engineered as a fast, specialized vector storage engine. Its core task is indexing high-dimensional embeddings and computing vector distances (Cosine, L2, IP) at bare-metal speed.

Chroma intentionally omits complex application heuristics like MMR re-ranking or natural-language query translation from its core engine to preserve high-throughput indexing and minimal memory overhead.

ORCHESTRATION LAYER // THE CHASSIS

LangChain: Memory-Level Reranking

LangChain provides the orchestration logic that wraps around the vector engine. In MMR, LangChain requests an over-sampled candidate pool from Chroma (fetch_k=20) into application memory.

The MMR algorithm runs in Python space, iteratively computing pairwise cross-similarity penalties across the 20 candidates to select the final diverse top 5 chunks before passing them to Google Gemini.

[04] CODE HARNESS & IMPLEMENTATIONS

AUTONOMOUS QUERY DECOMPOSITION & COMPRESSION

python // self_query_pipeline.py (Branch: self-query) PYTHON 3.11
from langchain_chroma import Chroma
from langchain_google_genai import GoogleGenerativeAIEmbeddings, ChatGoogleGenerativeAI
from langchain.chains.query_constructor.base import AttributeInfo
from langchain.retrievers.self_query.base import SelfQueryRetriever

# 1. Define explicit metadata schema bounds for the LLM Query Constructor
metadata_field_info = [
    AttributeInfo(
        name="source",
        description="The filename or document origin, e.g. 'state_of_the_union_2022.txt'",
        type="string",
    ),
    AttributeInfo(
        name="year",
        description="The calendar year the speech or report was delivered (2022 or 2023)",
        type="integer",
    ),
]

document_content_description = "Official US Presidential State of the Union Addresses"
llm = ChatGoogleGenerativeAI(model="gemini-2.5-pro", temperature=0)

# 2. Build SelfQueryRetriever: Natural Language -> Structured Query AST
retriever = SelfQueryRetriever.from_llm(
    llm=llm,
    vectorstore=vectorstore,
    document_contents=document_content_description,
    metadata_field_info=metadata_field_info,
    verbose=True
)

# Asking: "What were the remarks on infrastructure in the 2022 address?"
# Emits: query='infrastructure', filter=Comparison(comparator=eq, target='year', value=2022)
results = retriever.invoke("What were the remarks on infrastructure in the 2022 address?")
python // embeddings_filter_pipeline.py (Branch: compression-filter) PYTHON 3.11
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import EmbeddingsFilter
from langchain_google_genai import GoogleGenerativeAIEmbeddings

embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001")

# Mathematical Gatekeeper: Discard retrieved chunks with cosine similarity < 0.76
embeddings_filter = EmbeddingsFilter(
    embeddings=embeddings, 
    similarity_threshold=0.76
)

compression_retriever = ContextualCompressionRetriever(
    base_compressor=embeddings_filter, 
    base_retriever=vectorstore.as_retriever(search_kwargs={"k": 10})
)

# Returns only high-signal passages without invoking expensive secondary LLM extraction
compressed_docs = compression_retriever.invoke("Inflation reduction strategies")
[05] STATUS & ACTIVE CHALLENGE

CURRENT STAGE & THE HARD PART

STAGE // OPERATIONAL BASELINE ALL 6 BRANCHES VALIDATED

Reproducible Benchmarking Suite

All 6 branches are fully functional and reproducible. Users can switch branches via git checkout [branch-name] to inspect the exact architectural delta between baseline similarity search, MMR diversity reranking, metadata filtering, self-query AST translation, and embeddings compression.

THE HARD PART // ACTIVE CHALLENGE LATENCY VS ACCURACY

Multi-Hop Query Latency Bottlenecks

While LLMChainExtractor dramatically cuts prompt context tokens, running a secondary LLM inference pass across 10 retrieved chunks adds 1.2s to 2.8s of round-trip latency. Current active research focuses on hybrid vector-BM25 routing and small quantized cross-encoders to eliminate secondary LLM calls.