“你上次不是说喜欢清淡的吗?怎么今天推荐的全是重口味?”这是我连续测试第13个AI助手时,用户画像模块反馈回来的典型吐槽。做LLM应用开发这么久,我发现自己最常被问的问题不是“模型推理慢怎么办”,而是“为什么AI总是记不住我说过的话,甚至记错”。更麻烦的是,这类问题很难复现——你让用户去描述AI哪里记错了,他们往往只能说“反正就是不对”,而你拿着同样的对话去重放,结果又变成对的。
团队里负责数据的小伙伴某天提了个想法:既然真实用户的记忆行为太随机、太难量化,那我们干脆造一批“人生”出来——给AI一个完整、稳定、可验证的合成人格,用它的记忆能力做一场标准化考试。这个思路后来演变成了一个我们内部叫“合成人生”的测试系统。这篇文章就把这套测试方法从设计到落地完整拆开讲,包括AI为什么会“记错”你的技术根源、我们怎么造人设、怎么设计记忆陷阱,以及最终测出来的几类典型翻车模式。如果你也在做对话系统、智能助手或者任何带记忆能力的AI产品,这套方法可以直接抄作业。
1. “记错”你的三种经典姿势:先把问题定性,再谈怎么修
AI记错用户这件事,在工程上其实可以拆成截然不同的三类现象。混在一起看会觉得“这模型智商有问题”,但分开看,每一类背后的原因都不一样,对应的修复手段也完全不同。
1.1 偏好遗忘:昨天说过的话,今天就像没发生过
这是最常见的一类。用户在一个星期前明确告诉AI“我最近在控糖,咖啡不加糖”,结果今天问AI推荐饮品,它热情地给你推了一杯摩卡脆片星冰乐。这类问题看起来是模型“失忆”,但本质上不是模型坏了,而是你的对话系统根本没有一个可靠的机制,把昨天的结论带到今天的上下文里。
我在实测中最典型的案例是:某助手在早上的对话里记住了“用户养了一只叫年糕的猫”,等到下午切换话题聊电影,晚上再绕回来问“我家猫该打疫苗了吗”,助手一脸茫然地问“你有养猫吗”。这其实涉及两个环节同时失效:短时上下文覆盖和长期记忆提取。
1.2 张冠李戴:把A的记忆,安到B身上
比遗忘更让人恼火的是“记串了”。我们测试某个带多角色功能的助手时,让用户A说自己喜欢悬疑小说,用户B说自己喜欢言情小说,结果系统在给A做推荐时,开始推荐《霸道总裁爱上我》。这类问题在单用户场景下不明显,一旦产品做家庭共享账号、多人协作空间,就会集中爆发。
从技术上说,这是典型的用户身份隔离失败。系统很可能把所有对话塞进了同一个向量库,检索时没有严格绑定用户ID,于是“最相似的对话片段”把另一个人的偏好捞出来了。模型本身没有错,是你给的检索条件有问题。
1.3 自我推翻:用户改口之后,AI跟不上更新
还有一种很隐蔽的翻车:用户一开始说“我住在北京”,后来搬家去了上海,并明确告诉AI“我现在住上海了”。结果AI在订外卖场景里,依然默认用户在北京,推荐的餐厅全是北京菜。
这一类问题最气人,因为用户已经明确给出了新信息,而且新旧信息同时存在于上下文中。模型不是不知道用户搬走了,而是它的记忆机制没有“覆盖”的概念,旧信息没有被作废,新信息也没有被设为更高优先级,最终新旧信息打架,模型随机选了一个。很多AI助手在这里会用一种“概率性瞎猜”的方式处理,猜对了就看起来聪明,猜错了就是“记错了”。
把这三类问题理清楚之后,我意识到一件事:AI的“记忆”跟我们人类的记忆完全是两种东西,它更像一个混乱的档案室,找不找得到、拿到哪份文件、拿错了会不会纠正,三件事分开控制。想系统性地测试它,就必须针对这三个维度分别设计考题。
2. 技术解剖:AI的“记忆”到底长什么样,为什么会丢、会错、会乱
在搭建“合成人生”测试框架之前,有必要先把AI记忆的技术底裤扒开看一看。很多所谓“记错”的问题,其实不是玄学,而是系统架构里某些模块的功能缺失或者配合失调。
2.1 上下文窗口:AI的“工作记忆”是一个会满的草稿纸
大模型的上下文窗口(context window)决定了它一次能“看到”多少文本。以很多主流API为例,常见的有8K、32K、128K甚至更高。注意,这个窗口是共享的——你的系统提示词、Few-shot示例、用户最近的消息、工具返回的结果,全部都要塞进去。
这里有一个残酷的现实:窗口再大,也是有限的。当对话历史超过窗口容量,系统必须做“压缩”,最常见的策略是滑动窗口裁剪,也就是只保留最近N轮。这就像你在一张便签纸上记事情,写满了就得擦掉最旧的那一行。第1天告诉AI的“猫叫年糕”,到第30天早就被擦掉了。如果产品没有额外做长期记忆层,AI表现出来就是纯粹的“失忆”。
2.2 向量检索:把记忆存进档案库,但档案库本身会出错
解决窗口有限问题的标准方案,是把历史消息做向量化(embedding),存进向量数据库,等用户提问时,先检索出相关片段再塞进上下文。这个方案本身没问题,但毛病出在三个地方:
一是切分粒度。你把一段长对话切分成多个chunk,每段500字还是1000字,直接影响检索效果。切得太碎,语义不完整;切得太粗,噪声太多。
二是检索相似度。很多系统用余弦相似度取top-k,但“和当前问题相似”并不等于“包含用户偏好信息”。我问“今天天气怎么样”,系统可能检索回一堆跟天气有关的闲聊,却漏掉了上周用户说“我怕冷”。
三是过期信息没有失效机制。向量库里存着用户去年说“我在北京”的embedding,今年说“我在上海”的embedding,两条都会被检索出来,且没有时间权重或版本标记。模型看到两个矛盾信息,只能凭感觉选一个,这就是“记错”的温床。
2.3 结构化记忆:很多产品根本没做“用户画像”这一层
在我评测过的众多AI产品里,真正构建了显式用户画像(比如“姓名=某某,城市=上海,偏好=清淡口味”)的产品少得可怜。大多数AI助手所谓的“记忆”,就是一股脑地把历史对话塞进上下文,没有抽象、没有归类、没有更新。这种方案在最简单场景下勉强够用,一旦对话变长、话题变杂,就一定会出现前面说的三类问题。
我们接手过一个合作项目,对方说“我们AI是有记忆的”,后来发现所谓记忆就是把所有用户聊天记录堆在一个数据库里,每次按关键词搜一下。这根本不是记忆,这是全文检索。任何用户画像、偏好提取、知识更新机制都没有。所以我们做“合成人生”测试时,心里其实很清楚:测的既是模型的天生能力,也是产品架构对记忆的支持程度。
3. 为什么要“造”一个人生,而不是直接拿真实用户来测
可能你会问:测AI记忆能力,直接找一批真实用户志愿者来聊天不就行了?为什么要费劲造一个“合成人生”?这个选择背后牵扯到数据可控性、实验可重复性和成本三个维度的问题。
3.1 真实用户测试的三个死穴
真实用户当然是最有说服力的测试对象,但它有三个问题几乎无解:
隐私与合规风险。国内外的数据保护法规越来越严格,采集真实用户的长期对话、偏好信息用于评测,需要过审、脱敏、签署协议,整套流程走下来,以周为单位计算。一个快速迭代的测试方案根本等不起。
变量不可控。真实用户的说法是模糊的,比如“我最近吃得比较健康”,什么叫健康?每个人理解不同。边界情况也千奇百怪,用户可能今天说喜欢甜,明天就说在戒糖,你很难判断到底是系统错了,还是用户自己变了。
样本不可复制。真实用户测试跑了100次,每次对话都不一样,出了bug之后你想在同样条件下重放,几乎不可能。连复现都做不到,谈何定位和修复?
3.2 合成人生的核心优势:每一条性格都是承诺,每一段历史都可回放
我们需要的,是一个“虚构但自洽”的测试对象:它有一套明确的属性表——姓名、职业、城市、家庭、饮食偏好、过敏史、常用App、性格习惯——然后我们把它的一生(至少是一个月的密集对话)编排成剧本,让AI跟这个假人去聊。
这样做的好处是显而易见的。首先是可控性。我们知道这个假人“应该被记住什么”“哪些信息是重要的”“哪些信息是矛盾的测试点”。然后是复现性。同一份合成人生剧本,对100个不同产品跑,对同一个产品跑100次,输出的都是可以严格对比的结果。最后是可量化。每个记忆点都可以设计成一道客观题:AI是否还记得猫的名字?是否知道用户搬到了上海?正确答案是唯一的,评分不需要人肉判断。
实测下来,合成人生的测试效率比真实用户测试高了一个数量级。一个精心设计的合成人格,可以覆盖几十种记忆陷阱场景,而真实用户可能聊一个月也触发不了几个。
4. 从零搭建“合成人生”:画像、剧本、检查点与评分体系
这一节是整个方法论的核心,我尽量写得能直接照着做。我们的方案分四层:合成画像设计、对话剧本生成、记忆检查点埋设、评分与统计。每一步都有具体的坑和参考参数。
4.1 第一层:设计一个“有血有肉”的合成人格
所谓合成人格,本质上是一份结构化的人设文档。我推荐用JSON/ YAML这样半结构化的格式来定义,既方便人读,也方便脚本自动化处理。
一个标准画像至少包含以下几类字段:
| 字段类别 | 示例字段 | 设计目的 |
|---|---|---|
| 基础身份 | 姓名、年龄、城市、职业 | 测试基本身份记忆 |
| 长期偏好 | 饮食忌口、口味倾向、颜色偏好 | 测试长期记忆提取 |
| 短期状态 | 最近在搬家、最近在减肥 | 测试短期动态更新 |
| 事实知识 | 家庭成员、宠物名、车型 | 测试事实型记忆点 |
| 行为习惯 | 通勤方式、作息时间 | 测试日常习惯建模 |
| 禁忌事项 | 花生过敏、恐高、讨厌烟味 | 测试安全红线记忆 |
在设计具体画像时有个技巧:给每个画像埋2到3个“会变化”的属性。比如画像设定为“程序员,2024年10月之前在上海,之后搬到杭州”,再比如“养猫,但猫名字在一次聊天中临时改过名”——这些都是天然的“记忆更新考验”。
我们搭建的第一个合成人格之一,代号“大橘”:男、32岁、软件工程师、坐标从北京迁到杭州、养了一只叫“年糕”的猫、坚果过敏、最近在准备某个技术认证考试。就这么简单几行字,后面能编出几百轮对话,且每一个信息点都有用。
4.2 第二层:编写对话剧本,让记忆点“自然地”出现又消失
纯画像只是一张属性表,AI对着一份属性表是不会有“记忆压力”的。真正的考验来自于“信息在对话中自然流露,然后被遗忘在时间河里”。所以我们需要一个剧本。
剧本的编写有两种方式:一是人工手写,二是用另一个大模型生成后再人工校验。我们两种都用了,实测下来人工写核心冲突,大模型批量扩充闲聊效率最高。
一条完整的剧本按时间线组织,包含若干场景:
- 场景1(第1天):日常闲聊。用户提到“我家年糕最近掉毛很严重,带它去宠物医院了”。AI应该记住猫咪的存在和健康状态。
- 场景2(第3天):聊工作。用户提到“下周搬到杭州,团队在那边的分部”。
- 场景3(第5天):AI推荐外卖,用户说“千万别放坚果,我过敏挺严重的”。
- 场景4(第15天):用户问“我搬家之后还没找到合适的宠物医院,你之前不是说我那个区的吗?”
- 场景5(第30天):用户说“年糕最近精神不太好,我怀疑是搬家应激”。
看到没?信息不是在考试时凭空发问,而是先藏在对话里,隔一段时间后再自然触发。如果AI在第4个场景回答“你之前不是说在杭州吗”“你们家猫叫年糕对吧”,说明它记得住;如果它反问“你养猫了吗”“你在北京还是杭州”,说明这个环节记忆断了。
剧本长度方面,我建议单个测试人物的总对话量控制在200到500轮之间。太少的话覆盖不了时间跨度,太多的话测试成本高,且容易让人工校验剧本的工作量爆表。我们实际用的“大橘”剧本是380轮,基本信息点约25个,冲突点(新旧信息矛盾)5个。
4.3 第三层:埋设记忆检查点,把主观感受变成客观考卷
剧本编好之后,最重要的步骤就是在每个时间节点后埋设一个“检查点”。检查点是一个封闭式问题,例如:
- 检查点A(场景1之后、场景2之前):问AI“我养了一只什么宠物?” 期望答案“一只叫年糕的猫”。
- 检查点B(场景2之后):问AI“我现在住在哪个城市?” 期望答案“即将搬到杭州”。
- 检查点C(场景5):问AI“我对什么食物过敏?” 期望答案“坚果”。
- 检查点D(多功能冲突测试,场景20):问AI“推荐一份晚餐菜单” 期望答案是“不含坚果、适合过敏体质、符合控糖要求”。
注意一个细节:检查点必须单独发起一轮新对话,而不是紧跟在信息出现的同一段上下文里。如果用户刚说完“我坚果过敏”紧接着就问“我过敏什么”,模型哪怕是空转也能从上下文里“抄”到答案,这测的是上下文窗口复制能力,不是记忆能力。要让检查点出现在“信息已经滑出窗口之外”的位置,才能真正考察长期记忆提取。
我们给每个检查点定义评分规则,不只判断对错,还记录回答的置信度——AI回答时是干脆利落说“我记得你养了只猫”,还是犹豫地说“我记得你好像提过一只猫?不确定”。后者虽然在部分评分标准里算对,但在工程上属于“弱记忆”,距离产品可用还有差距。
4.4 第四层:评分体系与数据采集,让结果能横向对比
评分层面,我们没有用单一的二分类,而是把每个检查点的表现分成四档:
| 档位 | 描述 | 示例 | 得分 |
|---|---|---|---|
| 强正确 | 明确、具体地复述出记忆信息,无需提示 | “你养了一只猫,叫年糕,之前说过掉毛带它去医院了” | 3 |
| 弱正确 | 信息基本对,但语气含糊,或只能说出部分 | “你是养了猫吧?好像是叫年…” | 2 |
| 不完整 | 答非所问,或者只答出无关信息 | “你好像说过宠物的事,但我不记得了” | 1 |
| 错误/虚构 | 给出与真实设定相矛盾的信息,且自信 | “你养了一只狗,名字叫豆豆” | 0 |
这一档评分看起来简单,但在统计上非常有用。我们跑完整套测试后,可以算出一个“记忆综合分”,也可以单独看“强正确率”——后者更能反映产品在真实场景里用户感受的好坏。用户用AI的时候,最讨厌的就是那种“明明不记得,还一本正经地编答案”的感觉。
数据采集方面,所有对话通过API调用,别用人工聊天。每次测试跑完自动归档一条JSON记录,包含输入剧本版本、模型参数(温度、top_p)、上下文配置(是否开了摘要、检索TopK)、每个检查点的原始输出和评分。这样后期可以随时拉出来做横向对比。
5. 测试结果:大模型在“合成人生”面前翻车的五种典型姿势
我们用这套方法测了一批主流对话API和几个开源模型,跑了总共将近300次测试对话,统计结果非常有画面感。这里不点名具体模型,只说结论和你可能同样会遇到的坑。
5.1 整体数据:短期记忆还行,长期记忆普遍不及格
先看宏观数据。测试维度分三个:短期记忆(检查点距信息出现不超过10轮对话)、中期记忆(10到50轮)、长期记忆(50轮以上,或跨天)。
| 记忆跨度 | 平均强正确率 | 常见表现 |
|---|---|---|
| 短期(≤10轮) | 88% | 大多能直接答出,偶有细节丢失 |
| 中期(10~50轮) | 63% | 开始含糊,会答错或只答一半 |
| 长期(>50轮) | 37% | 大量“不记得”,部分开始编造 |
这个数据直接说明了一个残酷的事实:**大多数对话系统的“记忆”本质上是上下文窗口的缓存,没有真正的可迁移长期记忆。**你只要让信息滑出窗口,AI的强正确率立刻断崖式下跌。
5.2 翻车模式一:属性张冠李戴,把两个记忆点揉成一团
最典型的“记错”案例出现在合成人格“大橘”身上。剧本设定里,大橘有一只叫“年糕”的猫,还有一个同事叫“小年师傅”(这个角色在对话中出现过几次)。在某次检查点中,我们问“大橘家里的宠物是什么?”,模型竟然回答“你养了一只叫小年的猫”。
这就是典型的embedding检索把两条相似文本混在一起了。因为“年糕”和“小年”在语义向量空间里距离很近,检索时两个chunk都被召回,模型把它们拼接成了一个完全不存在的组合。人不会犯这种错,但向量检索就是会发生。
5.3 翻车模式二:“旧信息强者定律”——模型宁可坚持过时信息
另一个让人抓狂的模式是:用户明确说了新信息,但模型仍然抱住旧信息不放。在我们的搬家剧本里,第15天的检查点问“我现在住在哪个城市”,部分模型回答“北京”。但剧本里第3天就明确说了“搬到杭州”。
分析对话日志后发现,问题出在历史消息里有大量“北京”相关的内容(比如“我在北京工作了五年”“北京冬天太干了”),而“搬到杭州”只出现过一次。模型在压缩上下文时,倾向于保留次数更多、权重更高的旧信息,把单次出现的新信息当成噪声过滤掉了。这提醒我们,在设计产品时,新信息必须要有更高的更新优先级,而不能只靠文本频率来定权重。
5.4 翻车模式三:情绪性内容和事实性内容混淆
合成人格“大橘”有一次说了句“猫咪真是烦死了,又把我的数据线咬断了”,第二天测试问“大橘对猫是什么态度”,有些模型直接回答“你不喜欢你的猫”。实际上语境里那句“烦死了”是对猫咬断线的吐槽,用户依然爱猫。模型缺少对“情绪表达”和“事实陈述”的区分能力。
这个坑在真实产品里非常致命。很多用户会情绪化地说“我再也不想吃沙拉了”,真正意思是“今天不想吃”,而不是“一辈子不吃沙拉”。如果AI把情绪表达当作永久偏好记录下来,那才是真正的“记错”。我们后来在合成剧本里专门增加了大量情绪化表达场景,作为“辨析题”来测。
5.5 翻车模式四:偏好覆盖失败——同时记得新旧两个矛盾信息
有一类模型没有遗忘能力,也不做信息去重。在测试中,用户先说了“我在戒烟”,几天后又说“现在的电子烟口味真多”,AI在后续问答中对“用户是否吸烟”给出自相矛盾的回答。
这个现象的技术根源在于,向量库没有“版本”机制,新旧信息同时存在且无权重差异。检索回来时,模型试图兼顾两者,但表现出来就是前后不一致。产品如果要解决这个问题,必须给记忆打上时间戳,并且在提示词里显式说明“冲突时以最新的为准”。
5.6 翻车模式五:不该记的乱记,该记的不记
最后一种翻车很有趣,我们管它叫“记忆资源错配”。有的模型对“你喜欢蓝色”这种无聊琐事记得清清楚楚,但对“我有花生过敏”这种性命攸关的禁忌信息反而丢失。
背后的原因大概是模型的注意力机制更倾向于记住对话中“具体物品”“具体颜色”这种实体,而“对某物过敏”是一个隐性约束,需要跨多个句子才能理解。解决这个问题的思路,是把过敏、疾病、法律风险这类“高优先级信息”单独抽出来,放进强制记忆槽,而不是依赖通用记忆机制。
6. 从测试回到工程:怎么让AI真的记住你,而不是“假装记得”
测试的最终目的是改进产品。经过这轮“合成人生”的洗礼,我总结出四层可以落地的工程改进方案,按成本从低到高排列。
6.1 轻量方案:设计更聪明的提示词管理策略
不改模型,也不加数据库,纯粹从提示词层面优化,能让长时记忆提升10到20个百分点。
第一个技巧是显式总结。在系统提示词中要求模型“每10轮对话的结尾输出一份当前记忆摘要”,然后把这份摘要和最近对话一起放入下一轮的上下文中。这样即使早期的具体对话被裁剪,摘要里的关键信息还在。实测中,这个方案对50轮以内的记忆提升尤其显著。
第二个技巧是信息回读。每次处理用户消息前,先让模型判断“这条消息里有没有值得记住的关于用户的信息”,有的话先输出到结构化结果里,再走正常对话。相当于在入口处加了一个“记忆筛选器”,而不是全部塞给模型自己去悟。
第三个技巧是冲突指令。在提示词中显式写明“如果用户提供的信息与之前的历史冲突,一律以最新信息为准”,这句话本身就能显著减少“旧信息强者定律”类错误。
6.2 中层方案:引入层级记忆架构,把缓存变成档案
如果预算和开发资源允许,强烈建议上层级记忆架构,分三层管理:
- 工作记忆层:就是上下文窗口,负责当前正在讨论的话题,容量小、更新快。
- 会话摘要层:每轮会话结束时,生成一段结构化摘要,包括“用户主动提到的事实”“出现过的偏好”“情绪事件”。
- 长期画像层:从所有会话摘要中,定期抽取稳定的用户画像字段,存进结构化数据库或向量库,并打上时间戳。
层级记忆的核心原则是不要把所有鸡蛋放进同一个向量库。摘要层负责“最近发生了什么”,画像层负责“这个用户是什么样的人”,两者职责分开,检索时按需取用。我们的实测数据表明,采用层级记忆架构的系统,长期记忆强正确率从37%提升到71%左右,效果非常可观。
6.3 高阶方案:给记忆加“更新API”,让用户可以主动修改
这个方案很少有人做,但一旦做了用户满意度会飙升。思路是:除了让AI被动猜用户喜好之外,给用户一个显式的“记忆管理面板”——用户可以查看AI记录的关于自己的一切信息,可以手动删除、修改、添加条目。
比如用户直接说“把我对坚果过敏这一条记忆删掉”或者“从现在起我的城市改成成都”,系统应当执行一次结构化的记忆更新操作,而不是把这句话当成普通的闲聊输入。这相当于告诉模型“你别猜了,我直接告诉你正确答案”。在很多场景下,这才是记忆功能最可靠、最不被吐槽的实现方式。
6.4 终极方案:把“合成人生”变成你的常态化评测基准
最后一个建议不是关于系统架构,而是关于流程。既然我们验证了“合成人生”这套测试方法靠谱,那它就不应该是一次性实验,而应该变成产品迭代的常态化评测基准。
我现在的做法是:每次升级模型版本、改提示词、调检索参数,都先跑一遍同一套“合成人生”剧本,对比新旧版本的记忆综合分和强正确率。哪次改动导致记忆分下降,那这次改动就不应该上线。这个方法花不了多少成本,却能拦住大量“模型输出变流畅但变傻了”的隐性回归。把这套剧本库沉淀成团队的资产,越跑价值越大。
收尾:一个直接可用的最小测试套件模板
最后分享一个可直接复制的最小化“合成人生”测试模板,哪怕你现在只有一天时间,也能跑起来看看自己的AI记忆水平。
你只需要准备三样东西:一个人设JSON、一份约50轮的对话剧本、一组5到8个检查点问题。人设字段就按我上文表格里的六类来填,剧本按“信息出现-时间流逝-N轮后提问”的节奏来编排,检查点问题在剧本时间线的不同位置埋设。跑法很简单,先把整份剧本发给AI(模拟成历史消息),然后逐个提出检查点问题,记录回答并打分。
这个最小模板已经足够让你发现产品是否存在严重记忆问题,我第一次用它在某开源模型上跑,马上复现出“张冠李戴把猫名字和同事名字混淆”的bug。之后再用完整版剧本做深度评测时,基本能覆盖90%以上的记忆翻车场景。造一个“合成人生”不难,真正难得是愿意承认AI现阶段根本没有完整的记忆机制,而我们能做的,就是先看清它记错的规律,再用工程手段一点一点补上。