{ "cells": [ { "cell_type": "markdown", "id": "0b4221ae", "metadata": { "papermill": { "duration": 0.0, "end_time": "2026-05-28T02:50:57.355778+00:00", "exception": false, "start_time": "2026-05-28T02:50:57.355778+00:00", "status": "completed" }, "tags": [] }, "source": [ "# 26 · Adaptive RAG — router picks no/single/multi-step\n", "\n", "> **TL;DR.** One LLM call classifies each query into a complexity bucket (`no_retrieval` / `single_step` / `multi_step`); Python routes to the matched strategy. Combines [Meta-Controller (nb 11)](./11_meta_controller.ipynb)'s pre-routing with the RAG family's three execution modes.\n", "\n", "| Property | Value |\n", "|---|---|\n", "| Origin | Jeong et al., *Adaptive-RAG* (NAACL 2024). [arXiv:2403.14403](https://arxiv.org/abs/2403.14403) |\n", "| Routing | Categorical (3-way) classifier — deterministic-picker |\n", "| Cost | 1 classify + 1-3 execution calls (depending on bucket) |\n", "| Default LLM | Llama-3.3-70B |" ] }, { "cell_type": "markdown", "id": "f1d0630e", "metadata": { "papermill": { "duration": 0.0, "end_time": "2026-05-28T02:50:57.355778+00:00", "exception": false, "start_time": "2026-05-28T02:50:57.355778+00:00", "status": "completed" }, "tags": [] }, "source": [ "## 2 · Architecture at a glance\n", "\n", "```mermaid\n", "flowchart TB\n", " A([task]) --> C[CLASSIFY
categorical complexity]\n", " C -->|no_retrieval| N[Parametric answer]\n", " C -->|single_step| S[1 retrieve → answer]\n", " C -->|multi_step| M[2 retrievals → answer]\n", " N --> Z([final])\n", " S --> Z\n", " M --> Z\n", "\n", " style C fill:#fff3e0,stroke:#f57c00\n", " style N fill:#e3f2fd,stroke:#1976d2\n", " style S fill:#e8f5e9,stroke:#388e3c\n", " style M fill:#fce4ec,stroke:#c2185b\n", "```" ] }, { "cell_type": "markdown", "id": "9f6a1af1", "metadata": { "papermill": { "duration": 0.0, "end_time": "2026-05-28T02:50:57.355778+00:00", "exception": false, "start_time": "2026-05-28T02:50:57.355778+00:00", "status": "completed" }, "tags": [] }, "source": [ "## 3 · Theory\n", "\n", "### 3.0 · Why pre-classify\n", "\n", "Self-RAG (nb 25) and CRAG (nb 24) make per-doc decisions *after* retrieval. Agentic RAG (nb 23) makes iterative decisions *during* retrieval. Adaptive RAG makes the **strategy** decision *before* anything else — one classifier call replaces a more expensive routing loop.\n", "\n", "Trade-off: cheaper, but locks in the strategy. A misclassified `single_step` query gets one retrieval even if it really needed multi-hop.\n", "\n", "### 3.1 · Where this sits\n", "\n", "| Pattern | Where the routing happens |\n", "|---|---|\n", "| Plain RAG | Nowhere — always retrieve once |\n", "| [Agentic RAG (nb 23)](./23_agentic_rag.ipynb) | Each loop iteration |\n", "| [CRAG (nb 24)](./24_corrective_rag.ipynb) | After retrieval, on the batch |\n", "| [Self-RAG (nb 25)](./25_self_rag.ipynb) | After retrieval, per-doc |\n", "| **Adaptive RAG (this nb)** | **Pre-retrieval, on the query** |" ] }, { "cell_type": "markdown", "id": "c1cd18be", "metadata": { "papermill": { "duration": 0.0, "end_time": "2026-05-28T02:50:57.371783+00:00", "exception": false, "start_time": "2026-05-28T02:50:57.371783+00:00", "status": "completed" }, "tags": [] }, "source": [ "## 4 · Setup" ] }, { "cell_type": "code", "execution_count": 1, "id": "fada2838", "metadata": { "execution": { "iopub.execute_input": "2026-05-28T02:50:57.371783Z", "iopub.status.busy": "2026-05-28T02:50:57.371783Z", "iopub.status.idle": "2026-05-28T02:50:59.254924Z", "shell.execute_reply": "2026-05-28T02:50:59.254924Z" }, "papermill": { "duration": 1.883141, "end_time": "2026-05-28T02:50:59.254924+00:00", "exception": false, "start_time": "2026-05-28T02:50:57.371783+00:00", "status": "completed" }, "tags": [] }, "outputs": [ { "data": { "text/html": [ "
LLM: meta-llama/Llama-3.3-70B-Instruct  ·  Corpus: 12 docs ────────────────────────────────────────────────────────\n",
       "
\n" ], "text/plain": [ "\u001b[1;36mLLM: meta-llama/Llama-\u001b[0m\u001b[1;36m3.3\u001b[0m\u001b[1;36m-70B-Instruct · Corpus: \u001b[0m\u001b[1;36m12\u001b[0m\u001b[1;36m docs\u001b[0m \u001b[92m────────────────────────────────────────────────────────\u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from agentic_architectures import get_llm, enable_langsmith, settings\n", "from agentic_architectures.architectures import AdaptiveRAG\n", "from agentic_architectures.data import STARDUST_CORPUS\n", "from agentic_architectures.ui import print_md, print_header\n", "\n", "enable_langsmith()\n", "llm = get_llm(provider=\"nebius\", model=\"meta-llama/Llama-3.3-70B-Instruct\", temperature=0.2)\n", "print_header(f\"LLM: {llm.model} · Corpus: {len(STARDUST_CORPUS)} docs\")" ] }, { "cell_type": "markdown", "id": "04509d7b", "metadata": { "papermill": { "duration": 0.0, "end_time": "2026-05-28T02:50:59.254924+00:00", "exception": false, "start_time": "2026-05-28T02:50:59.254924+00:00", "status": "completed" }, "tags": [] }, "source": [ "## 5 · Library walkthrough" ] }, { "cell_type": "code", "execution_count": 2, "id": "101e304e", "metadata": { "execution": { "iopub.execute_input": "2026-05-28T02:50:59.254924Z", "iopub.status.busy": "2026-05-28T02:50:59.254924Z", "iopub.status.idle": "2026-05-28T02:50:59.270682Z", "shell.execute_reply": "2026-05-28T02:50:59.270682Z" }, "papermill": { "duration": 0.015758, "end_time": "2026-05-28T02:50:59.270682+00:00", "exception": false, "start_time": "2026-05-28T02:50:59.254924+00:00", "status": "completed" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"description\": \"Pre-classification of the query into a RAG complexity bucket.\",\n", " \"properties\": {\n", " \"complexity\": {\n", " \"description\": \"Routing class: 'no_retrieval' = answer from parametric memory (arithmetic, common knowledge); 'single_step' = one retrieval is sufficient (single-fact lookup); 'multi_step' = multi-hop or follow-up retrievals needed.\",\n", " \"enum\": [\n", " \"no_retrieval\",\n", " \"single_step\",\n", " \"multi_step\"\n", " ],\n", " \"title\": \"Complexity\",\n", " \"type\": \"...\n" ] } ], "source": [ "from agentic_architectures.architectures.adaptive_rag import _ComplexityClass\n", "import json\n", "print(json.dumps(_ComplexityClass.model_json_schema(), indent=2)[:500] + '...')" ] }, { "cell_type": "markdown", "id": "1c6dcb93", "metadata": { "papermill": { "duration": 0.0, "end_time": "2026-05-28T02:50:59.273748+00:00", "exception": false, "start_time": "2026-05-28T02:50:59.273748+00:00", "status": "completed" }, "tags": [] }, "source": [ "## 7 · Build the graph" ] }, { "cell_type": "code", "execution_count": 3, "id": "be3e44c9", "metadata": { "execution": { "iopub.execute_input": "2026-05-28T02:50:59.279759Z", "iopub.status.busy": "2026-05-28T02:50:59.279759Z", "iopub.status.idle": "2026-05-28T02:51:05.736305Z", "shell.execute_reply": "2026-05-28T02:51:05.735288Z" }, "papermill": { "duration": 6.462557, "end_time": "2026-05-28T02:51:05.736305+00:00", "exception": false, "start_time": "2026-05-28T02:50:59.273748+00:00", "status": "completed" }, "tags": [] }, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from IPython.display import Image, display\n", "arch = AdaptiveRAG(llm=llm, documents=STARDUST_CORPUS, top_k=3)\n", "graph = arch.build()\n", "try:\n", " display(Image(graph.get_graph().draw_mermaid_png()))\n", "except Exception as e:\n", " print(f\"(PNG render unavailable: {e}; see § 2)\")\n", " print(graph.get_graph().draw_mermaid())" ] }, { "cell_type": "markdown", "id": "f8f69640", "metadata": { "papermill": { "duration": 0.002981, "end_time": "2026-05-28T02:51:05.742315+00:00", "exception": false, "start_time": "2026-05-28T02:51:05.739334+00:00", "status": "completed" }, "tags": [] }, "source": [ "## 8 · Live run — 3 tasks of varying complexity\n", "\n", "Tasks chosen to exercise each routing bucket." ] }, { "cell_type": "code", "execution_count": 4, "id": "e5030ad3", "metadata": { "execution": { "iopub.execute_input": "2026-05-28T02:51:05.747722Z", "iopub.status.busy": "2026-05-28T02:51:05.747722Z", "iopub.status.idle": "2026-05-28T02:51:32.302139Z", "shell.execute_reply": "2026-05-28T02:51:32.302139Z" }, "papermill": { "duration": 26.557834, "end_time": "2026-05-28T02:51:32.302139+00:00", "exception": false, "start_time": "2026-05-28T02:51:05.744305+00:00", "status": "completed" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "TASK_TAG: arithmetic\n", " TASK: What is 15 plus 27? Return only the integer.\n", " ROUTED_TO: no_retrieval\n", " CLASSIFICATION_RATIONALE: The question is asking for a simple arithmetic operation that can be performed using a strong LLM's parametric memory.\n", " RETRIEVAL_COUNT: 0\n", " FINAL_ANSWER: 42\n", "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "TASK_TAG: simple_lookup\n", " TASK: What propellant does the Stardust 9 rocket use?\n", " ROUTED_TO: single_step\n", " CLASSIFICATION_RATIONALE: The question requires a single-fact lookup about the Stardust 9 rocket's propellant.\n", " RETRIEVAL_COUNT: 1\n", " FINAL_ANSWER: Methalox propellant, which is a combination of liquid methane and liquid oxygen.\n", "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "TASK_TAG: multi_hop\n", " TASK: Who founded Stardust Aerospace, and what did the CEO do before founding it?\n", " ROUTED_TO: multi_step\n", " CLASSIFICATION_RATIONALE: The question requires multiple pieces of information: the founder of Stardust Aerospace and the CEO's previous experience, which likely necessitates follow-up retrievals.\n", " RETRIEVAL_COUNT: 2\n", " FINAL_ANSWER: Stardust Aerospace was founded by Dr. Amara Okonkwo and Jin-ho Park in 2019. Before founding Stardust Aerospace, Dr. Amara Okonkwo, the CEO, worked at Blue Origin on the New Glenn program. She holds a PhD in aerospace engineering from Caltech, which she obtained in 2012.\n", "\n" ] } ], "source": [ "TASKS = [\n", " (\"arithmetic\", \"What is 15 plus 27? Return only the integer.\"),\n", " (\"simple_lookup\", \"What propellant does the Stardust 9 rocket use?\"),\n", " (\"multi_hop\", \"Who founded Stardust Aerospace, and what did the CEO do before founding it?\"),\n", "]\n", "\n", "for tag, q in TASKS:\n", " r = arch.run(q)\n", " print(f\"TASK_TAG: {tag}\")\n", " print(f\" TASK: {q}\")\n", " print(f\" ROUTED_TO: {r.metadata['complexity']}\")\n", " print(f\" CLASSIFICATION_RATIONALE: {r.metadata['classification_rationale']}\")\n", " print(f\" RETRIEVAL_COUNT: {r.metadata['retrieval_count']}\")\n", " print(f\" FINAL_ANSWER: {r.output[:300]}\")\n", " print()" ] }, { "cell_type": "markdown", "id": "315cdc7a", "metadata": { "papermill": { "duration": 0.00324, "end_time": "2026-05-28T02:51:32.312496+00:00", "exception": false, "start_time": "2026-05-28T02:51:32.309256+00:00", "status": "completed" }, "tags": [] }, "source": [ "## 9 · What we just observed\n", "\n", "The cells above ran Adaptive RAG on 3 task types matched to the 3 routing buckets. The classifier picks the bucket once upfront; Python routes to the matched executor.\n", "\n", "### 9.1 · Classification + routing summary\n", "\n", "| Tag | Routed to | Retrievals | Classification rationale | Final answer |\n", "|---|---|---|---|---|\n", "| `arithmetic` | `no_retrieval` | 0 | The question is asking for a simple arithmetic operation that can be performed u | 42 |\n", "| `simple_lookup` | `single_step` | 1 | The question requires a single-fact lookup about the Stardust 9 rocket's propell | Methalox propellant, which is a combination of liquid methane and liquid oxygen. |\n", "| `multi_hop` | `multi_step` | 2 | The question requires multiple pieces of information: the founder of Stardust Ae | Stardust Aerospace was founded by Dr. Amara Okonkwo and Jin-ho Park in 2019. Bef… |\n", "\n", "### 9.2 · Routing accuracy + patterns\n", "\n", "- **✅ `arithmetic` correctly routed to `no_retrieval`** (matches expected).\n", "\n", "- **✅ `simple_lookup` correctly routed to `single_step`** (matches expected).\n", "\n", "- **✅ `multi_hop` correctly routed to `multi_step`** (matches expected).\n", "\n", "- **Routing accuracy: 3/3** correct against the expected buckets.\n", "\n", "### 9.3 · The takeaway\n", "\n", "Adaptive RAG's value is **all in the classifier**. Read §9.1's `Routed to` column against §9.2's expected buckets. A mismatch means the classifier mis-bucketed the query, and the subsequent execution will under-perform (single_step retrieve when multi was needed → incomplete answer; or wasted calls on no_retrieval that wasn't really no-retrieval).\n", "\n", "The deterministic-picker pattern is the LLM's categorical `complexity` field plus Python's `if/elif` route. No numeric scoring — the LLM never emits a confidence-of-route score that could flatten." ] }, { "cell_type": "markdown", "id": "3ecdd208", "metadata": { "papermill": { "duration": 0.002005, "end_time": "2026-05-28T02:51:32.316509+00:00", "exception": false, "start_time": "2026-05-28T02:51:32.314504+00:00", "status": "completed" }, "tags": [] }, "source": [ "## 11 · Failure modes & extensions\n", "\n", "| Failure | Mitigation |\n", "|---|---|\n", "| **Misclassification** | Classifier sends multi_hop to single_step → incomplete answer | Add a post-answer \"is the answer complete?\" check |\n", "| **Bucket too coarse** | Some queries need 3+ retrievals | Add `deep_multi_step` bucket and an Agentic-RAG-style iterative executor |\n", "| **Cost of classifier call** | One extra call per task | Cache classifications by query template |\n", "\n", "Extensions: (1) learned classifier (train on labelled query→complexity pairs), (2) compose with CRAG inside each executor for grade-based fallback, (3) per-bucket different LLMs (cheap LLM for no_retrieval, stronger for multi_step).\n", "\n", "Reference: Jeong et al. 2024 — [arXiv:2403.14403](https://arxiv.org/abs/2403.14403)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.0" }, "papermill": { "default_parameters": {}, "duration": 37.308545, "end_time": "2026-05-28T02:51:32.999790+00:00", "environment_variables": {}, "exception": null, "input_path": "all-agentic-architectures/notebooks/26_adaptive_rag.ipynb", "output_path": "all-agentic-architectures/notebooks/26_adaptive_rag.ipynb", "parameters": {}, "start_time": "2026-05-28T02:50:55.691245+00:00", "version": "2.7.0" } }, "nbformat": 4, "nbformat_minor": 5 }