十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

RAG、Memory与Agent:大模型应用三层架构实战指南

RAG、Memory与Agent:大模型应用三层架构实战指南 很多同学在做大模型应用的时候常常会被这三个概念绕晕RAG、Memory、Agent。团队里讨论方案有人说用 RAG 做知识库有人说要加 Memory 才能让对话连贯还有人直接说上 Agent 就全解决了。结果一圈讨论下来代码一行没写方案已经改了三次。这篇文章就围绕一个核心问题展开RAG、Memory、Agent 到底分别解决什么问题它们是不是非此即彼的关系落到实际项目里应该怎么选、怎么结合文章会先从概念入手把三者的边界讲清楚然后用一份完整的代码示例演示“RAG Memory Agent”怎么在一个项目里协同工作最后给出选型建议、常见坑点和工程落地经验。适合正在做 RAG 知识库、AI Agent 开发、或者准备把大模型接入业务系统的开发者阅读。1. 背景与核心概念在正式写代码之前先把三个概念放在同一个坐标系里看待。很多人会误以为 RAG、Memory、Agent 是三个并列的技术方案选了 A 就不用 B。实际上它们属于不同层次的能力模块面对的是不同的问题。1.1 RAG 解决的是“模型不知道”的问题RAG 的全称是 Retrieval-Augmented Generation检索增强生成。它的核心思路很简单大模型的知识是训练时固化的无法覆盖你业务里的私有数据。RAG 先把外部文档切片、向量化建立索引等用户提问时先从知识库中检索出相关片段再把片段和问题一起交给大模型生成答案。用一句话概括RAG 是给大模型装了一个“外部知识库”。RAG 适合的场景非常明确企业内部的规章制度、产品手册、维修文档问答。基于私有 PDF、Word、网页内容构建问答系统。实时性要求高、需要引用来源的信息查询。工程上RAG 有四个关键环节也是后续容易出现问题的四个环节文档加载与解析、文本切块、向量化与存储、检索与重排。1.2 Memory 解决的是“模型记不住”的问题大模型本身是无状态的。你上一轮问了“北京明天天气怎么样”下一轮问“那后天呢”如果模型不记得“那”指代的是“北京”回答就会跑偏。Memory 模块的作用就是让 Agent 或对话系统具备“记忆能力”。它通常分为三类记忆类型类比典型实现短期记忆临时记住当前对话上下文把最近几轮对话拼进 Prompt长期记忆跨会话记住用户偏好和历史事实存入数据库按用户 ID 读取工作记忆任务执行过程中临时保存中间状态Agent 执行计划时维护状态变量注意Memory 和 RAG 有一个容易混淆的点两者都要“存取数据”。区别在于Memory 存的是“关于用户、对话、任务状态”的信息RAG 存的是“领域知识、文档内容”。1.3 Agent 解决的是“模型不会做”的问题如果说 RAG 是让模型“知道得更多”Memory 是让模型“记得住”那么 Agent 是让模型“动起来”。Agent 的核心是让大模型充当一个“大脑”通过推理来决定调用哪些工具、按什么顺序执行最终完成一个复杂任务。一个标准的 Agent 循环通常包含接收用户目标。推理并拆解任务生成计划。按计划调用工具搜索、计算、调 API、操作数据库等。观察工具返回结果判断是否继续或结束。输出最终答案。Agent 的出现解决的是“大模型只能生成文本不能完成操作”的问题。它把大模型从“问答机器”变成了“执行者”。1.4 三者不是三选一而是三层结构用一个生活化的例子来说明。你去医院看病导诊台Agent先问你的症状根据你的描述决定让你去内科还是外科医生翻看你之前的病历Memory遇到不确定的罕见病还会查阅医学指南和文献RAG。最终给出诊断和治疗方案。看到没有Agent、Memory、RAG 本来就在同一个系统里协同工作。这也引出了文章的核心观点选择不是“用 RAG 还是用 Agent”而是“这个环节需不需要检索、需不需要记忆、需不需要行为决策”。2. 环境准备与版本说明下面进入实战。本文的示例以一个“企业知识库问答 多轮对话记忆 Agent”为业务背景使用 Python LangChain 体系来实现。先说明一下环境。大模型技术栈更新非常快具体版本建议以你本机为准。本文示例基于以下环境你实际使用时需要根据版本差异调整参数组件说明操作系统Windows 10/11、macOS、Linux 均可Python3.9 及以上LangChain0.1.x 或 0.2.x接口有差异注意兼容向量数据库Chroma本地运行无需额外服务Embedding 模型使用 OpenAI 的 text-embedding-ada-002或本地 BGE/M3E 模型LLM以 OpenAI GPT 系列为例也可替换为 Qwen、DeepSeek 或本地 llama.cpp 部署的模型如果你在本地通过 llama.cpp Qwen2-7B 搭建过 RAG 知识库会发现核心流程没有区别只是 Embedding 和 LLM 的加载方式不同。2.1 安装依赖创建项目目录和虚拟环境mkdir rag-memory-agent-demo cd rag-memory-agent-demo python -m venv venv source venv/bin/activate # Windows 下执行 venv\Scripts\activate安装依赖pip install langchain langchain-openai langchain-community chromadb faiss-cpu python-dotenv说明一下langchain-openai是 LangChain 官方维护的 OpenAI 集成包。chromadb作为本地向量数据库零配置适合学习和原型验证。faiss-cpu是可选依赖如果你只用 Chroma 可以不装。python-dotenv用于管理环境变量。2.2 项目结构rag-memory-agent-demo/ ├── .env # 存放 API Key ├── data/ │ └── employee_handbook.md # 示例知识库文档 ├── rag_service.py # RAG 检索模块 ├── memory_service.py # 会话记忆模块 ├── agent_service.py # Agent 编排模块 └── main.py # 入口文件这个结构把 RAG、Memory、Agent 拆成三个独立模块方便你看清每一层做了什么。3. 核心原理拆解在把代码串起来之前先分别拆解三个模块的关键实现点。这样后面看完整代码时你能知道每一行是在做什么。3.1 RAG 检索流程的四个关键环节RAG 的实现并没有多玄妙核心就是“文档进、答案出”的四步流水线文档加载 → 文本切块 → 向量化入库 → 检索并生成文档加载从 PDF、Word、Markdown 等文件里提取纯文本。这一步的坑最多尤其是 PDF 里的表格、扫描件需要 OCR 或者专门的表格解析工具。对 Markdown 和纯文本来说直接读取即可。文本切块因为大模型有上下文窗口限制同时检索单位太大也会导致“检索到一大段无关内容”所以需要把长文本切成小块。切块策略直接影响检索效果。向量化入库把每个文本块通过 Embedding 模型转成向量存入向量数据库。这里的“语义相近的文本向量距离也近”是检索能工作的基础。检索并生成用户提问时把问题也向量化然后从库里找到最相似的 Top-K 个文本块拼进 Prompt 交给大模型。切块策略重点说一下。常见的切法有固定长度切块例如每 500 个字符切一块块与块之间重叠 50 字符。按结构切块例如 Markdown 标题、段落、句子边界。递归切块先按大单位切再对超长块按小单位切。在 LangChain 中推荐使用RecursiveCharacterTextSplitter它的逻辑是先按段落切段落太长再按句子切句子太长再按字符切。这比固定长度切块更能保留语义完整性。3.2 Memory 的三种实现层次LangChain 的 Memory 体系经历了比较大的演进。早期版本通过ConversationBufferMemory等类维护对话历史新版本推荐直接使用langchain.memory里的不同组件或者干脆在Runnable/ Agent 里手动管理消息列表。实际项目中最简单可靠的记忆实现方式有两种第一种会话级消息列表。把历史对话保存在一个列表里每次请求时拼到 Prompt 中。适合短期记忆。messages [] messages.append({role: user, content: 我住在杭州}) messages.append({role: assistant, content: 你好杭州是个好地方})第二种持久化长期记忆。把用户的关键信息抽取出来存入 Redis 或 MySQL用户下次访问时加载。适合长期记忆。需要注意把全部历史对话都塞进 Prompt 是不行的。上下文窗口有限、成本会线性增长、模型对过长的历史反而会“迷失”。所以工程上要做“记忆压缩”只保留最近几轮对话或者对历史做摘要。3.3 Agent 的执行循环一个最精简的 Agent 循环可以这样理解用户问题 ↓ LLM 根据指令 工具描述决定是否调用工具、调用哪个、传什么参数 ↓ 执行工具拿到结果 ↓ LLM 观察结果决定继续调用工具还是直接回答 ↓ 输出最终答案这个“决策—执行—观察—再决策”的循环就是 Agent 和普通 API 调用的本质区别。LangChain 中对这个模式做了高度封装你只需要定义 Tool 的name、description、args_schema和funcAgent 框架就会让 LLM 根据description来决定何时调用。这里有个关键经验Tool 的 description 写得好不好直接决定 Agent 的准确率。如果你写“use this when user asks about anything”那 LLM 什么都会去调这个工具如果你写“use this when user asks about company policies from the knowledge base”LLM 就知道这是知识库专用工具。4. 完整实战案例构建一个带记忆的知识库 Agent接下来我们将把三个模块组合到一个项目中。业务场景是企业员工手册问答 Agent。它需要做到用户提问关于公司制度的问题如年假、报销从知识库中检索回答。用户进行多轮对话时Agent 记住用户姓名、岗位、之前的问答内容。用户可以要求 Agent 基于已知信息执行简单操作例如“根据我的年假余额提醒我今年还剩几天”。4.1 准备示例文档创建data/employee_handbook.md# 员工手册节选 ## 年假制度 员工入职满一年后享有每年 5 天带薪年假。工龄满 10 年年假增加至 10 天。 年假需要提前 3 个工作日申请经部门主管审批后方可休假。 ## 报销制度 员工因公出差产生的交通、住宿、餐饮费用可在回国后 7 个工作日内提交报销申请。 报销金额超过 5000 元需要总经理审批。 ## 远程办公 员工每周可申请最多 2 天远程办公。远程办公期间需要保持即时通讯在线并按时参加每日站会。4.2 编写 RAG 模块文件路径rag_service.pyimport os from dotenv import load_dotenv from langchain_community.document_loaders import TextLoader from langchain_community.vectorstores import Chroma from langchain_openai import OpenAIEmbeddings from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_core.runnables import RunnableLambda load_dotenv() class RAGService: def __init__(self, doc_path: str, persist_dir: str ./chroma_db): self.persist_dir persist_dir self.embeddings OpenAIEmbeddings( modeltext-embedding-ada-002, api_keyos.getenv(OPENAI_API_KEY) ) self.vector_store self._build_or_load(doc_path) def _build_or_load(self, doc_path: str): # 如果本地已有向量库直接加载 if os.path.exists(self.persist_dir): return Chroma( persist_directoryself.persist_dir, embedding_functionself.embeddings ) # 否则从文档构建 loader TextLoader(doc_path, encodingutf-8) documents loader.load() text_splitter RecursiveCharacterTextSplitter( chunk_size200, chunk_overlap50, separators[\n\n, \n, 。, , , , ] ) docs text_splitter.split_documents(documents) return Chroma.from_documents( docs, self.embeddings, persist_directoryself.persist_dir ) def search(self, query: str, k: int 3): # 返回检索到的文档片段列表 return self.vector_store.similarity_search(query, kk) def as_tool_func(self): # 方便 Agent 直接调用 def search_func(query: str) - str: docs self.search(query, k3) return \n\n.join([doc.page_content for doc in docs]) return search_func几点说明chunk_size200表示每个文本块约 200 字符这个数值需要根据文档情况调整。chunk_overlap50让相邻块之间有 50 字符重叠避免切在语义边界导致信息丢失。separators的优先级是从左到右先按段落切再按句号切。OpenAIEmbeddings需要你在.env里配置OPENAI_API_KEY。如果你使用本地模型可以替换成langchain_community.embeddings里的HuggingFaceBgeEmbeddings或OllamaEmbeddings。4.3 编写 Memory 模块文件路径memory_service.py为了演示长期记忆和短期记忆的区别这里用 JSON 文件做简单的长期记忆持久化同时在内存里维护短期会话历史。import json import os from datetime import datetime class MemoryService: MEMORY_FILE ./memory_store.json def __init__(self, user_id: str): self.user_id user_id self.short_term_messages [] self._ensure_file() def _ensure_file(self): if not os.path.exists(self.MEMORY_FILE): with open(self.MEMORY_FILE, w, encodingutf-8) as f: json.dump({}, f) def _load_all(self): with open(self.MEMORY_FILE, r, encodingutf-8) as f: return json.load(f) def _save_all(self, data): with open(self.MEMORY_FILE, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse, indent2) def add_long_term(self, key: str, value: str): 长期记忆记录用户的稳定信息如姓名、岗位、偏好 data self._load_all() if self.user_id not in data: data[self.user_id] {} data[self.user_id][key] { value: value, updated_at: datetime.now().isoformat() } self._save_all(data) def get_long_term(self, key: str None): 如果指定 key返回对应值否则返回该用户的全部长期记忆 data self._load_all() user_data data.get(self.user_id, {}) if key: return user_data.get(key, {}).get(value, ) return {k: v[value] for k, v in user_data.items()} def add_short_term(self, role: str, content: str): 短期记忆保存当前会话的对话消息 self.short_term_messages.append({role: role, content: content}) # 只保留最近 6 条避免上下文过长 if len(self.short_term_messages) 6: self.short_term_messages self.short_term_messages[-6:] def get_short_term(self): return self.short_term_messages这里体现了一个很重要的工程思路长期记忆存的是“事实”短期记忆存的是“上下文”。事实需要跨会话保留上下文只需要当前会话内保持。4.4 编写 Agent 编排模块文件路径agent_service.py我们用 LangChain 的 AgentTool Calling Agent来串联 RAG 和 Memory。from langchain.agents import AgentExecutor, create_tool_calling_agent from langchain.tools import Tool from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_openai import ChatOpenAI from rag_service import RAGService from memory_service import MemoryService class AgentService: def __init__(self, rag: RAGService, memory: MemoryService): self.rag rag self.memory memory self.llm ChatOpenAI( modelgpt-4o-mini, temperature0.1 ) self.agent_executor self._create_agent() def _create_agent(self): # 定义 Agent 可用的工具 tools [ Tool( nameknowledge_base_search, description( Search the employee handbook knowledge base. Use this when user asks about company policies, leave, reimbursement, remote work, or other HR rules. ), funcself.rag.as_tool_func() ), Tool( nameget_user_memory, descriptionGet the long-term memory of the current user. Use this when you need to recall users stored information like name, position, preferences., funclambda x: str(self.memory.get_long_term()) ), Tool( namesave_user_memory, descriptionSave a piece of user information into long-term memory. Use this when user tells you personal facts like their name, role, or preferences., funcself.memory.add_long_term ) ]等等这里有一个问题需要修正Tool的func要求接受一个参数。save_user_memory需要接收两个参数key 和 value不能直接传给 Agent。我们改造一下用一个参数接收字符串解析后再保存。修正后的代码如下class AgentService: def __init__(self, rag: RAGService, memory: MemoryService): self.rag rag self.memory memory self.llm ChatOpenAI( modelgpt-4o-mini, temperature0.1 ) # 绑定内存服务到当前用户 self.agent_executor self._create_agent() def _create_agent(self): def save_memory_func(arg: str): # 参数格式: keyvalue # 实际项目中建议用 JSON 格式 if not in arg: return Invalid format. Please use keyvalue. key, value arg.split(, 1) self.memory.add_long_term(key.strip(), value.strip()) return fSaved {key.strip()} to memory. tools [ Tool( nameknowledge_base_search, description( Search the employee handbook knowledge base. Use this when user asks about company policies, leave, reimbursement, remote work, or other HR rules. ), funcself.rag.as_tool_func() ), Tool( nameget_user_memory, descriptionGet the long-term memory of the current user. Use this when you need to recall users stored information like name, position, preferences., funclambda x: str(self.memory.get_long_term()) ), Tool( namesave_user_memory, descriptionSave a piece of user information into long-term memory. Use this when user tells you personal facts like their name, role, or preferences. Argument format: keyvalue, funcsave_memory_func ) ] prompt ChatPromptTemplate.from_messages([ (system, 你是一个企业员工助手。你的职责是 1. 当用户询问公司制度时调用 knowledge_base_search 获取答案。 2. 记住用户提供的个人信息调用 save_user_memory 保存。 3. 回答问题时结合当前对话历史和长期记忆给出个性化回答。 ), MessagesPlaceholder(variable_namechat_history), (user, {input}), MessagesPlaceholder(variable_nameagent_scratchpad) ]) agent create_tool_calling_agent(self.llm, tools, prompt) return AgentExecutor(agentagent, toolstools, verboseTrue, handle_parsing_errorsTrue) def run(self, user_input: str): # 将短期记忆作为 chat_history 传入 result self.agent_executor.invoke({ input: user_input, chat_history: self.memory.get_short_term() }) # 更新短期记忆 self.memory.add_short_term(user, user_input) self.memory.add_short_term(assistant, result[output]) return result[output]需要特别说明一个关键点为什么要把短期记忆单独作为chat_history传入而不是简单拼在 system prompt 里因为 LangChain 的create_tool_calling_agent对于MessagesPlaceholder的处理方式不同。它会将这部分的对话内容作为“历史消息”提供给 LLM而用户当前输入作为新的 user message。这种结构对模型来说更清晰哪些是历史哪些是现在要处理的问题。4.5 编写入口文件并运行文件路径main.pyfrom rag_service import RAGService from memory_service import MemoryService from agent_service import AgentService def main(): # 初始化三个模块 rag RAGService(./data/employee_handbook.md) memory MemoryService(user_idzhangsan) agent AgentService(rag, memory) print( 企业知识库 Agent 已启动 ) print(输入 exit 退出\n) while True: user_input input(你: ) if user_input.lower() exit: break response agent.run(user_input) print(fAgent: {response}\n) if __name__ __main__: main()运行前在项目根目录创建.env文件OPENAI_API_KEYsk-your-key然后运行python main.py4.6 预期效果演示我们模拟一段对话看看整体表现。第一轮你: 我叫张三是技术部的工龄五年了 Agent: 好的张三你好我已经记住了你的信息。请问有什么可以帮你这轮对话中Agent 应该调用save_user_memory工具。如果 verbose 模式开启你会看到 Agent 的思考过程类似 Entering new AgentExecutor chain... Invoking: save_user_memory with {arg: name张三} Invoking: save_user_memory with {arg: department技术部} Invoking: save_user_memory with {arg: work_years5} Finished chain.第二轮你: 我的年假有几天 Agent: 张三你好根据员工手册入职满一年后享有每年 5 天带薪年假。工龄满 10 年年假增加至 10 天。你目前工龄 5 年所以年假是 5 天。这轮中Agent 先调用get_user_memory查看了张三的工龄再调用knowledge_base_search检索年假制度最后综合两者给出个性化回答。这就是 RAG Memory 结合的一个典型示例。第三轮你: 那我今年已经休了3天还剩几天 Agent: 你今年年假是 5 天已经休了 3 天所以还剩 2 天。记得提前 3 个工作日申请哦。这里依赖的是短期记忆Agent 记得上一轮对话中“年假 5 天”的信息。如果你没有短期记忆这一轮它就不知道“5 天”从哪里来的。5. 常见问题与排查思路在实际开发和部署过程中RAG、Memory、Agent 的组合会遇到很多问题。下面把频率最高的几类整理成表格并展开说明。问题现象常见原因解决思路Agent 不调用检索工具直接胡编答案工具 description 不够具体或 LLM 没有理解意图优化工具描述增加触发条件示例RAG 检索结果不相关文本切块策略不当、Embedding 模型不匹配调整 chunk_size 和 overlap尝试重排模型对话稍微变长回答就开始混乱短期记忆没有做裁剪Prompt 过长只保留最近 N 轮或对历史做摘要压缩Agent 反复调用同一个工具陷入死循环Agent 的停止条件设置不当或工具返回内容让 LLM 无法判断设置 max_iterations检查工具返回格式长期记忆写入失败或内容杂乱抽取信息时没有做字段校验用结构化格式保存信息增加校验逻辑向量库重建非常慢文档量大且没有增量更新分批次入库使用增量索引5.1 “Agent 不调用检索工具”的排查步骤这个问题最让人头疼明明知识库里就有答案Agent 却选择自己编一个。排查顺序如下第一步确认工具是否注册成功。打印agent_executor.tools检查工具列表里是否有knowledge_base_search。第二步确认工具描述是否足够具体。实践发现description中包含“use this when user asks about...”这类触发词能显著提升工具的调用概率。第三步检查 LLM 的 temperature 设置。如果设置得过高比如 0.7模型的决策行为会变得不稳定建议在 Agent 场景中设为 0.1 或 0。第四步开启 verbose 模式观察 Agent 的内部推理。LangChain 的AgentExecutor设置verboseTrue后会打印出 LLM 的每一步思考帮助你定位是没理解问题还是理解后没选对工具。5.2 “RAG 检索结果不相关”的排查步骤如果你单独测试 RAG 模块时发现检索结果不对按这三个方向排查第一检查切块参数。chunk_size过长可能使一个块包含多个主题检索时语义不够聚焦过短则可能切断完整句子。经验值是 200-500 字符之间但需要根据文档语言和类型调整。第二检查文档内容本身。比如员工手册这种结构清晰的 Markdown 文档可以直接按标题切块而不是按固定字符数切。LangChain 里有MarkdownHeaderTextSplitter专门处理这类结构化文档。第三检查 Embedding 模型。如果你的文档是中文建议使用中文表现更好的 Embedding 模型例如 BAAI/bge-large-zh-v1.5 或 M3E。使用 OpenAI 的text-embedding-ada-002虽然也能处理中文但对某些特定领域术语的匹配效果可能不如中文专用模型。6. 最佳实践与工程建议把 RAG、Memory、Agent 组合起来做产品代码只是最基础的部分。真正决定项目能否上线的是工程化细节。下面结合实践给出几条高价值的建议。6.1 先模块化再组合很多项目失败不是因为技术选型错了而是因为代码耦合太严重。RAG、Memory、Agent 应该在代码层面完全分离rag_service.py # 只管文档加载、切块、向量化、检索 memory_service.py # 只管记忆的读写、裁剪、持久化 agent_service.py # 只管工具调度和任务编排这样的好处是你可以单独测试 RAG 的准确率而不用启动整个 Agent 流程。未来替换向量数据库从 Chroma 换成 Milvus时只改rag_service.py。Agent 框架升级或更换从 LangChain 换成 LlamaIndex 或自研时RAG 和 Memory 模块可以复用。6.2 不要把整个对话历史都塞进 Prompt这是新手最容易犯的错误。直接在 system prompt 里拼接全部历史对话短期来看能用但当上下文长度增长到几千 token 时会有三个问题成本线性上升。模型对早期信息的注意力大幅下降反而更注意最近内容。Agent 可能会从历史中提取出错误的“用户意图”。推荐的做法是只保留最近 4-8 条消息。对早期对话做摘要把摘要作为一种长期记忆存储。对每轮对话设置 token 上限超出则丢弃最旧消息或触发摘要。6.3 RAG 的召回质量优先于生成质量一个 RAG 系统好不好60% 取决于检索质量30% 取决于 Prompt 设计只有 10% 取决于 LLM 本身的生成能力。如果检索出来的内容本身就是错的再强的模型也生不成正确答案。所以在优化 RAG 时优先看召回率相关文档有没有被检索出来准确率检索出来的 Top-K 里有多少是真正相关的引用溯源生成的回答能否追溯到具体的文档片段很多企业级 RAG 项目会引入重排模型Rerank在向量检索之后再做一轮精细化排序。这是一个性价比很高的优化手段。6.4 对 Agent 设置严格的执行边界Agent 在开发环境看起来一切正常一旦上生产就会出现各种意外行为。这是因为 Agent 本质上是“不确定的”它的每一步决策都由 LLM 推理生成而 LLM 有随机性。生产环境必须设置以下保护措施设置最大工具调用轮数防止死循环。对工具返回结果做长度限制防止超大文本撑爆上下文。对 Agent 的最终输出做格式校验防止输出 JSON 解析失败。对危险操作删除数据、发送邮件、支付增加人工确认环节。6.5 日志记录是 Agent 项目的第一优先级Agent 的调试比传统程序难得多因为同一个输入可能产生不同的输出。没有日志你根本不知道 Agent 在内部“想”了什么。在开发阶段开verboseTrue在生产阶段把 Agent 的每一步决策记录下来时间戳 | 用户ID | 输入 | 推理过程 | 调用的工具 | 工具参数 | 工具结果 | 最终输出记录这些内容既方便问题排查也是数据分析和效果评估的基础。7. 总结与下一步学习方向回到文章开头的问题RAG、Memory、Agent 到底该用哪个答案已经很明确了这不是一道选择题。RAG 解决的是外部知识引入问题Memory 解决的是对话状态与个性化问题Agent 解决的是任务执行与工具调度问题。它们面向的是不同维度的能力在完整的企业级 AI 应用中三者往往需要协同工作。如果你的业务只是“文档问答”不需要多轮个性化那可以只用 RAG不必上 Agent。如果你的业务是“客服助手”需要记住用户、多轮对话、查规则那 RAG Memory 就够用。如果你的业务是“自动化处理”需要根据用户需求查询数据、调用 API、完成任务那才需要引入 Agent。从学习路径的角度看建议按这个顺序逐步深入先掌握 RAG搞清楚文档加载、切块、向量化、检索、重排这是最基础也最容易拿到业务价值的能力。再深入 Memory理解短期记忆、长期记忆、摘要记忆、向量记忆的区别学会在多轮对话中保持一致性。最后学习 Agent掌握工具定义、工具调用、任务规划、异常恢复。在熟悉前两者之后Agent 的学习曲线会平缓很多。动手建议先把文章的示例代码跑通然后逐步替换组件——把 OpenAI 换成本地模型把 Chroma 换成 Milvus把文本切块改成按 Markdown 标题切块。每换一个组件你都会对这套技术栈有更深的理解。如果这篇文章对你有帮助建议收藏备用。后续也可以继续关注 RAG 引用溯源、Agent 评估体系、长期记忆的向量化存储等进阶主题。
返回列表