Module 3

Module 3: RAG 知识检索

构建完整的 RAG 系统,让 Agent 能基于外部知识库回答专业问题。

文档加载分块策略向量嵌入ChromaDB高级检索

学习目标

构建完整的 RAG(Retrieval-Augmented Generation)系统,让 Agent 能基于外部知识库回答问题。

RAG 解决了什么问题?

LLM 的两大缺陷:

1. 知识截止日期:训练数据有时间限制,不知道最新论文

2. 幻觉:可能编造不存在的信息

RAG 的解决思路:先检索相关文档,再让 LLM 基于文档回答


3.1 文档加载 (document_loading.py)

LangChain Document 对象


from langchain_core.documents import Document

doc = Document(
    page_content="BEVFormer uses spatiotemporal transformers...",
    metadata={"source": "BEVFormer", "year": 2022, "venue": "ECCV"}
)

支持的加载器

格式 加载器 用法
PDF PyPDFLoader Loader("paper.pdf").load()
网页 WebBaseLoader Loader("https://...").load()
CSV CSVLoader Loader("data.csv").load()
文本 TextLoader Loader("file.txt").load()

3.2 分块策略 (chunking_strategies.py)

这是 RAG 质量最关键的参数

chunk_size 效果
太小 (100) 检索精确,但可能丢失上下文
太大 (2000) 上下文完整,但检索精度下降
中等 (300-500) 推荐:平衡精度和完整性

chunk_overlap

相邻块的重叠字符数(通常为 chunk_size 的 10-20%)。

为什么需要 overlap?

答案可能恰好落在两个 chunk 的边界上,overlap 确保不会丢失这段信息。

三种分割器


# 1. 递归分割(推荐默认)
RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)

# 2. 固定字符分割(简单但可能截断句子)
CharacterTextSplitter(chunk_size=500, separator="")

# 3. 语义分割(最智能,需要 embedding 模型)
SemanticChunker(embeddings)

3.3 向量嵌入与存储 (embeddings_vectorstore.py)

流程


文本 → Embedding 模型 → 768 维向量 → 向量数据库 → 相似度搜索

Embedding 选择

选项 维度 成本
sentence-transformers (all-MiniLM-L6-v2) 384 免费,本地运行
OpenAI text-embedding-3-small 1536 按 token 收费

Vector Store 选择

选项 特点
ChromaDB 本地持久化,内置元数据过滤,推荐开发用
FAISS 纯内存,速度最快,需手动保存

相似度搜索


# 基础搜索
docs = vector_store.similarity_search("BEV perception", k=3)

# MMR 搜索(避免结果重复)
docs = vector_store.max_marginal_relevance_search(query, k=3, fetch_k=6)

# 带元数据过滤
docs = vector_store.similarity_search(query, filter={"year": {"$gte": 2022}})

3.4 基础 RAG Chain (basic_rag_chain.py)

完整流水线


# 1. 构建检索器
retriever = vector_store.as_retriever(search_kwargs={"k": 3})

# 2. RAG Prompt
prompt = ChatPromptTemplate.from_messages([
    ("system", "基于以下参考资料回答:\n{context}"),
    ("human", "{question}"),
])

# 3. 组合
def format_docs(docs):
    return "\n\n".join(d.page_content for d in docs)

rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt | llm | StrOutputParser()
)

# 4. 使用
answer = rag_chain.invoke("BEVFormer 的架构是什么?")

3.5 高级检索策略 (advanced_retrieval.py)

Multi-Query


# 自动生成多个查询变体,综合检索结果
retriever = MultiQueryRetriever.from_llm(retriever=base, llm=llm)
# "BEV perception" → ["BEV perception survey", "bird's eye view detection", ...]

HyDE (Hypothetical Document Embeddings)


用户问题 → LLM 生成"假设答案" → 用假设答案的 embedding 检索

当问题和文档用词不一致时非常有效。

Self-Query


# 从自然语言中提取元数据过滤条件
# "2022年后的 BEV 论文" → filter={"year": {"$gte": 2022}}

3.8 RAG Agent (rag_agent.py) ⭐

将检索封装为 Agent 工具

这是 RAG 最强大的用法:Agent 可以自主决定何时检索、检索什么


@tool
def query_papers(question: str) -> str:
    """查询论文知识库"""
    docs = knowledge_base.query(question)
    return format_docs(docs)

# 与其他工具一起注册
tools = [query_papers, calculator, search_papers]

对比:RAG Chain vs RAG Agent

RAG Chain RAG Agent
检索次数 1 次 多次,Agent 自主决定
工具组合 检索 + 计算 + 搜索...
灵活性 固定流程 动态决策

Module 3 核心总结

步骤 关键决策
文档加载 选对 Loader(PDF/Web/CSV)
分块 chunk_size 500 + overlap 100(中文英文有所不同)
Embedding 本地免费(sentence-transformers)vs 云端收费(OpenAI)
向量存储 ChromaDB(持久化)vs FAISS(纯内存)
检索 默认 similarity + MMR,特殊场景用 Multi-Query / HyDE
RAG Agent 检索作为工具,Agent 自主决策何时使用