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

VehicleMemBench:用可执行车机任务评测长期记忆

VehicleMemBench 不以问答得分为终点,而是检查 Agent 能否从多人长期历史中找回偏好、调用正确车机工具,并把虚拟车辆调整到目标状态。

Agent Memory
Benchmark
In-Vehicle Agent
合集目录:Agent 记忆评测:基准、数据与方法第 7 / 8 篇

调研对象:VehicleMemBench(An Executable Benchmark for Multi-User Long-Term Memory in In-Vehicle Agents),arXiv:2603.23840,2026-03。

材料来源:论文 PDF、当前仓库的全部 benchmark/、environment/、evaluation/ 与示例脚本;另参照同目录的 HaluMem、LoCoMo、LongMemEval 调研以做横向定位。

贯穿全文的真实样例:qa_1.json 的第 0 题。Gary 想恢复自己常用的“平静氛围”,但车里还有喜欢白色仪表盘的 Patricia、喜欢蓝色的 Justin;正确动作是把仪表盘设为绿色。

摘要

VehicleMemBench 把“长期记忆是否有用”落到可执行结果上。系统不只要回答 Gary 喜欢什么颜色,还要从多人长期历史中找回他的偏好,选择正确的车机 API,并把虚拟车辆调整到标准状态。这个设计比纯问答更接近工具型 Agent 的实际链路,但主分数同时受记忆、检索、LLM 推理和工具执行影响,不能只凭最终 ESM 判断故障发生在哪一环。

每个场景包含一辆由三名固定使用者共享的虚拟车、一份长期历史和十道新请求。Agent 可以检索记忆、发现车机工具,并调用 carcontrol_instrumentPanel_set_color 等 API。评测器把模型动作作用到一份虚拟车状态,把标准动作作用到另一份,再比较两者。仓库覆盖 23 个可控模块和 111 个 API。

论文中,无记忆设置下表现最好的 Gemini-3-Pro-Preview 得到 19.43 ESM;提供 Gold Memory 后达到 90.60 ESM。同一模型使用递归摘要时为 64.80 ESM,比 Gold Memory 低 25.8 点。这组结果表明,当前请求不足以让模型直接猜中答案,正确记忆和正确工具执行也是两项可以分开的能力。

阅读和复现时需要把握三个边界:

  • 它测的是记忆带来的任务效用,不是记忆库的纯质量。代码会记录检索调用和工具序列,但主聚合指标不计算检索结果相对标准记忆的 Recall@k、Precision@k,也不测写入是否完整。

  • 接入是 adapter 开发,不是填一个 URL。当前 CLI 只接受 Mem0、MemOS、LightMem、Memobase、Supermemory 五个硬编码名字。自己的系统需新增 Python adapter,至少实现历史写入、按用户检索、结果文本化等约定。

  • 当前实现是离线全历史写入。每份 history_N.txt 会完整灌入记忆系统后,再评该场景的十题;代码没有按题目发生时间截断可见历史。因此它测“完成一段长期历史后的检索”,不是严格防未来信息的在线会话回放。

它适合检查“记忆系统 + 工具型 Agent”能否完成会改变外部状态的任务,也适合验证接入不同记忆后端后的端到端收益。若目标是单独比较检索 Recall@k / NDCG、定位写入或更新阶段的丢失,仍需搭配 LongMemEval、HaluMem 或自建过程指标;它也不能替代真实车载环境中的安全和物理行为验证。


1. 评测对象与核心流程

先不要把 VehicleMemBench 想成“一个问答数据集”。它更像一场给 Agent 的驾驶舱操作考试:试卷先给它一段很长的多人聊天记录,最后只给一句模糊的车机请求;它必须自己查记忆、自己找到正确的车机函数、自己执行操作。裁判不看它说得是否漂亮,只看虚拟车有没有被调到标准状态。

它的核心目标可以写成:

它测的不是「模型能否说出偏好」,
而是「接上记忆后,Agent 能否把虚拟车调成偏好要求的状态」。

1.1 先看全局:四块拼成一个 benchmark

下面这张图把全文最重要的对象放在一起。读后续章节时,只要沿着“数据从哪来 → 哪种评测用它 → Agent 对车做什么 → 怎么判分”这条线走,就不会把数据集、模拟器和记忆系统混成同一件事。

VehicleMemBench 的全局结构:数据集提供历史和标准动作;模型评测或外部 memory adapter 驱动 Agent;最终统一在 VehicleWorld 的状态上判分。

图 0 VehicleMemBench 的全局结构:数据集提供历史和标准动作;模型评测或外部 memory adapter 驱动 Agent;最终统一在 VehicleWorld 的状态上判分。

这张图有一个容易忽略的要点:被测的 memory system 并不直接操作车辆。它只负责把历史写进去、在 Agent 请求时返回相关记忆;真正决定动作的是 LLM Agent,真正被比较的是两份虚拟车的最终状态。

1.2 先在 30 秒内跑完一题

以下图中的每一步都发生在一次真实评测中。Gary 的颜色偏好只是一个例子;换成座椅、空调、导航或车窗,链条不变。

一题的最短链条:历史不是直接送进评分器,而是要先经记忆、推理与工具调用,最后才落到可比较的车辆状态。

图 1 一题的最短链条:历史不是直接送进评分器,而是要先经记忆、推理与工具调用,最后才落到可比较的车辆状态。

这张图也解释了“为什么需要工具”。如果题目只问“Gary 喜欢什么颜色”,答案是文本;但真正的车机助手需要让仪表盘变绿,所以必须调用能改变状态的函数。仓库里的 VehicleWorld 是一辆在内存中的虚拟车,不是实体汽车,也不是连接车厂云端的真实 API。

1.3 它为什么不是普通记忆问答

传统长期记忆 benchmark 的终点通常是“问一个问题,看答案是否正确”。这能测模型是否找回事实,却绕开了 Agent 落地时更麻烦的后半程:谁的偏好应当优先、该调用什么工具、参数填什么、以及是否误动了别的设备。

车载场景把问题放大得很自然。一辆共享汽车有多个长期使用者;“把灯调回舒服的状态”不是一个确定指令,而是需要识别当前人、历史偏好、时间、天气、地点与乘客关系。即使模型回了一句“已为你调整”,也不能说明车真的被调对。

VehicleMemBench 的核心选择是:给 Agent 一个可执行的虚拟车,而不是只给标准文本答案。车由 Python 对象 VehicleWorld 表示,包含 HUD、座椅、空调、导航、灯光、车窗等模块;每个车机 API 都会改变对象中的字段状态。最终裁判只问一件事:

模型实际执行后的车辆状态 == 标准动作执行后的车辆状态 ?

这带来两项真优势。

  • 不用 LLM 裁判。“绿色还是白色”“驾驶位头枕是否为 44”都落在程序状态里,可重复比较。

  • 惩罚多余操作。只把仪表盘调绿是正确;若同时无故改了空调,即使关键颜色正确,完整状态也不一致,Exact State Match 仍失败。

代价也清楚:最终状态是一个端到端信号。失败可能来自没写入偏好、没检索到、检索到了但没理解、找错工具、参数填错、或多调用了无关 API。状态比较能准确发现“车没调好”,但不能自动诊断“记忆在哪一步坏了”。后文 §5 和 §7 会把这个边界拆开。


2. 一个完整例子:Gary 的绿色仪表盘

全文只用 qa_1.json 的第一题说明机制,避免在不同例子之间来回切换。它属于 preference_conflict(偏好冲突):

{
  "gold_memory": [
    "Justin 喜欢蓝色仪表盘。",
    "Gary 说绿色仪表盘让他想起森林,喜欢绿色。",
    "Patricia 夜晚觉得绿色太暗,改成白色。"
  ],
  "query": "Gary 坐在驾驶位,Patricia 是乘客;"
           "Gary 说:让我们恢复我平常那种平静氛围。",
  "new_answer": [
    "carcontrol_instrumentPanel_set_color(color=\"green\")"
  ]
}

这里至少有四件事不能混:

信息它的作用谁能看见
完整 history_1.txt真正的长期对话,含大量无关聊天写入阶段给记忆系统
gold_memory本题相关事实的人工整理片段仅 Gold Memory 模式直接给 Agent;也可供离线审计
query当前要执行的新请求被测 Agent
new_answer标准动作序列评测器,不给 Agent

为什么答案是绿色。当前驾驶者是 Gary;“平常”“平静氛围”指向他自己的绿色偏好。Patricia 的白色偏好有“夜晚看不清”这个条件,且她现在只是乘客;Justin 的蓝色偏好也不属于当前人。正确动作不是复述“Gary 喜欢绿色”,而是实际调用设色 API。

这类题最难的地方不是记住三种颜色,而是把“历史事实”筛成“当前情境下该生效的事实”。可以把 Gary 题的判断过程看成下面三次过滤;它描述的是这道题的推理,不是代码里写死的一条“驾驶者永远优先”的通用规则。

多人偏好如何落到一个动作:不是取“最新一次设置”,而是同时过滤人物、条件和指代,再得到本题应生效的偏好。

图 2 多人偏好如何落到一个动作:不是取“最新一次设置”,而是同时过滤人物、条件和指代,再得到本题应生效的偏好。

2.1 两份“车”不是两辆实体车

每题运行时,评测程序在内存中新建两个相同的 VehicleWorld() 对象:

初始状态:仪表盘颜色 = white

参考副本 vw_ref:执行标准动作 set_color(green)
                → 参考最终状态:颜色 = green

模型副本 vw_pred:执行模型实际选择的动作
                → 模型最终状态:由模型决定

若模型调用 set_color("white"),模型副本没有完成应有的变更;若调用 set_color("green") 后又改了空调,模型副本多出不应有的变更;两种都不能 Exact Match。只有最终完整状态与参考副本相同才算通过。

这就是“可执行”的准确含义:不是连真车,也不是调用某个云端车机服务,而是执行仓库内自己定义的 Python 方法。InstrumentPanel 的默认颜色为 white,carcontrol_instrumentPanel_set_color 会校验并写入其 color 属性。


3. 数据长什么样:50 份长期多人历史,挂 500 道可执行题

一条 benchmark 样本不是“一问一答”。正确的心智模型是“50 套共享车辆档案,每套有一本长历史和十道操作题”:

benchmark/
├── history/history_1.txt  ─┐
├── qa_data/qa_1.json      ─┘ 同一组三名用户;10 个新请求
├── history/history_2.txt  ─┐
├── qa_data/qa_2.json      ─┘ 下一组独立用户;10 个新请求
└── ...

本地数据统计与论文 Table 3 相互印证:50 个用户组、每组三人,合计 150 个 persona、500 条可执行查询。论文还报告每组由 30 条事件链交织而成,平均 81.78 个事件、2,690 行 / 92,819 GPT-4o tokens 的历史。

表 1 本地发布数据的离线统计——历史很长,题目本身很短

对象数量 / 范围说明
history_N.txt50 份每份对应一个三人用户组
qa_N.json50 份每份恰有 10 个可执行请求
总请求500每题含 query、reasoning type、标准动作
历史字符数28.4 万 ~ 44.3 万;中位数 33.0 万全量约 1,684 万字符
历史覆盖天数38 ~ 77;中位数 46.5由每行时间戳离线统计
历史行数2,382 ~ 3,469;中位数 2,642对话与事件穿插
每题 Gold Memory 长度104 ~ 621 字符;中位数 306仅相关证据摘要,不是完整历史
参考动作数432 题 1 个、64 题 2 个、4 题 3 个多动作题会同时改变多个字段

3.1 五种“记忆为什么会难”的类型

表 2 五类推理任务分布——偏好冲突最多,条件约束是论文中最难的一类

类型数量占比它在考什么Gary 题对应什么
Preference Conflict14929.8%多人偏好冲突时识别当前应优先谁Gary / Patricia / Justin 对仪表盘颜色不同
Conditional Constraint10220.4%同一偏好只在时间、天气、地点、活动等条件下成立“工业区开内循环”“夜间白色面板”
Coreference Resolution9719.4%“他的最爱”“上次那个设置”究竟指谁、指哪条历史“把灯设成他喜欢的颜色”
State Shift9018.0%偏好或状态后来改变,应使用新值而非旧值治疗建议后按摩强度从 2 改为 3
Error Correction6212.4%用户纠正过一次,应记住纠正后的值通风 3 太强,舒适值应为 2

五类任务均有自然语言表面形式,但其标准答案都是可解析的工具调用字符串。论文的目标模块分布以导航 96 题、座椅 85 题、灯光和空调各 64 题为主,其余模块合计 108 题;这避免 benchmark 只在单一设备上成立。

3.2 数据如何构造

数据不是从真实车机日志采集的,而是 persona 与事件链驱动的合成数据。图 0 已给出它在全局流程中的位置;它的内部顺序可压缩为五步:三人 persona → 车载与非车载偏好事件链 → 按时间交织 → 生成并人工核查长对话 → 生成、人工复核且在模拟器中验证 query 与标准动作。

特别重要的是第二步:每组不仅有 10 条可执行的车载偏好链,还有 20 条不直接控制车辆的背景链。历史中会有工作、旅行、家人、爱好等看似真实却无关的聊天。被测系统若把所有信息都压进记忆,不一定更好——它可能在检索时把噪声一并递给 Agent。


4. 评测怎样运行:写入记忆、检索、调车、对状态

VehicleMemBench 有两条相关但不同的评测路径。第一条是“模型在不同内置记忆构造下表现如何”;第二条才是“把一个外部记忆系统接进来后表现如何”。

先区分两条路径,再看各自细节。两者都用同一批 QA、同一个 VehicleWorld 和同一套状态指标;差别只在 Agent 在做题前如何获得历史信息。

两套评测方法的关系:A 测同一模型在不同“记忆供给方式”下的表现;B 测“外部 memory + 固定 Agent”这套组合的端到端效用。

图 3 两套评测方法的关系:A 测同一模型在不同“记忆供给方式”下的表现;B 测“外部 memory + 固定 Agent”这套组合的端到端效用。

4.1 模型评测:四种记忆条件

模式Agent 在做题时拿到什么主要隔离什么
none只有当前 query,没有历史无记忆下的下限
gold本题的 gold_memory给定正确记忆后的工具与推理上限
summary对整份历史按天递归更新的摘要压缩记忆能否保住关键偏好
key_valueLLM 逐日写入的键值库;做题时可 memory_search / memory_list结构化记忆与按键检索

README 把 none 叫作 “Raw History”,但源代码实际对该模式传入空历史;它是无记忆基线,并非把完整原始历史塞给模型。这是文档和实现的一个小口径差异。

摘要模式会按日期分组,提示 LLM 只保留车载偏好、条件、冲突和纠错;代码希望摘要少于 2,000 词,并把超过 8,192 字符的单次记忆截断。KV 模式也明确要求丢弃与车辆无关的生活信息,再通过 memory_add/remove/search 维护偏好键值。

4.2 外部记忆系统评测:真正的接入路径

外部系统评测分两个阶段。第一阶段先把一份完整历史灌入某个记忆后端;第二阶段让 LLM Agent 在每个新请求中自主决定是否搜索、搜索什么、再调用车机工具。图 3 的 B 路径说明了两阶段的边界:add 发生在做题之前,test 才发生检索和车辆操作。

Agent 一开始并不会得到全部 111 个工具,而是先看到 list_module_tools(module_name)。它要先决定“这是仪表盘问题”,加载 instrumentPanel 模块的函数 schema,再能调用具体 API。这个设计既能测工具发现,也避免把全量 schema 直接塞入 prompt。

外部记忆模式额外提供 search_memory(query, top_k);代码要求“请求依赖历史偏好时先查记忆”,但 LLM 是否遵循仍是被测行为。每次搜索、工具发现、车辆调用都写入逐题结果。

4.3 标准动作如何变成目标状态

new_answer 不是直接拿来和模型输出字符串比,而是先被解析成 {name, args},在参考车对象中执行。例如 Gary 题的标准字符串会让参考车的 instrumentPanel.color 从 white 改为 green。

模型的实际函数调用作用在另一份车对象上。最后,评测器递归展开初始状态、参考最终状态、模型最终状态的所有标量字段,找出应变字段、已变字段、错误值与意外变更。顺序不同但最终状态相同可以通过状态指标;相反,工具名看似合理但末状态不对也会失败。


5. 指标与一遍手算:状态是主判据,过程只被记录

论文定义的主指标围绕状态变化。设初始状态为 v_init,标准动作执行后为 v_ref,模型执行后为 v_pred:

Δref  = 相比 v_init,标准答案应该改变的字段集合
Δpred = 相比 v_init,模型实际改变的字段集合

状态指标的对象不是“模型回复的文本”,而是四份可比较的状态:一份初始车、标准动作后的参考车、模型动作前后的模型车。为了便于理解,当前实现把两条路径都从同样的初始状态展开:

状态评分究竟在比什么:它比较两条动作路径造成的字段变化,而不是直接比较两段自然语言或两个工具字符串。

图 4 状态评分究竟在比什么:它比较两条动作路径造成的字段变化,而不是直接比较两段自然语言或两个工具字符串。

表 3 官方状态指标——同一答案可从“是否完成”“改对字段”“填对值”“是否乱动”四个角度看

指标代码中的含义高分说明
Exact State Match(ESM)没有差异、没有意外变更、没有应变未变整辆虚拟车完全对
字段 Recall / Precision / F1字段是否应该变、是否实际变找到正确的控制目标,且不乱动
值级 Change Accuracy / F1应变字段中,最终值是否等于参考值绿色、44、inside 等参数也对
负向 Accuracy / F1本应不变的字段是否维持不变没有把无关设备调坏
平均调用数 / 输出 token每题交互量与模型输出量执行成本低

代码还对模型工具序列计算了精确的 Tool-call F1:工具名和全部参数序列化后必须匹配才算 TP。不过它保存在每题 all_results.json 的 tool_score 中,当前 metric.json 并没有聚合输出 Tool-call F1;需要自行汇总。

5.1 用 Gary 题手算

初始时,仪表盘颜色为 white。标准答案只改一个字段:

Δref = { instrumentPanel.color : white → green }

下表分别演示四种模型行为。这里先只关注颜色与额外空调字段,其他状态均保持初始值。

表 4 Gary 题的手算账本——“改了正确字段”并不等于“最终正确”

模型实际操作Δpred 的关键内容字段 TP / FP值正确数ESM解释
不调用工具空集0 / 00❌应改颜色却没改,属于应变未变
set_color("black")只改颜色,但值错1 / 00❌字段 Recall=1,但值级 F1=0
set_color("green") + 无故改空调颜色正确,外加空调1 / 11❌字段 Precision=1/2,存在意外变更
set_color("green")只改颜色且值对1 / 01✅状态与参考车一致

第三行可把 F1 真正算一遍。模型改了两个字段,其中仪表盘颜色是应变字段、空调不是:

字段 Precision = TP / (TP + FP) = 1 / 2
字段 Recall    = TP / |Δref|     = 1 / 1
字段 F1        = 2 × 1/2 × 1 / (1/2 + 1) = 2/3

值级 Precision = 正确值数 / (TP + FP) = 1 / 2
值级 Recall    = 正确值数 / |Δref|     = 1 / 1
值级 F1        = 2/3

ESM 仍为 0,因为它不是“平均正确率”,而是“完整状态是否全对”的严格门槛。这恰好是本 benchmark 相对纯 QA 的强项:它能区分“核心偏好找对了但做了多余操作”和“真正完成了任务”。

5.2 过程指标的缺口

外部记忆评测的逐题结果会保存:

  • memory_tool_calls:调用了什么检索 query;

  • num_memory_calls:检索次数;

  • pred_call_outputs:每次工具返回;

  • tool_score:标准动作与模型动作的精确匹配;

  • state_score:状态级 TP / FP / 差异。

但聚合器只平均 ESM、字段/值指标、总调用数与输出 token;它不把检索文本同 gold_memory 做语义或事实对齐。因此,以下问题官方不会直接回答:

  • 记忆系统是否写入了 Gary 喜欢绿色这条事实?

  • Agent 搜索 “Gary preference” 时,前 k 条是否包含这条事实?

  • 检索到了绿色,但 Agent 是否因为 prompt、工具 schema 或推理失误没有使用?

  • 记忆系统是漏掉了事实,还是取回了很多无关事实导致决策受干扰?

把这件事画出来会更直观:同样一个 ESM=0,可能代表完全不同的工程问题。

端到端状态分数的归因盲区:不同根因会汇聚成同一个失败结果,因此需要读取逐题日志并补检索审计。

图 5 端到端状态分数的归因盲区:不同根因会汇聚成同一个失败结果,因此需要读取逐题日志并补检索审计。

论文讨论的 MemoryScore = ESM_auto / ESM_gold 和 MemToken 能在概念上缓解这个问题:前者用 Gold 上界归一化,后者衡量检索内容量。但当前仓库的 metric.json 实现没有计算 memory_score 或 mem_token,只输出 avg_output_token。使用者不能把论文图表中的字段误认为“一跑仓库就会得到”。


6. 论文结果与关键发现

论文报告了 12 个模型的内置记忆构造实验,以及两种 backbone 上若干外部记忆系统的接入实验。以下数字均来自论文 Table 1、2、6;并非本文本地复跑的结果。

6.1 Gold Memory 把“工具能力”与“记忆能力”分开

表 5 三种记忆条件下的代表性 ESM——Gold 是上界,不是可部署方案

模型Recursive SummaryKey-Value StoreGold MemoryGold → Summary 落差
Gemini-3-Pro-Preview64.8057.3790.6025.80
Qwen3-Max60.6046.6083.6023.00
GPT-561.2052.4081.6020.40
Doubao-Seed-1.659.0026.6085.4026.40
GLM-4.7-Flash24.2019.6055.4031.20

读法有两层:

Gold 高,不表示记忆系统强。 Gold Memory 是把正确相关事实直接塞给 Agent,因此更接近“模型在已知偏好时会不会选工具、填参数”。Gemini 的 90.60 证明该模型在这个虚拟车环境里有很强的执行上限;GLM-4.7-Flash 的 55.40 则提示即使记忆正确,工具调用能力仍可能成为瓶颈。

Summary / KV 到 Gold 的缺口,才是端到端记忆损失。 Gemini 从 90.60 到 64.80,Qwen3-Max 从 83.60 到 60.60。论文据此认为,历史压缩与取用比单纯工具执行更常成为误差来源。需要谨慎的是:这个差值仍包含 Agent 接收、理解、利用记忆时的失败,不能直接等同于“记忆库自身的 Recall 损失”。

无记忆实验进一步支持任务确实依赖历史:论文中所有模型 ESM 都低于 20,Gemini-3-Pro-Preview 为 19.43。模型无法只从“恢复我常用的氛围”猜到 Gary 的绿色偏好。

6.2 通用记忆系统不一定胜过朴素的领域基线

表 6 外部记忆系统结果(ESM / Mem Token)——读法重点是“端到端效用与上下文成本”

Backbone系统ESMMem Token
Gemini-3-Pro-PreviewGold Memory90.6093.29
Gemini-3-Pro-PreviewRecursive Summary64.80303.25
Gemini-3-Pro-PreviewKey-Value Store57.3729.25
Gemini-3-Pro-PreviewLightMem60.72170.19
Gemini-3-Pro-PreviewMem052.10171.16
Gemini-3-Pro-PreviewMemOS56.11444.91
Gemini-3-Pro-PreviewSupermemory65.79960.79
Gemini-3-Pro-PreviewMemobase29.40993.49
Qwen3-MaxRecursive Summary60.60215.22
Qwen3-MaxKey-Value Store46.6026.03
Qwen3-MaxSupermemory58.20972.19

论文的主要发现是:简单、任务定制的递归摘要和 KV baseline 具有很强竞争力;若干通用 memory system 并未稳定超过它们。原因并不一定是某个后端“没有记忆”,也可能是通用系统保留了许多与车机决策无关的信息,检索阶段把噪声递给 Agent。这个解释与数据构造中 20 条背景链的设计是对应的。

条件约束最难。 在 Qwen3-Max + Recursive Summary 下,Preference Conflict 为 67.79,而 Conditional Constraint 仅 51.96;KV 下则是 61.07 与 38.24。多人冲突可以靠识别当前驾驶者解决;“工业区”“夜间”“雨天”“读蓝图”等条件需要把场景和偏好绑定,后端表示与检索更容易丢失这种关联。

不能只看 ESM。 论文还观察到自主记忆条件下字段级 F1 与值级 F1 的差距扩大:系统可能知道“应该调仪表盘”,但忘了“具体应为 green、white 还是 10”。对车机工具来说,后半步才决定真实状态是否正确。


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

7.1 真盲区:没有独立的记忆写入与检索正确率

这是最重要的限制。VehicleMemBench 通过状态结果间接评价记忆系统;它记录调用过程,却没有用题目 gold_memory 自动计算检索覆盖,也没有检查 memory store 内部是否存有正确事实。

这使它特别适合回答“接上后任务有没有成功”,不适合单独回答“哪个检索器 Recall 更高”。若两个系统都拿 60 ESM,原因可能完全不同:

系统 A:写入完整、检索命中,但 Agent 常把参数填错。
系统 B:Agent 工具很稳,但检索常漏掉条件偏好。

官方成绩单无法自动区分 A 和 B。实践中应在 §8 所述的端到端跑分之外,再做 retrieval-level 审计。

7.2 时序边界:代码是“先完整写入,再统一答题”

run_add 会遍历 history_N.txt 的所有时间桶并写入后端;test 阶段再读取同一 qa_N.json 的十题。查询数据结构不带“只允许读取到哪天”的 cutoff,评测器也没有在搜索时附带或过滤该时间界限。

这并不必然说明发布数据存在未来泄漏——题目设计者可能已确保查询发生在所有相关事件之后——但代码本身没有执行这个保证。若把框架用于自己的在线产品数据,应自行加上 query_timestamp,并让 add / search 严格遵守历史上界。

7.3 接入门槛:是代码 adapter,不是通用插件协议

支持列表写死在 evaluation/memorysystems/init.py,CLI 的 --memory_system 也用同一列表做 choices。传一个未注册服务名会在命令行参数阶段被拒绝。

这有好处:每个 adapter 能处理其后端特有的鉴权、用户隔离、时间戳与结果格式。代价是新系统需要改仓库代码,不能只填 MEMORY_URL。此外,不同后端并不完全等价:有些按小时写入,有些需要单线程或复用本地模型;示例脚本甚至对 LightMem、Supermemory、Memobase 使用了不同文件范围,横向复现时应统一范围。

7.4 论文口径与仓库输出并非完全一致

论文定义并展示了 MemToken、MemoryScore,而当前评测聚合只写 ESM、状态指标、avg_pred_calls、avg_output_token。Tool-call F1 与检索次数保留在逐题 JSON,未在汇总报告中显示。

这不是说论文数字错误,而是说仓库公开的脚本尚未把所有论文分析字段复现为一键输出。做横向实验时,建议保存论文同口径的原始日志并自己补聚合,不要把 avg_output_token 当成 MemToken。

7.5 快速脚本目前不能按 README 的“从根目录运行”直接复现

README 写“从 repository root 运行”,并给出 bash scripts/model_test.sh。但该脚本内部执行的是 python model_evaluation.py,而该文件实际位于 evaluation/model_evaluation.py,根目录没有同名文件。示例脚本的相对路径也像是默认在 evaluation/ 下执行。

scripts/memorysystem_test.sh 虽然正确算出评测脚本绝对路径,但使用了 py 命令;本文撰写环境中该命令不存在。更关键的是,该脚本要求一次性配置所有外部后端的密钥,即使你只想跑其中一个也会被前置检查挡住。

建议做法:不要把示例脚本当作最小可跑入口;直接从仓库根目录运行 python evaluation/memorysystem_evaluation.py add ... 与 python evaluation/memorysystem_evaluation.py test ...,先用一个后端、一个场景、十道题验证 adapter。具体命令见 §11.2。


8. 怎样接入自己的记忆系统

这一节给的是工程接入路径,而不是假装“填配置就能用”。假设你的系统叫 your_memory,它至少要能做到:

写入:add(messages, user_id, timestamp)
检索:search(query, user_id, top_k)

你可以内部使用向量库、图数据库、抽取式 memory、RAG、规则引擎或远端 API;VehicleMemBench 不限制内部实现。它真正要求的是把系统包装成既有 adapter 的形状。

从框架视角看,adapter 有两条完全不同的 I/O 链路:离线写入时接收时间桶对话;在线做题时把后端搜索结果翻译成 Agent 能阅读的文本。只实现其中一条都无法完成完整评测。

自定义 memory adapter 的边界:上半段负责把历史写进你的系统;下半段负责把检索结果转换为 LLM 可用的上下文。

图 6 自定义 memory adapter 的边界:上半段负责把历史写进你的系统;下半段负责把检索结果转换为 LLM 可用的上下文。

8.1 最小 adapter 契约

以 evaluation/memorysystems/mem0.py 为模板,新建 evaluation/memorysystems/your_memory.py。五个现有后端都实现了下表函数;没有显式抽象基类,但这是事实上的接口。

表 7 自定义 adapter 的契约——真正需要接通的是“写入”和“检索”两条线

函数阶段你要负责什么
validate_add_args(args)写入前检查地址、密钥、模型等必要参数
validate_test_args(args)评测前检查检索阶段所需配置
run_add(args)写入读取每份 history_N.txt,逐时间桶调用你的写入 API
init_test_state(...)评测初始化可选:加载共享模型、连接池、索引
build_test_client(...)每场景返回带 search(query, user_id, top_k) 的客户端
format_search_results(raw)每次搜索把后端响应转成 (text, count),交给 LLM 阅读
is_test_sequential()并发控制后端若不线程安全,返回 True
close_test_state(...)清理关闭客户端、释放本地模型等

还需在 evaluation/memorysystems/init.py 中 import 并注册:

from . import your_memory

SYSTEM_MODULES = {
    # 既有后端 ...
    "your_memory": your_memory,
}

评测框架会为第 N 个场景设置 user_id = "your_memory_N"。adapter 必须把它真正传给后端的写入和搜索,不能把 50 个场景混入同一个共享用户空间,否则结果会跨样本泄漏。

8.2 建议的最小验证顺序

先把模型、题目范围、并发全部固定,只替换 memory system;否则得分变化无法归因。

  1. 基线:跑 none,确认任务不是模型凭 query 猜出来的。

  2. 执行上界:跑 gold,确认所选 LLM 能理解车辆工具;Gold 很低时不要先优化记忆。

  3. 你的系统:只跑 history_1.txt / qa_1.json 的十题,手看 Gary 题是否检索到绿色偏好。

  4. 扩大范围:统一跑 50 个场景,保存每题日志。

  5. 补过程审计:把检索文本与 gold_memory 对齐,额外计算事实覆盖、噪声率、检索延迟与写入成本。

第 5 步不是锦上添花,而是回答“为什么 ESM 掉了”的必要条件。一个实用的四格诊断表如下:

Gold你的系统解释优先改什么
低低LLM 或工具使用能力不足工具 schema、Agent prompt、模型
高低,且检索漏证据memory 写入/检索有问题索引、query rewrite、时间/用户过滤
高低,且检索命中证据Agent 没利用记忆检索结果格式、上下文编排、规划
高接近 Gold端到端记忆效用好再测成本、鲁棒性与线上时序

8.3 从根目录运行的最小命令

以下是面向自定义 adapter 的最小结构;密钥以环境变量或 CI secret 注入,勿写进脚本或提交。

# 1. 先只写入场景 1 的历史
python evaluation/memorysystem_evaluation.py add \
  --memory_system your_memory \
  --history_dir benchmark/history \
  --file_range 1 \
  --memory_url "$YOUR_MEMORY_URL" \
  --memory_key "$YOUR_MEMORY_KEY"

# 2. 用同一场景的 10 个 query 做端到端评测
python evaluation/memorysystem_evaluation.py test \
  --memory_system your_memory \
  --benchmark_dir benchmark/qa_data \
  --file_range 1 \
  --api_base "$LLM_API_BASE" \
  --api_key "$LLM_API_KEY" \
  --model "$LLM_MODEL" \
  --memory_url "$YOUR_MEMORY_URL" \
  --memory_key "$YOUR_MEMORY_KEY" \
  --max_workers 1

输出目录中应至少检查四个文件:

  • results_1.json:该场景逐题结果;

  • all_results.json:可审计的 memory_tool_calls、工具序列、状态差异;

  • metric.json:聚合 ESM 与字段/值指标;

  • config.json:模型、范围、并发等复现实验配置。


9. 怎么选:和 HaluMem、LongMemEval、LoCoMo 的根本差别

这四个基准看似都在测“长期记忆”,但它们对“记忆应该怎样被验证”的假设不同。选择的第一问不应是“哪个分高”,而应是“你要定位哪一层”。

表 8 四种范式的对照——VehicleMemBench 的独特性是“可执行状态”,缺口是“检索与写入诊断”

基准主要终点是否直接诊断记忆过程是否可执行环境状态检索指标适合什么系统
VehicleMemBench虚拟车辆最终状态❌,仅间接✅❌,需自己补记忆 + 工具型 Agent
HaluMem抽取、更新、问答各步的幻觉✅❌❌,以操作级语义判定为主抽取改写型 memory,想定位漏与编
LongMemEval检索证据 + 最终回答✅,检索/阅读两条线❌✅,依赖 session ID原文存储 / RAG 型 memory
LoCoMo长期对话问答、事件总结、生成部分,按任务结果❌仅特定 RAG 设定超长对话理解、多模态、时间与因果

VehicleMemBench 与 HaluMem 是互补,不是替代。 HaluMem 把记忆系统的抽取、更新、问答拆开,适合问“偏好改写为什么错”;VehicleMemBench 不看 memory card 本身,而是问“错误有没有让车辆操作失败”。前者白盒诊断强,后者环境后果更真实。

VehicleMemBench 与 LongMemEval 的差异在于可归因性。 LongMemEval 为每题标记证据 session ID,因此能分别算检索是否找回证据、读到证据后是否答对。VehicleMemBench 的 gold_memory 是自由文本相关片段,没有发布为面向检索的细粒度证据 ID 与自动对齐器;因此它天然更容易做“最终操作对不对”,不容易做“第 k 条是否找到了正确证据”。

VehicleMemBench 与 LoCoMo 的差异在于任务后果。 LoCoMo 适合测能否理解很长、跨月、含多模态的对话;VehicleMemBench 则把任务限制到可执行车载偏好,换来状态级客观判分与工具使用压力。若你的 Agent 不操作外部系统,VehicleMemBench 的最大特色就发挥不出来。


10. 结论与适用场景

VehicleMemBench 给长期记忆评测补上了一块常被忽略的拼图:记忆不只是为了答出一句正确的话,而是为了让 Agent 把外部世界改成正确状态。 多用户、条件变化、纠错和车机 API 使这种“从记忆到行动”的链条具体可测;状态比较又避免了 LLM 裁判的主观性。

但它的成绩单应被准确解读:ESM 低不等于你的 memory system 一定差,ESM 高也不等于它的写入、检索、更新都正确。它衡量的是“你的 memory system 与指定 Agent、指定 prompt、指定工具环境组合起来,完成这 500 道车载任务的效用”。

因此最稳妥的使用方式是:

  • 用 VehicleMemBench 测端到端任务成功、动作正确性与误操作;

  • 用 LongMemEval 或自建证据标注测检索覆盖与排序;

  • 用 HaluMem 或自建更新审计测抽取、冲突、更新中的幻觉;

  • 在线上数据上补齐严格时序、延迟、成本、安全与真实用户行为。

因此,VehicleMemBench 适合作为“记忆系统是否能帮助工具型 Agent 完成任务”的集成测试;若要形成完整的记忆质量诊断,还需要补充过程级指标。


11. 附录:术语、最小流程、代码索引与来源

11.1 术语速查

术语一句话解释
Agent收到 query 后会选择调用记忆或车辆函数的 LLM 程序
工具 / tool以 function calling 暴露的函数;既包含 search_memory,也包含 carcontrol_*
模拟器仓库内的 VehicleWorld Python 对象,不是真车或真实车厂 API
参考车 vw_ref执行标准动作、用于生成正确最终状态的虚拟副本
模型车 vw_pred执行模型实际动作、用于生成预测最终状态的虚拟副本
Gold Memory该题相关历史的标准摘要;只用于提供理想记忆上界
ESM预测最终状态与参考最终状态完全相同才为 1
adapter把一个具体 memory backend 包装成 benchmark 所需写入/检索接口的代码
条件约束偏好只在某环境、时间、活动或关系成立,例如“工业区开内循环”

11.2 最小可跑流程

  1. 安装 requirements.txt,配置一个 LLM 的 OpenAI-compatible API;

  2. 先跑内置 none / gold,确认模型与工具调用链工作;

  3. 以 mem0.py 为模板写 adapter,先只跑场景 1;

  4. 检查 all_results.json 中 Gary 题的检索和工具日志;

  5. 固定 LLM 与参数后扩大到 50 场景;

  6. 在官方状态指标外,追加检索覆盖、噪声、延迟与存储成本统计。

11.3 代码索引

看什么位置
23 个模块的初始状态组装environment/vehicleworld.py:5
模块列表与 API 状态包装器environment/utils.py:12、environment/utils.py:57
动态生成车机函数 schemaevaluation/model_evaluation.py:154
按日期构造递归摘要evaluation/model_evaluation.py:410、evaluation/model_evaluation.py:595
按日写入 KV memoryevaluation/model_evaluation.py:635、evaluation/model_evaluation.py:781
模型任务执行循环与两份虚拟车evaluation/model_evaluation.py:848
参考动作执行与状态比较入口evaluation/model_evaluation.py:1052
字段和值级指标计算evaluation/eval_utils.py:181
工具序列 F1evaluation/eval_utils.py:111
外部 memory 的搜索 / 车辆调用循环evaluation/memorysystem_evaluation.py:118
外部 memory 写入、测试与输出evaluation/memorysystem_evaluation.py:603、evaluation/memorysystem_evaluation.py:631
当前硬编码支持的后端列表evaluation/memorysystems/init.py:4
可模仿的 adapter 模板evaluation/memorysystems/mem0.py

11.4 参考资料


调研时间:2026-07-12。本文依据论文、当前本地代码与发布数据完成;未运行需要模型/记忆后端密钥的完整 pipeline。本文中“当前仓库未聚合某指标”“示例脚本路径不可直接按 README 使用”“无按 query cutoff”的结论均为对本地代码和命令的独立核对;行号对应撰写时的本地版本,后续提交可能变化。

分享这篇文章

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

评论

发表评论

0 / 1000