短期状态与长期记忆
为会话状态、用户偏好和知识建立不同的生命周期。
学完这一课,你将能够
- 设计带作用域与过期时间的记忆
- 避免跨用户读取与过期信息
- 支持记忆更正和删除
学习目标
- 区分任务状态、会话历史、用户偏好和知识资料。
- 为记忆设置作用域、来源与过期时间。
- 支持更正、删除以及用户间隔离。
前置要求:理解上下文组织和检索基本流程。 本节使用内存字典演示,不会保存到磁盘或调用外部服务。
记住什么由产品需求决定
“记住全部聊天”很容易实现,却很难保证相关、正确和可维护。 先明确记忆将帮助哪类后续任务。 例如“偏好中文回答”可能跨任务有用,而“今天正在查询哪个商品”通常只属于当前任务。
| 类型 | 例子 | 生命周期 |
|---|---|---|
| 任务状态 | 已查到的库存、下一步 | 本次执行 |
| 会话历史 | 本轮问题与澄清 | 当前会话 |
| 用户偏好 | 喜欢简洁中文回答 | 可更正、可删除 |
| 知识资料 | 公司报销制度 | 按来源版本更新 |
这几类数据不必存到同一种数据库。 先定义谁可以读、何时写、什么时候失效,再选择存储技术。
不要把推断直接变成事实
用户说“今天用英文写这封信”,不一定表示长期偏好英文。 模型猜测“用户可能在上海”也不能当成已确认地址。 显式表达与推断应区分,保存来源和确认状态。
更正需要覆盖旧值,或形成清楚的版本链。 删除操作还应覆盖相关索引和派生摘要,否则被删除的信息可能又从另一个入口召回。
实现一个带作用域的记忆存储
保存为 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 的数据。
- 更正后的值不会同时返回旧值。
- 删除后无法再读取。
- 文档明确说明基础版只使用内存。
延伸阅读
- LangGraph:Overview,了解持久化与状态编排的适用范围。
- Microsoft:AI Agents for Beginners
下一课组合检索、证据和弃答,交付知识助手。
让这一课,真正成为你的收获
完成练习后标记完成,也可以随时回来复习。
笔记与进度保存在当前浏览器,无需登录