如果你还在为 Agent 记不住上一句话而头疼,或者被 RAG 检索不准搞得怀疑人生,那么这篇实战笔记就是为你准备的。

之前我们聊过了 ReAct 和 Plan-and-Solve,但那些都是“一次性”的智能。真正的智能,必须建立在记忆之上。今天,我们不谈虚的,直接拆解《Hello Agents》第八章的核心——如何从零构建一个拥有“工作记忆、情景记忆、语义记忆”且具备高级 RAG 能力的 Agent 框架。

为什么你的 Agent 像个“失忆症患者”?

在动手写代码前,我先问自己一个问题:LLM 到底缺什么?

很多人觉得 LLM 不够聪明,其实它缺的不是智商,而是状态(State)
当你关闭对话窗口,之前的所有交互对模型来说就“从未发生过”。这种无状态(Stateless)的设计,导致了三个致命问题:

  1. 上下文丢失:聊着聊着,它忘了你叫张三。
  2. 知识断层:它不知道昨天刚发布的 Python 3.13 新特性。
  3. 无法进化:它不会从之前的错误中学习,下次还犯同样的错。

为了解决这些问题,我们需要给 Agent 装上两样东西:

  • Memory(记忆系统):解决“我是谁,我之前说过什么”的问题。
  • RAG(检索增强生成):解决“我知道什么,外部世界发生了什么”的问题。

第一部分:模仿人类,设计分层记忆系统

认知心理学告诉我们,人类记忆不是存在一个“大硬盘”里,而是分层的。Hello Agents 框架的设计者非常敏锐地捕捉到了这一点,设计了四层记忆架构

1. 工作记忆 (Working Memory):Agent 的“短期缓存”

这就好比我现在的脑子,只记得住最近几秒的事。

  • 实现逻辑:纯内存存储 + TTL(生存时间)机制。

  # 伪代码示意
  class WorkingMemory:
      def add(self, item):
          self._expire_old_memories() # 先清理过期的
          if len(self.memories) > 50: # 容量满了?
              self._remove_lowest_priority_memory() # 删掉最不重要的
          self.memories.append(item)

  • 我的理解:这里最妙的是混合检索。它不仅看关键词,还用 TF-IDF 算向量相似度。为什么要混用?因为在工作记忆里,速度比精度更重要,TF-IDF 够快,能兜底。

2. 情景记忆 (Episodic Memory):Agent 的“日记本”

“2024年4月10日,用户张三问我怎么配置 Neo4j。” —— 这就是情景记忆。

  • 技术选型:SQLite + Qdrant。
  • 为什么这么选?
    • SQLite 存结构化数据(时间、会话ID、重要性),方便做复杂过滤(比如“查找上周所有的报错记录”)。
    • Qdrant 存向量,负责语义检索(比如“查找关于数据库配置的讨论”)。
  • 评分算法揭秘
      # 这里的权重设计很有讲究
      score = (向量相似度 * 0.8 + 时间近因性 * 0.2) * (0.8 + 重要性 * 0.4)
  • 注意到了吗?时间近因性占了 20%。这意味着,越近发生的事,越容易被想起来。这非常符合人类“喜新厌旧”的特性。

3. 语义记忆 (Semantic Memory):Agent 的“知识库”

这是最高级的记忆,存储的是抽象概念和规则。比如“Python 是解释型语言”,这不随时间改变。

  • 硬核架构:Neo4j(图数据库) + Qdrant(向量数据库)。
  • 深度思考:为什么要引入图数据库?
    • 向量检索只能找到“相似”的东西,但找不到“关系”。
    • 比如你问“张三和李四是什么关系?”,向量检索可能只会给你推一堆包含这两个名字的句子。但 Neo4j 可以顺着图谱路径告诉你:张三 -> 同事 -> 李四
    • 混合排序公式(向量分 * 0.7 + 图关联分 * 0.3)。向量负责广度,图负责深度。

4. 感知记忆 (Perceptual Memory):Agent 的“五官”

支持图片、音频。这里用了 CLIP 模型做图像编码,让 Agent 能“看懂”截图里的代码。


第二部分:RAG 不只是“搜一下”那么简单

很多人对 RAG 的理解还停留在:切分文档 -> 存向量 -> 搜一下 -> 扔给 LLM
但在 Hello Agents 的实现里,我看到了工业级 RAG 的影子。

1. 统一入口:MarkItDown 的威力

不管你是 PDF、Word、Excel 还是 PPT,全部通过 MarkItDown 转成 Markdown。

  • 好处:Markdown 有天然的层级结构。
  • 智能分块:不再是死板的每 500 字切一刀,而是基于标题层级切分。这样每个 Chunk 都带着完整的上下文路径,比如 第一章 > 第二节 > Python基础

2. 高级检索策略:MQE 与 HyDE

这是本章最让我惊艳的部分。普通的 RAG 搜不到,往往是因为用户问法和文档写法不一致

  • MQE (多查询扩展)
    • 用户问:“怎么学 Python?”
    • Agent 内部自动扩展成:“Python 入门教程”、“Python 学习路线”、“Python 基础语法”。
    • 效果:召回率直接拉升 30%。
  • HyDE (假设文档嵌入)
    • 思路极其清奇:先用 LLM 编一个假答案,然后用这个假答案去搜真文档。
    • 为什么有效?因为“假答案”和“真文档”在语义空间里长得更像,而和问题长得不像。
    • 实测感受:在处理专业术语时,HyDE 简直是神技。

第三部分:实战!构建一个“会学习”的 PDF 助手

理论讲再多,不如跑个 Demo。我基于框架写了一个 PDFLearningAssistant,它不仅能回答问题,还能记住你的学习轨迹

智能路由

def ask(self, question: str):
    # 1. 先查记忆:用户之前问过类似的问题吗?
    memory_result = self.memory_tool.search(question, type="semantic")
    
    # 2. 再查文档:RAG 检索最新知识
    rag_result = self.rag_tool.ask(question, enable_hyde=True)
    
    # 3. 融合回答
    return self.llm.generate(f"基于记忆:{memory_result} 和文档:{rag_result},回答:{question}")

当我上传了 Happy-LLM.pdf 后:

  1. 加载阶段:自动解析 PDF,建立向量索引,并在情景记忆里记下:“用户加载了 Happy-LLM 文档”。
  2. 提问阶段:我问“什么是 RAG?”,它不仅给出了定义,还提示我:“你之前在第三章也问过类似的概念,需要对比看看吗?”
  3. 报告生成:结束时,它能生成一份 JSON 格式的学习报告,包含我读了多久、问了几个问题、掌握了哪些概念。

这一刻,我感觉它不再是一个冷冰冰的搜索框,而是一个真正的“助教”。


第四部分:我的深度思考与踩坑总结

1. 为什么不用 LangChain?

很多人会问,LangChain 不是都有吗?

  • 黑盒 vs 白盒:LangChain 封装得太好,导致你很难修改底层的检索逻辑。而 Hello Agents 这种轻量级框架,让你清楚地看到每一个向量是怎么存、怎么查的。
  • 过度设计:对于学习而言,LangChain 的复杂性掩盖了核心原理。手写一遍 Memory Manager,胜过读十篇教程。

2. 向量数据库的选型陷阱

在配置 Qdrant 时,我踩了一个坑:维度不匹配

  • 如果你用的是 text-embedding-v3,维度是 1024。
  • 如果你用的是本地 all-MiniLM-L6-v2,维度是 384。
  • 教训:在初始化 Vector Store 时,一定要动态获取 Embedding 模型的维度,不要硬编码!

3. “遗忘”也是一种智慧

框架里实现了 forget 机制。起初我觉得多余,后来发现:

  • 如果不遗忘,向量库会越来越大,检索越来越慢。
  • 如果不遗忘,过时的信息(比如“Python 3.9 是最新版”)会干扰当前的回答。
  • 建议:在生产环境中,一定要设置基于时间的自动遗忘策略。

结语:从“调包侠”到“架构师”的距离

读完第八章,我最大的感触是:AI 应用的竞争,最终是数据架构的竞争。

谁能更好地管理记忆,谁能更精准地检索知识,谁的 Agent 就更智能。Hello Agents 框架虽然轻量,但它展示的分层记忆思想混合检索策略,是构建任何高级 Agent 系统的基石。

下一步计划:
我打算在这个框架基础上,加一个“主动反思”模块。当 Agent 发现回答置信度低时,主动去更新自己的语义记忆。


👋 互动时间:
你在做 RAG 应用时,遇到过最头疼的检索不准的情况是什么?欢迎在评论区留言,我们一起探讨解决方案!

如果觉得这篇文章对你有帮助,欢迎点赞、收藏、转发!你的支持是我继续深挖底层原理的最大动力。

更多推荐