返回学习路线/阶段 04 · 连接你的知识与记忆
LESSON 11 / 18

短期状态与长期记忆

为会话状态、用户偏好和知识建立不同的生命周期。

30 分钟 · 含动手练习进阶Memory会话隔离

学完这一课,你将能够

  • 设计带作用域与过期时间的记忆
  • 避免跨用户读取与过期信息
  • 支持记忆更正和删除

学习目标

  • 区分任务状态、会话历史、用户偏好和知识资料。
  • 为记忆设置作用域、来源与过期时间。
  • 支持更正、删除以及用户间隔离。

前置要求:理解上下文组织和检索基本流程。 本节使用内存字典演示,不会保存到磁盘或调用外部服务。

记住什么由产品需求决定

“记住全部聊天”很容易实现,却很难保证相关、正确和可维护。 先明确记忆将帮助哪类后续任务。 例如“偏好中文回答”可能跨任务有用,而“今天正在查询哪个商品”通常只属于当前任务。

类型例子生命周期
任务状态已查到的库存、下一步本次执行
会话历史本轮问题与澄清当前会话
用户偏好喜欢简洁中文回答可更正、可删除
知识资料公司报销制度按来源版本更新

这几类数据不必存到同一种数据库。 先定义谁可以读、何时写、什么时候失效,再选择存储技术。

不要把推断直接变成事实

用户说“今天用英文写这封信”,不一定表示长期偏好英文。 模型猜测“用户可能在上海”也不能当成已确认地址。 显式表达与推断应区分,保存来源和确认状态。

更正需要覆盖旧值,或形成清楚的版本链。 删除操作还应覆盖相关索引和派生摘要,否则被删除的信息可能又从另一个入口召回。

实现一个带作用域的记忆存储

保存为 memory.py 后运行。 这里传入 now 是为了让例子可以确定地验证过期行为。

class MemoryStore:
    def __init__(self):
        self.records = {}

    def put(self, user_id, key, value, *, source, now, ttl_seconds):
        if ttl_seconds <= 0:
            raise ValueError("ttl_seconds 必须为正")
        self.records[(user_id, key)] = {
            "value": value,
            "source": source,
            "updated_at": now,
            "expires_at": now + ttl_seconds,
        }

    def get(self, user_id, key, *, now):
        record = self.records.get((user_id, key))
        if record is None:
            return None
        if now >= record["expires_at"]:
            del self.records[(user_id, key)]
            return None
        return dict(record)

    def delete(self, user_id, key):
        return self.records.pop((user_id, key), None) is not None

store = MemoryStore()
store.put("user-a", "language", "中文", source="用户明确设置", now=100, ttl_seconds=60)
print(store.get("user-a", "language", now=120))
print(store.get("user-b", "language", now=120))
store.put("user-a", "language", "英文", source="用户更正", now=130, ttl_seconds=60)
print(store.get("user-a", "language", now=140))
print(store.get("user-a", "language", now=191))
print(store.delete("user-a", "language"))

依次应读到中文、空值、更正后的英文、过期后的空值,以及删除不存在记录的 False。 这说明隔离、更正和过期都是可验证的行为。 当前实现重启就丢失数据,它是机制演示,不是持久化服务。

用户标识必须来自可信身份

例子中手工传入用户 ID 便于演示。 真实应用必须从已验证的会话或访问令牌解析用户身份。 不能因为模型参数写了 user-b,就允许它读取另一位用户的记忆。

数据库查询也应强制附带租户和用户作用域。 只在提示词里写“不要泄露其他用户数据”,不能替代数据层隔离。

怎样把记忆加入上下文

只选择本次任务相关、未过期且来源可信的记录。 给模型说明记录是用户偏好还是外部事实,以及更新时间。 当前明确指令与旧偏好冲突时,通常应遵循当前指令,并按产品规则决定是否更新偏好。

避免让模型无条件保存每轮对话。 写入记忆应该是一个明确动作,有可检查的字段和用户可理解的更正方式。

练习与验收

给存储增加 list_for_user,只返回该用户尚未过期的记录。 写两个用户、两个键以及一个过期记录的用例。

  • 用户 A 的列表不出现用户 B 的数据。
  • 更正后的值不会同时返回旧值。
  • 删除后无法再读取。
  • 文档明确说明基础版只使用内存。

延伸阅读

下一课组合检索、证据和弃答,交付知识助手。

让这一课,真正成为你的收获

完成练习后标记完成,也可以随时回来复习。

笔记与进度保存在当前浏览器,无需登录

AgentStudy · Learn by building.以理解为起点,以作品为答案