RAG:检索增强生成

7/6/2026 AI AgentRAG向量检索文档切分

# RAG:检索增强生成

第五篇:综合实战 — 让 Agent 拥有"外挂知识库"——从向量检索到生产级 RAG

# 16.1 为什么 Agent 需要 RAG?

大模型有两个硬伤:知识截止日期(训练数据有时效性)和领域知识不足(通用模型不懂你的业务)。微调可以解决一部分,但成本高、周期长、更新慢。RAG(Retrieval-Augmented Generation,检索增强生成)提供了更灵活的方案:先检索,再生成。

💡 RAG 的核心思想 不是把知识"塞进"模型参数,而是在生成回答前,先从外部知识库检索相关文档,把检索到的内容作为上下文喂给 LLM。模型只需要"阅读理解",不需要"死记硬背"。

🔴 纯 LLM(无 RAG)

  • 知识截止到训练日期,不知道最新信息
  • 企业内部文档一概不知
  • 容易产生幻觉(编造事实)
  • 无法引用信息来源
  • 更新知识需要重新训练或微调

🟢 LLM + RAG

  • 知识实时更新,随时新增文档
  • 接入企业内部知识库(Wiki/文档/工单)
  • 基于检索到的真实内容回答,减少幻觉
  • 可以引用来源文档,可追溯
  • 无需重新训练,成本极低

# RAG vs 微调:什么时候用什么?

对比维度 RAG 微调
知识更新 实时,加文档即可 需要重新微调
适合场景 事实性问答、文档检索 风格/格式/推理模式定制
成本 低(向量数据库 + 检索) 高(GPU 训练)
延迟 多一次检索(+200-500ms) 无额外延迟
幻觉控制 ✅ 强(基于检索内容) ⚠️ 弱(仍可能编造)
最佳实践 RAG + 微调结合:微调改善风格,RAG 提供知识

# 16.2 RAG 的完整流程

RAG 不是简单的"搜索 + 拼接",一个生产级 RAG 系统包含五个阶段:

# 阶段一:文档处理(Chunking)

文档不能整篇丢给模型——上下文窗口有限,检索精度也不够。需要将长文档分块(Chunking)。


# 递归字符分割器:按优先级依次尝试分隔符
splitter = RecursiveCharacterTextSplitter(
    chunk_size=512,        # 每块最大 512 字符
    chunk_overlap=64,      # 块间重叠 64 字符(保持上下文连贯)
    separators=["\n\n", "\n", "。", "!", "?", ",", " ", ""],
    keep_separator=True
)

chunks = splitter.split_text(long_document)

print(f"文档被分为 {len(chunks)} 块")
# chunk_size 太大 → 检索不精确、浪费 Token
# chunk_size 太小 → 上下文断裂、语义不完整
1
2
3
4
5
6
7
8
9
10
11
12
13
14

⚠️ 分块策略选择

  • 简单快速,适合大多数场景
  • 可能在句子中间截断
  • 按段落/标题/语义边界分块
  • 检索质量更高,但实现复杂

# 阶段二:向量化(Embedding)

把文本块转成向量(高维浮点数组),使语义相近的文本在向量空间中距离也近。


# 选择 Embedding 模型
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

# 单文本向量化
vector = embeddings.embed_query("什么是 RAG?")
# 返回 1536 维浮点数组,如 [0.012, -0.034, 0.056, ...]

# 批量向量化(生产环境推荐批量操作)
texts = [chunk for chunk in chunks]
1
2
3
4
5
6
7
8
9
10
Embedding 模型 维度 特点 适合场景
text-embedding-3-small 1536 OpenAI,性价比高 通用英文/中文
text-embedding-3-large 3072 精度更高,成本翻倍 高精度检索
bge-large-zh-v1.5 1024 开源,中文最强 中文场景/私有部署
jina-embeddings-v3 1024 开源,多语言 多语言混合

# 阶段三:向量数据库存储

向量数据库专门存储和检索高维向量,支持近似最近邻搜索(ANN),比暴力遍历快几个数量级。

向量数据库 类型 特点 适合场景
Chroma 嵌入式 零配置,Python 原生 原型/小项目
Pinecone 云服务 全托管,弹性扩展 生产环境/无运维
Weaviate 自部署 GraphQL API,混合检索 企业自建
Milvus 自部署 亿级向量,分布式 大规模生产
pgvector PostgreSQL 插件 SQL 查询,事务支持 已有 PG 的项目

# 创建客户端(数据持久化到磁盘)
client = chromadb.PersistentClient(path="./vector_db")

# 创建集合(相当于数据库表)
collection = client.get_or_create_collection(
    name="knowledge_base",
    metadata={"hnsw:space": "cosine"}  # 使用余弦相似度
)

# 写入向量
collection.add(
    documents=chunks,                    # 原始文本
    embeddings=vectors,                  # 向量
    metadatas=[{"source": "doc1"} for _ in chunks],  # 元数据
    ids=[f"chunk_{i}" for i in range(len(chunks))]   # 唯一 ID
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 16.3 检索策略:不只是相似度搜索

最简单的 RAG 只做向量相似度搜索,但生产级 RAG 需要更复杂的检索策略。

# 16.3.1 基础:向量相似度搜索

query = "Agent 的记忆系统有哪些类型?"
query_vector = embeddings.embed_query(query)

results = collection.query(
    query_embeddings=[query_vector],
    n_results=5,              # 返回 Top-5 最相似
    include=["documents", "distances", "metadatas"]
)

# results['documents'][0] → ["记忆分为短期记忆和长期记忆...", ...]
1
2
3
4
5
6
7
8
9
10

三种相似度度量:

度量 公式 特点 适合
余弦相似度 cos(A,B) = A·B / ( A
欧氏距离 d = √Σ(Ai-Bi)² 看绝对距离 图像检索
内积 IP = A·B 考虑向量大小 归一化后的向量

# 16.3.2 进阶:混合检索(BM25 + 向量)

纯向量检索的弱点:关键词匹配能力差。比如搜"GPT-4o",向量检索可能返回"GPT-4"的内容(语义相似但不是同一个模型)。BM25(关键词检索)正好互补。

from langchain_community.retrievers import BM25Retriever
from langchain_community.vectorstores import Chroma

# 1. 向量检索器(语义匹配)
vector_retriever = Chroma(
    collection_name="knowledge_base",
    embedding_function=embeddings
).as_retriever(search_kwargs={"k": 10})

# 2. BM25 检索器(关键词匹配)
bm25_retriever = BM25Retriever.from_documents(chunks)
bm25_retriever.k = 10

# 3. 混合检索器(加权融合)
ensemble_retriever = EnsembleRetriever(
    retrievers=[bm25_retriever, vector_retriever],
    weights=[0.4, 0.6]  # BM25 占 40%,向量占 60%
)

# 混合检索效果最好:语义匹配 + 关键词精准匹配
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 16.3.3 进阶:重排序(Reranker)

向量检索速度快但精度有限,返回 Top-20 中可能有噪声。重排序模型对这 20 条结果做精细打分,选出最相关的 Top-5。

📊 两阶段检索:快召回 + 精排序

  • 召回阶段:向量检索快速从百万文档中召回 Top-50(毫秒级)
  • 重排阶段:Cross-Encoder 模型对 50 条逐一精细打分,选 Top-5(百毫秒级) Cross-Encoder 比 Bi-Encoder(向量检索)精度高,但速度慢 100 倍,所以只用在小规模候选集上。
from langchain_cohere import CohereRerank

# 重排序模型
reranker = CohereRerank(top_n=5)  # 从候选集中选 Top-5

# 压缩检索器:先向量检索召回 → 再重排序
compression_retriever = ContextualCompressionRetriever(
    base_compressor=reranker,
    base_retriever=vector_retriever  # 先召回 Top-20
)

# 最终结果:精度远超纯向量检索
1
2
3
4
5
6
7
8
9
10
11
12

# 16.4 RAG 高级优化技巧

# 16.4.1 Query 改写

用户提问往往模糊或口语化,直接检索效果差。先用 LLM 改写 Query,提升检索质量。


llm = ChatOpenAI(model="gpt-4o-mini")

# 改写策略
rewrite_prompt = """你是一个搜索查询优化器。将用户的口语化问题改写为更适合检索的查询。

用户问题:{question}

改写要求:
1. 提取核心关键词
2. 补充可能的同义词
3. 生成 3 个不同角度的查询

输出格式:JSON 数组,如 ["query1", "query2", "query3"]
"""

# 原始问题:"Agent 怎么记住东西的?"
# 改写后:["Agent 记忆系统架构", "Agent 短期记忆 长期记忆", "LLM memory management"]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 16.4.2 HyDE(假设性文档嵌入)

有时候用户的问题太短,向量化后语义信息不足。HyDE 的思路是:先让 LLM 生成一个"假回答",用假回答去检索,再用检索结果生成真回答。

🔄 HyDE 流程

# 16.4.3 父子分块(Parent-Child Chunking)

检索时用小块(精确匹配),生成时用大块(上下文完整)。

# 小块(Child Chunk):128 字符 → 检索时使用

# 流程:
# 1. 文档先分成 512 字符的大块
# 2. 每个大块再细分为 128 字符的小块
# 3. 小块做 Embedding 并存储,但保留 parent_id
# 4. 检索时匹配小块 → 找到对应的大块 → 用大块作为上下文

1
2
3
4
5
6
7
8

# 16.5 Agent + RAG:让 Agent 自主决定何时检索

最简单的 RAG 是"每次提问都检索",但有些问题不需要检索(如"你好"、"1+1=?")。把 RAG 包装成 Agent 的一个工具,让 Agent 自主决定何时检索。

from langchain.agents import create_react_agent, AgentExecutor

def rag_search(query: str) -> str:
    """检索知识库并返回相关文档"""
    # 1. Query 改写
    rewritten = llm.invoke(rewrite_prompt.format(question=query))
    
    # 2. 多查询并行检索
    all_docs = []
    for q in parse_queries(rewritten):
        docs = ensemble_retriever.get_relevant_documents(q)
        all_docs.extend(docs)
    
    # 3. 去重 + 重排序
    unique_docs = deduplicate(all_docs)
    ranked_docs = reranker.compress_documents(unique_docs, query)
    
    # 4. 返回拼接的上下文
    return "\n\n".join([doc.page_content for doc in ranked_docs[:5]])

# 将 RAG 注册为 Agent 工具
tools = [
    Tool(
        name="knowledge_search",
        description="搜索内部知识库,获取产品文档、技术文档、FAQ等信息。当需要查找具体信息时使用。",
        func=rag_search
    ),
    # ... 其他工具
]

# Agent 自主决定何时检索
agent = create_react_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 用户:"你好" → Agent 不检索,直接回答
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

✅ Agent + RAG 的优势

  • 智能路由:简单问题不检索,省 Token、降延迟
  • 多轮检索:复杂问题可以多次检索不同关键词
  • 结果验证:Agent 可以判断检索结果是否相关,不相关则换关键词重搜
  • 引用来源:Agent 可以在回答中标注"根据 [文档名] ..."

# 16.6 生产级 RAG 架构

🏭 企业级 RAG 系统架构 文档加载器(PDF/Word/HTML/Confluence)→ 文档清洗 → 元数据提取 分块 → 向量化 → 写入向量数据库(增量更新、版本管理) Query 改写 → 混合检索(BM25 + 向量)→ 重排序 → 上下文组装 Prompt 模板 → LLM 生成 → 回答后处理(去幻觉、加引用) 检索准确率、回答忠实度、用户反馈 → 持续优化

# 16.7 GraphRAG:知识图谱增强检索

传统向量 RAG 有一个致命弱点:只能检索局部相似片段,无法回答全局性问题。比如"整个系统架构包含哪些模块?"这样的问题需要跨文档、跨段落的全局视角。GraphRAG 通过构建知识图谱,让 RAG 具备"关联推理"的能力。

流程图

RAG 核心流程:用户查询 -> 向量化 -> 向量检索(Top-K)-> 合并上下文 -> LLM 生成 -> 最终回答

文档处理流程:文档加载 -> 文档切分 -> 向量化 -> 存入向量数据库

# 16.7.1 GraphRAG 的四步流程

from llama_index.core.graph_stores import SimpleGraphStore
from llama_index.llms.openai import OpenAI

# 1. 实体抽取 + 关系构建(LLM 自动完成)
llm = OpenAI(model="gpt-4o-mini")

# KnowledgeGraphIndex 自动从文档中抽取实体和关系
kg_index = KnowledgeGraphIndex.from_documents(
    documents,
    llm=llm,
    max_triplets_per_chunk=5,  # 每个块最多抽取 5 个三元组
    include_embeddings=True     # 同时生成实体嵌入
)

# 抽取的三元组示例:
# ("RAG", "属于", "检索增强生成技术")
# ("向量数据库", "用于", "RAG")
# ("Agent", "调用", "RAG")

# 2. 子图检索:从问题实体出发,沿关系边遍历
query_engine = kg_index.as_query_engine(
    include_text=True,     # 同时返回原文片段
    similarity_top_k=5,    # 返回 Top-5 相关子图
    graph_depth=2          # 图遍历深度 2 跳
)

# 3. 生成回答时,上下文 = 子图结构 + 原文片段
response = query_engine.query("Agent 和 RAG 是什么关系?")
# → 沿 "Agent" → "调用" → "RAG" → "属于" → "检索增强生成技术" 遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 16.7.2 GraphRAG vs 向量 RAG:什么时候用什么?

对比维度 向量 RAG GraphRAG
检索方式 语义相似度搜索 实体关系图遍历
擅长问题 事实性问答("X 是什么?") 关联性问答("X 和 Y 什么关系?")
全局视角 ❌ 只看局部相似片段 ✅ 跨文档关联推理
多跳推理 ❌ 最多 1 跳(检索到的片段) ✅ 多跳图遍历(A→B→C→D)
构建成本 低(分块 + Embedding) 高(LLM 抽取实体关系)
更新成本 低(增量加向量) 中(需更新图谱边)
延迟 毫秒级 百毫秒~秒级
最佳实践 混合使用:向量 RAG 做日常问答,GraphRAG 做复杂关联分析

⚠️ GraphRAG 的代价

  • 构建成本高:需要用 LLM 从每篇文档中抽取实体和关系,Token 消耗大
  • 维护复杂:文档更新时需要同步更新图谱结构,比加向量复杂得多
  • 实体歧义:"苹果"是公司还是水果?需要实体消歧(Entity Disambiguation)
  • 不适合简单问答:杀鸡用牛刀,"RAG 是什么"用向量检索就够了

✅ GraphRAG 的黄金场景

  • 多跳推理问答:"A 公司的 CEO 毕业于哪所大学?" → 需要跨文档追溯
  • 关系分析:"这个故障影响了哪些下游服务?" → 微服务依赖图
  • 全局摘要:"整个系统架构包含哪些模块?" → 需要全局视角
  • 因果追溯:"为什么这个指标下降了?" → 因果链路遍历

# 16.8 Agentic RAG:Agent 驱动的自适应检索

传统 RAG 是一个固定流水线:用户提问 → 检索 → 拼接上下文 → LLM 生成。无论问题难易,流程都一样。但这不合理——有些问题不需要检索,有些需要检索多次,有些需要先检索再反思再检索。Agentic RAG 把 Agent 引入检索循环,让 Agent 动态决策是否检索、检索几次、何时停止。

💡 Agentic RAG 的核心思想 不再是一条固定的"检索→生成"流水线,而是让 Agent 作为检索编排者,根据问题难度动态决定检索策略:简单问题直接回答,复杂问题多轮检索+反思,检索不充分则换角度重搜,直到信息充分才生成最终回答。

# 16.8.1 传统 RAG vs Agentic RAG

🔴 传统 RAG Pipeline

  • 固定流程:Query → Retrieve → Generate
  • 每次提问都检索,不管是否需要
  • 只检索一次,不管结果够不够
  • 检索结果直接拼接,不做质量判断
  • 无法根据结果调整检索策略

🟢 Agentic RAG

  • 动态流程:Agent 自主决策每一步
  • 判断是否需要检索(简单问题跳过)
  • 支持多轮检索,直到信息充分
  • 每次检索后反思:结果是否相关?
  • 可以改写 Query 换角度重新检索

# 16.8.2 Agentic RAG 的核心循环

from typing import TypedDict, List

class RAGState(TypedDict):
    question: str
    retrieved_docs: List[str]
    answer: str
    reflection: str       # 反思结果
    search_count: int     # 检索次数
    sufficient: bool      # 信息是否充分

def decide_to_search(state: RAGState) -> str:
    """Agent 决策:是否需要检索"""
    question = state["question"]
    # 简单问题不检索(如打招呼、算术题)
    if is_simple_question(question):
        return "generate_direct"
    # 已有文档是否充分?
    if state.get("sufficient", False):
        return "generate"
    # 最多检索 3 轮,防止死循环
    if state.get("search_count", 0) >= 3:
        return "generate"
    return "search"

def search(state: RAGState) -> RAGState:
    """执行检索:Query 改写 + 混合检索 + 重排序"""
    question = state["question"]
    count = state.get("search_count", 0)
    
    # 第 2 轮起,根据反思结果改写 Query
    if count > 0:
        question = llm_rewrite_query(question, state.get("reflection", ""))
    
    docs = hybrid_search(question, top_k=10)
    ranked_docs = reranker.rerank(docs, question, top_n=5)
    
    state["retrieved_docs"] = state.get("retrieved_docs", []) + ranked_docs
    state["search_count"] = count + 1
    return state

def reflect(state: RAGState) -> RAGState:
    """反思:检索结果是否足以回答问题?"""
    prompt = f"""问题:{state['question']}
已有文档:{state['retrieved_docs']}
判断:当前文档是否足以完整回答问题?
如果不足,指出缺少什么信息。"""
    result = llm.invoke(prompt)
    state["reflection"] = result
    state["sufficient"] = "信息充分" in result
    return state

def generate(state: RAGState) -> RAGState:
    """生成最终回答"""
    context = "\n\n".join(state["retrieved_docs"])
    state["answer"] = llm.invoke(f"基于以下信息回答问题:\n{context}\n\n问题:{state['question']}")
    return state

# 构建工作流图
workflow = StateGraph(RAGState)
workflow.add_node("decide", decide_to_search)
workflow.add_node("search", search)
workflow.add_node("reflect", reflect)
workflow.add_node("generate", generate)

workflow.set_entry_point("decide")
workflow.add_conditional_edges("decide", decide_to_search, {
    "search": "search",
    "generate": "generate",
    "generate_direct": "generate"
})
workflow.add_edge("search", "reflect")
workflow.add_conditional_edges("reflect", lambda s: "search" if not s["sufficient"] and s["search_count"] < 3 else "generate")
workflow.add_edge("generate", END)

agent_rag = workflow.compile()

# 用户:"你好" → decide 判断简单问题 → 直接生成
# 用户:"我们系统的限流策略和降级策略分别是什么?" →
#   第1轮检索限流策略 → 反思:缺少降级策略 →
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

# 16.8.3 Agentic RAG 什么时候触发检索?

这是面试高频追问点。Agent 通过以下信号判断是否触发检索:

触发信号 说明 示例
问题类型判断 事实性问题 → 检索;闲聊/算术 → 跳过 "今天天气" → 检索;"1+1" → 跳过
知识边界检测 问题涉及模型训练截止后的信息 → 检索 "2025年新发布模型" → 检索
领域关键词匹配 问题包含企业专有名词 → 检索内部知识库 "我们的SLA策略" → 检索
反思触发再检索 已有文档不足以回答 → 改写Query重搜 第1轮只有限流,缺降级 → 第2轮搜降级
用户显式要求 用户要求查证或引用来源 → 检索 "帮我查一下文档" → 检索

📊 Agentic RAG 的关键设计:防止死循环

  • 最大检索次数限制:通常设 3 轮,超过则用已有信息生成(宁可答案不完美,也不能死循环)
  • 反思质量评估:反思模型判断信息充分性,避免无意义的重复检索
  • Query 改写递进:每轮检索改写 Query,避免相同查询返回相同结果
  • 成本控制:每轮检索消耗 Token,Agent 需要在质量和成本间权衡

🔥 2026 面试视角:Agentic RAG vs 传统 RAG

📋 八股总结 — 面试高频考点

Q:Q1: RAG 的原理是什么?和微调有什么区别?

RAG 原理:在生成回答前,先从外部知识库检索相关文档,将检索结果作为上下文喂给 LLM 生成回答。

与微调的区别:RAG 是"外挂知识库",不改模型参数,知识实时更新,成本低;微调是"内化知识",修改模型参数,适合定制风格/格式,成本高。最佳实践是两者结合:微调改善输出风格,RAG 提供最新知识。

Q:Q2: 向量数据库和传统数据库有什么区别?

传统数据库做精确匹配(WHERE id=123),向量数据库做相似度搜索(找到最接近的 K 个向量)。向量数据库使用 ANN(近似最近邻)算法索引,如 HNSW、IVF,能在百万级向量中毫秒返回结果。主流方案:Chroma(原型)、Pinecone(云托管)、Milvus(大规模自部署)、pgvector(PostgreSQL 插件)。

Q:Q3: 什么是混合检索?为什么要做重排序?

混合检索:BM25(关键词匹配)+ 向量检索(语义匹配)加权融合。BM25 擅长精确关键词(如"GPT-4o"),向量擅长语义(如"大语言模型")。

重排序:向量检索召回快但精度有限,用 Cross-Encoder 对候选集逐一精细打分。两阶段:先快召回 Top-50(毫秒级),再精排序 Top-5(百毫秒级),兼顾速度和精度。

Q:Q4: RAG 系统如何评估?

从两个阶段评估:

检索质量:召回率(相关文档是否被检索到)、精确率(检索结果中有多少相关)、MRR(平均倒数排名)。

生成质量:忠实度(回答是否基于检索内容,有没有幻觉)、相关性(回答是否切题)、完整性(是否覆盖了用户问题的所有方面)。可用 Ragas 框架自动化评估。

Q:Q5: 如何解决 RAG 检索不到相关文档的问题?

① Query 改写:用 LLM 改写用户问题,生成多个角度的查询并行检索;

② HyDE:先让 LLM 生成假回答,用假回答去检索(语义更丰富);

③ 调整分块策略:chunk_size 太大不精确,太小语义不完整,尝试 512-1024;

④ 混合检索:加入 BM25 关键词检索,弥补向量检索关键词匹配弱的缺陷;

⑤ 增加召回量:先召回 Top-20,再用 Reranker 精选 Top-5。

Q:Q6: RAG 检索出的内容相互冲突,Agent 该怎么取舍?

企业知识库文档版本多、来源杂,冲突是常态。三种策略:

① 元数据加权排序:根据文档的发布时间、权威等级赋予不同权重,优先采信高权威 + 最新的内容。时间维度和权威维度双重保障。

② 多智能体辩论(Multi-Agent Debate):让不同 Agent 分别对应冲突的文档内容,相互对比论证,梳理出矛盾点,筛选出逻辑最通顺的答案。用"辩论"机制替代"单点裁决"。

③ 强制溯源:要求 Agent 输出答案必须附带检索来源,方便用户最终校验核对。把最终裁决权交给人类。

面试要点:不能只说"取最新的",要展示元数据加权+多Agent辩论+溯源三重保障的组合思维。

Q:Q7: 企业 RAG 怎么解决权限隔离问题?会不会泄露涉密数据?

这是企业落地 RAG 的硬性安全要求,面试高频追问。我的解决方案是RAG权限对齐:

存入阶段:在向量数据库存入数据时,给每一条向量绑定对应的访问控制权限元数据(如部门、角色、保密等级)。

检索阶段:用户发起检索请求时,系统自动带入当前用户的身份权限做过滤。

关键点:不是在"结果返回后"做过滤(可能已泄露敏感信息到上下文),而是在向量检索的源头就完成数据隔离。从根本上杜绝普通用户查到高管敏感数据的问题。

面试要点:强调"源头过滤"而非"事后过滤",体现对数据安全闭环的理解。

Q:Q8: 面对新闻/股价等实时更新知识库,RAG 怎么适配?

实时性是 RAG 落地的关键挑战。三种机制:

① 动态路由 Agent:先判断用户问题是否需要实时数据。需要实时 → 优先调用搜索/实时 API,不检索静态向量库;不需要 → 正常走向量库检索。类似"先思考再行动"的智能分发。

② 流式增量更新:通过消息队列监听知识库的实时变动,动态新增/更新向量数据,不用全量重构。增量更新效率高。

③ 缓存失效机制:给高频问题设置缓存时效,元数据更新后立刻清空旧缓存,保存答案的时效性,避免返回过期信息。

面试要点:三机制覆盖"判断要不要实时"(路由)、"怎么更新"(增量)、"怎么保证不过期"(缓存失效),体现全链路思维。

Q:Q9: 怎么系统提升 RAG 问答准确率?三层体系是什么?

这是最综合的一道题,需要展示"从解析到检索到生成全链路"的完整体系思维:

第一层:深度解析层——解决文档拆分错乱

传统按字符切分会打断表格/标题/正文的关联。我用布局感知解析模型,把文档识别成标题、正文、表格、列表等完整模块,按标题层级切块,保证每一段内容语义完整不会断裂。核心思路:先理解文档结构,再按结构切。

第二层:检索增强层——多阶段精准检索

① 向量检索 + BM25 关键词检索混合模式:兼顾语义匹配和专有名词匹配。单一向量检索会丢掉精确关键词匹配能力。

② 重排序模型对初筛内容精排:这是提升准确率性价比最高的操作。初筛粗选 → 精排精选,二次提纯。

③ 扩展 Query 生成多个同义问题并行检索:解决用户提问太简短、信息不全的问题。一个问题变成多个角度同时检索。

第三层:生成校验层——实现自我纠错

答案生成前,Agent 做两次自检:

第一检:判断检索内容是否足够回答问题 → 不足就重新检索。

第二检:核对答案内容是否全部来自检索结果 → 杜绝无依据的幻觉输出。

面试要点:三层体系覆盖解析(输入端)、检索(中间端)、生成(输出端),体现全链路精度提升而非单点优化。

Q:Q10: GraphRAG 和向量 RAG 的区别是什么?各自适合什么场景?

核心区别在检索方式:向量 RAG 做语义相似度搜索,检索的是"像"的文本块;GraphRAG 从文档中抽取实体和关系构建知识图谱,检索时做图遍历,找到的是"有关联"的信息。

向量 RAG 擅长:事实性问答("RAG 是什么?"),单点查询,毫秒级响应,构建成本低。

GraphRAG 擅长:多跳推理("A 公司 CEO 毕业于哪所大学?"需要跨文档追溯),关系分析("这个故障影响哪些下游服务?"),全局摘要,跨文档关联。

GraphRAG 的代价:构建成本高(LLM 抽取实体关系消耗大量 Token),维护复杂(文档更新需同步更新图谱),有实体歧义问题("苹果"是公司还是水果)。

最佳实践:混合使用。向量 RAG 做日常问答(90% 场景),GraphRAG 做复杂关联分析(10% 场景)。面试要点是展示"不是 GraphRAG 替代向量 RAG,而是互补"的思维。

Q:Q11: Agentic RAG 什么时候触发检索?和传统 RAG pipeline 有什么本质区别?

本质区别:传统 RAG 是固定流水线(Query → Retrieve → Generate),每次提问都检索且只检索一次;Agentic RAG 引入 Agent 做动态决策,具备三个传统 RAG 没有的能力:

① 决策能力(是否检索):Agent 判断问题类型——简单问题("你好"、"1+1")直接回答不检索,事实性问题才触发检索。触发信号包括:问题类型判断、知识边界检测(超出训练数据)、领域关键词匹配、用户显式要求。

② 反思能力(够不够):每轮检索后,Agent 评估已有文档是否足以完整回答问题。不足则指出缺什么,触发再检索。

③ 迭代能力(换角度重搜):根据反思结果改写 Query,换角度重新检索。比如第 1 轮搜"限流策略",反思发现还缺"降级策略",第 2 轮改搜"降级策略"。

防止死循环:设最大检索次数(通常 3 轮),超过则用已有信息生成。面试要点:强调"决策+反思+迭代"三重能力,这是从"工具"升级为"智能体"的关键。

# 课后练习

# 第 1 题(单选)

RAG 的核心思想是什么?

A. 把知识微调进模型参数 B. 在生成回答前先从外部知识库检索相关文档,作为上下文喂给 LLM C. 用更大的模型来提升回答质量 D. 把所有文档都放进 Prompt

答案与解析

答案:B

RAG = Retrieval-Augmented Generation,先检索再生成。不改模型参数,知识实时更新。

# 第 2 题(单选)

向量数据库检索使用什么算法?

A. B-Tree 索引 B. 哈希索引 C. 近似最近邻搜索(ANN) D. 全文倒排索引

答案与解析

答案:C

向量数据库使用 ANN(Approximate Nearest Neighbor)算法,如 HNSW、IVF,在百万级向量中毫秒返回结果。

# 第 3 题(多选)

以下哪些是 RAG 相比纯 LLM 的优势?(多选)

A. 知识可以实时更新 B. 回答可以引用来源 C. 完全消除幻觉 D. 无需重新训练模型

答案与解析

答案:A, B, D

RAG 减少幻觉但不能完全消除。其他三项都是 RAG 的优势。

# 第 4 题(单选)

混合检索(BM25 + 向量检索)的优势是?

A. 运行速度更快 B. 同时具备关键词精准匹配和语义匹配能力 C. 减少 Token 消耗 D. 不需要 Embedding 模型

答案与解析

答案:B

BM25 擅长精确关键词匹配(如

# 第 5 题(单选)

重排序(Reranker)的作用是?

A. 加快检索速度 B. 对召回的候选集做精细打分,提高检索精度 C. 减少向量维度 D. 压缩文档大小

答案与解析

答案:B

两阶段检索:先快召回 Top-50,再用 Cross-Encoder 精排 Top-5。Reranker 精度高但慢,只用于小规模候选集。

# 第 6 题(多选)

RAG 高级优化技巧包括?(多选)

A. Query 改写(生成多个角度的查询) B. HyDE(用假回答去检索) C. 父子分块(小块检索、大块生成) D. 增加 LLM 参数量

答案与解析

答案:A, B, C

Query改写、HyDE、父子分块都是 RAG 优化技巧。增加 LLM 参数量与 RAG 优化无关。

# 第 7 题(单选)

在 Agent + RAG 架构中,Agent 的作用是?

A. 替代 LLM 生成回答 B. 自主决定何时检索、检索什么、是否需要重新检索 C. 替代向量数据库存储文档 D. 提高 Embedding 速度

答案与解析

答案:B

Agent 将 RAG 作为工具使用,自主判断:简单问题不检索,复杂问题多轮检索,检索结果不相关则换关键词重搜。

# 第 8 题(单选)

文档分块时 chunk_overlap 的作用是?

A. 减少存储空间 B. 保持块间上下文连贯,避免在句子中间截断丢失语义 C. 加快检索速度 D. 提高 Embedding 质量

答案与解析

答案:B

chunk_overlap 让相邻块有重叠部分,保持上下文连贯。经验值是 chunk_size 的 10-15%。

# 第 9 题(单选)

GraphRAG 相比向量 RAG 的核心优势是什么?

A. 检索速度更快 B. 支持多跳推理和跨文档关联分析 C. 构建成本更低 D. 不需要 LLM 参与

答案与解析

答案:B

GraphRAG 通过知识图谱的实体关系遍历,支持多跳推理(A→B→C→D)和跨文档关联分析,这是向量 RAG 做不到的。但 GraphRAG 构建成本更高、速度更慢。

# 第 10 题(单选)

Agentic RAG 中,Agent 什么时候决定不检索?

A. 问题包含关键词时 B. 简单问题如闲聊或算术题,或已有文档信息充分时 C. 每次提问都不检索 D. 用户没有明确要求时

答案与解析

答案:B

Agent 通过问题类型判断(闲聊/算术跳过)、知识边界检测、信息充分性评估来决定是否检索。简单问题直接回答,已有文档充分也不再检索。

# 第 11 题(多选)

Agentic RAG 防止死循环的关键设计包括哪些?(多选)

A. 最大检索次数限制(通常 3 轮) B. 每轮检索后反思评估信息充分性 C. 每轮改写 Query 避免重复结果 D. 使用更大的 LLM 模型

答案与解析

答案:A, B, C

防止死循环三要素:最大检索次数限制(硬兜底)、反思评估(避免无意义重复)、Query 改写递进(避免相同查询返回相同结果)。使用更大模型与防死循环无关。

# 第 12 题(单选)

以下哪个场景最适合用 GraphRAG 而非向量 RAG?

A. RAG 是什么? B. ,

C. 我们系统中 A 服务的故障影响了哪些下游服务? D. ,

E. 今天天气怎么样? F. ,

G. 帮我总结这篇文章

答案与解析

答案:B

关系分析需要遍历服务依赖图(A→B→C),是 GraphRAG 的黄金场景。事实性问答、实时查询、单文档摘要用向量 RAG 即可。