AI Agent 评测最隐蔽的坑-记忆

前言:

断言写好了、Case 结构化了、Mock 也分层了------你以为输入已经完全可控。但跑完一轮调整计划,再跑创建计划,9 条结果全偏了。排查半天发现:上一轮写进去的用户画像,悄悄成了这一轮的隐形输入。你控制了你能看见的输入,但没控制你看不见的那个 - 记忆。


1、一次真实坑

我先跑了调整计划的用例(修改训练日),再跑创建计划的 9 条核心用例。结果全部偏了------训练日排布、频次、甚至运动类型都跟预期对不上。

排查了半个下午,最后发现:调整计划那一轮执行时,系统把"用户将训练日调整为周一、三、五"写进了长期画像。之后跑创建计划时,模型看到的不是我 Mock 的干净输入,而是我 Mock 的输入 + 上一轮留下的画像。两边冲突,模型自己决定听谁的。

我以为在测"给定输入生成计划",实际测的是"给定输入 + 一堆历史偏好生成计划"。输入被污染了,而我完全不知道。


2、记忆是什么(两行讲清)

Agent 系统通常有两类记忆,存在数据库里,每次请求时被塞进给模型的提示词:

类型 内容 比喻
短期记忆(history) 最近几轮对话流水 "你上次说了啥"
长期记忆(memory) 用户画像、偏好、伤病、事件日志 "你是个什么样的人"

模型看到的不只是你这句话,它看的是:你这句话 + 你是谁 + 你刚才说过什么。

这意味着:即使你的请求参数完全一样,只要记忆不同,模型的输入就不同,输出就可能不同。


3、它怎么影响创建计划

创建计划的正式输入应该只有产品定义的那些:目标、周数、训练日、设备。评测里我们用 Mock 把这些全写死了,就是为了控制变量。

但记忆是从旁边溜进来的第二个输入:

复制代码
你 Mock 的输入:   8周 / 增肌 / 周一、周四、周五
记忆里写着:       偏好训练时间:周一、周三、周五上午
模型看到的:       两个都看到了,自己决定听谁的

你以为控制了变量,其实有个你没控制的变量在悄悄起作用。Mock 再精确,如果记忆没清干净,你测的就不是"给定输入生成计划",而是"给定输入 + 未知历史生成计划"。


4、它怎么影响修改计划

修改计划的输入是三样:用户这句话 + 当前计划(Mock 的) + 记忆。记忆在两个方向同时插手:

4.1 读取方向:影响模型怎么理解你的话

理解层面: "下周""周三"这种相对时间表达,模型可能参考历史对话来定位------如果历史里有"用户之前把训练改到周三",它可能会和新请求里的"周三"产生关联。

猜测层面: 长期画像里的偏好会被顺手带上。比如画像里有一条"用户确认只用某设备,另一设备停用"。你现在跑的 Case 只想改日期,模型看到那条画像,可能顺手把设备也给你换了。你以为"改日期把设备改错了"是 Bug,其实是记忆在起作用。

4.2 写入方向:每次对话完,系统把总结写进记忆

更麻烦的是写入方向。每次对话结束后,系统会自动把这轮的摘要写进长期记忆。而它写得不一定准:

复制代码
实际发生的:用户问了"能不能改成周一三五",没点确认,没保存
记忆写的:  用户将后续训练日调整为每周一、三、五,系统已保存  ← 编的

实际发生的:这只是一个未来的训练安排
记忆写的:  [2026-09-02] 运动:低强度恢复骑行              ← 未来的事写成已发生

于是上一条 Case 的执行结果(甚至是错误的总结),变成了下一条 Case 的前提。


5、为什么这对测试特别致命

5.1 同一条 Case 不可复现

复制代码
第 1 次跑 Case-01 → 输入 = 用户话 + 计划 + 空记忆
第 2 次跑 Case-01 → 输入 = 用户话 + 计划 + 第 1 次留下的记忆  ← 输入变了

同一条 Case,两次输入不同,结果不可复现。断言是基于"相同输入应得到相同结果"这个前提的------如果输入本身在变,断言就失去意义了。 你的 PASS/FAIL 不反映产品质量,反映的是"这次记忆里恰好有什么"。

5.2 污染跨套件

这更要命:不同测试套件之间会互相污染。调整计划写的画像,会影响创建计划;A 账号的用例结果,如果复用同一个账号跑 B 套件,B 的输入就不干净了。

你以为每个套件是独立的,其实它们通过记忆这个隐形通道连在一起。

5.3 污染是累积的

第 1 条 Case 跑完,写入 1 条记忆。 第 2 条 Case 跑完,写入 2 条记忆。 第 15 条 Case 跑完,记忆里堆了 15 条历史。

越往后跑,记忆里的噪声越多,结果越不可信。 如果你不在每条 Case 前清记忆,你的第 15 条 Case 的输入里包含了前 14 条的所有副作用------你测的根本不是第 15 条 Case 本身,而是"前 14 条的残留 + 第 15 条"。


6、但:目前观察到的影响有限

老实说,在当前这一轮实测中:

  • 清干净记忆跑某条 Case,和带着脏记忆跑,结果逐字段对比完全一样
  • 修改计划这条链路,大多数时候压根不写记忆(15 次执行里只清出 2 次有东西)

所以准确的说法是:记忆是个不受控的变量,理论上会影响结果,当前这几条 Case 上没有观测到它真的改变输出。

但不能因此说它无害------它是随时可能起作用的变量。 换一个账号(长期画像更丰富的老用户),换一个模型版本(对记忆更敏感的),换一个 Case(刚好触发了画像里的某条偏好),它可能就发作了。

测试的规矩是:把不受控的变量摁住,让结果可复现,而不是赌它今天不发作。


7、怎么处理:三步摁住记忆

7.1 每条 Case 前清记忆

这是最基本的。跑每条 Case 之前,清掉该账号的所有短期和长期记忆,让模型看到的只有你 Mock 的输入,没有任何历史残留。

复制代码
清记忆
→ 验证清干净(查询记忆条数 = 0)
→ 发请求
→ 跑断言

"验证清干净"这一步不能省。 我们实测遇到过清记忆脚本报成功、但实际没清干净的情况(依赖没装好、环境变量没设)。如果你只清不验,你以为输入是干净的,其实不是------这比不清还危险,因为你带着错误的信心在看结果。

7.2 跨套件隔离

不同测试套件(创建计划、调整计划)用不同账号,或者确保每个套件开始前完整清一次所有测试账号的记忆

我们这次踩的坑就是:先跑了调整计划(写了画像),再跑创建计划(读到了画像)。如果两个套件用不同账号,这个污染就不会发生。如果必须用同一个账号,那跑完调整计划后、跑创建计划前,必须清一次。

7.3 第一条 Case 清记忆失败 → 整批终止

我们实测还有一个教训:清记忆失败时,脚本没有终止,而是继续跑了 15 条------全部带着脏记忆跑完,全部结果不可信,白跑了一下午。

正确的做法是:第一条 Case 清记忆失败 → 立即终止整批,打印错误原因。 不要让 15 条 Case 在脏环境里逐条重复失败,那不是测试,是浪费时间。


8、记忆还暴露了一个更深的问题

清记忆只是"摁住变量"。但记忆这件事本身,暴露了 Agent 评测一个更深的挑战:Agent 的输入不是你发的那一句话,而是"你这句话 + 系统悄悄塞进去的一切"。

记忆是一种"悄悄塞进去的输入"。但它不是唯一一种:

隐形输入 例子 对评测的影响
长期记忆 用户画像、历史偏好 本文重点
短期记忆 最近几轮对话 多轮场景中前一轮的回答影响后一轮
系统时间 "下周四"→ 具体哪天取决于今天几号 Case 里写死时间会过期(前一篇讲过)
账号状态 已有的计划、订阅状态、设备绑定 不同账号跑同一个 Case,结果可能不同
模型版本 同一个 prompt,不同模型版本输出不同 模型升级后回归结果波动

所有这些"隐形输入",都需要在评测时显性地控制或记录。 记忆要清、时间要相对化、账号要隔离、模型版本要锁定。如果你只控制了"你发的那句话"和"你 Mock 的数据",而忽略了这些从旁边溜进来的东西,你的评测结果就不完全可信。

这也是为什么 Agent 评测比传统接口测试难------不是断言难写,是输入本身就不完全在你手里。 传统接口测试,你发什么参数,接口就收到什么参数,干干净净。Agent 评测,你发的只是输入的一部分,系统还会自己加料。你要做的不只是"控制你发的",还要"摁住系统自己加的"。


9、总结

Agent 评测的前提不是"断言写对了",而是"输入是干净的"。断言再好、Case 再结构化、Mock 再分层,如果记忆没清、时间在变、账号在串,你测的就不是你以为在测的东西。

先保证输入可控、可复现,然后断言才有意义。这是所有评测方法论的第零步------前面几篇讲的三层断言、松紧度、Mock 分层,全都建立在这一步之上。

相关推荐
csdn_aspnet1 小时前
Copilot能换成本地吗?VSCode接本地大模型本地化接入方案
ide·vscode·ai·ollama
Hotchip_MEMS1 小时前
TWS耳机微米级较量:超薄LGA封装如何助力MEMS麦克风小型化?
人工智能·笔记·物联网·电脑
lucas_AI1 小时前
给YOLO检测器插 LoRA,'插对地方'比'插什么'更要命
人工智能·算法
墨_浅-1 小时前
20260811金融科技动向:国金证券deepseek金融适配度评测方法
人工智能·科技·金融
菜冻鱼1 小时前
Python-sklearn-评估指标
开发语言·人工智能·python·机器学习·numpy·pandas·sklearn
2601_963869951 小时前
【计算机毕业设计】基于Java的线上就医平台设计与实现
大数据·人工智能·课程设计
打呵欠的猫1 小时前
我让 AI 封装了一个 ImageUpload 组件,它设计的 5 层校验链路比我想的周全
前端·ai编程
guyiICtestsocket1 小时前
国内支持定制的手机LPDDR芯片测试座工厂多种结构
人工智能·python·智能手机
程序员黑豆1 小时前
深入解析Java数据类型:基本类型与引用类型的本质区别与实战选择
前端·ai编程·全栈