AgentDepthAgent 工程学习指南
输入概念或问题,检索正文和待编写目录。
第一次学习?从 L0 总览开始 →

记忆写入、召回与更新

我的学习 →

正在读取学习记录…

聊天中出现一句“以后请用中文回复”,Agent可以把它整理为语言偏好。写入记忆后,下一次会话也能用这个偏好。提取出来的候选内容需要先验证、确认,才能成为以后反复使用的记录。

记忆写入像修改客户资料:先有修改提议,再核对字段和归属,用户确认具体内容后保存。否则一句猜测可能被长期保留,后续回答会一直重复这个错误。

给偏好变更一个明确过程

固定场景中,u1提议将语言设为中文。程序先验证支持的字段和值,再检查用户是否确认这份提议。第一次未确认不写入;确认后存成v1;重复相同偏好不增加版本;明确改为英文后存成v2。

版本是同一条记忆的修订编号。召回时按用户与字段读取当前版本,避免把另一个客户的偏好带入本次回答。

偏好提议到当前版本:提议:u1 / language / 中文,验证归属、字段和值;尚未确认 → 保持空存储,确认这份提议 → 写入v1;再次确认中文 → 保持v1,确认英文 → 更新v2;按u1召回当前值:英文v2,按u2召回:无记录
图1:偏好提议到当前版本。

跟着固定样本运行

先在 PowerShell 创建并进入学习目录:

Bash
mkdir "F:\学习\l5-memory-write" -Force
cd "F:\学习\l5-memory-write"

保存下面的文件后,在这个终端运行 dir 核对文件名,再执行本节给出的运行命令。

新建 F:\学习\l5-memory-write,将下面完整代码保存为 memory_write_demo.py。

先在 PowerShell 创建并进入学习目录:

Bash
mkdir "F:\学习\l5-memory-write" -Force
cd "F:\学习\l5-memory-write"

保存下面的文件后,在这个终端运行 dir 核对文件名,再执行本节给出的运行命令。

Python
"""偏好提议经过验证与确认后,按用户更新当前版本。"""
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 中进入保存目录并运行:

Bash
cd "F:\学习\l5-memory-write"
ls
python -X utf8 memory_write_demo.py

输出为:

TXT
未确认:等待确认
确认中文:已写入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
Python
"""检查确认前后、重复、纠错与用户隔离。"""
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()
Bash
cd "F:\学习\l5-memory-write"
python -X utf8 -m unittest -v test_memory_write_demo

应显示6项通过。将主程序恢复到上面的固定输入后,可以再次对照完整输出。

课后练习展开习题收起习题

4 道练习 · 客观题规则评分 · 其余题目待批改

正在读取本地记录…

不调用模型,不执行代码。简答、代码和场景题仅保存答案并展示自查标准,不生成评分、徽章或认证。输入内容不会自动保存,请点击提交;不要填写个人信息或密钥。

练习 1 / 4 · v1.0.1

选择题 · 先判断边界

关于“记忆写入、召回与更新”,哪种做法更稳妥?

对应知识点:L5-memory-write

选择一个答案
练习 2 / 4 · v1.0.0

简答题 · 解释失败

写出一个失败输入并说明记录字段。

对应知识点:L5-memory-write

练习 3 / 4 · v1.0.0

代码题 · 边界测试

补充正常、边界、失败三组输入和预期结果。

对应知识点:L5-memory-write

练习 4 / 4 · v1.0.0

场景题 · 结果未知

证据不足时如何设计状态和人工接管?

对应知识点:L5-memory-write

图片查看器
100%

文章配图 · 按 Esc 关闭