LangGraph 10. 记忆管理与三层记忆 与 OpenClaw Memory 模块介绍

摘要 :智能体要在多轮对话中保持连贯、在跨会话中记住用户偏好与关键信息,离不开记忆管理 。本章围绕一个完整的「中介留学咨询智能办理」案例展开,刻意不依赖任何 LangGraph Memory 模块 ,而是用最普通的工程手段------history 参数、SQLite 数据库和本地 Markdown 文件------来实现一套与 OpenClaw Memory 思路高度相似的三层记忆体系:短期记忆:当前会话的对话历史与槽位状态;中期记忆:按日记录的槽位变更日志;长期记忆:机构规则与经验沉淀在 MEMORY.md 中,并在前端可视化编辑。在后文中,我们还会引入 OpenClaw 的 Memory 设计(Short-Term / Daily Logs / MEMORY.md + Hybrid Search),并给出与本章实现的结构映射与差异对照,帮助你在自建项目时,既理解 LangGraph 的 State + Checkpointer / Store 方案,又能借鉴 OpenClaw 在记忆运营与维护上的最佳实践。

关键词:记忆管理;短期记忆;长期记忆;SQLite;三层记忆;每日日志;MEMORY.md;OpenClaw;Hybrid Search


1 为什么智能体需要记忆?

想象一位助手:若每次见面都像第一次见面,你需要反复介绍自己、重复偏好、重复项目背景,体验会非常糟糕。智能体同样如此:若没有记忆,每次请求都从零开始,无法维持对话连贯性,也无法在多次交互中学习与个性化。

记忆管理要解决两类需求:

  • 当前会话内的连贯:刚说过的话、上一条回复、本轮的中间结果,都要在「当前这一条对话线」里可用。
  • 跨会话的持久与召回:用户偏好、历史决策、项目关键信息等,要在不同会话、甚至不同线程间被检索并注入当前上下文。

前者对应短期(上下文)记忆 ,后者对应长期(持久)记忆。二者结合,智能体才能既「记得本轮在聊什么」,又「记得用户是谁、以前做过什么决定」。

💡 理解要点 :记忆 = 短期(会话内 state + 持久化) + 长期(跨会话、可检索的存储) ;LangGraph 用 checkpointer 管短期、用 Store 管长期。


2 短期记忆与长期记忆的区分

维度 短期记忆(上下文记忆) 长期记忆(持久记忆)
作用范围 单一线程/会话内 跨会话、跨线程,可按用户/应用组织
典型内容 当前对话消息、本轮的中间状态 用户画像、偏好、历史决策、事实与经验
容量与限制 受 LLM 上下文窗口限制,需做裁剪/摘要 外部存储,容量大,通过检索按需注入
在本章 Demo 中 Gradio 传入的 history + SQLite 中的 slots_info_dict 本地 Markdown 文件(MEMORY.md + 每日日志),按需人工或程序检索

在「纯工程实现」里,短期记忆本质上就是「当前会话可见的状态」:通常包括前端传入的 history(上一轮对话消息列表)和后端从数据库中恢复的结构化槽位。我们可以在进入 LLM 之前对 history 做截断(例如只保留最近 N 轮),再把当前轮用户输入 append 上去,构造出这一轮调用所需的上下文。\n\n长期记忆则往往存放在图外部的可检索存储 里:可以是关系型数据库、KV 存储,或像本章一样直接用 Markdown 文件(MEMORY.md)承载规则和经验;真正「记忆」的是这些持久文件或表,而在对话中只是在需要时读出来,拼进 prompt 再调用模型。

🔍 实际例子:用户在第一轮说「请记住我喜欢用暗色主题」;短期记忆里会有这条消息和助手的回复;若同时把「用户偏好:暗色主题」写入 Store 的长期记忆,下一周在新会话里问「根据我的偏好推荐一个 IDE 设置」,智能体可以从 Store 检索到该偏好并回答。


3 本章 Demo 项目:中介留学咨询智能办理

本章使用的 Demo 项目是一个中介留学咨询售前机器人,目标是在官网/小程序中自动完成「售前接待 + 信息引导收集」,替代人工客服,降低运营成本。典型业务场景是:

  • 家长或学生发来一句自然语言问题(如「想去英国读博士」);
  • 机器人主动引导,围绕 六大主题 有序地收集关键信息:
    1. 留学目标与意向(目标院校、学位类型);
    2. 学业背景(当前学校、GPA);
    3. 专业与职业规划(目标专业、留学目的);
    4. 经济与预算(学费预算、生活费预算);
    5. 奖学金需求;
    6. 用户补充说明。

在产品体验上有三个要求:

  • 主动引导:机器人能根据缺失信息自动追问,而不是被动回答;
  • 按主题推进:每次围绕一个主题的所有子问题展开,收集完再总结并开启下一主题;
  • 灵活对话:用户可以一次说多个主题的信息(如院校 + 学位 + 当前学校 + GPA),系统也能正确抽取并更新槽位。

核心方案:一次 LLM + 策略编排。这个 Demo 的核心设计是:

  • 一次 LLM 调用完成槽位抽取

    • 每一轮仅调用一次大模型,使用 Function Calling 把用户输入中的信息抽到预定义的槽位结构中(如 intention_schoolacademic_degree 等);
    • 是否继续追问、追问哪些槽位、如何总结当前主题,都不再让 LLM 来"自由发挥",而是由纯逻辑和模版控制
  • 策略编排层负责「总结 + 追问」

    • 使用 get_next_message_by_slots 遍历当前 filled_slots,找出第一个还有缺失槽位的主题,并返回:
      • next_collect_slot_list:下一轮要收集的槽位列表;
      • is_all_field_missing:当前主题是否一个槽位都没填;
      • theme:当前主题函数名(如 get_academic_info)。
    • 根据缺失情况决定:
      • 若当前主题完全没填 → 使用 main_question_schema[theme] 里的整句标准话术发问;
      • 若部分已填 → 使用 params_schema 中的中文槽位名拼出「还缺哪些信息」的追问话术;
      • 若当前主题已填完且还有下一个主题 → 调用 FunctionCallSummaryConfig 对本主题做总结,并开启下一个主题;
      • 若全部主题都填满 → 用 final_message_template 生成结束语。
  • 槽位持久化与跨会话恢复

    • 所有槽位信息以 JSON 字符串的形式保存在本地 SQLite 数据库 consult.dbslot_info_table 中,键为 group_id
    • 用户再次进入时,只要带上同一个 group_id,系统就能从数据库中读出上次的槽位进度,继续推进后续主题。

这套架构的优势是:

  • 高效:每轮只调用一次 LLM,不做「总结 + 追问」的第二次调用;
  • 可控:总结与追问完全由模板和逻辑驱动,避免 LLM 临场发挥导致流程跑飞;
  • 稳定:槽位持久化在 SQLite 中,跨会话连续性和一致性有保障。

4 基于案例的三层记忆设计

在中介留学咨询这个业务场景中,我们希望不仅能在一轮对话内保持连贯 ,还能按天回看发生了什么 ,并逐渐沉淀出一份跨会话可复用的"经验库"。为此,本章在原方案上叠加了一套三层记忆 + 文件为源的设计,与 LangGraph 的「state + checkpointer / store」形成互补。

4.1 三层结构与对应代码

层级 对应物 持久化与范围 主要代码位置
短期 当前会话对话 + 槽位状态 单次会话,受上下文窗口限制 chat_process_client.py / main.py / memory_file_utils.py
中期 每日日志(每日槽位变更摘要) memory_files/memory/YYYY-MM-DD.md memory_file_utils.append_daily_log
长期 精选记忆(规则、经验、画像等) memory_files/MEMORY.md memory_file_utils.load_memory_md/save_memory_md

下面分别说明三层记忆在代码中的具体实现方式。

4.2 短期记忆:当前会话上下文 + 槽位状态

短期记忆的来源有三部分:

  1. LLM 调用上下文(传给大模型的 history)

    chat_process_client.chat_round 中,函数签名为:

    python 复制代码
    async def chat_round(
        current_message: str,
        history: List[Dict[str, str]],
        group_id: str = "12",
        slot_info_out: Optional[Dict[str, Any]] = None,
    ) -> AsyncGenerator[str, None]:
    • history 是上一轮 Gradio 传入的消息列表,元素形如:
      {"role": "user"|"assistant", "content": "..."}
    • 为避免上下文过长,只保留最近 MAX_SHORT_TERM_ROUNDS 轮问答:
    python 复制代码
    MAX_SHORT_TERM_ROUNDS = 5
    trimmed_history = history[-2 * MAX_SHORT_TERM_ROUNDS :] \
        if len(history) > 2 * MAX_SHORT_TERM_ROUNDS else list(history)
    
    new_history_list: List[Dict[str, str]] = []
    new_history_list.append({"role": "system", "content": SYSTEM_PROMPT})
    new_history_list.extend(trimmed_history)
    new_history_list.append({"role": "user", "content": current_message})
    • 这部分就是传给 DeepSeek 模型的短期上下文
  2. 槽位状态(结构化短期记忆)

    • 每次进入 chat_round,都会从 SQLite 中读取当前 group_id 的槽位:

      python 复制代码
      past_records = await Read_SlotInfo(db_client, table_name=config.slot_table_name, group_id=group_id)
      if past_records:
          all_filled_slots = copy.deepcopy(json.loads(past_record["slots_info_dict"]))
          all_filled_slots = sort_nested_dict(input_dict=all_filled_slots)
      else:
          all_filled_slots = copy.deepcopy(tool_config_instance.slot_dict)
          # 首次对话时插入空槽位记录
          await insert_SlotInfo(...)
    • all_filled_slots 的结构大致为:

      python 复制代码
      {
        "get_academic_info": {"intention_school": "英国", "academic_degree": "博士"},
        "get_major_info": {"current_school": "某大学", "gpa_point": "3.5"},
        ...
      }
    • chat_round 会把最新的 all_filled_slots 写入 slot_info_out["slots"],供前端展示:

      python 复制代码
      def _emit_slots() -> None:
          if slot_info_out is not None:
              slot_info_out["slots"] = copy.deepcopy(all_filled_slots)
    • 前端 main.py 中的 slot_display 使用 _format_slots_as_markdown(all_filled_slots) 将其渲染为 Markdown 表格,作为短期记忆的结构化视图

  3. 短期记忆快照文件(人类可读)

    • 为了方便调试与教学,本项目还会将当前会话的完整 history 写入 Markdown 文件:

      python 复制代码
      from memory_file_utils import save_short_term_history
      
      # 在 chat_round 读取完 all_filled_slots 后调用
      save_short_term_history(group_id=group_id, history=history)
    • memory_file_utils.py 中:

      python 复制代码
      def save_short_term_history(group_id: str, history: List[Dict[str, str]]) -> str:
          path = _SHORT_TERM_DIR / f"{group_id}.md"
          lines = [f"# 短期记忆快照(group_id: {group_id})\n"]
          for msg in history or []:
              role = msg.get("role", "")
              content = str(msg.get("content", "") or "").strip()
              ...
              if role == "user":
                  lines.append(f"**[用户]** {content}\n")
              elif role == "assistant":
                  lines.append(f"**[助手]** {content}\n")
          path.write_text("\n".join(lines), encoding="utf-8")
    • 这些文件保存在 memory_files/short_term/{group_id}.md,在 Gradio 的「记忆可视化」Tab 中以只读形式展示。

⚠️ 注意 :真正传给 LLM 的短期记忆是 trimmed_history + current_message,而 short_term/*.md 更偏向「人类审计」用途。

4.3 中期记忆:每日日志(Daily Logs)

中期记忆用来回答「这几天我们都聊了什么、填了哪些信息」,在代码中通过 memory_files/memory/YYYY-MM-DD.md 实现。

  1. 写入时机:槽位有实质更新后

    chat_round 中,当 Function Calling 导致某些槽位发生变化时,会设置 is_slot_changed = True 并更新 all_filled_slots。更新完成、写回 SQLite 后,会调用:

    python 复制代码
    if is_slot_changed:
        summary_for_log = whole_function_response.strip() or current_round_slots_info.strip()
        append_daily_log(group_id=group_id, slots=all_filled_slots, summary=summary_for_log)
    • whole_function_response:本轮函数调用的自然语言总结(如「目标院校:UCLA 攻读学位:博士生」);
    • current_round_slots_info:本轮新增或更改的槽位信息。
  2. 具体写入逻辑

    memory_file_utils.append_daily_log 的实现如下:

    python 复制代码
    def append_daily_log(group_id: str, slots: Dict[str, Dict[str, str]], summary: str) -> str:
        today = date.today()
        path = _DAILY_DIR / f"{today.isoformat()}.md"
        if not path.exists():
            path.write_text(f"# {today.isoformat()}\n\n", encoding="utf-8")
    
        with path.open("a", encoding="utf-8") as f:
            ts = datetime.now().strftime("%H:%M")
            f.write(f"## {ts} - group_id: {group_id}\n")
            if summary.strip():
                f.write(f"槽位摘要:{summary.strip()}\n")
            slots_json = json.dumps(slots, ensure_ascii=False)
            f.write(f"原始槽位:`{slots_json}`\n\n")
        return str(path)
    • 每天一个文件,例如 memory_files/memory/2026-03-16.md
    • 每次槽位更新会追加一个小节,包含时间戳、group_id、本轮摘要、完整槽位 JSON。
  3. 前端展示

    • 在「记忆可视化(三层)」Tab 中,mid_term_display 会调用:

      python 复制代码
      mid_term_display = gr.Markdown(value=load_daily_logs(), label="最近几天的每日日志")
    • load_daily_logs(days=3) 会合并最近 3 天的 daily log,以 Markdown 形式展示所有条目。

4.4 长期记忆:MEMORY.md(语义知识与经验)

长期记忆使用 memory_files/MEMORY.md 承载,更偏向于规则 / 经验 / 机构画像,而不是具体对话细节。

  1. 文件结构与代码接口

    • 文件路径:demo_codes/memory_files/MEMORY.md

    • memory_file_utils.py 中:

      python 复制代码
      def load_memory_md() -> str:
          _ensure_dirs()
          return _MEMORY_MD.read_text(encoding="utf-8") if _MEMORY_MD.exists() else ""
      
      def save_memory_md(content: str) -> str:
          _ensure_dirs()
          _MEMORY_MD.write_text((content or "").strip() + "\n", encoding="utf-8")
          return str(_MEMORY_MD)
    • _ensure_dirs() 会在首次运行时创建 memory_files/ 目录,并写入一份默认的 MEMORY.md 模板。

  2. 前端编辑与刷新

    在「记忆可视化(三层)」Tab 中:

    python 复制代码
    long_term_box = gr.Textbox(
        value="",
        label="MEMORY.md(长期精选记忆)",
        lines=14,
        max_lines=30,
    )
    
    save_btn.click(
        fn=_on_save_long_term,  # 内部调用 save_memory_md
        inputs=[long_term_box],
        outputs=[save_status, long_term_box],
    )
    
    refresh_lt_btn.click(
        fn=load_memory_md,
        inputs=[],
        outputs=[long_term_box],
    )
    
    # 页面加载时自动从磁盘读取最新 MEMORY.md
    demo.load(
        fn=load_memory_md,
        inputs=[],
        outputs=[long_term_box],
    )
    • 用户可以在前端直接编辑 MEMORY.md,并点击「保存到长期记忆」覆盖写入文件;
    • 点击「刷新显示」或刷新浏览器页面时,会再次从磁盘读取最新内容,保证前后端一致。
  3. 使用长期记忆增强 LLM(可选)

    当前 Demo 中,MEMORY.md 主要用于展示和教学。实际项目中,可以在调用 LLM 前增加一步:

    • MEMORY.md 做关键词或向量检索,选出与当前问题相关的若干段落;
    • 将这些段落拼接到 system prompt 或 context 中,让模型在回答时能利用长期知识;
    • 这样可以实现「记得机构规则与经验」的留学顾问,而不必把所有规则硬塞进 prompt。

5 参考体系:OpenClaw Memory 与本章三层记忆对比

本节简要介绍 OpenClaw 的 Memory 体系(基于官方文档 https://learnopenclaw.com/core-concepts/memory),并对照本章的三层记忆设计,帮助你把「平台级记忆框架」和「单项目工程实现」放在一起理解。

5.1 OpenClaw Memory 的整体设计(更详细版)

按照 OpenClaw 官方文档,Memory 分为三层,并配套若干 hook + 搜索策略 + 运维 ritual,组成一个「既能记、又能管、还能定期清洗」的完整体系。

注意,在 OpenClaw 语境里,hook 指的是:当系统运行到某个固定时机(例如会话结束、会话启动、执行命令后),就会自动触发一段预先定义好的流程来做事(比如写 daily log、加载 MEMORY.md、记录命令)。开发者只需要在 openclaw.json 里开关 + 配置参数,不需要自己在代码里到处插入文件读写逻辑。

5.1.1 三层结构与职责边界
  • Layer 1:Short-Term(Conversation Context)

    • 载体:当前会话的上下文窗口(历史消息列表);
    • 生命周期:仅限本次对话,会话结束即失效;
    • 限制:受模型上下文长度约束,对超长会话会自动「遗忘」早期内容;
    • 工程上不额外持久化,由 LLM / 对话框架自然承担。
  • Layer 2:Medium-Term(Daily Logs)

    • 载体:按日期划分的 Markdown 文件,例如:
      • memory/daily/2026-02-16.md
      • 每个文件中按时间分小节(09:15 / 11:30 / ...),记录当天多个会话的摘要;
    • 生成方式:由 session-memory hook 在每次会话结束时 自动触发:
      • 对本次会话做摘要(可调「短 / 中 / 长」三档,是否包含 actions);
      • 以时间戳 + 主题 title 形式 append 到当日文件;
    • 角色:作为「预压缩前的原材料」,后续从中抽取值得进入长期记忆的条目。
  • Layer 3:Long-Term(MEMORY.md

    • 载体:单一的 MEMORY.md 文件,结构推荐类似:
      • ## Active Projects / ## Key Decisions Made / ## Ongoing Preferences / ## People & Context 等分区;
    • 内容:仅保留长期稳定、跨会话都重要的事实与偏好,例如:
      • 正在进行的项目、上线节奏;
      • 做过的重要决策及日期与依据;
      • 长期偏好(写作风格、作息、沟通偏好等);
    • 加载方式:通过 boot-md hook,在每次新对话「启动阶段」自动读入,成为 agent 的默认背景。
5.1.2 关键 hooks:如何写入 / 加载记忆

OpenClaw 把记忆操作抽象为若干 hook,开发者只需在 openclaw.json 中配置,不必自己写 IO 逻辑:

  • session-memory hook:负责"写日记"

    json 复制代码
    {
      "hooks": {
        "session-memory": {
          "enabled": true,
          "summaryLength": "medium",
          "includeActions": true,
          "dailyLogPath": "./memory/daily/"
        }
      }
    }
    • summaryLengthshort / medium / long,控制 daily log 中摘要的粒度;
    • includeActions:是否记录 agent 执行的命令、修改文件等操作;
    • dailyLogPath:daily logs 的根目录;
    • 触发时机:每次对话结束;若会话异常中止(crash / timeout)则可能不会写入。
  • boot-md hook:负责"上电就读配置"

    json 复制代码
    {
      "hooks": {
        "boot-md": {
          "enabled": true,
          "files": [
            "SOUL.md",
            "IDENTITY.md",
            "USER.md",
            "MEMORY.md"
          ]
        }
      }
    }
    • 作用:每次新建会话前,自动把上述文件内容读入模型上下文;
    • 影响:这些文件越长,占用的上下文预算越多,留给「当前任务」的空间越少,因此文档中强烈建议控制 MEMORY.md 长度(例如 < 200 行)
  • command-logger hook:负责"记录动作轨迹"

    json 复制代码
    {
      "hooks": {
        "command-logger": {
          "enabled": true,
          "logPath": "./memory/commands/",
          "includeOutput": false
        }
      }
    }
    • 记录 agent 实际执行过的命令、文件修改、API 调用;
    • 主要用于「审计 + 调试」,有需要时再结合 daily logs 与 MEMORY.md 一起分析。
5.1.3 Hybrid Search:如何从记忆中检索

当 agent 需要「想起」某些信息时,OpenClaw 对 MEMORY / daily logs 使用 Hybrid Search

  • 70% 语义向量搜索

    • 把段落 embedding 进向量索引,找出语义上最相关的若干条;
    • 适合问题表达和记忆条目用词不完全一致的情况(如「课程定价策略」 vs 「Course pricing」)。
  • 30% BM25 关键词搜索

    • 对具体名称、日期、项目ID 等做精确匹配;
    • 保证关键字不会被语义距离「平均掉」。

因此,OpenClaw 文档特别强调写 MEMORY.md 的时候要:

  • 使用自然语言完整句子,给向量搜索足够语义上下文;
  • 同时保留关键名词和术语,保证 BM25 能抓到;
  • 将相关信息按段落分块,避免一个段落塞太多不相关事实。
5.1.4 记忆"运营":预压缩、每周回顾与陈旧记忆

OpenClaw 不是只解决「怎么写入」,还很强调「怎么清理和重构」:

  • Pre-Compaction(预压缩)流程:

    1. 定期(比如每周)回看最近 7--14 天的 daily logs;
    2. 抽取真正长期有价值的信息(新项目、关键决策、稳定偏好);
    3. 将其写入 / 更新 MEMORY.md 中相应板块;
    4. 已经抽取完毕的 old daily logs 可以归档或删除。
  • Weekly Memory Review(每周记忆回顾)

    • 官方给的 checklist 包括:

      • 是否有新的常驻项目 / 偏好需要加入 MEMORY.md
      • MEMORY.md 中是否有已结束项目 / 废弃偏好需要移除?
      • 当前长度是否过长(>200--300 行)?能否合并或删减?
    • 推荐用 cron 自动提醒:

      json 复制代码
      {
        "crons": [
          {
            "label": "Weekly Memory Review",
            "schedule": "0 18 * * 0",
            "prompt": "It's time for the weekly memory review. Summarize the daily logs from this past week and suggest updates to MEMORY.md. Show me the proposed changes before making them."
          }
        ]
      }
  • Stale Memory(陈旧记忆)问题与诊断:

    • 典型症状:
      • Agent 总提已经结束的老项目;
      • 建议基于几个月前的偏好;
      • MEMORY.md 巨长,daily logs 中反复出现同样信息。
    • 对策:
      • 主动删除或归档过期项目;
      • 对「偏好」类记忆设置"保鲜期"(如 3 个月没用就考虑移除);
      • 保持 MEMORY.md 只存真正「长期稳定」的信息。

5.2 与本章三层记忆的结构映射

如果把本章的实现与 OpenClaw 的三层结构对照,大致对应关系如下:

OpenClaw 层级 OpenClaw 载体 本章对应层级 本章载体
Short-Term 当前会话上下文(模型上下文窗口) 短期记忆 trimmed_history + current_message + SQLite 中的 all_filled_slots
Medium-Term Daily Logs(memory/daily/2026-02-16.md 等) 中期记忆 memory_files/memory/YYYY-MM-DD.md,记录时间、group_id、本轮槽位摘要与完整槽位 JSON
Long-Term MEMORY.md(通过 boot-md hook 加载) 长期记忆 memory_files/MEMORY.md,可在前端直接编辑与刷新

可以看到,两者在分层思想和持久化载体(Markdown 文件)上是高度一致的

  • 都用对话上下文做短期记忆;
  • 都通过按日 Markdown 日志承载中期记忆;
  • 都用单一 MEMORY.md 文件来保存长期精选记忆。

不同的是,本章出于教学与业务 Demo 的目的,对中期层加上了更多结构化槽位信息group_id 维度,对长期层则提供了一个简单可视化编辑界面,更贴近「单个业务项目」的实际接入形态。

5.3 差异与互补点:平台级框架 vs. 项目级实现

从工程视角看,两套方案可以理解为「同一理念的两个落点」:

  • OpenClaw 更像是"平台级记忆基础设施"

    • 通过 session-memory / boot-md / command-logger 等 hook,把「写日记、加载长期记忆、记录命令」统一封装;
    • 提供 Hybrid Search 与「Weekly Memory Review」等运维建议,关注记忆的长期健康与陈旧问题
    • 上层应用不必关心具体文件结构,只通过框架能力使用记忆。
  • 本章 demo 更像是"单项目的工程化实现模板"

    • 把 Short-Term / Daily Logs / MEMORY.md 三层记忆全部用显式代码实现(SQLite + Markdown + Gradio UI),便于在任何框架下复用;
    • 中期层紧贴业务槽位(留学咨询六大主题),方便运营同学按 group_id 回看具体填数过程;
    • 长期层 MEMORY.md 目前主要展示/人工编辑,未来可以再叠加「预压缩」与「混合检索」逻辑,向 OpenClaw 的实践看齐。

换句话说:OpenClaw 给了一个「怎么运营记忆」的宏观实践,本章给了一个「如何在你自己的 Python 项目里抄一套类似架构」的最小可行代码实现。你可以同时参考两者:

  • 架构上沿用本章的三层结构与 SQLite + Markdown 方案;
  • 流程与治理上借鉴 OpenClaw:定期从 daily logs 抽取/更新 MEMORY.md,控制文件长度,避免陈旧记忆。

6 本仓库示例一览与运行方式

文件/目录 说明
demo_codes/README.md 环境、依赖、两种运行方式(LangGraph 记忆图 / 文件型记忆)及步骤说明
demo_codes/requirements.txt Python 依赖(langgraph、langchain-*、python-dotenv 等)
demo_codes/config_parser.py .env 读取 API Key 等配置
demo_codes/memory_graph.py LangGraph 图:短期记忆(MemorySaver + thread_id)+ 长期记忆(InMemoryStore + namespace),节点内 search/put
demo_codes/file_style_memory.py 文件型记忆:MEMORY.md + memory/YYYY-MM-DD.md 文件结构、混合检索(关键词 + 可选向量)、预压缩前刷新模拟,对应 OpenClaw 三层记忆的项目级实现版本
demo_codes/main.py 入口:运行 LangGraph 记忆示例,或运行文件型记忆示例(见 README)

demo_codes 目录下执行:

bash 复制代码
pip install -r requirements.txt
# 配置 .env 中的 OPENAI_API_KEY(或 DASHSCOPE_API_KEY 等)
python main.py               # LangGraph 短期+长期记忆示例
python main.py --file-style  # 文件型记忆(MEMORY.md + 每日日志 + 混合检索)示例

详见 demo_codes/README.md


7 小结

  • 短期记忆 :LangGraph 用 State(如 messages)+ Checkpointer 按 thread 持久化,实现多轮对话不丢上下文;在本章的非 LangGraph 版中,用 history + SQLite 槽位实现同等能力,对标 OpenClaw 的 Short-Term 会话上下文。
  • 长期记忆 :用 Store (namespace + put/get/search),在节点内通过 Runtime 注入;在文件型实现中则落地为 MEMORY.md + 每日日志 + 混合检索,对标 OpenClaw 的 MEMORY.md 与 Daily Logs。
  • 基于文件的记忆设计 :三层(对话 / 每日日志 / MEMORY.md)、文件为源、混合检索、预压缩前刷新;本仓库在 demo_codes/file_style_memory.py 中提供了可复现的简化实现,你可以将其视为「OpenClaw Memory 思想在单一 Python 项目中的最小实现模板」,再在下一章对比 LangGraph 的官方 Memory 方案。

参考

相关推荐
QQsuccess2 小时前
PyTorch保姆级安装教程
人工智能·pytorch·python·深度学习
糖果店的幽灵2 小时前
【大模型】大模型学习总结之机器学习 - 1.基础知识
人工智能·学习·机器学习
五度易链-区域产业数字化管理平台2 小时前
2026年315启示:用技术手段“穿透”产业链,实现风险“事前预防”
人工智能
VillanelleS2 小时前
AI工程化之LLM基础入门
人工智能
Hello.Reader2 小时前
深入理解学习率调度器原理、公式与 PyTorch 实战
人工智能·pytorch·学习
码农小白AI2 小时前
IACheck赋能教学实验样品分析检测,AI报告审核保障实验报告精准可靠
大数据·人工智能
钮钴禄·爱因斯晨2 小时前
AIGC | Midjourney使用指南,直接拿捏~
人工智能·aigc·midjourney
纤纡.2 小时前
基于 OpenCV 的银行卡号识别:传统计算机视觉实战详解
人工智能·opencv·计算机视觉
云安全联盟大中华区2 小时前
[特殊字符] | OpenClaw威胁模型:MAESTRO框架分析
大数据·人工智能·深度学习·安全·ai