记忆写入、召回与更新
正在读取学习记录…
聊天中出现一句“以后请用中文回复”,Agent可以把它整理为语言偏好。写入记忆后,下一次会话也能用这个偏好。提取出来的候选内容需要先验证、确认,才能成为以后反复使用的记录。
记忆写入像修改客户资料:先有修改提议,再核对字段和归属,用户确认具体内容后保存。否则一句猜测可能被长期保留,后续回答会一直重复这个错误。
给偏好变更一个明确过程
固定场景中,u1提议将语言设为中文。程序先验证支持的字段和值,再检查用户是否确认这份提议。第一次未确认不写入;确认后存成v1;重复相同偏好不增加版本;明确改为英文后存成v2。
版本是同一条记忆的修订编号。召回时按用户与字段读取当前版本,避免把另一个客户的偏好带入本次回答。
跟着固定样本运行
先在 PowerShell 创建并进入学习目录:
mkdir "F:\学习\l5-memory-write" -Force
cd "F:\学习\l5-memory-write"保存下面的文件后,在这个终端运行 dir 核对文件名,再执行本节给出的运行命令。
新建 F:\学习\l5-memory-write,将下面完整代码保存为 memory_write_demo.py。
先在 PowerShell 创建并进入学习目录:
mkdir "F:\学习\l5-memory-write" -Force
cd "F:\学习\l5-memory-write"保存下面的文件后,在这个终端运行 dir 核对文件名,再执行本节给出的运行命令。
"""偏好提议经过验证与确认后,按用户更新当前版本。"""
from dataclasses import dataclass
@dataclass(frozen=True)
class Proposal:
user: str
key: str
value: str
@dataclass(frozen=True)
class Entry:
value: str
version: int
source: str
def validate(proposal, actor):
# 调用方身份与提议归属一致,字段和值均属于允许集合。
return (proposal.user == actor and proposal.key == "language"
and proposal.value in {"中文", "英文"})
def write(store, proposal, actor, confirmed):
if not validate(proposal, actor):
return "验证失败"
# 确认必须是明确的布尔值;确认绑定传入的这份固定提议。
if confirmed is not True:
return "等待确认"
key = (proposal.user, proposal.key)
previous = store.get(key)
if previous and previous.value == proposal.value:
return "内容相同,保持v" + str(previous.version)
version = previous.version + 1 if previous else 1
store[key] = Entry(proposal.value, version, "用户明确确认")
return "已写入v" + str(version)
def recall(store, user, key):
return store.get((user, key))
if __name__ == "__main__":
store = {}
chinese = Proposal("u1", "language", "中文")
print("未确认:" + write(store, chinese, "u1", False))
print("确认中文:" + write(store, chinese, "u1", True))
print("重复确认:" + write(store, chinese, "u1", True))
english = Proposal("u1", "language", "英文")
print("改为英文:" + write(store, english, "u1", True))
current = recall(store, "u1", "language")
print(f"召回:{current.value},v{current.version},来源={current.source}")
print("u2召回:" + str(recall(store, "u2", "language")))在 PowerShell 中进入保存目录并运行:
cd "F:\学习\l5-memory-write"
ls
python -X utf8 memory_write_demo.py输出为:
未确认:等待确认
确认中文:已写入v1
重复确认:内容相同,保持v1
改为英文:已写入v2
召回:英文,v2,来源=用户明确确认
u2召回:None第一次调用返回等待确认,字典为空。确认中文后产生v1,重复确认保留v1,这种“重复执行得到相同保存结果”的性质叫幂等性。用户改变偏好才产生v2。
召回得到英文、版本2和确认来源,说明读取的是更新后的当前值。None表示u2没有该记录,调用方可以使用默认回复语言。
提取、验证、确认、保存怎样衔接
提取把原句整理成候选字段;验证检查字段、值与用户归属;确认表示用户认可具体候选;保存更新当前值与版本;召回根据用户和字段取回记录。每一步输出都应足够明确,才能定位“错误是在提取还是保存”。
示例在同一进程内将不可变提议直接传给写入函数,并用布尔值模拟界面的确认事件。界面跨请求实现时,需要保存候选编号及内容摘要,确认事件引用该编号,并在保存前核对候选未变化。用户确认中文后,后端不能换成英文再使用同一个确认。
新信息与旧记忆冲突时怎么办
明确的偏好变更可以替换旧值;来自他人转述、模型推断或含糊表达的候选应先澄清。“这次用英文”可能是一次任务指令,不应自动改成永久偏好。保存来源和适用范围,有助于判断后续何时覆盖。
多个请求同时更新时,仅在本地加一还可能覆盖对方修改。数据库可要求“当前版本等于我读取的版本”才允许更新,这叫乐观并发控制:如果版本已变化,就重新读取并协调。语义相似的偏好也需要归并到同一规范字段,防止“语言”“回复语言”各存一份冲突记录。
改动确认状态
把主程序“改为英文”那一行的True改成False,再运行。它返回“等待确认”,召回仍为中文、v1。恢复True后才变成英文、v2。这能检查候选内容有没有在未确认时影响长期记忆。
| 现象 | 检查位置 |
|---|---|
| 未确认也改了偏好 | 保存是否发生在确认检查之后 |
| 相同内容反复产生新版本 | 重复写入的值比较 |
| 另一个客户可修改记录 | 提议归属与调用方身份 |
| 旧确认写入了新内容 | 候选编号、摘要与确认绑定 |
检查实现中的六种情况
在同一目录将下面测试保存为 test_memory_write_demo.py。测试覆盖正文中的正常路径与边界条件。
测试代码:test_memory_write_demo.py
"""检查确认前后、重复、纠错与用户隔离。"""
import unittest
from memory_write_demo import Proposal, write, recall
class MemoryWriteTests(unittest.TestCase):
def setUp(self):
self.store = {}
self.proposal = Proposal("u1", "language", "中文")
def test_unconfirmed(self):
self.assertEqual(write(self.store, self.proposal, "u1", False), "等待确认")
self.assertEqual(self.store, {})
def test_confirmed(self):
write(self.store, self.proposal, "u1", True)
self.assertEqual(recall(self.store, "u1", "language").version, 1)
def test_same_value_idempotent(self):
write(self.store, self.proposal, "u1", True)
write(self.store, self.proposal, "u1", True)
self.assertEqual(recall(self.store, "u1", "language").version, 1)
def test_update(self):
write(self.store, self.proposal, "u1", True)
write(self.store, Proposal("u1", "language", "英文"), "u1", True)
self.assertEqual(recall(self.store, "u1", "language").value, "英文")
self.assertEqual(recall(self.store, "u1", "language").version, 2)
def test_invalid_owner_or_value(self):
self.assertEqual(write(self.store, self.proposal, "u2", True), "验证失败")
self.assertEqual(write(self.store, Proposal("u1", "language", "猜测"),
"u1", True), "验证失败")
self.assertIsNone(recall(self.store, "u2", "language"))
def test_string_confirmation_rejected(self):
self.assertEqual(write(self.store, self.proposal, "u1", "yes"), "等待确认")
if __name__ == "__main__":
unittest.main()cd "F:\学习\l5-memory-write"
python -X utf8 -m unittest -v test_memory_write_demo应显示6项通过。将主程序恢复到上面的固定输入后,可以再次对照完整输出。
课后练习展开习题收起习题
正在读取本地记录…
不调用模型,不执行代码。简答、代码和场景题仅保存答案并展示自查标准,不生成评分、徽章或认证。输入内容不会自动保存,请点击提交;不要填写个人信息或密钥。
选择题 · 先判断边界
关于“记忆写入、召回与更新”,哪种做法更稳妥?
对应知识点:L5-memory-write
简答题 · 解释失败
写出一个失败输入并说明记录字段。
对应知识点:L5-memory-write
代码题 · 边界测试
补充正常、边界、失败三组输入和预期结果。
对应知识点:L5-memory-write
场景题 · 结果未知
证据不足时如何设计状态和人工接管?
对应知识点:L5-memory-write
描述会发送给本站维护者,用于修订文章,保存90天。请只填写文章问题,省略个人信息、密钥和内部资料。