<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mithilesh Kumar</title>
    <description>The latest articles on DEV Community by Mithilesh Kumar (@mithxcode).</description>
    <link>https://dev.to/mithxcode</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4066830%2Fb9998848-6ae0-4829-8a40-d780510d7725.jpg</url>
      <title>DEV Community: Mithilesh Kumar</title>
      <link>https://dev.to/mithxcode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mithxcode"/>
    <language>en</language>
    <item>
      <title>The RAG Pipeline I Wouldn't Build the Same Way Twice</title>
      <dc:creator>Mithilesh Kumar</dc:creator>
      <pubDate>Fri, 18 Sep 2026 16:01:00 +0000</pubDate>
      <link>https://dev.to/mithxcode/the-rag-pipeline-i-wouldnt-build-the-same-way-twice-3ga2</link>
      <guid>https://dev.to/mithxcode/the-rag-pipeline-i-wouldnt-build-the-same-way-twice-3ga2</guid>
      <description>&lt;p&gt;&lt;strong&gt;Subtitle:&lt;/strong&gt; A practical look at failure modes, query routing, hybrid retrieval, and knowing when agentic workflows are actually worth the complexity.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Illusion of a Perfect Prototype
&lt;/h2&gt;

&lt;p&gt;Every developer's first naive RAG system feels like magic. You chunk a few PDFs, pass them through an embedding model, save the vectors to a database, and hook up a top-k similarity search to an LLM. It takes 50 lines of Python, runs in a couple of seconds, and answers basic questions surprisingly well.&lt;/p&gt;

&lt;p&gt;Then real users show up.&lt;/p&gt;

&lt;p&gt;They ask questions with precise technical identifiers (&lt;code&gt;error code 0x80070005&lt;/code&gt;), temporal constraints (&lt;em&gt;"What changed in our deployment policy last month?"&lt;/em&gt;), or broad multi-part requirements (&lt;em&gt;"Compare our feature set with our competitor's pricing tier"&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Suddenly, top-k vector similarity breaks down completely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exact strings get ignored because the semantic embedding space flattens precise tokens into vague concepts.&lt;/li&gt;
&lt;li&gt;Short, high-level queries pull irrelevant chunks that happened to share superficial tone rather than domain substance.&lt;/li&gt;
&lt;li&gt;Multi-part queries return fragments of information while missing the broader context needed to synthesize a coherent response.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article documents how my architectural thinking moved away from "vector search by default" toward a system built around query intent, multi-strategy retrieval, and selective complexity.&lt;/p&gt;




&lt;h2&gt;
  
  
  The First Failure Modes: Why Naive Retrieval Fails
&lt;/h2&gt;

&lt;p&gt;A simple RAG architecture assumes a linear pipeline:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;User Query -&amp;gt; Vector Search (Top-k) -&amp;gt; Context Assembly -&amp;gt; LLM Generation&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This model assumes that semantic similarity is equivalent to relevance. In practice, they are two very different metrics.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Token Precision Loss
&lt;/h3&gt;

&lt;p&gt;Dense vector embeddings condense the meaning of a text segment into a fixed-dimensional space (e.g., 768 or 1536 dimensions). This works well for conceptual queries (&lt;em&gt;"How do I reset my credentials?"&lt;/em&gt;), but fails for token-exact queries (&lt;em&gt;"What is the threshold for MAX_RETRY_ATTEMPTS in config.v2?"&lt;/em&gt;). &lt;/p&gt;

&lt;p&gt;Because the vector space prioritizes overall semantic meaning, the specific token string &lt;code&gt;MAX_RETRY_ATTEMPTS&lt;/code&gt; loses its distinctiveness.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Chunk Size Dilemma
&lt;/h3&gt;

&lt;p&gt;If your chunks are too small (e.g., 200 tokens), you preserve fine-grained facts, but you lose the broader context needed to make sense of them. If your chunks are too large (e.g., 2000 tokens), you preserve context, but you dilute the relevance signal and waste the LLM's context window on noise.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The Top-k Fallacy
&lt;/h3&gt;

&lt;p&gt;Static top-k retrieval assumes that the ideal context size is constant. For a simple question, k=2 might be plenty. For a complex synthesis query, k=10 might still be insufficient. Retrieving a fixed number of chunks forces a trade-off between missing critical information and swamping the generation prompt with distraction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Query Routing: Treating Queries Differently
&lt;/h2&gt;

&lt;p&gt;The first major architectural shift was realizing that every incoming query does not deserve the same retrieval path. Treating all user input identically is an architectural flaw.&lt;/p&gt;

&lt;p&gt;Instead of passing every string directly to an embedding model, the system first passes the query through a fast classification layer—a lightweight query router.&lt;/p&gt;

&lt;h3&gt;
  
  
  Classification Categories:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Factual / Keyword-Exact:&lt;/strong&gt; Route to a lexical index (BM25 or full-text search engine).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conceptual / Intent-Based:&lt;/strong&gt; Route to a vector index via dense embedding models.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex / Multi-Attribute:&lt;/strong&gt; Route to a hybrid path that executes both lexical and semantic searches in parallel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conversational / System Instructions:&lt;/strong&gt; Bypass retrieval completely to save latency and vector database compute.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0uzwlfi4tcq30tkfjooa.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0uzwlfi4tcq30tkfjooa.jpeg" alt="Query Routing Architecture" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hybrid Retrieval and Exact Matching
&lt;/h2&gt;

&lt;p&gt;To balance conceptual matching with token precision, hybrid retrieval combines sparse keyword search (BM25) with dense vector search.&lt;/p&gt;

&lt;p&gt;Sparse models track exact word frequencies and term rarity, while dense models capture broader intent. Combining them ensures that exact product IDs or error codes aren't missed, while conceptual queries still return contextually relevant documents.&lt;/p&gt;

&lt;p&gt;Once both retrievers return candidate lists, their score distributions must be normalized. A simple, effective technique for combining these distinct score metrics is &lt;strong&gt;Reciprocal Rank Fusion (RRF)&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;RRF_Score(d) = Sum of (1 / (60 + Rank(d)))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Where 60 is a constant that prevents high-ranking outliers from disproportionately dominating the output.&lt;/p&gt;




&lt;h2&gt;
  
  
  Re-Ranking and Context Selection
&lt;/h2&gt;

&lt;p&gt;Retrieval models prioritize recall—getting all potentially relevant chunks into a candidate list. Generative LLMs, on the other hand, require precision—receiving only the most useful context to formulate an answer.&lt;/p&gt;

&lt;p&gt;Passing 30 hybrid-retrieved candidate chunks directly into an LLM causes the &lt;strong&gt;"Lost in the Middle"&lt;/strong&gt; phenomenon: transformer models pay disproportionate attention to information placed at the very beginning or the very end of their prompt context, often ignoring facts buried in the middle.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Role of Cross-Encoders
&lt;/h3&gt;

&lt;p&gt;Bi-encoder models (standard vector embeddings) process the query and document chunks independently to create static vector representations. This is fast, but it prevents the query terms from interacting directly with the document terms.&lt;/p&gt;

&lt;p&gt;Cross-encoder re-rankers process the query and document chunk &lt;strong&gt;together&lt;/strong&gt; through transformer layers. This allows full cross-attention between every query token and every document token. While too computationally expensive to run against millions of database documents, running a cross-encoder against the top 20 or 30 retrieved candidates adds minimal latency while significantly sharpening relevance.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Engineering reliable RAG systems requires testing retrieval strategies against real-world query failure modes rather than relying solely on synthetic benchmarks.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Temptation to Add Agents Everywhere
&lt;/h2&gt;

&lt;p&gt;When a static retrieval pipeline fails on multi-step reasoning, it's tempting to immediately rewrite the system as a fully autonomous agentic loop using frameworks like LangGraph or AutoGen.&lt;/p&gt;

&lt;p&gt;An agentic loop gives the LLM tool access (e.g., query generation, external search, reflection) and allows it to run in a loop until it decides it has enough context to answer the user.&lt;/p&gt;

&lt;p&gt;However, adding agentic loops introduces significant engineering trade-offs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Non-Deterministic Latency:&lt;/strong&gt; A standard hybrid RAG pipeline might execute in 400ms to 800ms. An agentic loop that decides to re-query, critique its own output, and loop three times can easily spike to 5–10 seconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infinite Loops and Drift:&lt;/strong&gt; Without tight control flow, agents can enter tool-call loops or wander away from the original query intent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost Escalation:&lt;/strong&gt; Every reflection loop and intermediate decision step multiplies token consumption.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  When is an Agentic Workflow Actually Justified?
&lt;/h3&gt;

&lt;p&gt;An agentic approach is worth the complexity when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The query requires multi-step dependency resolution (e.g., &lt;em&gt;"Find the deployment logs for the service that failed after yesterday's DB migration"&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;The retrieval strategy depends on the outcome of a previous retrieval step.&lt;/li&gt;
&lt;li&gt;Self-correction is strictly necessary to validate structured output against a pre-defined schema.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a query can be answered by routing it to a structured hybrid search path, adding an agentic framework is unnecessary overhead.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Practical Composite Architecture
&lt;/h2&gt;

&lt;p&gt;A production-grade pipeline layout that balances latency, deterministic behavior, and retrieval precision follows this execution flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;User Query&lt;/strong&gt; enters the system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query Router&lt;/strong&gt; classifies the intent (Direct Pass, Hybrid Pipeline, or Agentic Loop).&lt;/li&gt;
&lt;li&gt;If &lt;strong&gt;Hybrid Pipeline&lt;/strong&gt;, execute &lt;strong&gt;Dense Vector Search&lt;/strong&gt; and &lt;strong&gt;Sparse Lexical Search (BM25)&lt;/strong&gt; in parallel.&lt;/li&gt;
&lt;li&gt;Merge results using &lt;strong&gt;Reciprocal Rank Fusion (RRF)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Pass top candidate chunks through a &lt;strong&gt;Cross-Encoder Re-Ranker&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Send filtered, high-precision context to the &lt;strong&gt;LLM for Final Generation&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Architectural Lessons Learned
&lt;/h2&gt;

&lt;p&gt;If I were rebuilding a RAG architecture from scratch today, these core engineering principles would guide my design decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Optimize your data ingestion before tweaking models.&lt;/strong&gt; Bad chunking, missing metadata, and poor document cleaning cannot be fixed by a top-tier re-ranker or an expensive LLM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat vector databases as one component of a broader retrieval system.&lt;/strong&gt; Vector search is a powerful feature, but it is not a complete search infrastructure on its own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure retrieval precision independently from generation quality.&lt;/strong&gt; Evaluate your retrieval candidate lists using metrics like MRR (Mean Reciprocal Rank) and NDCG before rating the final generated text output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep the default execution path deterministic.&lt;/strong&gt; Use routing heuristics to send 80% of standard queries through a fast, deterministic hybrid retrieval path. Reserve non-deterministic agentic loops for complex edge cases.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Previous Articles in This Series
&lt;/h2&gt;

&lt;p&gt;If you found this deep-dive useful, check out my earlier technical guides on building production AI systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/"&gt;Building Scalable Multi-Agent Workflows &amp;amp; RAG Pipelines with LangGraph and FastAPI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/"&gt;Why Basic RAG Fails in Production and How Adaptive Query Routing Fixes It&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/"&gt;Beyond Basic RAG: Building Production-Grade Agentic Workflows with Hybrid Search and Custom Re-Ranking&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;







&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Mithilesh Kumar&lt;/strong&gt; | AI Engineer &amp;amp; Full-Stack Developer&lt;/p&gt;

&lt;p&gt;Mithilesh Kumar is an AI Engineer and Full-Stack Developer who specializes in building autonomous applications, Multi-Agent Systems, Agentic AI workflows, and Retrieval-Augmented Generation (RAG) pipelines. He is currently pursuing his Bachelor of Technology (B.Tech) in Computer Science &amp;amp; Engineering at Chandigarh Engineering College, Landran. He designs scalable architectures by blending AI-driven automation with modern web technologies, focusing on production reliability, retrieval precision, and practical engineering trade-offs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Portfolio:&lt;/strong&gt; &lt;a href="https://mithilesh-kumar-ai-engineer.netlify.app/" rel="noopener noreferrer"&gt;mithilesh-kumar-ai-engineer.netlify.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/mithxcode" rel="noopener noreferrer"&gt;github.com/mithxcode&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LinkedIn:&lt;/strong&gt; &lt;a href="https://linkedin.com/in/mithileshkumar-ai" rel="noopener noreferrer"&gt;linkedin.com/in/mithileshkumar-ai&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>python</category>
      <category>learning</category>
    </item>
    <item>
      <title>Beyond Basic RAG: Building Production-Grade Agentic Workflows with Hybrid Search and Custom Re-Ranking</title>
      <dc:creator>Mithilesh Kumar</dc:creator>
      <pubDate>Tue, 11 Aug 2026 14:30:22 +0000</pubDate>
      <link>https://dev.to/mithxcode/beyond-basic-rag-building-production-grade-agentic-workflows-with-hybrid-search-and-custom-5c5e</link>
      <guid>https://dev.to/mithxcode/beyond-basic-rag-building-production-grade-agentic-workflows-with-hybrid-search-and-custom-5c5e</guid>
      <description>&lt;p&gt;By &lt;strong&gt;Mithilesh Kumar&lt;/strong&gt; | AI Engineer &amp;amp; Systems Architect&lt;/p&gt;

&lt;p&gt;Standard Retrieval-Augmented Generation (RAG) pipelines often hit a wall in production environments. While simple vector similarity search works well for basic Q&amp;amp;A demos, real-world enterprise applications demand multi-step reasoning, precise contextual retrieval, and dynamic decision-making.&lt;/p&gt;

&lt;p&gt;When building scalable AI systems, relying solely on dense vector embeddings leads to missing exact-keyword matches, failing on complex multi-part queries, and introducing unnecessary LLM hallucinations.&lt;/p&gt;

&lt;p&gt;In this guide, I will walk you through building a &lt;strong&gt;Production-Grade Agentic RAG Architecture&lt;/strong&gt; using &lt;strong&gt;Hybrid Search (Dense + Sparse)&lt;/strong&gt;, &lt;strong&gt;Cross-Encoder Re-Ranking&lt;/strong&gt;, and &lt;strong&gt;Stateful Agent Workflows&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Bottlenecks of Naive RAG in Production
&lt;/h2&gt;

&lt;p&gt;In a standard Naive RAG setup, the pipeline follows a rigid pattern: &lt;code&gt;User Query -&amp;gt; Embedding -&amp;gt; Vector DB Lookup -&amp;gt; LLM Context Window&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;This approach fails in production due to three critical bottlenecks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Semantic Shift &amp;amp; Loss of Keywords:&lt;/strong&gt; Vector embeddings capture semantic meaning but struggle with specific product IDs, technical code snippets, or proper nouns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Top-K Irrelevance:&lt;/strong&gt; Retrieving top-k documents purely based on cosine similarity often pulls in contextually adjacent but factually useless chunks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single-Shot Failure:&lt;/strong&gt; Real-world queries require multi-step decomposition. A single retrieval step cannot handle queries that require comparing two distinct documents or routing to different data sources.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  2. The Architectural Blueprint
&lt;/h2&gt;

&lt;p&gt;To solve these challenges, we replace the linear pipeline with an &lt;strong&gt;Agentic Workflow&lt;/strong&gt; supported by a dual-retrieval and re-ranking engine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frsj2ci8pv9d82zdvegpd.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frsj2ci8pv9d82zdvegpd.jpeg" alt="Mithilesh Kumar designing agentic workflows on a glass whiteboard" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Architectural Components:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Query Router (Agentic Layer):&lt;/strong&gt; Dynamically analyzes incoming intent and decides whether to route the request to a vector store, a relational database, or a web search API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid Search Engine:&lt;/strong&gt; Combines &lt;strong&gt;BM25 (Sparse Keyword Search)&lt;/strong&gt; and &lt;strong&gt;Dense Vector Search (e.g., OpenAI / BGE Embeddings)&lt;/strong&gt; using Reciprocal Rank Fusion (RRF).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Encoder Re-Ranker:&lt;/strong&gt; A specialized model (like &lt;code&gt;bge-reranker-large&lt;/code&gt;) that evaluates the exact query-document pairs to assign a true relevance score before sending context to the LLM.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Implementation: Hybrid Search &amp;amp; Re-Ranking Code
&lt;/h2&gt;

&lt;p&gt;Here is a modular Python implementation demonstrating how to combine hybrid retrieval with a re-ranking step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sentence_transformers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CrossEncoder&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductionRAGPipeline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reranker_model_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;BAAI/bge-reranker-large&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Initialize Cross-Encoder for precision scoring
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reranker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CrossEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reranker_model_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;reciprocal_rank_fusion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dense_results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;sparse_results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Combines Dense and Sparse search results using Reciprocal Rank Fusion (RRF).&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;rrf_scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dense_results&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;doc_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;doc_id&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rrf_scores&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;rrf_scores&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;doc_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;doc&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;score&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;rrf_scores&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;doc_id&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;score&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sparse_results&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;doc_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;doc_id&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rrf_scores&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;rrf_scores&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;doc_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;doc&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;score&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;rrf_scores&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;doc_id&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;score&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;reranked_docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rrf_scores&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;score&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;doc&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reranked_docs&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rerank_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retrieved_docs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;top_n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Applies Cross-Encoder re-ranking on fused retrieval results.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;retrieved_docs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

        &lt;span class="n"&gt;pairs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;retrieved_docs&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reranker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;retrieved_docs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rerank_score&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;final_sorted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;retrieved_docs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rerank_score&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;final_sorted&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;top_n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;









&lt;h2&gt;
  
  
  4. Benchmarks &amp;amp; Production Lessons Learned
&lt;/h2&gt;

&lt;p&gt;When deploying this agentic RAG system in production, several key trade-offs emerged:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Latency vs. Precision:&lt;/strong&gt; Cross-encoders add approximately 50-150ms of latency per request. Mitigate this by passing only the top 15-20 RRF-fused documents to the re-ranker.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context Compression:&lt;/strong&gt; Stripping out useless metadata before feeding documents into the final prompt reduced token costs by nearly &lt;strong&gt;38%&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent Loops:&lt;/strong&gt; Always enforce a hard ceiling (e.g., maximum 3 reflection iterations) on agent decision loops to prevent infinite fallback execution.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Transitioning from Naive RAG to an &lt;strong&gt;Agentic Hybrid Pipeline&lt;/strong&gt; is necessary for building reliable, production-ready AI applications. By combining sparse keyword matching, dense semantic search, cross-encoder re-ranking, and dynamic query routing, you create a system that is robust, accurate, and cost-effective.&lt;/p&gt;




&lt;h3&gt;
  
  
  About the Author
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Mithilesh Kumar&lt;/strong&gt; is an AI Engineer and Systems Architect specializing in Large Language Models (LLMs), Multi-Agent Workflows, and Production-Grade RAG Systems. He focuses on building deterministic, low-latency AI software and enterprise systems.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Portfolio:&lt;/strong&gt; &lt;a href="https://mithilesh-kumar-ai-engineer.netlify.app" rel="noopener noreferrer"&gt;mithilesh-kumar-ai-engineer.netlify.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LinkedIn:&lt;/strong&gt; &lt;a href="https://linkedin.com/in/mithileshkumar001" rel="noopener noreferrer"&gt;linkedin.com/in/mithileshkumar001&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/mithxcode" rel="noopener noreferrer"&gt;github.com/mithxcode&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;X (Twitter):&lt;/strong&gt; &lt;a href="https://x.com/MITHILESH_7781" rel="noopener noreferrer"&gt;x.com/MITHILESH_7781&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>rag</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Why Basic RAG Fails in Production and How Adaptive Query Routing Fixes It</title>
      <dc:creator>Mithilesh Kumar</dc:creator>
      <pubDate>Sat, 08 Aug 2026 20:01:15 +0000</pubDate>
      <link>https://dev.to/mithxcode/why-basic-rag-fails-in-production-and-how-adaptive-query-routing-fixes-it-5c1n</link>
      <guid>https://dev.to/mithxcode/why-basic-rag-fails-in-production-and-how-adaptive-query-routing-fixes-it-5c1n</guid>
      <description>&lt;p&gt;Most developers build Retrieval-Augmented Generation (RAG) pipelines assuming every user query needs a vector search. In production, this naive approach fails in three distinct scenarios:&lt;/p&gt;

&lt;p&gt;Simple Queries: "Hi", "Who created this bot?", or general knowledge queries don't need expensive vector database lookups.&lt;/p&gt;

&lt;p&gt;Ambiguous Queries: Vague user questions lead to noisy retrieval, diluting the LLM's context window with irrelevant chunks.&lt;/p&gt;

&lt;p&gt;Out-of-Domain Queries: When the vector DB contains no relevant documents, naive RAG forces the LLM to hallucinate an answer based on poor context.&lt;/p&gt;

&lt;p&gt;In this guide, I’ll break down how to implement Adaptive RAG with Dynamic Query Routing using LangChain, Vector Stores (Pinecone/Chroma), and FastAPI.&lt;/p&gt;

&lt;p&gt;What is Adaptive RAG?&lt;br&gt;
Instead of routing every request directly to vector retrieval, Adaptive RAG acts as an intent-aware orchestrator:&lt;/p&gt;

&lt;p&gt;graph TD&lt;br&gt;
    A[User Query Received] --&amp;gt; B[Intent Classifier Node]&lt;br&gt;
    B --&amp;gt;|General Query| C[Direct LLM Response]&lt;br&gt;
    B --&amp;gt;|Internal Docs| D[Vector DB Retrieval]&lt;br&gt;
    B --&amp;gt;|External/News| E[Web Search Fallback]&lt;br&gt;
    D --&amp;gt; F[Hallucination Grader Node]&lt;/p&gt;

&lt;p&gt;Classify Intent: Determine whether the query needs internal vector docs, web search, or a direct response.&lt;/p&gt;

&lt;p&gt;Retrieve &amp;amp; Grade: Fetch documents, then evaluate their relevance score before generating the answer.&lt;/p&gt;

&lt;p&gt;Fallback Circuit: If document relevance is low, trigger fallback web search (e.g., Tavily API) or ask the user for clarification.&lt;/p&gt;

&lt;p&gt;Step 1: Building a Structured Router with Pydantic&lt;br&gt;
We enforce a strict JSON output schema using Pydantic to ensure our routing decision is 100% deterministic.&lt;/p&gt;

&lt;p&gt;from pydantic import BaseModel, Field&lt;br&gt;
from typing import Literal&lt;/p&gt;

&lt;p&gt;class RouteQuery(BaseModel):&lt;br&gt;
    """Route a user query to the most appropriate data source."""&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;datasource: Literal["vectorstore", "web_search", "direct_llm"] = Field(
    ...,
    description="Given a user question, choose whether to route it to vectorstore, web search, or direct LLM."
)
reasoning: str = Field(
    ..., description="Brief explanation for the routing decision."
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Step 2: Query Classification Node&lt;br&gt;
Using function calling / structured output capabilities of LLMs (like Google Gemini or OpenAI):&lt;/p&gt;

&lt;p&gt;from langchain_core.prompts import ChatPromptTemplate&lt;br&gt;
from langchain_google_genai import ChatGoogleGenerativeAI&lt;/p&gt;

&lt;p&gt;llm = ChatGoogleGenerativeAI(model="gemini-1.5-flash", temperature=0)&lt;br&gt;
structured_router = llm.with_structured_output(RouteQuery)&lt;/p&gt;

&lt;p&gt;system_prompt = """You are an expert at routing user queries.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use 'vectorstore' for questions related to internal technical documents, architecture, or codebase.&lt;/li&gt;
&lt;li&gt;Use 'web_search' for recent events, live news, or external context.&lt;/li&gt;
&lt;li&gt;Use 'direct_llm' for greetings, general conversational queries, or basic coding syntax.
"""&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;route_prompt = ChatPromptTemplate.from_messages([&lt;br&gt;
    ("system", system_prompt),&lt;br&gt;
    ("human", "{question}")&lt;br&gt;
])&lt;/p&gt;

&lt;p&gt;question_router = route_prompt | structured_router&lt;/p&gt;

&lt;h1&gt;
  
  
  Test the router
&lt;/h1&gt;

&lt;p&gt;result = question_router.invoke({"question": "What is the API endpoint for CGC-NEXUS event registration?"})&lt;br&gt;
print(f"Destination: {result.datasource} | Reason: {result.reasoning}")&lt;/p&gt;

&lt;h1&gt;
  
  
  Output: Destination: vectorstore | Reason: Query asks about specific internal project endpoints.
&lt;/h1&gt;

&lt;p&gt;Step 3: Integrating into Async FastAPI Endpoint&lt;br&gt;
Here is how to expose the adaptive pipeline via a FastAPI service:&lt;/p&gt;

&lt;p&gt;from fastapi import FastAPI, HTTPException&lt;br&gt;
from pydantic import BaseModel&lt;/p&gt;

&lt;p&gt;app = FastAPI(title="Adaptive RAG Engine")&lt;/p&gt;

&lt;p&gt;class QueryRequest(BaseModel):&lt;br&gt;
    question: str&lt;/p&gt;

&lt;p&gt;@app.post("/api/v1/query")&lt;br&gt;
async def process_query(request: QueryRequest):&lt;br&gt;
    try:&lt;br&gt;
        # Step 1: Route Query&lt;br&gt;
        decision = await question_router.ainvoke({"question": request.question})&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    # Step 2: Execute based on intent
    if decision.datasource == "direct_llm":
        response = await llm.ainvoke(request.question)
        return {"source": "direct_llm", "answer": response.content}

    elif decision.datasource == "vectorstore":
        # Perform vector store search &amp;amp; hallucination check
        return {"source": "vectorstore", "answer": "Retrieved from vector database."}

    else:
        # Fallback to Web Search
        return {"source": "web_search", "answer": "Retrieved from web search fallback."}

except Exception as e:
    raise HTTPException(status_code=500, detail=str(e))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Key Production Insights&lt;br&gt;
Cost Optimization: Filtering out trivial questions before vector search reduces API calls and vector database read costs by up to 40%.&lt;/p&gt;

&lt;p&gt;Zero Hallucination Loop: By running a fast grader node on retrieved chunks, you ensure irrelevant text never enters the final LLM prompt context.&lt;/p&gt;

&lt;p&gt;Latency Reduction: Direct LLM calls bypass embedding generation and vector lookup entirely, responding in under 300ms.&lt;/p&gt;

&lt;p&gt;Connect &amp;amp; Explore Code&lt;br&gt;
Live Portfolio: &lt;a href="https://mithilesh-kumar-ai-engineer.netlify.app/" rel="noopener noreferrer"&gt;https://mithilesh-kumar-ai-engineer.netlify.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub Repository: &lt;a href="https://github.com/mithxcode" rel="noopener noreferrer"&gt;https://github.com/mithxcode&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/mithileshkumar001" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/mithileshkumar001&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;X (Twitter): &lt;a href="https://x.com/MITHILESH_7781" rel="noopener noreferrer"&gt;https://x.com/MITHILESH_7781&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How are you handling ambiguous queries in your RAG pipelines? Drop a comment below!&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>langchain</category>
      <category>fastapi</category>
    </item>
    <item>
      <title>Building Scalable Multi-Agent Workflows &amp; RAG Pipelines with LangGraph and FastAPI</title>
      <dc:creator>Mithilesh Kumar</dc:creator>
      <pubDate>Fri, 07 Aug 2026 05:14:38 +0000</pubDate>
      <link>https://dev.to/mithxcode/building-scalable-multi-agent-workflows-rag-pipelines-with-langgraph-and-fastapi-2lm0</link>
      <guid>https://dev.to/mithxcode/building-scalable-multi-agent-workflows-rag-pipelines-with-langgraph-and-fastapi-2lm0</guid>
      <description>&lt;p&gt;Building fully autonomous AI systems requires moving beyond simple linear prompts to robust, stateful agentic workflows. In this article, I share my core architecture for engineering Multi-Agent Systems and Retrieval-Augmented Generation (RAG) pipelines using &lt;strong&gt;LangGraph&lt;/strong&gt;, &lt;strong&gt;FastAPI&lt;/strong&gt;, and &lt;strong&gt;Python&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Agentic Workflows and LangGraph?
&lt;/h2&gt;

&lt;p&gt;Traditional LLM applications often struggle with complex, multi-step execution paths. By leveraging &lt;strong&gt;LangGraph&lt;/strong&gt;, we can model agent interactions as state machines (graphs), allowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cyclic execution loops&lt;/strong&gt; for iterative refinement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State management&lt;/strong&gt; across multiple tool calls and reasoning steps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human-in-the-loop&lt;/strong&gt; integration for safety and oversight.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Core Architecture Stack
&lt;/h2&gt;

&lt;p&gt;A modern agentic AI pipeline relies on a clean, scalable setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Orchestration Layer:&lt;/strong&gt; LangGraph / LangChain for handling agent routines and condition-based routing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend API Service:&lt;/strong&gt; FastAPI for ultra-fast async request handling and stream processing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retrieval Layer (RAG):&lt;/strong&gt; Vector databases paired with hybrid search algorithms for low-latency context retrieval.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Foundation Models:&lt;/strong&gt; OpenAI &amp;amp; Google Gemini APIs.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Key Takeaways for AI Engineers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic Routing:&lt;/strong&gt; Always keep edge transitions explicit to prevent agent loops.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured Outputs:&lt;/strong&gt; Enforce Pydantic schemas on LLM outputs for reliable API responses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability:&lt;/strong&gt; Track token usage and execution steps using tools like LangSmith.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  About the Author
&lt;/h3&gt;

&lt;p&gt;Hi! I am &lt;strong&gt;Mithilesh Kumar&lt;/strong&gt;, an AI Engineer specializing in Multi-Agent Systems, Agentic Workflows, and Modern Web Technologies. &lt;/p&gt;

&lt;p&gt;🌐 &lt;strong&gt;Explore my portfolio and live projects:&lt;/strong&gt; &lt;a href="https://mithilesh-kumar-ai-engineer.netlify.app/" rel="noopener noreferrer"&gt;https://mithilesh-kumar-ai-engineer.netlify.app/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>python</category>
      <category>langchain</category>
    </item>
  </channel>
</rss>
