Skip to content

02.2 — RAG 与长期记忆

定位: Agent 长期记忆的核心实现技术——深入理解 RAG 如何在 Agent 中发挥作用,以及如何将 RAG 与 Agent 深度集成 面试高频度: ⭐⭐⭐⭐⭐ 考查方式: 设计题(为 Agent 设计 RAG 系统)、对比题(RAG vs 微调)、机制题(RAG 检索流程和各组件优化)


一、这是什么?为什么需要它?

是什么

RAG(Retrieval-Augmented Generation,检索增强生成) 是一种在 LLM 生成回答前先从外部知识库检索相关信息的架构模式。在 Agent 中,RAG 是长期记忆的主要实现方式。

为什么需要 RAG?

❌ 没有 RAG 的 Agent(纯 LLM):
  知识截止于训练数据
  无法访问私有/实时数据
  "幻觉"无法被事实纠正
  每次都要把全部知识写入 prompt

✅ 有 RAG 的 Agent:
  可以访问最新的外部知识
  可以查询私有文档/数据库
  用检索到的事实约束生成,减少幻觉
  只注入相关信息,节省 token

核心洞察:RAG 就是给 Agent 装了一个"图书馆"——LLM 不需要记住所有知识,它只需要知道怎么去图书馆查资料。

RAG 在记忆系统中的位置

Agent 记忆层次中的 RAG:

  ┌─ 短期记忆 ───────────────────┐
  │ In-context (messages 数组)    │  ← 会话中的"刚刚"
  └──────────────────────────────┘
  ┌─ 长期记忆 ───────────────────┐
  │ RAG(向量检索 + 知识库)      │  ← 会话间的"记得"
  └──────────────────────────────┘
  ┌─ 模型参数 ───────────────────┐
  │ 预训练知识 / 微调             │  ← 模型"天生"知道的
  └──────────────────────────────┘

二、原理拆解

2.1 RAG 的标准流程

┌──────────────────────────────────────────────────────────┐
│                   RAG 核心流程                             │
│                                                          │
│  用户查询                                                  │
│     │                                                    │
│     ▼                                                    │
│  ┌──────────┐                                            │
│  │  1. 查询  │  "什么是 ReAct 模式?"                     │
│  │  Query   │                                            │
│  └────┬─────┘                                            │
│       │                                                  │
│       ▼                                                  │
│  ┌──────────┐    ┌──────────────────┐                    │
│  │  2. 编码  │───→│ 查询向量化        │                    │
│  │  Embed   │    │ [0.12, 0.87, ...]│                    │
│  └────┬─────┘    └──────────────────┘                    │
│       │                                                  │
│       ▼                                                  │
│  ┌──────────┐    ┌──────────────────┐                    │
│  │  3. 检索  │───→│ 向量相似度搜索    │                    │
│  │ Retrieve │    │ 找到 Top-K 匹配   │                    │
│  └────┬─────┘    └──────────────────┘                    │
│       │                                                  │
│       ▼                                                  │
│  ┌──────────┐    ┌──────────────────┐                    │
│  │  4. 增强  │───→│ 将检索结果注入     │                    │
│  │ Augment  │    │ prompt            │                    │
│  └────┬─────┘    └──────────────────┘                    │
│       │                                                  │
│       ▼                                                  │
│  ┌──────────┐                                            │
│  │  5. 生成  │  结合检索内容的回答                          │
│  │ Generate │  "ReAct 模式是一种..."                      │
│  └──────────┘                                            │
│                                                          │
└──────────────────────────────────────────────────────────┘

2.2 RAG 各组件详解

① 文档嵌入(Embedding)

组件说明常见方案
Embedding Model将文本转为向量text-embedding-3-small, bge-large
向量维度向量长度,影响精度和存储384/768/1536 维
分块策略如何切分文档固定大小、语义分块、递归分块
元数据附带的标量信息来源、时间、类型、权限

为什么分块大小很重要?

分块太小 (64 tokens) → 上下文不完整,检索不准确
分块合适 (256-512 tokens) → 语义完整,检索精确
分块太大 (2048+ tokens) → 噪音多,命中率低

② 检索策略

策略工作原理适用场景
向量检索余弦相似度/欧几里得距离语义搜索,通用场景
关键词检索BM25/TF-IDF精确匹配,专有名词
混合检索向量 + 关键词加权融合最佳实践——兼顾语义和精确
HyDE先生成假设文档再检索查询和文档语义差距大时
混合检索的权重策略:
  最终得分 = α × 向量相似度 + (1-α) × BM25 得分
  
  α = 0.7 → 偏向语义理解
  α = 0.3 → 偏向关键词匹配
  通常 α=0.5 是安全起点

③ 检索结果增强

python
# RAG 中如何将检索结果注入 prompt
def build_rag_prompt(query: str, retrieved_docs: list) -> str:
    context = "\n\n---\n\n".join([
        f"[来源 {i+1}]: {doc['content']}" 
        for i, doc in enumerate(retrieved_docs)
    ])
    
    prompt = f"""基于以下参考资料回答问题。

参考资料:
{context}

问题: {query}

要求:
1. 优先使用参考资料中的信息
2. 如果参考资料不足以回答问题,明确说明
3. 注明信息来源于哪个参考资料"""
    
    return prompt

2.3 RAG 在 Agent 中的深度集成

Agent 中的 RAG 比标准 RAG 更复杂,因为 Agent 需要动态决定何时检索、检索什么

┌─────────────────────────────────────────────────────────┐
│           Agent + RAG 深度集成架构                        │
│                                                         │
│  Agent 循环                                              │
│  ┌────────────┐                                         │
│  │  感知      │                                         │
│  │  用户问题  │                                         │
│  └─────┬──────┘                                         │
│        │  Agent 自主决定是否需要检索                      │
│        ▼                                                 │
│  ┌────────────┐    ┌──────────────┐                     │
│  │  思考      │───→│ 需要更多信息? │                     │
│  │  推理      │    │  ┌───┐ ┌──┐  │                     │
│  └─────┬──────┘    │  │是│ │否│  │                     │
│        │           └──┼───┼──┼──┘                     │
│        ▼              │   │  │                          │
│  ┌────────────┐       │   │  │                          │
│  │  检索行动  │←──────┘   │  │                          │
│  │  search()  │           │  │                          │
│  └─────┬──────┘           │  │                          │
│        │ 文档返回          │  │                          │
│        ▼                   ▼  ▼                          │
│  ┌────────────┐                                         │
│  │  观察      │  融合检索结果继续推理                    │
│  │  分析文档  │                                         │
│  └────────────┘                                         │
└─────────────────────────────────────────────────────────┘
python
# Agent 自主决定检索的 RAG 实现
class AgentRAG:
    def __init__(self, knowledge_base: VectorStore):
        self.kb = knowledge_base
        
    def decide_to_retrieve(self, query: str, context: str) -> bool:
        """让 LLM 自主判断是否需要检索"""
        prompt = f"""当前任务: {query}
已有上下文: {context}
是否需要搜索知识库来获取更多信息?回答 YES 或 NO。"""
        decision = llm.call(prompt)
        return "YES" in decision.upper()
    
    def run(self, user_query: str):
        messages = [{"role": "user", "content": user_query}]
        
        while True:
            # Agent 思考:需要检索吗?
            if self.decide_to_retrieve(user_query, str(messages)):
                # 执行检索(作为工具调用)
                query = llm.call(f"为检索生成搜索查询:{user_query}")
                docs = self.kb.similarity_search(query, k=3)
                
                messages.append({
                    "role": "system",
                    "content": f"【检索结果】\n{docs}"
                })
            
            # LLM 生成回答
            response = llm.call(messages)
            
            if response.has_tool_call:
                # 执行其他工具...
                continue
            
            return response.content

2.4 RAG vs 微调

这是面试中的经典对比问题:

维度RAG微调 (Fine-tuning)
知识更新即时——只需更新索引慢——需要重新训练
成本低(检索 + 生成)高(训练 + 部署)
幻觉控制好——用外部事实约束差——模型可能"创造"
长尾知识好——可以索引任意知识差——难以覆盖所有
推理能力保持 LLM 原有能力可能降低(灾难性遗忘)
实时性高——可以搜最新数据低——训练数据截止
适用场景知识问答、文档分析风格迁移、指令遵循
选择指南:
  需要访问最新/私有数据 → RAG
  需要模型改变行为/风格 → 微调
  两者兼顾 → RAG + 微调(最佳实践)

三、图解全景

┌──────────────────────────────────────────────────────────┐
│           Agent 中 RAG 的完整工作流程                      │
│                                                          │
│  数据准备阶段 (离线)                                      │
│  ┌─────────┐    ┌────────┐    ┌──────────┐              │
│  │ 文档源   │───→│ 分块   │───→│ 向量化    │              │
│  │ PDF/Wiki │    │ 策略   │    │ Embedding│              │
│  └─────────┘    └────────┘    └─────┬────┘              │
│                                     │                    │
│                                     ▼                    │
│                              ┌──────────┐               │
│                              │ 向量数据库 │               │
│                              │ Index    │               │
│                              └──────────┘               │
│                                                          │
│  推理阶段 (在线)                                          │
│  ┌─────────┐    ┌────────┐    ┌──────────┐              │
│  │ Agent   │───→│ 检索触发│───→│ 查询向量化│              │
│  │ 决策    │    │ 工具调用│    │          │              │
│  └─────────┘    └────────┘    └─────┬────┘              │
│                                     │                    │
│  ┌─────────┐    ┌────────┐         │                    │
│  │ LLM生成 │←───│ 注入   │←────────┘                    │
│  │ 最终回答│    │ Prompt │                                │
│  └─────────┘    └────────┘                                │
└──────────────────────────────────────────────────────────┘

四、实战验证

4.1 用 LangChain 实现 Agent RAG

python
# 一个完整的 Agent + RAG 示例
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import OpenAIEmbeddings
from langchain.agents import AgentExecutor, create_react_agent
from langchain.tools import Tool

# 1. 准备知识库
embeddings = OpenAIEmbeddings()
vectorstore = Chroma(
    persist_directory="./agent_knowledge",
    embedding_function=embeddings
)

# 2. 创建检索工具
def search_knowledge(query: str) -> str:
    """从知识库中检索相关信息"""
    docs = vectorstore.similarity_search(query, k=3)
    return "\n".join([d.page_content for d in docs])

tools = [
    Tool(
        name="search_knowledge",
        func=search_knowledge,
        description="搜索知识库获取相关信息"
    ),
    # 其他 Agent 工具...
]

# 3. 创建 ReAct Agent(自动在需要时检索)
agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(
    agent=agent, 
    tools=tools,
    verbose=True,
    max_iterations=5
)

# 4. 运行
result = agent_executor.invoke({
    "input": "解释 ReAct 模式并给出一个例子"
})
print(result["output"])

4.2 RAG 质量评估

bash
# RAG 系统的关键指标

# 1. 检索准确率 (Retrieval Precision)
#   检索到的文档中,真正相关的比例
#   目标: > 80%

# 2. 检索召回率 (Retrieval Recall)
#   所有相关文档中,被检索到的比例  
#   目标: > 70%

# 3. 生成准确率 (Generation Accuracy)
#   基于检索结果生成的回答是否正确
#   目标: > 90%

# 4. 端到端延迟
#   检索 + 生成的总耗时
#   目标: < 3s

# 优化的关键是"检索质量"——检索不对,生成一定不对。
# 检索质量 = f(分块策略, 嵌入模型, 检索算法, 重排序)

4.3 体验 Agent RAG 的效果

bash
# 对比测试:纯 LLM vs Agent + RAG

# 场景:询问最新的 Python 3.12 特性

# 纯 LLM:
# "Python 3.12 引入了..."
# → 可能准确,可能过时,可能幻觉

# Agent + RAG:
# Agent: "我需要搜索 Python 3.12 的官方文档"
# → search_knowledge("Python 3.12 new features")
# → 从索引的官方文档中检索
# → "根据 Python 3.12 官方文档..."
# → 有来源、更准确、更新

五、面试视角

追问答案要点
RAG 在 Agent 中扮演什么角色?长期记忆的实现技术。为 Agent 提供外部知识访问能力,解决知识截止、幻觉、私有数据访问三大问题
RAG 的核心流程是什么?各组件如何优化?Query → Embed → Retrieve → Augment → Generate。优化点:分块策略(256-512 tokens)、检索策略(混合检索 BM25+向量)、重排序(reranker)
Agent 中 RAG 和标准 RAG 的区别?标准 RAG:每次必检索。Agent RAG:Agent 自主决定何时检索、可以多次检索、检索是工具调用之一、结果可以被 Agent 进一步分析再用
RAG 如何解决"检索不准确"的问题?多查询扩展(生成多个搜索词)、HyDE(先假设再检索)、重排序(初检+精排)、混合检索(语义+关键词互补)
RAG vs 微调,什么场景选哪个?RAG 适合知识密集、需要更新、长尾知识的场景。微调适合行为改变、风格迁移。最佳实践是 RAG + 微调互补使用
Agent 中 RAG 的挑战是什么?检索时机(什么时候该检索)、检索内容(生成好的搜索查询)、结果融合(检索结果多怎么办)、成本(每次检索都有 embedding 和存储成本)

📚 相关链接

  • **记忆分类与架构** — 记忆类型的基础
  • **记忆管理与检索** — 记忆的检索和更新策略
  • **Agent 架构模式** — Agent 如何调用检索工具
  • **RAG 知识库** — RAG 技术的全面深入
  • ← 返回 **Agent记忆系统索引**

Knowledge4J — Java 知识库