学习来源 :awesome-agentic-ai-zh ------ 一份把 Agent 从「模型基础」一路带到「上线工程」的中文学习地图。
本篇范围 :Stage 5(Claude Code 生态系统)+ Stage 6(RAG 与 Memory)。
系列说明:Track B 构建者路线共三篇------下篇一(Stage 3--4)、下篇二(Stage 5--6)、下篇三(Stage 7 / 7.5 / 8 + 延伸路线)。三篇合起来才是完整的《下篇》。
前言 | 从「自己造」到「用现成的」
本篇在系列里的位置
下篇一你自己写出了 Agent Loop 和 workflow graph。到了本篇,问题换了两层:
- 能不能不自己造? 现成生态(Claude Code 的规则文件、Skill、MCP、Hook、Plugin、Subagent)已经把「读仓库、改代码、跑测试」这套动作打包好了,你要学的是怎么配置它、怎么划权限、怎么把它接进团队流程(Stage 5)。
- 能不能让它知道仓库之外的事? 模型不知道你的私有文档、不知道昨天的会议记录,也不会自己记住上次的结论。RAG 解决「现查」,Memory 解决「记住」(Stage 6)。
一句话记:Stage 5 把别人的轮子装上你的车,Stage 6 给你的车配上油箱和后视镜。
一次看清楚:本篇两个阶段的关系
| Stage 5 | Stage 6 | |
|---|---|---|
| 解决的问题 | 现成 agent 怎么被配置、被限制、被共享 | 怎么把外部资料与历史状态喂给它 |
| 核心结构 | 规则文件 / Skill / MCP / Hook / Plugin / Subagent | chunk → embed → retrieve → generate;semantic / episodic / procedural memory |
| 典型产物 | 一个「进同一个 repo 就懂同一套规矩」的 CLI agent | 一条能定位「哪一步坏了」的 RAG 流水线 |
| 最容易出的错 | 权限给太大、规则和 Skill 打架 | chunk 切错、检索不对却怪模型 |
两者可以并行:Stage 5 决定「谁来干活」,Stage 6 决定「它能看到什么」。
阅读建议
- Stage 5 先记「谁管什么」:五个组件(规则 / Skill / MCP / Hook / Plugin)的分工表要能默写,选错组件的成本比写错配置高得多。
- MCP 只连一个:练习 1 就够,重点是看懂「server 提供什么、权限边界在哪」,不是把能连的都连上。
- Stage 6 别急着上向量库:先用几十段文本跑通最小的 retrieve,再谈 rerank 与混合检索。
- 「先找出哪一步坏了」是 6.9 的全部意思:RAG 效果差时,先定位是切分、召回还是生成的问题,而不是直接换模型。
目录
- Stage 5 | Claude Code 生态系统
- 5.1 九个核心词:先记住谁管什么
- 5.2 零件怎样一起工作
- 5.3 一张表先选对组件
- 5.4 动手练习:五个组件各加一次
- 5.5 Subagent Cookbook
- 5.6 何时 NOT 该用 subagent
- 5.7 Agent 工具怎么分:身份、操作界面、部署位置
- 5.8 四个生活场景和安全边界
- 5.9 Subagent:在 agent runtime 里再 spawn agent
- 5.10 并行工作与 Worktree
- 5.11 剖析 agent loop
- 5.12 Claude Agent SDK
- 5.13 要点回顾与复习索引
- Stage 6 | RAG 与 Memory:先找数据,再记住重要的事
- 6.1 七个核心词
- 6.2 一张表先选对方法
- 6.3 Embeddings 与相似内容搜索
- 6.4 Vector DB 与两种搜索
- 6.5 比较三种 Chunking
- 6.6 把完整 RAG 接起来
- 6.7 让 Agent 下次还记得
- 6.8 RAG 基础流水线:资料怎么进去,答案怎么出来
- 6.9 进阶 RAG:先找出哪一步坏了,再加新技巧
- 6.10 Agent Memory:只记值得记、允许记、能删掉的事
- 6.11 要点回顾与复习索引
- 本篇速查卡
Stage 5 | Claude Code 生态系统
一句话导读:这一关把「一个会改文件的 agent」拆成九个可替换的零件。学完你要能在遇到具体问题时立刻说出:这该用 CLAUDE.md、Skill、MCP、Hook、Subagent、Worktree、Plugin,还是干脆写 SDK。
5.1 九个核心词:先记住谁管什么
Claude Code
它是能读写文件并执行命令的编码代理。它像坐在终端旁的助手;本章教你约束它,而不是一次开放所有权限。
CLAUDE.md
它是每次工作都要读取的项目守则,适合写测试命令、命名规范和禁止事项。
Skill(SKILL.md)
它是需要时才拿出来的操作卡,适合部署、审查和数据处理等可重复流程。
MCP(Model Context Protocol)
它是让编码代理连接外部工具和数据的通用接口。连上 GitHub、数据库或浏览器后,代理才能实际使用这些服务。
Hook
它是在事件发生时自动执行的检查。例如 Claude 要运行危险命令前,Hook 可以先拦截。
Plugin 与 Marketplace
Plugin 把 Skills、Hooks、Subagents 或 MCP 配置打包成一盒;Marketplace 是摆放许多盒子的目录。前者像应用,后者像应用商店。
Subagent
它是拥有独立 context window 的小助手。大量中间内容留在它那里,最后只把结论带回主对话。
Worktree
它是同一 Git 仓库的另一个工作目录。多个代理同时改文件时,它能避免彼此踩到同一份未提交内容。
Claude Agent SDK
它让你的 Python 或 TypeScript 程序控制代理。只有要把代理嵌入产品或服务时才需要它。
九个词记住一句话就够:CLAUDE.md 管「每次都要」,Skill 管「按需」,MCP 管「接外部」,Hook 管「事件触发」,Subagent 管「隔一段工作」,Worktree 管「隔一份文件」,Plugin 管「打包分享」,SDK 管「嵌进程序」。
再看它们怎么拼在一起:模型在中间跑 Agent Loop,规则与操作卡从左上进来,外部能力经 MCP 接入,检查和隔离在下面兜底。
5.2 零件怎样一起工作

图 5-2 零件怎样一起工作:CLAUDE.md、Skill、Hook、MCP、Subagent、Worktree、Plugin 各站在哪一层
5.3 一张表先选对组件
而「现在到底该装哪个」,可以照下面这张图从上往下问:先看遇到什么问题,再选最小的那个组件。

图 5-1 Claude Code 扩展工具怎么选:八个组件对应八类问题,先用最小的那个
| 你的问题 | 先用什么 | 先不要做什么 |
|---|---|---|
| 每次都要记住同一条项目规则 | CLAUDE.md |
把整本手册塞进去 |
| 只在特定场景需要一套流程 | Skill | 每次都粘贴同一大段 prompt |
| 要连接 GitHub、数据库或浏览器 | MCP | 直接把未审查 server 接到高权限账户 |
| 事件发生时都要自动检查 | Hook | 把陌生 shell script 当作安全工具 |
| 大量搜索会挤满当前对话 | Subagent | 为一个小问题多开代理 |
| 多项工作会修改同一仓库 | Worktree | 让多个代理共享未提交文件 |
| 要与团队共享配置 | Plugin | 第一题就自建 marketplace |
| 要把代理嵌进产品 | Agent SDK | 把 CLI 已能完成的工作重写成服务 |
5.4 动手练习:五个组件各加一次
主项目是一个"安全的 Claude Code 练习仓库"。每题只添加一个组件;前一题成功后再做下一题。
练习 1:写一张最小项目守则
完成后,你会有一份短 CLAUDE.md,其中只有用途、禁止事项、验证命令和交付格式。
plain
请先阅读这个仓库,只回复:用途、最重要的 3 个目录,以及你会先运行哪个只读检查。不要修改文件。
练习 1 的步骤与检查
- 在不含敏感数据的练习仓库根目录创建
CLAUDE.md。 - 只写四部分:
Purpose、Do not、Verify、Deliver。 - 先人工阅读一遍,再请 Claude 按上面的 prompt 说明它理解到什么。
- 成功条件:Claude 没有改文件,且它说出的验证命令与
CLAUDE.md一致。
CLAUDE.md 最好少于 200 行。@path import 可以整理文件,但被 import 的内容仍会进入 context;需要按路径延后加载时,使用 .claude/rules/ 的 paths frontmatter。
练习 2:把重复流程做成 Skill
完成后,你可以输入一条简短需求,让 Claude 按固定清单检查 README。
python
New-Item -ItemType Directory -Force .claude\skills\readme-check
练习 2 的步骤、macOS/Linux 命令与示例
创建 .claude/skills/readme-check/SKILL.md:
plain
---
name: readme-check
description: Check a README for a clear purpose, install steps, one example, and a license link. Use when the user asks to review README onboarding.
disable-model-invocation: true
---
1. Read the README without changing it.
2. Check: purpose, install steps, one runnable example, license link.
3. Return PASS or a short list of missing items with line references.
先人工检查 YAML frontmatter,再在 Claude Code 输入 /readme-check。disable-model-invocation: true 表示只有你能主动调用它,适合有副作用或需要控制时机的流程。
练习 3:添加一个只观察、不拦截的 Hook
完成后,每次 Claude 想写文件或改文件时,Hook 都会记录 event 名称和 tool 名称;它不保存 prompt,也不替你批准或拦截操作。
plain
New-Item -ItemType Directory -Force .claude/hooks
练习 4:连接受限的 MCP server
完成后,Claude 只能读取你指定的示例文件夹,不能访问整台电脑。
python
我要连接一个 filesystem MCP server。请先解释它能看到哪个目录、有哪些 tools、如何移除,然后等我批准;不要直接安装。
练习 4 与 MCP 2026 补充
- 创建一个只放虚构数据的文件夹。
- 按 Claude Code MCP 文档 添加 filesystem server,scope 只指向该文件夹。
- 先列出 tools,再读取一个假文件,最后移除 server。
- 成功条件:读取指定文件夹成功;请求读取外部路径时失败。
MCP 的三项核心抽象:Tools 是模型可调用的动作,Resources 是可读数据,Prompts 是 server 提供的 prompt 模板。多数入门 server 先使用 Tools。
练习 5:用 Subagent 做只读检查
完成后,大量搜索会留在独立 context,主对话只收到摘要。
自定义 Subagent 示例
Claude Code 内置的主要 Subagent 是 Explore、Plan 和 general-purpose。其他名称可能来自 plugin、组织设置或你自己的 .claude/agents/<name>.md,不要假设每台机器都有。
markdown
---
name: docs-finder
description: Find documentation related to a named feature and return file paths. Use for read-only documentation discovery.
tools: Read, Glob, Grep
model: haiku
---
Search only. Return up to five file paths with one-sentence reasons. Do not edit files or run shell commands.
派遣时直接在对话框里这样说:
text
Use the Explore subagent to find where tests are documented. Read only. Return the three most useful file paths and one sentence for each.
Use the Explore subagent to find where tests are documented. Read only. Return the three most useful file paths and one sentence for each.
Subagent 由现行 Agent tool 派遣。它有独立的 context 与权限设置,接收一份自足任务,最后向主对话交回摘要。小问题、需要频繁来回或高度共享 context 的工作,留在主对话更简单。
Subagents:隔离大段工作
能判断何时需要独立 context,并写出一份自足的 delegation brief。

图 5-3 Skill 与 Subagent 的差别:一个复用知识与流程,一个隔离一段工作
自定义 Subagent 的 description 是路由提示,不是代码层的 if。prompt 应自足,明确任务、范围、工具、输出和停止条件。现行官方还支持 skills、mcpServers、permissions、hooks 与 isolation: worktree 等设置;只在确有需要时添加。
多开代理会增加 token、延迟与集成工作。不要声称固定倍数;应按任务、模型和用量记录实测。
五个练习串起来是一条完整的升级路径:先给规则(CLAUDE.md)→ 再把重复流程做成 Skill → 再加一个只观察不拦截的 Hook → 然后连一个受限的 MCP server → 最后用 Subagent 把大段搜索隔离出去。
5.5 Subagent Cookbook
每个 recipe 都用同样的 4 段结构:
| 段 | 内容 | 为什么有这段 |
|---|---|---|
| 场景 | 你今天工作会遇到的具体场景 | 从"我有 X 问题"找到 recipe,而不是从"我想用 subagent"找 |
| Subagent | 用哪一个(Claude Code 内置名称) | 直接 copy 名字,不用想 |
| Prompt 模板 | 复制粘贴即可用的指令文字 | 不用自己想怎么写 |
| 何时不用 | 比用 subagent 更好的替代方案 | 避免"大材小用" |
怎么实际派遣 subagent:在你的 Claude Code 终端对话框里,直接输入(或粘贴)prompt 模板------就这样。Claude 看到指令,会自动通过 Agent tool(内部派遣机制)找到对应 subagent 跑,跑完后向主 session 回报一段摘要。不需要 slash command,不需要特殊语法。
📌 subagent ≠ slash command:/agents 是列表命令,不是调用 subagent 的方式;派遣 subagent 直接打对话 prompt 文字即可。
5.6 何时 NOT 该用 subagent
Subagent 不是免费的------每次派遣会烧 token,也有延迟 。下面 4 种场景不该用 subagent,自己跑更划算:
- 任务 < 5 分钟可自己完成 --- 大材小用;subagent overhead 不划算
- 结果需要逐步 user feedback --- subagent 是"派出去、跑完回报一次",不能中间问你;要逐步确认的任务直接在主 session 跑
- 任务需要主 session 的 context memory --- subagent 是独立 context window,看不到主 session 前面的对话;要用"我们刚刚讨论的 X..."这种 reference 的任务,不适合
- 任务涉及 conversation-level judgment --- 像"这个 architecture 决策该怎么权衡",需要对话协作,不适合丢给 subagent
判断的快速办法 :如果任务可以用"写一份完整 brief 给陌生人接手做 "描述清楚 → 适合 subagent;如果需要"我跟你讨论一下"→ 留在主 session。
5.7 Agent 工具怎么分:身份、操作界面、部署位置
同一个工具可以出现在终端、IDE 和桌面应用中,也可以连接本地或云端模型。所以不要硬把工具塞进五个互斥"类型"。

图 5-4 Agent 工具的三条轴:身份(负责什么)、操作界面(从哪说话)、部署位置(跑在哪里)
| 轴 | 五岁也能懂的说法 | 正确问题 |
|---|---|---|
| Identity(身份) | 这个东西的工作是什么? | 它是 Coding Agent、Router、Local Runtime、Framework,还是 Chat Gateway? |
| Surface(操作界面) | 你从哪扇门跟它说话? | 终端、IDE、桌面、Web、Chat app 还是 API? |
| Deployment(部署位置) | 它的身体放在哪里? | 你的电脑、云端主机、边缘设备,还是托管服务? |
一个产品可以同时有很多 Surface ,也可以更换 Deployment 。这不会改变它的主要 Identity。
身份:它到底负责什么
| 核心词 | 白话定义 | 例子 | 它不自动负责什么 |
|---|---|---|---|
| Coding Agent/Harness(程序代理/工作台) | 能在允许范围内读文件、改文件、跑命令,再回来报告 | Claude Code、Codex、OpenCode、Pi、Aider、goose | 不一定包含模型、Router 或 Sandbox |
| Router(路由器) | 把模型请求转发给不同 Provider | OpenRouter | 不会自己修改 repo,也不管理文件权限 |
| Local Runtime(本地模型引擎) | 在自己的电脑加载并运行模型 | Ollama、vLLM | 不会自己理解任务或操作工作目录 |
| Agent Framework(代理框架) | 给开发者编写状态、步骤、Handoff 和 Workflow 的工具箱 | LangGraph、CrewAI、Microsoft Agent Framework | 不是安装后就能替你完成工作的成品 Agent |
| Chat Gateway(聊天入口) | 把 Agent 连接到 Telegram、Slack 等消息入口 | Hermes Agent 的 gateway/messaging 模式 | 不代表底层模型、权限和部署已经安全 |
最短识别法:谁运行模型?谁转发请求?谁能碰文件?谁安排多个步骤?你从哪里说话?
常见工具放在哪里
| 工具 | 主要 Identity | 常见 Surface | 可用 Deployment | 初学者最容易搞错的地方 |
|---|---|---|---|---|
| OpenCode | Coding Agent/Harness | 终端、桌面、IDE | OpenCode 程序在本地运行 | 连接云端 Provider 只会发出模型请求,不会把 OpenCode 程序搬到云端;仍要选择模型和 permission |
| Pi | Coding Agent/Harness | 终端、SDK、RPC | 本地 | 这里的 Pi 不是 Raspberry Pi;它没有内置 Sandbox |
| OpenRouter | Router | API | 托管云端服务 | 它不会自己读文件或执行命令 |
| Ollama | Local Runtime | CLI、API | 本地或自己的服务器 | 它不是 Coding Agent;要由 Client/Agent 调用 |
| Aider | Coding Agent/pair programmer | 终端 | 本地 | 先看清 Git auto-commit/--no-verify 行为 |
| goose | Coding/general Agent | CLI、桌面、API | 本地 | Extension 权限要单独审查 |
| Hermes Agent | Agent runtime+Chat Gateway | CLI、消息平台 | 本地或自己的主机 | Chat 入口不等于 24/7、安全或零维护 |
| OpenClaw | 可自建的 Agent/assistant 平台 | Web、Chat、CLI,取决于部署 | 本地、云端或 edge | 在 edge 运行不代表没有网络、工具或数据外泄风险 |
三步选择法
- 先选 Identity:要修改 repo 就选 Coding Agent;只想转接模型就选 Router;要在本地运行模型就选 Local Runtime;要自己编写 Workflow 才选 Framework。
- 再选 Surface:眼睛一直看程序就偏 IDE;需要命令、Git 和长任务就偏终端;需要手机消息入口才考虑 Chat Gateway。
- 最后选 Deployment:先从可恢复的 demo repo 和最小权限开始,再决定本地、云端或 edge。部署位置不会自动消除风险。
5.8 四个生活场景和安全边界
编写一个小功能
选择一个 Coding Agent/Harness,在 demo branch 中要求它先说明计划、再修改一个文件、运行测试并显示 diff。模型可以来自 Provider API,也可以由 Ollama 在本地运行。
用一个 API key 尝试不同 Provider
Coding Agent 仍负责文件和命令;OpenRouter 只负责转发模型请求。两者的账单、数据政策和权限要分开看。
手机接收例行整理
Hermes Agent 这类工具可以连接 Messaging Gateway。你仍要处理主机更新、密钥、允许的工具、失败重试和消息平台权限。
在 edge 设备处理敏感数据
本地模型可以减少把 Prompt 发送给外部 Provider 的需要,但 Agent 如果能联网、调用工具或读取其他文件夹,仍可能把数据带出去。要使用防火墙、容器/VM、最小权限、假数据测试和人工审核。
5.9 Subagent:在 agent runtime 里再 spawn agent
Subagent(子代理) 是主 Agent 把一小块任务交给另一个隔离工作者。它回答的是"工作怎么分",不是"产品运行在哪里"。
| 路径 | 谁负责建立子代理 | 适合什么 |
|---|---|---|
| Framework-based | 你的 Python/TypeScript orchestration 程序 | 要自己控制状态、Provider、Handoff 和 Workflow |
| Coding-Agent native | Claude Code、Codex 等 Agent runtime | 在同一个 repo 中拆分研究、实现或审查任务 |
不论哪条路径,都要给子代理明确范围、输出格式、预算、停止条件和验证方式。主代理仍要读取结果;"使用了多个 Agent"不是正确性的证明。
5.10 并行工作与 Worktree
能分清"谁协调工作"与"谁隔离文件"。
Subagent、agent view、agent teams、Dynamic workflows、Worktree 与 /batch
| 做法 | 谁协调 | 适合什么 | 当前状态/边界 |
|---|---|---|---|
| Subagent | 主对话 | 隔离搜索或专业任务 | 同一 session 内返回结果 |
| Agent view | 用户 | 监看多个独立后台 session | Research preview |
| Agent teams | Lead 与 teammates | Workers 要共享任务并互相传讯 | Experimental,默认关闭 |
| Dynamic workflows | 协调脚本/运行时 | 大型审计、迁移或交叉核验研究 | 可读、可重跑的 JavaScript 编排;会增加 token 用量 |
| Worktree | Git/用户 | 隔离同一仓库的文件修改 | 不负责代理通信 |
/batch |
Claude 规划后分派 | 5--30 个可切开的机械改动 | 每个 worker 都要独立范围与 review |
Worktree 解决"不要改同一份文件";Subagent/team 解决"谁做哪件事"。两者可一起使用,但不是同一功能。Agent teams 不会自动为每个 teammate 建 Worktree,所以仍要清楚划分文件 ownership。
Dynamic workflows 会把计划放进可读的 JavaScript 脚本,而不是绑定到某个特定 Claude 模型;用 /workflows 查看进度。现行官方文件列出付费方案、API、Bedrock、Google Cloud Agent Platform 与 Foundry,但没有声明一个通用最低版本;Pro 需从 /config 的对应项目开启。
5.11 剖析 agent loop
能画出"读取 context → 模型决定 → 工具执行 → 结果返回 → 再决定"的 loop
5.12 Claude Agent SDK
能判断出CLI 已够用,还是确实需要把代理嵌入程序
需要 SDK 的情况:
- 用户不会打开终端,你要把代理放进自己的 App。
- 需要程序化输入输出、调度、审计、限额或多租户。
- 服务需要控制 allowed tools、session 与结果格式。
5.13 要点回顾与复习索引
- 九个组件各管一段,不要把它们当同一种东西;装之前先问「我现在遇到什么问题」。
- 先用最小的 :能用
CLAUDE.md解决就不要上 Plugin;能在一个 session 里做完就不要派 Subagent。 - Subagent 的四个「不该用」:任务 < 5 分钟、需要逐步反馈、需要主对话 context、需要对话级判断。
- 三条轴分清工具:Identity(负责什么)/Surface(从哪说话)/Deployment(跑在哪里)。
- Worktree 隔文件,Subagent 隔工作:一个解决「别改同一份文件」,一个解决「谁做哪件事」。
- Custom Subagent 的 description 是路由提示 ,不是代码里的
if;prompt 必须自足。 - SDK 只在要嵌进产品时才需要;CLI 能完成的活不必重写成服务。
| 关键词 | 一句话记忆 | 常见坑 |
|---|---|---|
| CLAUDE.md | 每次都要看的守则 | 塞成一本手册 |
| Skill | 按需的操作卡 | 忘写「何时使用」 |
| Hook | 事件触发就检查 | 把陌生脚本当安全工具 |
| Subagent | 独立 context 的小助手 | 为小问题多开代理 |
| Worktree | 同一 repo 的另一份目录 | 多个 agent 共享未提交文件 |
Stage 6 | RAG 与 Memory:先找数据,再记住重要的事
一句话导读 :这一关把「模型不知道的事」分成两类------知识 交给 RAG 去查,状态交给 Memory 去记。两者都要求同一件事:只把相关的一小部分放进 context。
RAG(Retrieval-Augmented Generation):先找相关资料,再依资料回答。
模型不是什么都知道。RAG 像叫它先翻书再回答;Memory 像给它一本笔记本,记住下次还会用到的事。这一关会把两者分清楚,再带你一步一步做出来。
先把七个词认清,再动手。它们的区别不在名字,而在「谁负责找、谁负责存」。
6.1 七个核心词
| 核心术语 | 好理解的说法 | 正确意思 |
|---|---|---|
| Retrieval(检索) | 去书架找几页可能有答案的书 | 收到问题后,从外部资料找出相关内容。 |
| RAG(Retrieval-Augmented Generation) | 先翻书,再用自己的话回答 | 先 retrieval,再把找到的内容交给模型生成答案。 |
| Embedding(嵌入向量) | 帮句子的意思做一张坐标卡 | 把文字转成一串数字,让意思接近的文字在向量空间里靠近。 |
| Vector Store/Vector Database | 会按"意思"找卡片的抽屉 | 保存 embedding,并用相似度找回相关资料。 |
| Chunk(文字片段) | 把大书切成可拿取的小页卡 | 为了搜索与放进 context,把长文档切成较小片段。 |
| Reranking(重新排序) | 把第一次找来的卡片再排一次 | 用第二个方法重新评分候选内容,让更可能有用的片段排前面。 |
| Memory(记忆) | 助理自己的笔记本 | 把跨消息或跨 session 还需要的状态写下来,之后再读回来;它不是聊天记录的别名。 |

图 6-1 RAG 与 Memory:一个负责「找证据」,一个负责「记住状态」
6.2 一张表先选对方法
| 你遇到的问题 | 先考虑 | 为什么 |
|---|---|---|
| 资料不长,而且这次回答用完就好 | Long context | 直接把资料放进这次请求,流程最短。 |
| 文档很多,问题来了才知道要找哪几段 | RAG | 先找相关片段,不必每次塞入全部文档。 |
| 助理下次仍要记得偏好、任务状态或过往结果 | Memory | 把值得保留的信息写入可再次读取的存储层。 |
| 想稳定改变模型的行为或特定能力 | Fine-tuning | 调整模型权重与行为;它不会自动提供最新文档。 |
没有一个选项永远最好。请用自己的资料、问题与成功条件做评测。
每题都有 starter。直接复制命令执行,不需要先抄一份空白答案。
6.3 Embeddings 与相似内容搜索
想象你把每句话放到一张大地图上。意思接近的句子会站得比较近。Embedding(嵌入向量),就是每句话在这张地图上的数字坐标。
| 核心词 | 白话意思 | 程序里看到什么 |
|---|---|---|
| Embedding | 把文字变成一排数字,方便电脑比较意思 | model.encode(...) |
| Vector | 那一排数字 | [0.12, -0.04, ...] |
| Cosine similarity | 看两个向量的方向有多像;越接近 1,意思通常越近 |
sent_vecs @ q_vec |
**Normalize(正规化)**会把向量调成相同长度。完成后,dot product 就能直接当 cosine similarity 使用。
- 不同模型的向量不能混用:它们像两张不同的地图,坐标不能直接比较。
- 查询太短:只有一两个字时,意思不够清楚,搜索结果容易飘。
top_k不是越大越好:拿太多内容会把噪声一起带回来。
三个容易忽略的细节:不同模型的向量不能混用 (像两张不同的地图)、查询太短结果会飘 、top_k 不是越大越好(拿太多会把噪声一起带回来)。
6.4 Vector DB 与两种搜索
**Vector DB(向量数据库)**像一个会按"意思"找东西的抽屉。你先把文档与向量放进去,再用问题找出最接近的文档。
| 核心词 | 白话意思 |
|---|---|
| Collection | 装文档、向量和 metadata 的一个抽屉 |
| Semantic search | 比较意思,不要求文字一模一样 |
| Keyword search | 寻找相同字词,专有名词很准,但同义词容易漏 |
| Metadata filter | 先用标签缩小范围,例如只找 category=tech |
两种搜索怎么选
| 需求 | Keyword search | Semantic search |
|---|---|---|
| 找完全相同的编号或名称 | 很适合 | 可能混淆 |
| 找换句话说的内容 | 容易漏 | 很适合 |
| 要简单、快速 | 很适合 | 要先做 embedding |
| 实际 RAG | 常和 BM25 搭配 | 常和 keyword 结果合并 |
把 keyword 与 vector 结果合并,叫做 hybrid search(混合搜索)。这份练习先把两者分开,让差别看得清楚;Stage 6 主章再连到 Qdrant 与 Weaviate 的正式 hybrid search 文档。
6.5 比较三种 Chunking
**Chunking(切块)**就是把一份长文档切成几个小盒子。盒子太大,细节会被埋住;盒子太小,意思会被切断。
| 核心词 | 白话意思 |
|---|---|
| Chunk | 长文档切出来的一小段 |
| Chunk size | 每一段最多多大 |
| Overlap | 前后两段重复保留的文字,避免句子刚好被切断 |
| Retrieval | 用问题找回最有用的段落 |
三种切法比较
| 策略 | 怎么切 | 适合什么 |
|---|---|---|
| Fixed-length | 每 N 个字切一段 | 没有清楚格式的 log 或聊天记录 |
| Paragraph-based | 遇到空白行就切 | 段落整齐的文章 |
| Heading-aware | 遇到 #、## 标题就切 |
README、wiki、spec |
怎么判断哪种比较好
不要只数 chunk,也不要只看一个漂亮例子。准备真实问题,确认正确答案所在的段落有没有进入 top-k。
| 要看什么 | 问自己 |
|---|---|
| Recall | 正确段落有没有被找回来? |
| Precision | 找回来的段落里,有多少真的有用? |
| 完整性 | 答案需要的句子有没有被切到两边? |
| 成本 | chunk 变多后,embedding 与存储量增加多少? |
- Chunk 太大:一段塞太多主题,向量会变得模糊。
- Chunk 太小:答案需要的前后文可能分散在不同段。
- PDF 不等于纯文本:先处理栏位、表格、页眉页脚,再切块。
- CJK 文字不要用 byte 数硬切;用 Python 字符串、tokenizer 或结构化 parser。
- 进阶做法:先按 heading 切大段,再在段内用固定长度切小段。
6.6 把完整 RAG 接起来
**RAG(Retrieval-Augmented Generation,检索增强生成)**会先找数据,再让模型看着数据回答。它像开卷考试:先翻到对的页,再作答。
| 核心词 | 白话意思 |
|---|---|
| Retrieval | 先找回可能有答案的段落 |
| Generation | 模型读段落后组成答案 |
| Grounding | 答案要能在提供的数据中找到依据 |
| Top-k | 最多拿几段数据给模型看 |
RAG 四步
plain
文档 → 1. chunk → 2. embed/index → 3. retrieve top-k → 4. generate
collection = build_kb(doc)
contexts = retrieve(collection, query, top_k=2)
answer = generate(query, contexts)
| 步骤 | 主要设定 | 出错时会看到什么 |
|---|---|---|
| Chunk | size、overlap、文档结构 | 正确句子被切断 |
| Embed / index | embedding model、数据更新 | 新数据找不到 |
| Retrieve | top_k、filter、reranker |
拿回错段落或漏段落 |
| Generate | prompt、模型、输出限制 | context 对,答案仍乱猜 |
最小 grounding 规则
plain
只根据提供的 context 回答。
如果 context 没有答案,就清楚说不知道。
这能降低乱答,但不能保证零 hallucination。正式系统还需要无答案测试、引用、输出验证与人工抽查。
常见问题
top_k太小会漏数据;太大会把噪声和 token 成本一起放大。- 每次问题都重建 index 很浪费;数据没变时应重用持久化 collection。
- 只测"答得出来"不够,也要测"数据没有答案时会拒答"。
- 进阶可加入 query rewriting、reranker、citation 与 evaluation;先一次只改一个零件。
6.7 让 Agent 下次还记得
普通聊天记录像写在白板上:程序关掉,白板可能就擦掉了。**Long-term memory(长期记忆)**会把值得保留的事写进磁盘,下次开程序还能找回来。
| 核心词 | 白话意思 |
|---|---|
| Working memory | 这次任务眼前正在用的少量信息 |
| Long-term memory | 跨程序重开或跨 session 仍保留的信息 |
| Recall | 用现在的问题找回相关记忆 |
| Memory policy | 决定什么能记、要更新、要忘记、谁能读 |
记忆流程
plain
用户说话
→ 判断值不值得记
→ remember() 写入磁盘
→ 下次问题先 recall()
→ 只把相关记忆放进 prompt
memory = MemoryStore(path=".stage06-memory")
memory.remember("User prefers Python.")
recalled = memory.recall("Which language should I learn?")
Chat history 和长期记忆不是同一件事
| 比较 | Chat history | Long-term memory |
|---|---|---|
| 用途 | 保持眼前对话连续 | 下次还记得重要事实 |
| 放哪里 | 当前 messages | 磁盘或外部数据库 |
| 怎么读 | 最近几轮直接放进 prompt | 先搜索,再取少量相关内容 |
| 风险 | prompt 变太长 | 记错人、记过期数据、删不干净 |
正式系统要有清楚的 memory policy:用户同意、user ID 隔离、更新、删除、期限与审计。
常见问题与 production 下一步
- 不要每句都存;先判断是否真的值得长期保留。
- 同一事实重复出现时,要去重或更新,不要一直新增。
- 用户搬家或改偏好时,要让新记忆取代旧记忆。
- 每位用户必须有独立 namespace,不能互相看到数据。
- 用户要求删除时,要能找到所有副本并确实删除。
- 需要完整生命周期时,再评估 Mem0、Letta 或 LangGraph persistence。
RAG 的两条路可以用一张图讲完:上面一条是「先整理数据」,下面一条是「问题来了再检索」。最稳的起点是 2-step RAG------每个问题都先检索再回答,最容易测。
6.8 RAG 基础流水线:资料怎么进去,答案怎么出来
RAG 有两条路:一条先整理数据,一条在问题来时找资料。

图 6-2 RAG 的两条路:先整理数据,问题来了再检索,并带着证据回答
先从 2-step RAG 开始:每个问题都先检索,再回答,流程最容易测。Agentic RAG 让模型决定要不要找资料、是否改写问题或再找一次;Hybrid RAG 混合固定步骤与 agent 决策。它和 Hybrid Search 不同:Hybrid Search 只是在 retrieval 这一步合并候选。
| 阶段 | 做什么 | 好理解的说法 |
|---|---|---|
| Load | 读入 PDF、网页或数据库内容 | 把书搬到桌上 |
| Split | 切成 chunks | 把书分成小卡 |
| Embed | 把每张卡转成向量 | 帮意思做坐标 |
| Store | 保存向量与来源 metadata | 卡片放进有标签的抽屉 |
| Retrieve | 依问题找候选 chunks | 先拿出可能有答案的卡 |
| Rerank(可选) | 重新排候选内容 | 再检查哪张卡最有用 |
| Generate | 把问题与证据交给模型 | 看着卡片回答 |
| Cite/Evaluate | 显示来源并检查结果 | 告诉别人答案从哪里来 |
Retriever 是"收到问题后,回传相关文档"的接口。它不一定使用 vector database;BM25、SQL、网站搜索与混合搜索也能成为 retriever。
6.9 进阶 RAG:先找出哪一步坏了,再加新技巧
RAG(Retrieval-Augmented Generation):先找相关资料,再依资料回答。
基础 RAG 像"先翻书,再回答"。进阶 RAG 不是把更多零件全装上去,而是先看哪一步找错了资料,再只修那一步。
核心术语
| 核心术语 | 好理解的说法 | 正确意思 |
|---|---|---|
| Baseline(基线) | 还没加新招以前的成绩 | 可重复运行的最小系统与评测结果,用来比较改动是否真的有效。 |
| Hybrid Search(混合搜索) | 同时看"一样的字"和"相近的意思" | 合并 BM25/全文搜索与向量搜索的候选结果。 |
| Reranking(重新排序) | 把拿到的卡片再排一次 | 用另一个模型或规则,重新估计问题与候选文档的相关性。 |
| Query Transformation(查询转换) | 换几种问法再找 | 改写、拆分或扩充问题,以取得不同候选文档。 |
| Contextual Retrieval(上下文检索) | 每张小卡先写上"这张卡来自哪一章" | 建索引前替 chunk 补上文档背景,再做检索。 |
| Corrective/Adaptive RAG | 找得不好就换方法 | 先检查候选质量,再决定重查、改来源或直接回答。 |
| Agentic RAG | 让 agent 自己决定何时翻书 | 把 retrieval 当作工具,由 agent 决定是否、何时及如何调用。 |
| GraphRAG | 不只找卡片,也沿着人物与事件的线找 | 从 entity 与 relationship 建图,支持跨文档关系与整体主题查询。 |
先看症状,再找方法
| 你看到的问题 | 先量什么 | 第一个可试的方法 | 先不要做什么 |
|---|---|---|---|
| 文档里明明有答案,却完全没被找回 | Recall@k、命中率 | 改 chunk、metadata filter 或 Hybrid Search | 先换更大的生成模型 |
| 正确文档有找回,但排在很后面 | MRR(Mean Reciprocal Rank,看首项相关结果排多前)、nDCG(Normalized Discounted Cumulative Gain,对照理想排序看整个排序质量)、前 k 名人工检查 | Reranking | 一口气加 graph 与 agent loop |
| 问题太短、太模糊或包含多个小问题 | 各改写查询的命中率与延迟 | Multi-Query、拆题或 HyDE(Hypothetical Document Embeddings,用假想文档的向量找真实资料;假想内容不是证据) | 无限制产生大量查询 |
| 要回答跨很多文档的关系或整体主题 | 关系覆盖率、global question 测试集 | GraphRAG、LightRAG 或摘要树 | 把 graph 当成每个 RAG 的默认配置 |
| 有些问题根本不需要查资料 | 不必要检索率、成本、延迟 | Adaptive/Agentic RAG | 让 agent 无上限重试 |
| 找到正确证据,回答仍不受证据支持 | Faithfulness/人工引用核对 | 改回答 prompt、引用格式与拒答规则 | 继续调 retrieval 掩盖生成问题 |
从基础到进阶的顺序
先固定一个最小 Baseline
准备 20--50 个有人看过的问题,每题保存预期来源与可接受答案。每次只改一件事,记录 retrieval、answer、延迟与成本。没有 baseline,就不知道新技巧是在帮忙还是添乱。
先修 Retrieval,再修 Generation
- Chunking 决定资料怎么切;先用标题、段落与文档结构切,再测试 fixed-size、parent-child 或 semantic chunking。
- Hybrid Search 扩大候选来源;BM25 找精确字词,vector search 找语义相近内容。
- Reranking 不会创造新文档;它只把已找回的候选重新排列。
问题不好找时,再做 Query Transformation
- Multi-Query:把同一问题改成几种说法,各自搜索后合并。
- HyDE:先产生一段假想答案,再用它搜索;可能提升召回,也可能被假想内容带偏。
- RAG Fusion:对多组查询结果做 rank fusion,降低单一措辞的影响。
- Decomposition:把"比较 A、B 并解释原因"拆成数个可分别找证据的小问题。
需要跨文档关系时,才考虑 GraphRAG
Microsoft GraphRAG 是研究参考实现,官方目前标为 largely in maintenance mode,仍会修复 bug 与依赖问题,但不再以新增功能为主。它的 indexing 可能昂贵,应先用小数据集。LightRAG 是另一套活跃的 graph-based RAG 实现,数据模型与 Microsoft GraphRAG 不同,不能把两者当成同一个产品。
GraphRAG 适合"哪些人物共同影响这件事?"或"整批文档有哪些主题?";单份 FAQ 或精确条款查询,通常先用一般 retriever 就够了。
流程需要判断时,才加 Corrective 或 Agentic RAG
- Self-RAG:模型学习何时检索,并对证据与回答做反思。
- CRAG(Corrective Retrieval Augmented Generation,检索不够好时修正查询或来源)(Corrective RAG):先判断候选是否够好,不够时改查询或改来源。
- Adaptive RAG:依问题难度选择不同流程。
- Agentic RAG:让 agent 决定何时调用 retriever;必须设定步数、时间、成本与可用来源上限。
最后才碰摘要树与程序优化
RAPTOR (Recursive Abstractive Processing for Tree-Organized Retrieval) 把内容反复聚类、摘要成由细到粗的树;细节问题找叶节点,主题问题找高层摘要。DSPy 用 examples 与 metric 调整 LLM(Large Language Model,能读写语言的模型) program;它仍需要清楚任务、可靠资料与评测指标。
6.10 Agent Memory:只记值得记、允许记、能删掉的事
**Agent Memory(代理记忆)**像一本有管理规则的笔记本。它不是把所有聊天偷偷存起来;它只保存之后真的需要、用户允许,而且可以查看、修改与删除的内容。
| 核心术语 | 好理解的说法 | 正确意思 |
|---|---|---|
| Chat History(聊天记录) | 这次对话的逐字稿 | 消息记录;不代表每一则都应永久保存或放进模型 context。 |
| Context(上下文) | 这一刻放在桌上的资料 | 本次模型调用实际看到的 instructions、messages、工具结果与取回内容。 |
| RAG | 有问题时去书架找资料 | 从外部知识来源取回证据,再交给模型回答。 |
| Memory(记忆) | 助理留给下次的短笔记 | 跨步骤、thread 或 session 仍需读回的状态,必须有写入与治理规则。 |
**最重要的判断:**产品手册放知识库;当前任务做到哪里放短期 state;经用户同意保存的偏好才可能进入长期 memory。
两种时间范围
- Short-term Memory(短期记忆):只服务一个 thread 或当前任务,例如消息、上传文件、工具结果与做到哪一步。LangGraph 通常把它放在 thread-scoped state,通过 checkpointer 保存。
- Long-term Memory(长期记忆):跨 thread 或 session 仍需要,例如用户允许保存的偏好、项目事实或可重用经验。它必须用 namespace 隔离不同用户与应用。
短期不等于"只放 RAM";长期也不等于"永远不删"。差别在取回范围与生命周期,不是硬盘或内存的名称。
三种内容类型
| 类型 | 记什么 | 例子 | 风险 |
|---|---|---|---|
| Semantic Memory(语义记忆) | 较稳定的事实 | 用户偏好短答、项目使用 Python 3.13 | 事实会过期或互相冲突 |
| Episodic Memory(情节记忆) | 发生过的事件与结果 | 上次部署在哪一步失败、哪个修法有效 | 成功一次不代表永远适用 |
| Procedural Memory(程序记忆) | 做事规则与步骤 | 发版前要跑哪些 gate | 恶意内容可能污染未来行为 |
Semantic memory 和 semantic search 不是同一件事:前者是记住的内容类型,后者是按意思相近来搜索的取回方法。
一笔 Memory 的生命周期
- 提议写入:先判断是否真的需要跨 session 使用。
- 取得同意:敏感资料或个人偏好要让用户知道保存目的。
- 规范化:保存简短事实,不直接把整段聊天当记忆。
- 加上 metadata:至少有 owner、source、created_at、updated_at、expires_at 与 sensitivity。
- 隔离保存:用 user/workspace/agent namespace 分开,查询前先套权限。
- 搜索与使用:只取回与当前任务相关的少量记忆,并保留来源。
- 更新或解决冲突:新信息不能悄悄和旧信息并存;要标记版本或取代关系。
- 删除与遗忘:用户可查看、修改、删除;过期资料自动清除,备份也要有处理规则。
先选最简单的设计
| 问题 | 先用什么 | 何时升级 |
|---|---|---|
| 字段固定,例如语言、时区、通知偏好 | 直接状态表 | 字段种类变多或需要模糊搜索时 |
| 内容较自由,例如短摘要或可重用经验 | 可搜索文字 memory | 关系、时间与冲突成为主要问题时 |
| 人、事件与关系会随时间改变 | Temporal Knowledge Graph | 只有测试证明一般资料表/搜索不够时 |
| 只需恢复同一个工作流程 | Checkpoint/thread state | 真正需要跨 thread 分享时 |
**先从资料表开始。**能用明确字段保存的内容,不必先做向量搜索;能用短期 state 解决的问题,不必先做永久记忆。
Memory 的安全底线
- 默认不保存密码、API key、付款资料、医疗秘密或未经同意的个人资料。
- 不让不同用户、tenant、workspace 或 agent 共用同一个未隔离 namespace。
- 取回前做权限检查;不能先拿到秘密再靠 prompt 要模型"不要说"。
- 记忆内容是不可信输入。写入前做 schema、来源与 prompt-injection 检查。
- 每笔记忆要能回答"谁写的、从哪里来、何时更新、何时删"。
- 删除要涵盖主要存储、搜索索引、cache 与依政策管理的备份。
Hot path、Background 与冲突处理
- Hot path write:回答前立即写入,结果最新,但会增加延迟,错误也直接影响用户。
- Background write:回复后异步整理,交互较快,但要处理失败、重试与晚到更新。
- 同一事实有新旧版本时,保存时间、来源与有效范围;不要只依向量相似度随机挑一笔。
- 先把"模型建议的 memory"放入待确认区,再由规则或用户批准,适合高风险内容。
常见失败与排查顺序
- 找不到:先看 namespace、权限、filter 与保存是否成功。
- 找到旧资料:看 update 是否留下互相冲突的版本,以及 cache 是否刷新。
- 记太多:提高写入门槛、缩短保存期限,不要只扩大 context window。
- 记错:保留来源与信心,让用户能修改,不把模型推测直接当事实。
- 删不干净:追踪主库、索引、cache、事件串流与备份的删除路径。
6.11 要点回顾与复习索引
- RAG 四步:chunk → embed/index → retrieve top-k → generate;每一步都有各自的失败症状。
- grounding 规则:只依据 context 回答,没有就说不知道;这能降低幻觉,但不保证零幻觉。
- 检索两条路:keyword 精确、semantic 近义,实际系统常合成为 hybrid search。
- chunk 三切法:fixed-length / paragraph-based / heading-aware;用 recall、precision、完整性、成本来判断,不靠数 chunk。
- 检索不好时:先修 retrieval(chunk、filter、hybrid、rerank),再动 query,最后才上 GraphRAG。
- Memory ≠ chat history:前者跨 session、要先搜索再取少量;后者只维持眼前对话。
- 三类内容:semantic(事实)、episodic(事件)、procedural(做法),风险各不相同。
- 生命周期八步:提议 → 同意 → 规范化 → metadata → 隔离 → 搜索 → 更新/解冲突 → 删除。
- 先选最简单的设计:状态表 → 可搜索文字 → 时序知识图 → checkpoint,能简单就别上向量。
| 关键词 | 一句话记忆 | 常见坑 |
|---|---|---|
| Embedding | 句子的坐标卡 | 混用不同模型的向量 |
| Chunk | 切小页卡 | 用 byte 数硬切 CJK |
| top_k | 拿几段给模型 | 越大越好 |
| grounding | 答案要有依据 | 只测「答得出来」不测「拒答」 |
| Memory | 助理的笔记本 | 把整段聊天当记忆存 |
本篇速查卡
复习时只看这张表:看到关键词能接出后半句,说明这一关过了。
| 关键词 | 一句话记忆 |
|---|---|
| CLAUDE.md | 项目级常驻规矩,每次进入都生效 |
| Skill | 按需加载的操作卡,用到才读 |
| MCP | 把外部工具/数据接成标准接口 |
| Hook | 在固定时机自动执行的脚本,不靠模型自觉 |
| Plugin | 打包分发 Skill/Hook/命令的盒子 |
| Subagent | 独立 context 里跑子任务,只回摘要 |
| Chunk | 检索的最小单位,大小决定召回质量 |
| Embedding | 把「意思」变成可比较的坐标 |
| Rerank | 先粗召回再精排序,补向量搜索的短板 |
| Memory | 只记值得记、允许记、能删掉的事 |