Skip to content

Chapter 17 · Knowledge Bases and RAG Basics ​

Learning objectives: Understand the complete RAG pipeline, learn to use Agno's Knowledge to load documents, configure the local LanceDB vector store and third-party Embedding services, and attach a knowledge base to an Agent for traceable Q&A.

17.1 RAG Principles at a Glance ​

A large model only knows what it saw during training — it is ignorant of internal corporate documents and the latest materials, and may confidently fabricate answers (hallucinations). RAG (Retrieval-Augmented Generation) addresses this by first "retrieving" relevant snippets from your own document library, then stuffing those snippets into the prompt so the model can "answer with evidence."

The full pipeline has two phases:

  1. Write phase (Indexing): Documents → chunking → vectorization (embedding) → store in a vector database;
  2. Query phase (Retrieval): User question vectorized → find the most similar snippets in the vector DB → concatenate into the prompt → model generates an evidenced answer.

Three roles

  • Embedder: Converts text into vectors (a list of floats); semantically similar text has vectors that are closer together;
  • Vector DB: Stores vectors and supports "nearest-neighbor retrieval"; Agno supports LanceDB, PgVector, Chroma, and others;
  • Knowledge: Agno's wrapper around the entire pipeline above — responsible for reading, chunking, indexing, and retrieving.

17.2 Building a Knowledge Base with Knowledge ​

Knowledge is the core class for Agno's knowledge capabilities (the unified API carried over in 3.x). Specify the vector store and Embedder at creation, then pour content in via insert() — it supports local paths, URLs, raw text, and other sources, and automatically detects formats like PDF, DOCX, CSV, and Markdown to pick the right Reader:

python
# knowledge_basic.py
import os
from agno.knowledge.knowledge import Knowledge
from agno.knowledge.embedder.openai import OpenAIEmbedder
from agno.vectordb.lancedb import LanceDb, SearchType

# Local vector store LanceDB: no separate service deployment needed; data lives in a local directory
knowledge = Knowledge(
    vector_db=LanceDb(
        table_name="company_docs",          # Vector table name
        uri="tmp/lancedb",                  # Data storage directory
        search_type=SearchType.vector,      # Vector retrieval (hybrid retrieval covered in the next chapter)
        embedder=OpenAIEmbedder(            # Third-party OpenAI-compatible Embedding service
            id="Qwen/Qwen3-Embedding-8B",   # Use the actual model id provided by your platform
            api_key=os.getenv("EMBEDDING_API_KEY"),
            base_url="https://api.siliconflow.cn/v1",
        ),
    )
)

# Pour in content: supports url / path / directory / raw text
knowledge.insert(
    url="https://agno-public.s3.amazonaws.com/recipes/ThaiRecipes.pdf",
    skip_if_exists=True,     # Skip content already in the database to avoid duplicate indexing
)
knowledge.insert(text_content="Company annual leave policy: employees with one year of service receive 5 days of paid annual leave...")

Dependency installation:

bash
pip install "agno[lancedb]" pypdf   # lancedb and PDF reading support

Note

insert() makes real Embedding API calls and incurs fees and latency; always include skip_if_exists=True during development, or you'll re-index on every run.

17.3 Attaching a Knowledge Base to an Agent ​

Simply pass knowledge= to the Agent. Agno automatically registers a search_knowledge_base tool with the model — the model decides when to retrieve on its own. This is the Agentic RAG pattern expanded in the next chapter:

python
# rag_agent.py
from agno.agent import Agent
from agno.models.openai import OpenAIChat

agent = Agent(
    model=OpenAIChat(
        id="deepseek-chat",
        api_key=os.getenv("DEEPSEEK_API_KEY"),
        base_url="https://api.deepseek.com/v1",
    ),
    knowledge=knowledge,
    search_knowledge=True,   # Enabled by default when knowledge is provided; spelled out here for clarity
    instructions=[
        "Search the knowledge base before answering.",
        "Cite which sources you referenced at the end of your answer.",
        "If the knowledge base doesn't have the information, say so explicitly — do not fabricate.",
    ],
    markdown=True,
)

agent.print_response("How do you make Thai coconut chicken soup?")

Watch the logs after running — you'll see the model first issue a tool call (retrieval), then generate the final answer once it has relevant snippets.

17.4 Direct Retrieval and Result Traceability ​

Sometimes you need to test retrieval quality bypassing the model entirely — use knowledge.search(). Each returned result carries both content and metadata:

python
results = knowledge.search(query="How many days of annual leave?")
for r in results:
    print("Relevance score:", getattr(r, "score", None))
    print("Content:", r.content[:100])
    print("Metadata:", r.meta_data)       # Includes source filename etc. — useful for traceability

To auto-inject retrieved references into the user prompt (traditional RAG mode) instead of leaving the decision to the model, set add_knowledge_to_context=True; the trade-offs between the two approaches are covered in the next chapter.

python
# Traditional RAG: always run a retrieval before each question and concatenate into context
traditional_rag_agent = Agent(
    model=model,
    knowledge=knowledge,
    add_knowledge_to_context=True,   # Retrieved results auto-appended to user message
)
traditional_rag_agent.print_response("What is the company annual leave policy?")

17.5 Common Pitfalls ​

  • Embedding and querying in different "semantic spaces": indexing and retrieval must use the same Embedder config; switching models requires rebuilding the entire vector table;
  • Poor Chinese retrieval quality: usually the Embedding model doesn't support Chinese — choose a multilingual model (e.g., Qwen/BGE series);
  • Forgetting the persistence directory: pointing uri at a temp directory means re-inserting on every restart;
  • Chunks too large: stuffing too much irrelevant content into a single chunk dilutes similarity; Chapter 18 covers chunking strategies in detail.

Chapter Summary ​

  • RAG = Write (chunking → vectorization → indexing) + Query (retrieval → prompt concatenation → generation) two-phase pipeline;
  • Knowledge(vector_db=LanceDb(...), embedder=OpenAIEmbedder(...)) is the standard combo; LanceDB is deployment-free and ideal for local development;
  • Agent(knowledge=..., search_knowledge=True) lets the model retrieve autonomously via a tool;
  • knowledge.search() validates retrieval quality independently of the LLM;
  • Indexing and retrieval must share the same Embedding configuration.

🧪 随堂测验

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

1. In the RAG write phase, what is the correct processing order for a document?

2. After passing a knowledge parameter to an Agent, what does Agno do by default?

3. Regarding Embedding configuration, which statement is false?

4. To verify "whether a given question can retrieve the correct snippet" without calling the LLM, what should you do?

🛠️ Hands-On Exercises ​

  1. Build a small knowledge base with LanceDB + a third-party Embedding service; insert 3 paragraphs of your own notes and test the recall for 5 questions using knowledge.search().
  2. Run the RAG Agent from 17.3; deliberately ask a question that is NOT in the knowledge base, and verify that it admits "I don't know" per the instructions.
  3. Insert a public PDF URL into the knowledge base and compare the answer quality for the same question before and after insertion.

With the basics in hand, proceed to Chapter 18: RAG Advanced to learn chunking strategies, filtering, and reranking.