Skip to content

Chapter 18 · RAG Advanced: Agentic RAG and Hybrid Retrieval ​

Learning objectives: Distinguish between Agentic RAG and Traditional RAG, and master three key techniques for improving retrieval quality: chunking strategies, metadata filtering, and rerankers.

18.1 Agentic RAG vs. Traditional RAG ​

The example from the previous chapter was Agentic RAG: the model receives a search_knowledge_base tool and decides for itself "whether to search and with what query," and can even rewrite the query and perform multi-round supplementary retrieval. Traditional RAG, on the other hand, is a fixed pipeline — every question triggers a retrieval first, and the results are injected directly into the prompt:

python
from agno.agent import Agent

# Traditional RAG: retrieve before every request; references auto-appended to user message
traditional = Agent(
    model=model,
    knowledge=knowledge,
    add_knowledge_to_context=True,   # Retrieved results directly added to context
)

# Agentic RAG: model autonomously decides whether/how to retrieve (default behavior)
agentic = Agent(
    model=model,
    knowledge=knowledge,
    search_knowledge=True,           # Register retrieval tool; leave decisions to the model
)
DimensionTraditional RAGAgentic RAG
Retrieval timingAlways retrievesModel decides on demand
Latency & costLow and predictableOne extra tool-call round
Complex questionsSingle retrieval may be insufficientCan rewrite queries, retrieve multiple times
Suitable scenariosSimple Q&A, low-latency requirementsKnowledge work requiring multi-step reasoning

Selection guidance

For customer-service FAQ "one question, one answer" scenarios, traditional RAG is sufficient; for research and analysis tasks, use Agentic RAG. Both can coexist in the same project.

18.2 Chunking Strategies: The First Factor Determining Recall Ceiling ​

The smallest unit stored in a vector DB is a chunk. Cut too large, and irrelevant content in a single snippet dilutes similarity; cut too small, and semantics become incomplete. Agno ships multiple built-in Chunking strategies wired through the Reader:

python
from agno.knowledge.chunking.fixed import FixedSizeChunking
from agno.knowledge.chunking.recursive import RecursiveChunking
from agno.knowledge.chunking.document import DocumentChunking
from agno.knowledge.reader.pdf_reader import PDFReader
from agno.knowledge.knowledge import Knowledge

# Fixed-size: simple and blunt; suitable for uniformly formatted text
fixed_reader = PDFReader(chunking_strategy=FixedSizeChunking(size=1500))

# Recursive: falls back through paragraph → sentence → character delimiters; best general-purpose choice
recursive_reader = PDFReader(chunking_strategy=RecursiveChunking())

# Document-structure: cuts at title/section boundaries; preserves chapter integrity
doc_reader = PDFReader(chunking_strategy=DocumentChunking())

knowledge = Knowledge(vector_db=vector_db)
knowledge.insert(path="handbook.pdf", reader=recursive_reader)

Selection experience: structured chunking for Markdown/HTML, Code Chunking for code, Recursive Chunking as the starting point for unstructured long-form text; try Semantic Chunking (sentence-break based on embedding similarity) only if initial results are unsatisfactory.

18.3 Metadata Filtering: Making Retrieval "Targeted" ​

Tag入库内容 with metadata, then filter by tag at query time to shrink the search scope from "the entire library" to "this user / this year / this type":

python
# Attach metadata at insert time
knowledge.insert(
    path="resumes/",
    metadata={"department": "engineering", "year": 2025},
)

# Method 1: Agent-level fixed filter — this Agent only ever sees engineering docs
agent = Agent(
    model=model,
    knowledge=knowledge,
    search_knowledge=True,
    knowledge_filters={"department": "engineering"},
)

# Method 2: Per-call temporary filter; multiple conditions combine with AND logic
agent.print_response(
    "Summarize the highlights of engineers hired in 2025",
    knowledge_filters={"year": 2025},
)

# Direct retrieval also supports filters
results = knowledge.search(query="Python experience", filters={"department": "engineering"})

You can also enable enable_agentic_knowledge_filters=True to let the model auto-infer filter conditions from the user's question (e.g., extracting user_id=jordan from "Jordan's skills"); this requires pairing with Contents DB to record available filter keys.

18.4 Reranker: The Final Gate of Precision Ranking ​

Vector retrieval returns a "coarse rank." Reranker uses a heavier but more accurate cross-encoding model to score and re-sort each candidate snippet, pushing truly relevant ones to the top:

python
import os
from agno.knowledge.reranker.cohere import CohereReranker
from agno.vectordb.lancedb import LanceDb, SearchType

knowledge = Knowledge(
    vector_db=LanceDb(
        uri="tmp/lancedb",
        table_name="docs",
        search_type=SearchType.hybrid,   # Hybrid retrieval: dual signals from vectors + keywords
        embedder=embedder,
        reranker=CohereReranker(model="rerank-v3.5"),   # Precision ranking model
    ),
)

The three components divide labor: hybrid retrieval captures both semantic similarity and exact keyword-match signals; reranking then performs fine-grained relevance sorting on those candidates. This is the standard trio for production-grade RAG.

18.5 How to Evaluate Retrieval Quality ​

Parameter tuning can't rely on gut feeling — build the smallest evaluation loop:

  1. Prepare 20–50 labeled pairs of「question → expected hit content」;
  2. Run them in batch with knowledge.search() and compute recall rate (whether the correct snippet appears in top-k);
  3. Re-run and compare after every adjustment to chunk size, Embedding model, or reranker addition.
python
def hit_rate(kb, cases, k=5):
    hits = sum(
        any(c["keyword"] in r.content for r in kb.search(q=c["q"], top_k=k))
        for c in cases
    )
    return hits / len(cases)   # e.g. 0.85 means 85% of questions retrieved the target snippet

Chapter Summary ​

  • Agentic RAG (search_knowledge=True, model-driven retrieval) and Traditional RAG (add_knowledge_to_context=True, retrieve-then-answer) each have their own suitable scenarios;
  • Chunking strategies are configured via the Reader's chunking_strategy; Recursive Chunking is the general-purpose starting point;
  • knowledge_filters enables metadata filtering; enable_agentic_knowledge_filters=True lets the model auto-infer filter conditions;
  • SearchType.hybrid + Reranker is the production-standard retrieval combo;
  • Use a small labeled set to quantitatively evaluate the impact of every tuning pass.

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. What is the core difference between Agentic RAG and Traditional RAG?

2. Regarding chunking, which statement is correct?

3. If you set knowledge_filters={"year": 2025} and then pass {"dept": "sales"}, how do the two conditions interact?

4. What role does the Reranker play in the retrieval pipeline?

🛠️ Hands-On Exercises ​

  1. Index the same PDF into two separate tables using FixedSizeChunking(size=1000) and RecursiveChunking() respectively; compare search() recall differences with the same set of questions.
  2. Tag knowledge base content with {"lang": "zh"/"en"} metadata; implement a bilingual query where Chinese questions only retrieve Chinese corpus and English questions only retrieve English corpus.
  3. Write a 10-case hit_rate evaluation script for your knowledge base and record the baseline score.

Next up: Chapter 19: Reasoning, where the model learns to "think before answering."