← 返回文章列表
Agent 记忆评测:基准、数据与方法 · 第 2 篇

LoCoMo:如何评测超长对话记忆

LoCoMo 用跨月、近 600 轮且包含图片线索的长对话,分别评估问答、事件总结和多模态生成。本文结合真实样本解释题型、评分、复现问题和适用边界。

Agent Memory
Benchmark
Long Context
合集目录:Agent 记忆评测:基准、数据与方法第 2 / 8 篇

调研对象:LoCoMo(Evaluating Very Long-Term Conversational Memory of LLM Agents),arXiv:2402.17753,ACL 2024,Snap Research × UNC × USC。 材料:论文正文(static/paper/locomo.pdf)+ 本仓库 task_eval/、generative_agents/ 代码逐文件审计 + 本地真实数据 data/locomo10.json 逐样本走查。文中所有规模数字、题型分布、代码行号,都来自离线 jq/阅读一手核对,未调用大模型或 GPU;论文实验数字标注了出处。 贯穿全文的例子:真实样本 conv-26,两位说话人 Caroline 与 Melanie,第一次对话发生在 2023 年 5 月 8 日下午。后文所有字段、题型、打分、检索示例,都取自这条对话,方便你把抽象概念落到一个具体故事上。

摘要

LoCoMo 将长期对话记忆扩展到跨月、近 600 轮且包含图片线索的规模。公开版本包含 10 段由人机流水线生成并经人工校对的长对话,平均 27 个会话、约 1.6 万 token,配有约 2000 道按五类推理划分的问答题,以及事件总结和多模态对话生成任务。

论文报告的人类问答得分为 87.9,表现最好的 gpt-4-turbo 为 51.6。对抗题还呈现出一个值得注意的现象:128K 上下文的 gpt-4-turbo 得到 15.7,而 4K 窗口的 Llama-3-70B 得到 80。结果同时表明,多跳推理比单点事实回忆更困难,时间推理和开放域常识仍是薄弱项;RAG 使用事实句作为检索库、只取最相关的 5 条时效果较好,继续增加检索结果反而会引入噪声。

LoCoMo 的评分主要依赖词面匹配,不使用大模型裁判,成本低且便于复现,但对语义正确、措辞不同的回答较苛刻。复现时还有三项具体问题需要先处理:

  • 题型编号:数据里的 category=1 是多跳,4 才是单跳,与论文正文的描述顺序不同。若照论文顺序切分数据,各类结果会整体错位(§5.1)。

  • 对抗题字段:446 道对抗题只有 adversarial_answer 字段,官方作答脚本却读取 qa['answer']。直接运行会触发 KeyError,需要先做字段映射(§8)。

  • 词面评分:问答评分使用词面 F1,没有大模型裁判。语义正确但措辞不同仍可能失分;对抗题则只识别 "not mentioned" 一类关键词(§5.2)。

它适合评估长上下文或 RAG 系统在超长对话中的综合记忆,也覆盖时间与因果推理、人设一致性和多模态线索。抽取改写型记忆更适合用 HaluMem 诊断操作级幻觉;需要独立检索评分时,LongMemEval 的 ID 闭环更完整。


1. 它在解决什么问题

几乎每个聊天助手都号称"记得住你"。但要验证这句话,得先有一段"足够长"的历史让它去记、去忘、去搞混。问题在于,LoCoMo 出现之前,业界用来测"长期对话"的尺子,短得几乎测不出东西。

论文在 Table 1 里摆了一排前辈数据集:MSC 平均只有 4 个会话、1200 词;Conversation Chronicles 是 5 个会话、1000 词;再早一些的 Daily Dialog、SODA 干脆就是单轮、几十个词。用这种数据,你没法区分"真的有长期记忆"和"上下文还没长到会出错"——因为历史压根没长到那个程度。

表 1 LoCoMo 与既有对话数据集的规模对比(摘自论文 Table 1)

数据集平均轮数/段平均会话数/段平均 token/段时间跨度带图片
Daily Dialog7.91114.7—否
SODA7.61122.4—否
MSC53.341,225.9几天否
Conversation Chronicles58.551,054.7几小时~几年否
LoCoMo(本文)588.227.216,618.1数月是

从表中可以看到,LoCoMo 的单段对话长度约为 MSC 的 16 倍,轮数约 10 倍,会话数约 5 倍;它也是其中唯一包含图片、时间跨度达到数月的数据集。

有了足够长的历史,才谈得上把"记性"拆开测。人在长对话里的记忆,其实混着好几种不同的本事:某句话说过没有(单点回忆)、把散落在多次聊天里的线索拼起来(跨会话综合)、算清时间先后和间隔(时间推理)、结合常识做推断、以及历史里根本没提过的事要敢说"不知道"而不是硬编(拒答)。LoCoMo 的核心动作,就是设计任务把这些能力分开打分,让"记性好不好"从一句主观感受,变成一张能逐项归因的成绩单。


2. 一份数据如何支撑三个任务

在钻进细节之前,先把 LoCoMo 的整体形状看清楚,后面就不会迷路。

它的结构可以用一句话描述:先用一条"人机流水线"造出若干段超长对话,每段对话配好标注,然后挂上三个任务,从三个角度考同一段记忆。

全文地图。数据先被"造"出来(①),整理成"对话 + 标注"(②),再由三个任务从不同侧面测记忆(③)。本文按这个顺序展开,每一节对应图里的一块。

图 0 全文地图。数据先被"造"出来(①),整理成"对话 + 标注"(②),再由三个任务从不同侧面测记忆(③)。本文按这个顺序展开,每一节对应图里的一块。

三个任务各管一件事,可以先记个大概,后面各有专节:

  • 问答(§5)是论文讨论最多的任务。模型读取一段可能被截断的对话历史后回答问题,结果按五种推理类型分别统计。

  • 事件总结(§6)考的是"能不能把散在多次聊天里的事,按因果和时间顺序梳理出来"。

  • 多模态对话生成(§7)考的是"能不能顺着人设和已经发生的事,生成风格一致、前后不矛盾的下一句(可能带图)"。

一个重要的前置认知:这套 benchmark 只有 10 段对话。它的规模优势全在"每段极长",不在"段数多"。这一点会反复影响后面的解读,先记住。


3. 一条数据长什么样

这一节把地基打好。LoCoMo 里,一条样本不是"一道题",而是一整段超长对话,外加它的全部标注。我们用真实样本 conv-26 走一遍。

3.1 先看对话本身

对话是两个人之间的多轮聊天,按会话(session)切分,每个会话带一个时间戳。下面是 conv-26 第一个会话开头的真实内容(2023 年 5 月 8 日):

D1:1  Caroline: Hey Mel! Good to see you! How have you been?
D1:2  Melanie:  Hey Caroline! ... What's up with you? Anything new?
D1:3  Caroline: I went to a LGBTQ support group yesterday and it was so powerful.
D1:5  Caroline: The transgender stories were so inspiring! ...   [这一轮还带了一张图]
D1:7  Caroline: The support group has made me feel accepted and given me courage to embrace myself.
D1:9  Caroline: Gonna continue my edu and check out career options, which is pretty exciting!
D1:11 Caroline: I'm keen on counseling or working in mental health - I'd love to support those with similar issues.

每一轮(turn)是一个小对象,最少三个字段:说话人 speaker、坐标 dia_id、内容 text。这里的 dia_id 很关键,它是贯穿全数据的"定位坐标",格式是 D<会话号>:<轮号>——D1:3 就是"第 1 个会话、第 3 轮"。后面问答的证据、事件的溯源、以及检索命中的判定,全靠这个坐标对齐(这套 ID 对齐机制本身有门槛,§5.3 会用真实 ID 手算一遍)。

如果这一轮还发了图,它会多出三个字段,比如 conv-26 里 Caroline 在 D1:5 发的那张:

{ "speaker": "Caroline", "dia_id": "D1:5",
  "text": "The transgender stories were so inspiring! ...",
  "img_url": ["https://i.redd.it/l7hozpetnhlb1.jpg"],   // 图片的网页链接
  "blip_caption": "a photo of a dog walking past a wall ...", // BLIP 模型给图配的文字
  "query": "transgender pride flag mural" }              // 当初爬这张图用的搜索词

这里要留意一个坑的伏笔:LoCoMo 只给图片的"线索",不给图片本身。你拿到的是网页链接(可能已经失效)、一句机器生成的图注、和一个搜索词,但没有图片文件(这是官方 README 明说的)。而且你注意上面这张图——图注说的是"一只狗经过墙",搜索词却是"跨性别骄傲旗壁画",两者对不上。这是网络爬图不精确留下的真实痕迹,§8 会再回来算这笔账。

3.2 再看挂在对话上的四种标注

同一段对话,配了四组标注,各有各的用途。先看一眼整条数据的骨架——locomo10.json 是一个数组,一共 10 条这样的记录,下面是其中一条(conv-26)的完整顶层结构。为了能放进一屏,数组只截取了真实的前一两项,用注释标出省略的真实数量;除了省略号,其余字段名和取值都是原文,没有改写、没有拼接:

{
  "sample_id": "conv-26",

  "qa": [
    { "question": "When did Caroline go to the LGBTQ support group?",
      "answer": "7 May 2023", "evidence": ["D1:3"], "category": 2 },
    { "question": "When did Melanie paint a sunrise?",
      "answer": 2022, "evidence": ["D1:12"], "category": 2 }
    // ... 共 199 条,覆盖 category 1/2/3/4/5 五种题型
  ],

  "conversation": {
    "speaker_a": "Caroline",
    "speaker_b": "Melanie",
    "session_1_date_time": "1:56 pm on 8 May, 2023",
    "session_1": [
      { "speaker": "Caroline", "dia_id": "D1:1",
        "text": "Hey Mel! Good to see you! How have you been?" },
      { "speaker": "Melanie", "dia_id": "D1:2",
        "text": "Hey Caroline! Good to see you! I'm swamped with the kids & work. What's up with you? Anything new?" }
      // ... session_1 共 18 轮
    ],
    "session_2_date_time": "1:14 pm on 25 May, 2023",
    "session_2": [
      { "speaker": "Melanie", "dia_id": "D2:1",
        "text": "Hey Caroline, since we last chatted, I've had a lot of things happening to me. I ran a charity race for mental health last Saturday – it was really rewarding. Really made me think about taking care of our minds." }
      // ... session_2 共 17 轮
    ]
    // ... 一路到 session_19,conv-26 共 19 个会话、419 轮
  },

  "event_summary": {
    "events_session_1": { "Caroline": ["Caroline attends an LGBTQ support group for the first time."],
                           "Melanie": [], "date": "8 May, 2023" }
    // ... 共 19 个会话的事件真值
  },

  "observation": {
    "session_1_observation": {
      "Caroline": [
        ["Caroline attended an LGBTQ support group recently and found the transgender stories inspiring.", "D1:3"],
        ["The support group has made Caroline feel accepted and given her courage to embrace herself.", "D1:7"]
        // ... Caroline 在 session_1 里共 3 条
      ],
      "Melanie": [
        ["Melanie is currently managing kids and work and finds it overwhelming.", "D1:2"],
        ["Melanie painted a lake sunrise last year which holds special meaning to her.", "D1:14"]
        // ... Melanie 在 session_1 里共 4 条
      ]
    }
    // ... 共 19 个会话的 observation
  },

  "session_summary": {
    "session_1_summary": "Caroline and Melanie had a conversation on 8 May 2023 at 1:56 pm. Caroline mentioned that she attended an LGBTQ support group and was inspired by the transgender stories she heard. The support group made her feel accepted and gave her the courage to embrace herself. ..."
    // ... 共 19 个会话的摘要
  }
}

顶层就 6 个字段:sample_id(对话编号)、qa(问答)、conversation(对话正文,外加 speaker_a/speaker_b/各会话时间戳)、event_summary(事件真值)、observation(检索用的事实句)、session_summary(检索用的整段摘要)。骨架看清楚了,下面逐个字段拆开看。

问答标注 ****qa:一串问题,每个带答案、证据坐标、类型编号。例如——

{ "question": "When did Caroline go to the LGBTQ support group?",
  "answer": "7 May 2023", "evidence": ["D1:3"], "category": 2 }

evidence 指明答案藏在哪几轮(这里是 D1:3),category 是题型编号(第 5 节详解,先记住它的编号有坑)。conv-26 一条对话就配了 199 道题。

事件真值 ****event_summary:按会话、按说话人,列出"这次聊天里发生的重要事件"。这是人工标注的,是事件总结任务的评分依据。conv-26 的前两个会话是这样:

"events_session_1": { "Caroline": ["Caroline attends an LGBTQ support group for the first time."],
                      "Melanie": [], "date": "8 May, 2023" }
"events_session_2": { "Caroline": ["Caroline ... starts researching adoption agencies."],
                      "Melanie": [], "date": "25 May, 2023" }

你能看到一条清晰的人物线:5 月 8 日 Caroline 第一次去 LGBTQ 支持小组,5 月 25 日她受到鼓舞、开始研究领养机构。这条线不是随机拼的,而是来自 §4 会讲的"时间事件图"。

观察 observation 和会话摘要 ****session_summary:这两组是"生成的"而不是"人工标的"——由 gpt-3.5-turbo 从对话里自动提炼,专门给 RAG 检索当"数据库"用(§5.3 会演示)。observation 是一条条带坐标的事实句,session_summary 是每个会话一段话。仓库直接附带了一份现成的,也提供脚本可以重新生成。

串起来看:同一个坐标,四层标注怎么对齐。 上面三组分开讲,容易让人觉得它们各管一段、互不相干。实际上它们经常锚定在同一个坐标上——往后翻到 conv-26 第 2 个会话(2023 年 5 月 25 日)的真实原文:

D2:1 Melanie:  Hey Caroline, ... I ran a charity race for mental health last Saturday ...
D2:3 Melanie:  Thanks, Caroline! The event was really thought-provoking. I'm starting to
               realize that self-care is really important. ...

同一句 D2:3,在四层标注里各留了一份完整记录:

问答正题(category: 4,单跳):

{ "question": "What did Melanie realize after the charity race?",
  "answer": "self-care is important", "evidence": ["D2:3"], "category": 4 }

问答对抗题(category: 5)——把主语从 Melanie 换成 Caroline,evidence 坐标不变,但这条 JSON 里没有 answer 字段,只有 adversarial_answer:

{ "question": "What did Caroline realize after her charity race?",
  "evidence": ["D2:3"], "category": 5,
  "adversarial_answer": "self-care is important" }

(这个字段名后面还会出场——评测代码要读的是 answer,不是 adversarial_answer,直接跑官方脚本会在这里报错,§8 坑二细讲。)

事件真值(event_summary,记在同一天、但另一个人名下的另一件事):

"events_session_2": { "Caroline": ["Caroline is inspired by her supportive friends and
                       mentors to start researching adoption agencies."],
                       "Melanie": [], "date": "25 May, 2023" }

observation(同一句话被提炼成一条带坐标的事实,挂在 Melanie 名下):

["Melanie is realizing the importance of self-care and its impact on her family.", "D2:3"]

四层标注,同一个坐标 D2:3,四种呈现——问答让你抠字面,事件让你连时间线,observation 给检索当弹药。反过来说,模型自己看不到这四层,只看得到对话原文(谁能看到什么,见下面表 2)。打分脚本、检索脚本各自拿着不同层的标注去核对模型的输出,核对的锚点全部是 dia_id 这个坐标——坐标错一位、字段名对不上,核对就失败,分数直接算错。这就是为什么"ID 对齐"在 LoCoMo 里是道实打实的门槛,而不是一句空话(§5.3、§8 会反复回来算这笔账)。

LoCoMo:如何评测超长对话记忆

图 0.1 `dia_id` 是四层标注共用的锚点。同一轮原话会被改写成不同用途的数据:问答用来判答案,observation 用来检索,事件真值用来评总结;被测模型只读左侧的对话原文。

3.3 谁能看到什么

和所有"大海捞针"式评测一样,成败系于一件事:严格区分"被测模型能看到什么"和"只有裁判能看到什么"。

表 2 字段可见性

字段被测模型问答打分检索(RAG)打分
对话正文 / 图注看得到(作为上下文)—看得到(作为被检索的库)
question看得到看得到看得到(作为检索的 query)
answer / adversarial_answer看不到看得到(金标准)看不到
evidence(含答案的坐标)看不到—看得到(判断检索有没有命中)
event_summary(事件真值)看不到事件任务用看不到

3.4 本地实测的规模

论文 Table 1 给的是平均值。我把真实 locomo10.json 里每一条都数了一遍,既验证了论文数字,也补出了分布:

表 3 本地实测规模(离线统计,10 段对话)

指标合计每段范围平均与论文对照
会话数27219 ~ 3227.2与论文 27.2 一致
轮数5,882369 ~ 689588.2与论文 588.2 一致
问答题1,986每段约 200—论文未给总数,此为实测
带图轮次910——图片本体不释放

数字对上了,说明我们手里这份数据就是论文用的那份。记住"10 段、每段近 600 轮"这个体量,它是理解后面一切的基准。


4. 这些对话是怎么造出来的

你可能已经在想一个问题:跨度半年、几百轮的私密聊天,去哪儿找这么多来做标注?答案是——造。这一节讲清楚它怎么造,你才会信任(或警惕)这份数据。理解了造法,前面那些字段(人设、事件、图片)也就都有了出处。

LoCoMo 的办法是:让两个 LLM 智能体,各自带着人设和一条"人生时间线",像真人一样聊上几个月,再请人把不通顺、不一致的地方修掉。

人机构造流水线。前三步机器生成,最后一步人工把关。

图 1 人机构造流水线。前三步机器生成,最后一步人工把关。

第一步,给每个智能体一个人设。 从 MSC 数据集取一段 4~5 句的人物种子,用 gpt-3.5-turbo 扩写成完整人设:姓名、年龄、职业、日常习惯、人际关系、人生目标。两个智能体拿不同人设,保证性格有区分。Caroline 和 Melanie 就是这么来的。

第二步,给每个人一条"人生时间线",这是 LoCoMo 最有特色的设计。 系统为每个智能体生成一张时间事件图:最多 25 个事件,每个带日期,事件之间还画上因果连线("因为 A 所以 B"),整条线铺在 6~12 个月里。生成是滚动式的——先出 3 个事件,再拿它们当输入生成后续,一边控制成本一边保证时间和因果连贯。正是这张图,让对话里能出现"上个月说领养了小狗 → 这次就聊带它去和邻居的狗玩"这种跨越数周的因果,也成了事件总结任务的真值来源。Caroline"5 月 8 日去支持小组 → 5 月 25 日受鼓舞去研究领养",就是这张图的一段。

第三步,让两个智能体带着记忆去聊。 每个智能体沿用 Generative Agents(Park et al., 2023)的记忆架构,有两套动作:

一套是"反思与回应"。它区分短期和长期记忆:每聊完一个会话,就把这次聊了什么压成一段摘要,存进短期记忆;每一轮对话,又被转成一条"观察"(observation)存进长期记忆。轮到它下一次开口时,它会同时参考四样东西——最近的会话摘要、检索回来的相关观察、当前会话已经聊到哪、以及自己的人设,再加上"上次见面到这次之间,人生时间线上发生了哪些事"。这套机制,就是数据里 observation 和 session_summary 字段的由来。

另一套是"发图与回图"。需要时,智能体先想一句图注,转成关键词,用爬虫(icrawler)去网上搜一张图发出来;收到对方的图,则先给图配一句文字再回应。这就是 img_url / blip_caption / query 三件套的由来,也是为什么图注质量参差——图是搜来的,不是画的。

第四步,人工校对。 标注员做三件事:删掉前后矛盾的地方、替换或移除不相关的图、核对对话和事件图对不对得上。论文报告:约 15% 的对话轮次被编辑、约 19% 的图片被移除或替换。这道人工关,是 LoCoMo 敢自称"高质量"的底气,也是它和"纯机器合成"数据集的一个区别。

需要诚实说明的边界:这份数据本质上是"LLM 生成 + 人工修",论文自己在局限里也承认,它未必完全还原真实在线对话的所有细微之处。用它时,把它当成"高度逼真的模拟",而不是"真人语料"。


5. 任务一 · 问答

前面几节说的都是"数据长什么样",接下来三节(§5/6/7)要说的是"拿这份数据怎么评测"。三个任务评测起来其实走的是同一条链路:数据 → 喂给模型的方式(喂料)→ 模型作答或生成 → 打分脚本 → 指标,区别只在"喂料方式"和"打分标准"这两处各不相同。先看一张全貌图,后面三节再把每条链路拆开讲:

三个任务共用的评测骨架:同一份数据分三路喂给不同任务,喂料方式和打分标准各不相同,但"数据→喂料→模型→打分→指标"这条主链路是一样的。问答里唯一的旁支是 RAG 模式下额外算的"检索命中 recall",它和右侧打分是两件独立的事(§5

图 2 三个任务共用的评测骨架:同一份数据分三路喂给不同任务,喂料方式和打分标准各不相同,但"数据→喂料→模型→打分→指标"这条主链路是一样的。问答里唯一的旁支是 RAG 模式下额外算的"检索命中 recall",它和右侧打分是两件独立的事(§5.3 细讲)。

先看问答这条链路——它是 LoCoMo 的核心,被引用得也最多,读懂它就掌握了 LoCoMo 的七成。它的整套逻辑可以用一个画面串起来:把那本半年的聊天记录摊在桌上,出题人指着某处问一句,考生(模型)作答,阅卷员(一段死板的字符串比对程序,不是大模型)拿标准答案逐字核对给分。 这一节顺着"出什么题 → 怎么阅卷 → 怎么给考生看材料 → 考出什么结果"往下走。

5.1 出什么题:五类推理,一个编号陷阱

出题很讲究:为了让阅卷能纯靠字面比对,答案被刻意设计成"尽量能从对话里抄到原词"。而题目按考察的能力分成五类。先看 conv-26 里四道真题,一眼就能感到它们考的完全不是一回事:

  • "Caroline 什么时候去的 LGBTQ 支持小组?" → 7 May 2023——翻到一处,读出日期(时间)

  • "慈善跑为什么募捐?" → mental health——翻到一处,读出事实(单跳)

  • "Melanie 平时做哪些活动?" → pottery, camping, painting, swimming——四项散在四个会话,得翻遍全书拼齐(多跳)

  • "Caroline 跑步后意识到了什么?" → 对话里根本没提,该答"没提到"(对抗,专门引诱你瞎编)

表 4 五类题型的真实映射(数据编号 ↔ 论文类型 ↔ 打分 ↔ 数量)

数据 category论文类型考什么本地题量真实例子(conv-26)
4单跳 Single-hop单个会话里的一个事实841"慈善跑为什么募捐?" → mental health
1多跳 Multi-hop跨多个会话拼答案282"Melanie 做哪些活动?" → 四项,来自四个会话
2时间 Temporal日期、先后、间隔321"Caroline 何时去的支持小组?" → 7 May 2023
3开放域常识 Open-domain结合信息与常识推断96"Caroline 可能会读什么专业?" → Psychology, ...
5对抗 Adversarial历史没答案,应拒答446"Caroline 跑步后意识到什么?" → 应答"没提到"

⚠️ 表里的编号别照直觉记:数据里 1 是多跳、4 才是单跳,和论文正文"1 单跳、2 多跳"的文字顺序正好拧着。这是全 repo 最容易翻车的地方——谁按"1 就是单跳"去切数据复现,成绩单会整体错位还很难发现。这个映射是从打分函数的分支逻辑、结果汇总的打印顺序、出题提示词三处代码交叉验证出来的(行号见 §11.C 代码索引)。另外题量极不均衡(单跳 841 vs 开放域 96),做分类对比时小类噪声要留意。

5.2 怎么阅卷:一位"只认字面"的阅卷员

这位阅卷员脾气很怪:只认字面,不懂意思——全程用词面 F1 比对,不请大模型帮忙。好处是便宜、可复现、换谁跑分都一样;代价是"意思对但措辞不同"照样扣分。阅卷前先把两边答案"洗"成朴素形态:转小写、去标点、删冠词、词干还原(agencies→agenc),这是它唯一的宽容(归一化与打分主逻辑集中在 evaluation.py,行号见 §11.C)。

洗干净之后,五类题其实只对应三套算法。挑真题各走一遍,就能感受到它们的脾气差多远。

单跳 / 时间 / 开放域,用最朴素的"重叠算分":命中词数分别除以预测长度、答案长度,得到精确率和召回率,再取调和平均就是 F1。看单跳题"慈善跑为什么募捐?",标准答案 mental health(2 个词),模型答了句完整话 It raised awareness for mental health issues:

预测(洗后)= {it, rais, awar, for, mental, health, issu}   7 个词
答案(洗后)= {mental, health}                              2 个词
命中 = 2    精确率 = 2/7 ≈ 0.29   召回率 = 2/2 = 1.0   →   F1 ≈ 0.44

意思完全正确,只拿 0.44 分——纯粹因为多说了几个词稀释了精确率。这是"字面阅卷"最大的软肋:论文因此反复叮嘱"答案尽量抄原词",也解释了爱长篇大论的模型在这里天然吃亏。(开放域题还有个小细节:标准答案是"结论;理由"格式,阅卷只取分号前的结论去比对,理由部分不参与打分。)

多跳,按逗号拆开分别算分再平均,是"重叠算分"的团体版:"Melanie 做哪些活动?"标准答案四项——pottery、camping、painting、swimming——分别来自四个不同会话。假设模型只答对了两项:

pottery ✓(≈0.4)   camping ✗(0)   painting ✗(0)   swimming ✓(≈0.4)   →   平均 = 0.2

说对一半、只拿 0.2 分。这套规则给"部分答对"一点情面,但代价很直白:漏掉任何一个会话的线索,分数就跟着掉——这也是模型在多跳题上普遍比单跳低一大截的直接原因(§5.4 会看到)。

对抗题不算 F1,只认一句"没提到":它考的不是记忆而是"知进退"——这道题历史上压根没答案,正确做法是拒答。阅卷简单粗暴:输出里出现 not mentioned / no information available 就给 1 分,没出现就 0 分。

LoCoMo:如何评测超长对话记忆

图 2.1 五类题并非都用同一种算法:三类普通题走词面 F1,多跳题把多项答案拆开平均,对抗题则只检查是否明确拒答。这解释了“语义对但措辞不同”仍会失分。

它的出题手法值得细说,因为它专挑"张冠李戴"下手。conv-26 里有这样一对真题,共用同一句原话(D2:3,Melanie 说"我开始意识到自我关怀很重要"):

  • 单跳题(真实存在):"Melanie 在慈善跑后意识到了什么?" → 标准答案 self-care is important。

  • 对抗题(同一句话,换了主语):"Caroline 在她的慈善跑后意识到了什么?" → 数据里存的诱饵答案同样是 self-care is important。

问题是,慈善跑是 Melanie 跑的,说这句话的也是 Melanie——Caroline 压根没跑过这场慈善跑。出题人就是把同一件事换了个主语,看模型会不会照单全收、把别人的经历安在 Caroline 头上。模型如果顺着"慈善跑…意识到…"的字面相似度把 Melanie 的原话搬出来,就会被判 0 分;只有先分清"这件事跟 Caroline 无关"、老实说没提到,才能拿分。这也是为什么上下文越长、模型反而越容易在对抗题上出错——历史里相似片段越多,越容易被"看着眼熟"带偏(§5.4 数据会印证这一点)。

5.3 RAG 怎么喂料,怎么算命中

同一道题,喂给模型看的"材料"可以完全不同。论文分三档:受限上下文模型(Mistral-7B、Llama-70B,窗口塞不下,早期对话被截掉)、长上下文模型(gpt-4-turbo 128K、claude-3 200K,尽量全塞)、RAG(不硬塞,先按问题检索出最相关的几段再作答;论文用 DRAGON 检索 + gpt-3.5 作答,代码还支持 DPR/Contriever/OpenAI)。

RAG 这一档最有意思:同一段历史,预先整理成三种"小抄",参与检索效果的对比。拿真实问题"Caroline 对什么职业感兴趣?",看三种小抄各自返回什么:

① dialog 原始对话轮——原汁原味,但口语、啰嗦、带噪声:
   D1:9  Caroline: Gonna continue my edu and check out career options ...
   D1:11 Caroline: I'm keen on counseling or working in mental health ...
② observation 事实句(带坐标)——去了噪、最聚焦:
   "Caroline plans to continue her education ... in counseling or mental health"  [D1:9]
③ summary 整段会话摘要——最短,但把无关的也裹进来:
   "... Caroline plans to continue her education ... Melanie painted a lake sunrise ..."

一句话概括三者取舍:dialog 最全但信噪比低,observation 干净聚焦,summary 最短但夹带无关信息(Melanie 画画)。

但"检索到"和"检索对"是两回事,得先讲清楚"对不对"是怎么判的——门槛就在坐标系统上。金标准的证据坐标精确到轮(D<会话号>:<轮号>),但三种小抄能给出的坐标"精度"并不一样:dialog / observation 都能精确到轮(observation 一条事实还可能挂一串坐标,如真实数据里的 D26:14, D26:34);summary 却只有会话级坐标 S1、S5,没有轮号。于是代码判定命中时分两条路:暗号以 S 开头就退化成只比会话号,否则比完整轮级坐标(判定逻辑见 evaluation.py#L228-237)。

拿 §5.2 那道多跳题练一遍——金标准证据是 [D5:4, D9:1, D1:12, D1:18] 这四个坐标:

  • 翻 dialog 库,top-5 捞回 D5:4 D3:2 D1:12 D7:9 D9:1,逐轮比对:命中 D5:4、D1:12、D9:1 三个,漏了 D1:18——recall = 3/4 = 0.75。

  • 翻 summary 库,top-2 捞回 S1、S5,退化成比会话号:D5:4→会话 5 ✓,D9:1→会话 9 ✗,D1:12、D1:18→都属于会话 1 ✓——recall 同样是 3/4 = 0.75。

两个 0.75,含义却完全不同:summary 库那一次,一个 S1 就把 D1:12、D1:18 两条证据一次性"盖"住了,不是真找到了两条独立信息,只是沾对了会话号。这是这套 ID 对齐机制最该记住的一点:recall 只认坐标对不对,不看内容读没读懂——摘要库天然粒度粗,召回数字容易好看,但那不代表模型真的把信息捞回来了;捞回来之后有没有读懂、答没答对,是 F1 那条线的事(§5.4 结果会印证)。两条线分开看,才能定位问题到底卡在"检索"还是"阅读"——这也是 LoCoMo 唯一的检索诊断指标,且只在 RAG 模式下存在。

LoCoMo:如何评测超长对话记忆

图 2.2 RAG 有两条独立成绩线:recall 只问检索结果的 ID 是否覆盖证据,F1 才问模型最终是否答对。`summary` 的会话级 ID 粒度更粗,因此可能让 recall 看起来不错,却不能证明答案读对了。

5.4 结果与四个发现

表 5 问答主要结果(F1,摘自论文 Table 2,节选;越高越好)

模型上下文单跳多跳时间开放域对抗总体
人类—95.185.892.675.489.487.9
gpt-4-turbo128K72.351.551.438.515.751.6
claude-3-sonnet200K70.738.126.952.22.542.8
gemini-1.0-pro32K62.435.334.219.05.239.1
gpt-3.5-turbo16K52.636.724.324.014.835.9
Llama-3-70B4K17.017.012.013.080.030.1

这张表里藏着四个发现,逐个说。

第一,模型离人类还差得远。 最强的 gpt-4-turbo 综合 51.6 分,人类 87.9 分,差 36 分。论文说,长上下文和 RAG 能把问答提升 12~20%,但这个鸿沟依然巨大。"能读进长文"和"真的记得住"是两回事。

第二,上下文越长,越容易在对抗题上自信地胡编。 看对抗那一列:128K 的 gpt-4-turbo 只有 15.7 分,而 4K 小窗口的 Llama-3-70B 高达 80 分。为什么?窗口一长,模型面前堆满"看着相关其实无关"的内容,就更容易被带着把一道本该拒答的题硬答出来;小窗口模型反而更干脆地说"没提到"。这是个反直觉但很重要的结论:长上下文不是免费的午餐,它会放大幻觉。

第三,会背不等于会想。 单跳(记住一个事实)分数普遍不低,但一到多跳(跨会话综合)就明显掉。说明模型已经挺擅长"在大窗口里记住东西",短板在"把记住的东西拿来做多步推理"。

第四,时间和开放域知识是两个最硬的骨头。 时间推理本就是 LLM 的老大难。更有意思的是开放域知识题在 RAG 下反而会变差——因为检索到不准的上下文,会干扰模型本来就记在参数里的常识,帮了倒忙。

关于 RAG 三种库的对比,论文的结论是:用 observation(事实句)当库、只取最相关的 5 条,效果最好,比直接检索原始对话轮高约 5%。但检索越多反而下滑——关键不是"塞得多",而是"信噪比高"。用 summary 当库则帮助有限:尽管它检索命中率很高(回看 §5.3,会话级坐标粒度粗、天然容易命中),问答却没怎么变好,因为"对话压成摘要"这一步本身丢了信息。


6. 任务二 · 事件总结

如果说问答考的是"记不记得住一个个点",事件总结考的就是"能不能把点连成线"——把散落在几十次聊天里的事,按时间和因果顺序理清楚,而且不能瞎编、不能漏掉、不能张冠李戴。

6.1 任务怎么设

给模型一段时间窗内的对话,让它总结这段时间发生了哪些事,再拿 §4 那张"人生时间线"里的真值来对答案。真值本身颗粒度很细——拿 conv-26 举例,Caroline 这条线上,光是前三个会话就分别对应一句话:

5 月  8 日(会话1):Caroline 第一次参加了 LGBTQ 支持小组。
5 月 25 日(会话2):受到朋友和导师的鼓励,Caroline 开始研究领养机构。
6 月  9 日(会话3):Caroline 在自己学校演讲,鼓励同学参与 LGBTQ 社群。

难点在于,这些事在对话里从不是"整段说完"的:可能这次提一句、下次才补一个细节,中间还夹杂大量无关的闲聊——比如会话 2 里,Melanie 还聊了跑步、自我关怀、孩子的暑期营,这些都不算"事件",模型得学会把它们筛掉。模型要跨越很长的距离,把真正重要的那句话准确地捞出来、按对的时间对的人归好类。论文特意强调,这比总结论文、剧本、书籍都难,因为后者是线性叙述,而这里的信息是碎片化的、夹杂着玩笑和闲聊、还带着指代。

6.2 怎么打分:FactScore 逐条较真

普通的 ROUGE、BLEU 只比"用词像不像",测不出"事实对不对"——一句话就算完全编造,只要词面重叠得多,分数照样不低。LoCoMo 用的是 FactScore(Min et al., 2023),思路很朴素:先把一段总结拆成一条条不能再拆的"原子事实",再逐条去真值里核对:

  • 精确率——总结里的每条原子事实,去真值里找不找得到对应,找得到就算数;这条指标专治"瞎编"。

  • 召回率——反过来看,真值里的每条事实,有没有被总结覆盖到;这条指标专治"漏掉"。

  • 两者取调和平均,就是 FactScore F1;论文还辅以 ROUGE 作参考。

光讲定义还是抽象,不如真算一遍。假设模型看完 conv-26 前三个会话,写出这样一段总结(这是本文构造的示例,用来演示打分逻辑,不是真实模型输出):

"5 月 8 日,Caroline 第一次参加了 LGBTQ 支持小组;5 月 25 日,受到朋友和导师的鼓励,Caroline 决定收养一个孩子;与此同时,Melanie 也对领养机构做了一些调研。"

把它拆成三条原子事实,逐条比对:

总结里的原子事实真值怎么说判定
Caroline 第一次参加 LGBTQ 支持小组(5/8)会话1真值完全一致✅ 对
Caroline 决定收养一个孩子(5/25)会话2真值只说"开始研究领养机构",还没到"决定收养"❌ 编造:说过头了
Melanie 也调研了领养机构去调研的人是 Caroline,不是 Melanie❌ 编造:张冠李戴

整条打分链路画出来是这样:

FactScore 逐条较真的完整过程:总结拆成原子事实、逐条去真值核对得到精确率;反过来看真值有没有被覆盖,得到召回率;两条独立的线各自算完,再取调和平均。

图 3 FactScore 逐条较真的完整过程:总结拆成原子事实、逐条去真值核对得到精确率;反过来看真值有没有被覆盖,得到召回率;两条独立的线各自算完,再取调和平均。

三条里只有一条站得住,精确率 = 1/3 ≈ 0.33。再看真值这边:三个会话各有一条真值,总结只命中了会话1那条,会话2、会话3的真值("研究领养机构""在学校演讲鼓励同学")都没被准确覆盖,召回率同样是 1/3 ≈ 0.33,F1 ≈ 0.33。"决定收养"看着像是"研究领养"的自然延伸,实则被判定为编造;把 Caroline 的事安在 Melanie 头上,更是直接暴露了模型没分清谁是谁。FactScore 就是这样不讲情面地逐条较真——一句听着很顺、语气也对的总结,可能大半分都拿不到。

6.3 五类常见失败

论文对生成的总结做了人工归类,五种错误反复出现。下面几个例子是论文自己报告的真实案例(Table 6,人物是 Nate 和 Joanna,来自另一段对话):

  • 漏掉信息:真值是"Joanna 提交了她第三份、关于失去与身份认同主题的剧本",模型总结成"Joanna 提交了她最近写的剧本"——具体是第几份、写的什么主题,全丢了。长对话里的因果链条一长,模型就容易"抓大放细"。

  • 无中生有:对话里 Nate 说了三句不相关的话——"游戏聚会办得很成功""大家还想下个月再办一次""对了我还做了纯素冰淇淋"——模型却把它们粘成了一句:"Nate 的纯素冰淇淋大获成功,大家还想下个月再来一次",硬把"聚会的成功"安在了"冰淇淋"头上。

  • 读不懂玩笑:Joanna 随口说"这些小径让我有种想写剧本的感觉",Nate 打趣接了句"那我也想想我自己的剧本好了",Joanna 笑着回"哈哈,那可真有意思"——明摆着是两人打趣。模型却当真了,总结成"Nate 认真考虑自己写一部剧本"。

  • 张冠李戴:真值是"Nate 邀请 Joanna 尝尝他自制的无乳糖冰淇淋",模型总结成"Joanna 邀请 Nate 到她家尝尝她的无乳制品冰淇淋配方"——邀请人和被邀请人对调了,连"谁做的冰淇淋"都说反了。这一类错误和上面 §5.2 那道对抗题的陷阱是同一种病:模型能记住"有这么件事",却记不准"这件事是谁的"。

  • 小题大做:Nate 只是寒暄了一句"嗨 Joanna,我们上次聊完之后你怎么样?",模型却把它当成一件正经事记了下来:"Nate 询问 Joanna 上次聊天之后的近况"——一句客套话被当成了"事件"。

这五类错误合在一起看,指向同一个根本困难:长对话里信息密度低、指代模糊、还夹杂着玩笑与闲聊,模型要在这堆"噪音"里既不漏事、也不编事、还得认清谁是谁。这恰恰是"总结"比"问答"更难的地方——问答只需要在一堆材料里精确定位一个点,总结却要对整段材料的因果和归属都心里有数。

6.4 结果

表 6 事件总结结果(摘自论文 Table 4;ROUGE 与 FactScore,越高越好)

模型上下文ROUGE-1ROUGE-2ROUGE-LFactScore 精确率FactScore 召回率FactScore F1
Mistral-7B-Instruct8K34.610.116.433.531.232.3
Llama-3-70B-Instruct4K36.711.419.240.335.637.8
claude-3-sonnet200K35.112.621.345.640.843.1
gemini-1.0-pro1M37.613.421.146.742.144.2
gpt-4-turbo128K41.213.821.651.946.548.9

趋势和问答任务如出一辙:窗口越大,成绩越好——最强的 gpt-4-turbo(128K)FactScore F1 达到 48.9,比只有 4K 窗口的 Llama-3-70B 高出 11 分。但即便是最好成绩,离"满分"也差得远,说明"把长对话的时间线和因果串起来"仍是长上下文模型的短板,而不只是"窗口不够大"的问题——上一节那五类错误就是这个短板的具体表现。这个任务不做 RAG:总结需要对全篇的通盘把握,检索出某几段是不够的。


7. 任务三 · 多模态对话生成

前两个任务都是"考记忆"——给一段历史,看模型能不能精确地把某个点或某条线捞出来。这个任务换了个角度,考"生成":把历史交给模型,不问它任何问题,只让它顺着人设和已经发生的事,自己写下一轮回复(可能还带一张图),看写出来的东西像不像真实该发生的那样。

7.1 任务怎么设

LoCoMo 的对话都锚定在人设和"人生时间线"上,话题会随着几周、几个月里发生的事自然演变。论文自己举的例子很形象:"如果一个人最近受了伤,接下来的对话大概率会聊养伤,而不是去蹦极。"——这正是 §4 那张事件图存在的意义:它不只是给事件总结任务当真值,也是这个生成任务里"话题该往哪走"的隐藏剧本。评测就是让模型生成下一轮多模态回复,再用 MM-Relevance(Feng et al., 2022)衡量它和真实发生的下一轮有多贴近,辅以 BLEU 等常规生成指标。

论文训练并对比了三个版本的 MiniGPT-5(Zheng et al., 2023),区别只在"喂给它多少上下文":Base 只喂之前的对话轮;+summary 额外喂一份全局摘要;+observation 额外喂从历史里检索回来的观察事实。三者用的是同一个 MiniGPT-5 底座,唯一变量就是"喂料方式"。

7.2 一个真实例子:同一句问话,两种喂法两种回答

论文里附了一个具体案例(Figure 4),正好能让"喂料方式怎么影响生成"这件事变得看得见摸得着。为方便叙述,把对话双方称作 James 和 Nate。输入对话是这样的:

James:嗨 Nate,最近怎么样?
Nate:……我这边还行,就是在忙这个。(配了一张图)
James:你这游戏房看着不错——最近是不是老在打游戏?

真实发生的下一句(真值)是:

"打游戏一直是我的重心——练了不少,还赢了几场比赛。上周我刚拿到我的第二个冠军!"

不做检索(Base),MiniGPT-5 是这么接的:

"是啊,看到大家在我们的活动室里一起愉快地打游戏,我真的很开心。"

这句话不算错,语气也搭,但它是一句"正确的废话"——泛泛地说"大家玩得开心",完全没接住"最近是不是老在打游戏"这个问题背后真正该聊的内容:Nate 最近赢了比赛。

换成 +observation,先从历史里检索出三条相关事实:

Nate 上周赢了他的第一场电子游戏比赛。
Nate 下个月要参加一场游戏比赛,这将是他第 4 次参赛。
Nate 享受比赛本身的乐趣,就算输了也会给对手鼓掌。

再看它接的话:

"谢谢!……竞技游戏最让我享受的部分,就是看到大家在电子游戏比赛里玩得开心……"

这一次明显更贴题——"比赛"这个具体的词被带出来了。虽然措辞上还是没有真值那样精准地报出"第二个冠军",但方向对了:它是顺着"Nate 最近在打比赛"这条真实的事实线索往下接的,而不是泛泛地聊"大家一起打游戏"。喂料方式的区别,就这样直接体现在了生成内容的具体程度上——这和 §5.3 里"observation 库更聚焦"的发现是同一个道理,只是这次影响的不是"答对没答对",而是"接得像不像"。

两条链路摆在一起看会更清楚:

同一句问话、两种喂法的完整对比:Base 不检索、泛泛而谈;+observation 先检索出相关事实再生成,明显更贴题。两条生成结果最终都要和真值比对 BLEU/ROUGE-L/MM-Relevance 三个指标。

图 4 同一句问话、两种喂法的完整对比:Base 不检索、泛泛而谈;+observation 先检索出相关事实再生成,明显更贴题。两条生成结果最终都要和真值比对 BLEU/ROUGE-L/MM-Relevance 三个指标。

7.3 结果

表 7 多模态对话生成结果(摘自论文 Table 7;BLEU/ROUGE-L/MM-Relevance,越高越好)

训练方式检索条数 top-kBLEU-1/2ROUGE-LMM-Relevance
Base(不检索)–56.4 / 31.811.654.2
+ summary157.2 / 31.611.954.7
+ summary256.6 / 30.911.754.1
+ summary556.2 / 30.511.554.0
+ observation558.7 / 32.212.655.8
+ observation1058.1 / 32.112.055.1
+ observation2557.8 / 31.611.854.9

表里能看出三条线:第一,+observation 全面优于 Base 和 +summary,最好的组合(top-5)比 Base 在 MM-Relevance 上高出 1.6 分;第二,喂全局摘要帮助有限,+summary 在 top-1 时略有提升,但 top 越大反而越差;第三,即便是最有效的 +observation,检索也不是越多越好——top-5 最优,top-10、top-25 反而掉分。这条"信噪比比数量重要"的规律,和 §5.4 里 RAG 问答的发现完全一致:把历史提炼成一条条聚焦的事实、只取最相关的几条,比塞原文、塞摘要、或者贪多都更管用。论文还发现 MM-Relevance 会随对话历史变长而下降(越长越容易跑偏),RAG 能缓解这个下滑趋势。

7.4 复现时的边界

这个任务在实践上和前两个有点脱节,值得单独提醒:它的训练数据是另外用同一套流水线生成的 50 段对话(没有经过人工校对),评测才用回这 10 段正式发布的数据;而且它是三个任务里唯一真正用到图片本体(而不是文字图注)的任务。结合"图片不释放、只留链接"这个事实(§8 坑四),它也是三个任务里最难开箱复现的一个——图注和搜索词本身还可能对不上号(回看 §3.1 那个"图注是狗、搜索词是跨性别壁画"的例子),复现时这条链路上的每一步都可能因为图片这个变量而失真。


8. 适用边界与复现注意事项

前面讲的是设计。这一节是逐文件审计的产物——只读论文和 README 发现不了、但会实打实影响复现和结论解读的地方。

坑一:题型编号和论文正文拧着。 这是最该记住的坑,§5.1 已详述:数据里 category 的 1 是多跳、4 是单跳,2 时间、3 开放域,和论文文字顺序(1 单跳、2 多跳……)不一致。复现时一切以代码里的 keys=[4,1,2,3,5] 和打分分支为准,否则成绩单会静默错位。

坑二:对抗题的答案字段错位,直接跑官方脚本会报错。 这是一手核实的复现 bug。数据里 446 道对抗题,全部只带 adversarial_answer 字段(那个诱人的错误答案),几乎都没有 answer 字段。但四个作答脚本(gpt / claude / gemini / hf)在处理对抗题时,引用的都是 qa['answer'](如 gpt_utils.py#L248)。我在全仓库搜过,没有任何一行代码读取 adversarial_answer。这意味着:拿官方 evaluate_gpts.sh 直接跑官方 locomo10.json,会在第一道对抗题就 KeyError: 'answer'。想跑通,得自己先把 adversarial_answer 映射成 answer。数据 schema 改了名,作答代码没跟上——这是发布代码和发布数据没对齐的典型。

坑三:这份数据是 50 段砍成的 10 段。 README 明说,当前 10 段是 2024 年 3 月首版 50 段的子集,为了保留最长、标注最好的对话并降低闭源模型评测成本而缩减。影响有二:一是论文里有些设置和这份数据对不上(比如多模态任务的训练数据是那另外的 50 段),引用规模数字时要说清是哪一版(论文摘要写平均 300 轮 / 9K token,那是 50 段全集的口径;发布的这 10 段因保留最长对话,实为平均 588 轮 / 16.6K token,本地实测印证);二是 10 段样本量偏小、题型分布悬殊,做子群统计时噪声要留意。

坑四:图片只给线索不给本体。 带图轮次约 910 个,但每个只有网页链接、机器图注和搜索词,没有图片文件。后果是:多模态任务不能开箱复现(得按链接重爬,而链接会腐烂);问答和事件总结任务里,论文的做法是直接用 BLIP 图注替代图片,也就是说这两个任务本质上是纯文本评测,多模态含金量有限——这一点论文自己也列为局限。加上 §3.1 那个"图注是狗、搜索词是壁画"的例子,图注质量本身也参差。

坑五:词面 F1 很脆,且没有大模型兜底。 §5.2 已算过,一个语义完全正确的答案可能只拿 0.44 分,纯粹因为多说了几个词。这套打分对同义改写零容忍,好处是便宜、可复现、无裁判偏差,坏处是分数偏保守、且会被模型的"措辞风格"污染。和 LongMemEval、HaluMem 用大模型当裁判相比,这是一体两面,用时心里有数即可。对抗题只认关键词更是脆——模型换个说法拒答("I don't see that in our chats")会被误判为答错。

坑六:一个容易读错的口径——"记忆距离"是按字符不是 token。 论文想分析"证据埋得越深越难答",但底层统计对话长度时,在没传编码器的默认情况下用的是字符数而非 token 数(evaluation_stats.py#L25),并据此每 1000 分桶。所以那些"按记忆长度分组"的曲线,横轴单位其实是字符。跨模型解读时别把它当 token。


9. 怎么选:和 LongMemEval、HaluMem 比

这三个 benchmark 经常被一起提,但它们对"记忆"的假设、测的东西并不相同。看清差异,才知道什么时候该用哪个。

表 8 三种记忆评测对比

维度LoCoMoLongMemEvalHaluMem
核心任务问答 + 事件总结 + 多模态生成检索 + 问答(两条线)抽取 + 更新 + 问答(三操作)
把"记忆"当成原始对话片段原始对话片段抽取改写后的新句子
打分方式词面 F1 / FactScore(不用大模型裁判)证据 ID(Recall@k) + 大模型裁判纯大模型语义比对
评测粒度端到端端到端,但拆检索/回答两条线操作级(每一步单独标注)
检索诊断有(仅 RAG 模式)有(强,独立一条线)无
测知识更新否是是
测抽取失真/幻觉否否是
测因果/时间线串联是(事件总结任务)部分(时间题)否
多模态是(三者中唯一)否否
单段规模~27 会话 / ~16K token~50 会话 / ~115K(S)~1.5M(M)token~1M token

这张表最该带走的是两点。

其一,"把记忆当成什么"决定了"怎么打分"。LoCoMo 和 LongMemEval 都认为记忆是原文片段、天然带坐标 ID,于是能用便宜又精确的 Recall@k 和词面匹配;HaluMem 认为现代记忆系统里存的是被嚼碎、改写过的新句子,没有原文页码可对,只能靠大模型逐条比意思。三者没有高下,是被各自的"记忆形态"逼出来的。

其二,LoCoMo 的不可替代性在"广度"。它是三者里唯一同时覆盖多模态、说话人人设一致性、以及事件因果与时间线串联的。想研究"长对话里连续的人物、事件、多模态的长程一致性",LoCoMo 几乎是唯一选择。反过来,它测不了记忆的"存/改"质量(那是 HaluMem 的地盘),也没有独立的检索诊断线(那是 LongMemEval 的强项)。


10. 结论与适用场景

LoCoMo 的历史地位,是把"超长对话记忆"这个方向从"5 轮会话的玩具设定"一举拉到"27 个会话、近 600 轮、跨月、带图"的真实量级,并用三任务框架把"记性好不好"拆成了能逐项归因的成绩单:单点回忆、跨会话综合、时间推理、常识推断、对抗拒答,再加上事件串联和多模态一致。它给出的"人类 87.9、最强模型 51.6"的差距,以及"长上下文反而更容易在对抗题上幻觉"这个反直觉发现,至今仍是记忆系统研究的重要参照。

什么时候用它:你要评测长上下文模型或 RAG 型系统在超长对话下的综合记忆;你关心时间/因果推理,或多模态、人设一致性;你想要一个便宜、可复现、无裁判偏差的自动化基准。

什么时候别用或要改造:你的系统是"抽取改写型"记忆(Mem0 / MemOS 那类),要测存改质量或抽取幻觉,去用 HaluMem;你要独立诊断检索质量、要强检索线,去用 LongMemEval;你需要对语义改写宽容的判分,LoCoMo 的词面 F1 会偏严。

用之前,把这几件事记在心里就不会踩坑:题型 category 编号和论文正文颠倒(§8 坑一);对抗题字段错位、直接跑官方脚本会报错(坑二);数据是 50→10 的子集、图片不释放、多模态任务不能开箱复现(坑三、坑四);词面 F1 和对抗关键词判分都偏脆,跨模型比分数时打个折(坑五)。


11. 附录:术语 / 复现命令 / 代码索引 / 参考

A. 术语速查

术语一句话解释
session / turn一次会话 / 会话里的一轮发言
dia_id对话坐标,格式 D<会话号>:<轮号>,如 D1:5
人设 persona说话人的性格设定,取自 MSC 再由 gpt-3.5 扩写
时间事件图每人一张:≤25 个带日期、有因果连线的人生事件,铺在 6~12 个月
observation从对话抽出的事实句(带坐标),RAG 的一种检索库
session_summary每个会话一段摘要,RAG 的另一种检索库
event_summary人工标注的事件真值,事件总结任务的评分依据
evidence含答案的坐标列表,用于判 RAG 检索有没有命中
adversarial_answer对抗题里那个"诱人但错"的答案,正确行为是拒答
FactScore把文本拆成原子事实逐条比对的事实准确度指标
MM-Relevance多模态回复与真值贴合度的指标
category(1-5)数据里的题型编号:1 多跳 / 2 时间 / 3 开放域 / 4 单跳 / 5 对抗(注意与论文正文顺序不同)

B. 最小可跑(问答)

# 1) 填 key 与路径
vim scripts/env.sh            # OPENAI_API_KEY / 数据路径等
# 2) 长上下文问答(把历史尽量塞进去)
bash scripts/evaluate_gpts.sh        # OpenAI
bash scripts/evaluate_claude.sh      # Anthropic
bash scripts/evaluate_gemini.sh      # Gemini
bash scripts/evaluate_hf_llm.sh      # HuggingFace 开源模型
# 3) RAG 问答(DRAGON 检索器需 GPU;三种库 × 多个 top-k)
bash scripts/evaluate_rag_gpts.sh

数据即仓库内 data/locomo10.json,无需额外下载。跑对抗题前,记得先把每道 category==5 的 adversarial_answer 映射成 answer,否则会 KeyError(§8 坑二)。

C. 代码索引(关键位置,可点击)

看什么位置
问答打分主逻辑 + 五类分支evaluation.py#L189-L241
多跳"多答案 F1"(逗号拆分)evaluation.py#L141
归一化(去冠词 / 词干还原)evaluation.py#L75-L138
开放域题"取分号前结论"evaluation.py#L203
对抗题关键词判分evaluation.py#L217-L221
RAG 检索命中(recall)判定,S开头退化为会话级evaluation.py#L228-L237
ROUGE-L 计算(事件总结辅助指标)evaluation.py#L148-L158
汇总顺序 keys=[4,1,2,3,5]evaluation_stats.py#L98
记忆距离按字符分桶evaluation_stats.py#L17-L27
时间题提示 / 对抗题二选一(引用 qa['answer'])gpt_utils.py#L243-L256
RAG 三种库检索 + 拼接gpt_utils.py#L145-L169
检索器(DPR/Contriever/DRAGON/OpenAI)rag_utils.py#L36-L66
对话生成流水线入口generative_agents/generate_conversations.py

D. 参考资料

  1. 论文:Maharana et al. Evaluating Very Long-Term Conversational Memory of LLM Agents, ACL 2024

  2. 代码 / 数据 / 主页:github.com/snap-research/locomo · snap-research.github.io/locomo

  3. 生成式智能体基础:Park et al. Generative Agents, 2023

  4. 人设来源:Xu et al. MSC (Beyond Goldfish Memory), 2022

  5. 事实性指标:Min et al. FactScore, 2023

  6. 多模态生成指标与底座:Feng et al. MMDialog / MM-Relevance, 2022 · Zheng et al. MiniGPT-5, 2023

  7. 姊妹 benchmark:LongMemEval arXiv:2410.10813 · HaluMem arXiv:2511.03506


本报告基于论文、开源代码逐文件审计、以及本地真实数据 locomo10.json 逐样本走查,未运行完整评测 pipeline(未调用大模型 / GPU)。规模统计、题型分布、category 映射、§8 各坑均经一手核对;代码行号对应撰写时的 main 分支,可能随更新变动。调研时间 2026-07。

分享这篇文章

复制链接,或分享到你常用的地方。

评论

发表评论

0 / 1000