📖 Day 9 学习页:记忆系统与 RAG

Day 9:记忆系统与 RAG

🎯 今日目标:让 Agent "记住"该记的东西——短期记忆管对话历史(带裁剪), 长期记忆/RAG 管知识检索。理解了今天的内容,你就理解了 ChatGPT 的"记忆"和"知识库问答"的全部原理。

📚 本日资源:📝 练习模板 | 📋 手动验收清单

⏱ 今日安排(约 2 小时)

时间内容方式
40min理论学习:三种记忆 + RAG 五步阅读 + 编码
40minRAG 实战:向量检索 + 检索器编码
40min动手实操:带记忆的 Agent + 上下文裁剪编码

📖 第一步:Agent 的三种记忆

类型存什么实现方式生命周期
短期记忆当前对话的消息历史消息列表 + 滑动窗口裁剪本次会话
长期记忆用户偏好、事实、文档知识向量库检索(RAG)跨会话持久
工作记忆当前任务的草稿/中间结果scratchpad / state 字段本次任务

为什么短期记忆要裁剪:模型上下文窗口有限(且越长越贵),10 轮对话后历史可能已超限—— 所以要滑动窗口(只留最近 N 条)或摘要压缩(把旧历史总结成一段话)。

class ShortTermMemory:
    def add(self, role, content):
        self.messages.append(ConversationMessage(role, content))
        if len(self.messages) > self.max_messages:
            # 裁剪最旧的非 system 消息(system 是人设,必须永远保留)
            for i, m in enumerate(self.messages):
                if m.role != "system":
                    del self.messages[i]
                    break

📖 第二步:RAG(检索增强生成)五步流程

① 知识入库    文档 → 切块(chunk) → 每块算 embedding → 存进向量库
                                        │
用户提问 ──► ② 问题也算 embedding ──────┤
              ③ 相似度检索:找出最相关的 top_k 块
              ④ 把检索到的知识拼进 Prompt:
                  "请参考以下资料回答:\n{检索结果}\n\n问题:{用户问题}"
              ⑤ LLM 生成 —— 答案基于真实资料,不再靠幻觉

本练习用关键词重合度代替 embedding(纯标准库能跑);原理完全一致—— 正式项目把 SimpleVectorStore 换成 ChromaDB/FAISS + embedding 模型即可,接口不变。 注意:英文按空格分词,中文没有空格,要按字/bigram 或 jieba 分词,否则检索直接失效(模板已处理)。

🛠 第三步:动手实操

  1. 打开模板:day09_practice_template.py:
    • TODO 1.1-1.4:ShortTermMemory 添加/裁剪/格式转换/清空
    • TODO 2.1-2.2:SimpleVectorStore 添加与检索(关键词重合度打分即可)
    • TODO 3.1-3.2:RAGRetriever 知识入库 + 检索并格式化成可拼接的文本
    • TODO 4.1:MemoryAgent.chat() —— 先检索相关知识注入 prompt,再走对话,回答写回短期记忆
    • TODO 5.1:compress_conversation() —— 按估算 token(1 个中文字 ≈ 2 token)从新到旧保留,system 不丢
  2. 运行自测:python day09_practice_template.py。 测试 4 是记忆的"图灵测试":先告诉它"我叫张三,我喜欢 Python",再问"我叫什么名字?"—— 答对了说明记忆链路通了。
  3. 验收:python day09_practice_validator.py —— 验收会真的裁剪你的记忆、 检索你的向量库、跑两轮对话检查记忆是否留存。
  4. 想清楚三个问题:裁剪为什么保留 system?检索为什么比"把所有知识塞 prompt"好?压缩和滑动窗口各适合什么场景?

⚠️ 避坑

  • ❌ 对话历史无限制地append → 超出上下文窗口直接报错;必须有裁剪或压缩策略
  • ❌ 中文文本用空格分词做检索 → 整句一个'词',检索永远失灵(要用分词/字符级匹配)
  • ❌ Embedding 模型中英文不匹配 → 中文用 bge-large-zh 或 text-embedding-3-small
  • ✅ 记忆不是越多越好——塞一堆无关历史反而稀释重点,相关性检索才是关键

🔗 延伸资源