MemEye: A Visual-Centric Evaluation Framework for Multimodal Agent Memory
Paper: arXiv:2605.15128 Code: MinghoKwok/MemEye Code reference:
main@0358e70d(2026-05-16)
1. Motivation (研究动机)
长期 Agent memory 正在从纯文本历史扩展到多模态交互:用户会给 agent 看房间照片、游戏状态截图、漫画页面、健康面板、导航帧,过几轮甚至几天之后再追问“之前那个物体/状态/界面细节现在是什么”。这类能力不是普通 VLM 的单轮 image understanding,也不是只把所有历史拼进 context 的文本记忆;它要求系统在长时间跨度里保存视觉证据、检索正确证据,并判断哪个视觉状态仍然有效。
现有评测的缺口主要有两个。第一,很多“视觉相关”的问题仍可由 caption、对话文字或选项偏置绕过:只要 caption 写到大致场景,模型就能猜出答案,不需要真的保存原图中细粒度区域、实例身份、颜色、纹理或小字。第二,长程记忆 benchmark 往往把状态变化写进文本,而不是让状态更新发生在视觉证据本身;这样无法暴露“检索到了相关但过期的图片”这种多模态记忆失败。MemEye 的动机就是把这两个因素拆开:视觉证据到底有多细,以及拿到证据后需要怎样跨记忆推理。
Figure 1 解读:左侧是 MemEye 的任务分布概览,任务被组织成 Leisure、Domestic、Professional、Personal 等生活场景;右侧展示了典型视觉记忆问题。它强调该 benchmark 不是只问“图片里有什么”,而是把图片证据散布在多 session 对话中,让 agent 之后必须根据历史视觉证据回答。
作者想解决的具体问题是:如何评估 multimodal agent memory 是否真的保留了不可替代的视觉信息,并能在多轮、多 session、状态变化的历史中选择当前有效证据。这个问题值得研究,因为未来个人助理、工作流 agent、家庭/健康/导航 agent 都会长期保存用户图像环境;若系统只会存 caption 或按语义相似度检索,就可能丢掉关键小细节,或拿过期截图回答当前状态。
Figure 2 解读:作者用相同文本问题比较 No Visual Info、Caption Only、Multimodal 三种输入设置。MemEye 相比 LoCoMo、MMRC、Mem-Gallery 有更大的 caption-to-multimodal gain,说明其中更多题目必须依赖原始图像,而不是可被 caption 充分替代的视觉线索。
2. Idea (核心思想)
核心思想:MemEye 不把 multimodal memory 评成一个总分,而是把失败拆成二维坐标: 轴衡量 decisive visual evidence 的粒度, 轴衡量 memory evidence 的使用方式。这样可以区分“系统没保存细粒度视觉证据”和“系统保存/检索了相关证据但没有选择当前有效状态”两类不同瓶颈。
关键创新有三点。第一,提出 — visual evidence granularity:从 scene-level、region-level 到 instance-level、pixel-level。第二,提出 — memory-reasoning depth:从 atomic retrieval、relational association 到 evolutionary synthesis。第三,把这套 taxonomy 实例化为 371 个 mirrored MCQ + open-ended questions,并用 answerability、shortcut resistance、visual necessity、reasoning-structure alignment 等 gate 过滤题目。
与 Mem-Gallery 或 LoCoMo 的区别在于:Mem-Gallery 已经把图像分布在多 session 中,但许多视觉题仍可由 caption 或上下文解决;LoCoMo 主要偏文本长期记忆。MemEye 则显式验证 caption-proof,并专门构造 evolving visual state,让系统面对“语义相关但时间上失效”的视觉证据。
更细地说,这篇论文的“核心思想”不是提出一个新的 memory module,而是提出一个可定位失败原因的 evaluation instrument。若一个方法在 失败,主要怀疑是像素级视觉证据被 caption/embedding 压缩掉;若在 或 失败,则即使视觉内容可读,也可能是系统没有按时间顺序更新状态、没有识别 stale clue、或没有把 latest clue 提升为 answer authority。因此 MemEye 把 future memory architecture 的设计需求拆成两条独立约束:一条是 evidence-preserving storage,另一条是 temporal-validity-aware selection。
3. Method (方法)
3.1 Overall framework:二维 taxonomy + mirrored questions
Figure 3 解读:MemEye 的二维坐标把每个问题放到一个 cell。横向 轴表示视觉证据粒度,越往右越依赖图像中不可压缩为文本的细节;纵向 轴表示记忆推理深度,越往上越要求跨证据关联、状态更新和冲突消解。这个图也展示了不同任务在坐标中的覆盖范围。
X-axis:visual evidence granularity
- Scene-level:只需整体场景、活动、语义 gist;高质量 caption 往往可以覆盖。
- Region-level:需要局部区域、局部空间结构或 grouped entities,例如某个区域里哪个样本靠近某个物体。
- Instance-level:需要在相似 object/person instances 中保持 identity binding,例如“之前那个样本/人/物体”到底是哪一个。
- Pixel-level:需要颜色、纹理、小字、计数、OCR-like evidence 等 caption 容易漏掉的细节。
Y-axis:memory-reasoning depth
- Atomic retrieval:一个证据单元足够回答,主要测试能否访问相应 memory。
- Relational association:需要关联多个非冲突证据,信息是 monotonic accumulation。
- Evolutionary synthesis:证据按时间产生 update、override 或 conflict,答案取决于当前有效状态,而不是任意一个相关证据。
3.2 Benchmark construction:371 题、8 个 life-scenario tasks
MemEye 包含 371 个问题,覆盖 221 sessions、848 dialogue rounds、438 images。每个问题有一个 MCQ 版本和一个 open-ended 版本;MCQ 还做四种 answer rotation,使正确答案在 A—D 中轮换,以降低 position bias。八个任务分布如下:Home Renovation 52、Brand Memory 29、Card Playlog 48、Cartoon Entertainment 76、CrossScene Memory 50、Outdoor Navigation 28、Health Care 51、Social Chat 37。按坐标统计: 有 113 题、 有 198 题、 有 60 题;按视觉粒度统计:、、、。
Figure 4 解读:该图概括了 benchmark filtering 流程:候选问题先被生成并标注 ,再经过 text leakage、minimal-caption bypass、oracle answerability、taxonomy-structure audit 等检查。关键点是:MemEye 不只是收集“看起来视觉相关”的题,而是排除可由文本/选项/caption shortcut 解决的题。
3.3 Item-level filtering:避免把 foundation-model 识别失败误判成 memory 失败
每个候选题经过三类过滤。第一类是 shortcut-resistance gates:option-only gate 只给问题和选项;text-only clue gate 给问题、选项和 gold clue-round text 但不给图像;minimal-caption gate 把图像替换成极短 caption(如 room photo、game board、cartoon panel、phone screenshot)。如果 gpt-5.4-mini 与 gpt-5.2 在四种 answer rotation 中都稳定答对(rotation-averaged EM ),该题会被标记为可绕过,需要修改或删除。
第二类是 oracle answerability gate:给模型 gold clue rounds 和原图,移除 memory retrieval 难度,只检查题目是否定义清楚且视觉上可答。如果两个 panel models 在 oracle visual evidence 下仍低于或等于 chance(rotation-averaged EM ),候选题会被视为 ambiguous、underspecified 或超过预期难度。
第三类是 taxonomy-structure audit: 必须由一个证据单元回答; 必须需要多个非冗余证据且没有冲突; 必须包含 later clue 对 earlier state 的更新、覆盖或冲突,答案依赖 valid current state。这个 audit 防止 轴退化为任务名或题目表面复杂度。
3.4 Construction and validation pipeline
Figure 5 解读:完整 pipeline 从 task scenario、visual evidence、target region 生成候选题,接着写成 mirrored MCQ/open-ended items,并标注 clue rounds。随后通过 clue sufficiency、option-bias rejection、text-leak rejection、reasoning-structure audit、Caption-Proof diagnostic 和 Oracle-Evidence diagnostic 等步骤,锁定最终 benchmark。
这条 pipeline 的直觉是:如果题目不锁定 clue rounds,就无法区分 retrieval failure 与 reasoning failure;如果不做 minimal-caption 与 dense-caption 检查,就无法证明该题真的需要原始视觉证据;如果不做 oracle answerability,就会把“基础 VLM 看不懂图”误记为“memory 系统失败”。MemEye 的设计把这些因素逐层隔离,所以最后的结果更像一个 diagnostic matrix,而不是普通排行榜。
3.5 Evaluation protocol and formulas
MemEye 对 MCQ 使用四种 answer rotation 后的 Exact Match: Open-ended 主要用 LLM-as-a-Judge,judge 输出 内的 semantic-correctness score;BLEU-1、F1、BERTScore 等作为辅助指标。Caption-Proof diagnostic 比较 matched text stream 与 visual stream: 其中 表示把图像替换为 dense captions 的文本记忆流, 表示保留 native images 的多模态流。检索诊断用 Any-Clue Recall@K、Coverage@K、Full-Clue Recall@K 衡量 gold clue rounds 是否被 top- 检索到;对 额外统计 Latest-Clue Recall@K 与 Stale-Dominance。
作者还做了一个 recency reranking diagnostic,不改变 SRAG(V) 的候选池,只重排候选: 其中 是 SigLIP2 retrieval similarity, 是 candidate round 到 query 的 dialogue-round age,。这不是新 memory method,而是用来证明 temporal authority failure:recency 可以减少 stale-over-latest ranking,但无法找回候选池中缺失的 latest clue。
3.6 Released code implementation pseudocode
下面伪代码按 released code main@0358e70d 抽象,主要来自 benchmark/runner.py、benchmark/methods.py、benchmark/retrieval.py、benchmark/evaluator.py。
def run_memeye_eval(task_cfg, model_cfg, method_cfg, judge_cfg=None):
dataset = MemoryBenchmarkDataset(task_cfg.dialog_json, task_cfg.image_root)
method = get_method(method_cfg.name, config={**method_cfg, "_model_cfg": model_cfg})
router = None if hasattr(method, "answer") else instantiate_router(model_cfg)
judge = build_llm_judge(judge_cfg) if judge_cfg else None
rows = []
for qa in dataset.iter_qas(limit=task_cfg.max_questions):
question_images = dataset.resolve_question_images(qa)
if method.modality in {"text_only", "no_visual"}:
question_images = []
if hasattr(method, "answer"):
history = []
predict = lambda q: method.answer(dataset, qa, q, question_images=question_images)
else:
history = method.build_history(dataset, qa)
predict = lambda q: router.answer(history, q, question_images=question_images)
if is_rotation_mcq(qa):
ems, choices = [], []
for rotation in qa["options"]:
q = format_rotated_options(qa["question"], rotation)
pred = predict(q)
choice = extract_choice(pred, valid_keys=set(rotation) - {"answer"})
ems.append(float(choice == rotation["answer"]))
choices.append(choice)
rows.append({"mode": "mcq", "em": sum(ems) / len(ems), "choices": choices})
else:
q = format_question(qa)
pred = predict(q)
row = {
"mode": "open",
"f1": f1_score(pred, qa["answer"]),
"bleu_1": bleu_score(pred, qa["answer"], weights=(1, 0, 0, 0)),
}
if judge is not None:
row["judge"] = llm_judge_score(q, qa["answer"], pred, judge)
rows.append(row)
return summarize_results(rows)def build_full_context_history(dataset, qa, modality, context_token_limit=128000, reserved_tokens=1000):
history = []
for session_id in dataset.session_order():
history.extend(history_from_round_ids(
dataset.get_session(session_id),
dataset.rounds,
modality=modality, # text_only uses captions; multimodal keeps images
))
return truncate_fifo(history, max_tokens=context_token_limit - reserved_tokens)def select_semantic_rag_history(dataset, qa, config):
retriever = get_retriever(dataset, config)
selected_round_ids, debug = retriever.select(qa)
allowed = set(selected_round_ids)
history = []
for session_id in dataset.session_order():
history.extend(history_from_round_ids(
dataset.get_session(session_id),
dataset.rounds,
allowed_round_ids=allowed,
modality=config["modality"],
))
return history, debugdef dense_multimodal_retrieve(dataset, qa, top_k=10, text_w=0.5, image_w=0.5):
q_text = qa["question"]
q_text_vec = text_embedder.embed_query(q_text)
q_image_vec = siglip2_embedder.embed_text(q_text)
scored = []
for round_id in dataset.round_order():
round_text = build_round_retrieval_text(dataset.rounds[round_id], modality="multimodal")
text_score = cosine(q_text_vec, text_embedder.embed_text(round_text))
image_score = max(
cosine(q_image_vec, siglip2_embedder.embed_image(path))
for path in dataset.rounds[round_id].get("images", [])
) if dataset.rounds[round_id].get("images") else 0.0
scored.append((text_w * text_score + image_w * image_score, round_id))
return [round_id for _, round_id in sorted(scored, reverse=True)[:top_k]]def oracle_and_caption_proof_diagnostics(qa, model):
no_image = answer_with(question=qa.question, text=qa.gold_clue_text, images=[])
caption_only = answer_with(question=qa.question, text=qa.gold_clue_text + qa.dense_captions, images=[])
multimodal = answer_with(question=qa.question, text=qa.gold_clue_text, images=qa.gold_clue_images)
return {
"caption_proof_delta": judge(multimodal) - judge(caption_only),
"oracle_answerable": rotation_em(multimodal) > 0.25,
"text_leak_rejected": rotation_em(no_image) == 1.0,
}论文公式与 released code 实现差异:本次检查未发现会改变结论的明确公式-代码不一致;需要注意的是论文把 recency reranking 明确定位为 appendix diagnostic,而 released repo 的主 benchmark runner 仍以 method config 中的 top_k、embedding 与 method adapter 为准。评测配置数字应引用实际 repo config:config/models/gpt_5_4_mini.yaml 中 max_new_tokens=128、timeout=90;config/methods/full_context_multimodal.yaml / config/methods/full_context_text_only.yaml 中 context_token_limit=128000、reserved_tokens=1000;config/methods/semantic_rag_multimodal.yaml / config/methods/semantic_rag_text_only.yaml 中 top_k=10、neighbor_window=0、text_embedding_model=all-MiniLM-L6-v2,多模态 SRAG 还使用 multimodal_embedding_model=siglip2-base-patch16-384 与 text/image equal weights。
Code reference:
main@0358e70d(2026-05-16) — pseudocode and mapping based on this commit
| Paper Concept | Source File | Key Class/Function |
|---|---|---|
| benchmark data loading / clue rounds / captioned vs native history | benchmark/dataset.py | MemoryBenchmarkDataset, history_from_round_ids, build_round_retrieval_text |
| full-context baselines FC(T/V) and oracle clue-only context | benchmark/methods.py | _MemGalleryFullContextMethod, FullContextTextMethod, FullContextMultimodalMethod, ClueOnlyContextMethod |
| semantic retrieval and multimodal dense retrieval | benchmark/retrieval.py | _DenseTextRetriever, _DenseMultimodalRetriever, select_round_ids_for_qa |
| benchmark execution, MCQ rotation, open-ended scoring loop | benchmark/runner.py | run_benchmark, run_modular_benchmark, format_question |
| scoring metrics and judge parsing | benchmark/evaluator.py | extract_choice, f1_score, bleu_score, llm_judge_score, summarize_results |
| method comparison matrix | benchmark/matrix.py, run_matrix.py | run_benchmark_matrix, CLI matrix wrapper |
| model/method hyperparameters | config/models/*.yaml, config/methods/*.yaml | gpt/qwen/gemini configs, SRAG/FC/SimpleMem/A-Mem/MMA/M2A configs |
| post-hoc open-ended judge scoring | score_locked_llm_judge.py, benchmark/llm_judge.txt | score_run_dir, LLM judge prompt template |
4. Experimental Setup (实验设置)
Datasets and scale
MemEye 是作者构建的新 benchmark:371 questions、221 sessions、848 dialogue rounds、438 images;每题有 MCQ 与 open-ended mirrored forms,MCQ 做 4 answer rotations。八个 life-scenario tasks:Home Renovation 52、Brand Memory 29、Card Playlog 48、Cartoon Ent. 76、CrossScene Memory 50、Outdoor Nav. 28、Health Care 51、Social Chat 37。图像来源包括 Pitt Image Ads、public-domain comic / Seed-Story、stock interior photos、Cardiverse-style rendered screenshots、StyleGAN synthetic faces + chat UI、Japan Open Driving Dataset dashcam frames、以及 gpt-5.2 生成图像。
Baselines / memory methods
作者评测 13 个方法:文本记忆 7 个,包括 FC(T)、SRAG(T)、Reflexion、Generative Agents、MemoryOS、A-Mem、SimpleMem(T);多模态记忆 6 个,包括 FC(V)、SRAG(V)、MIRIX、MMA、M2A、SimpleMem(V)。文本方法把每个 image-bearing round 替换为 gpt-5.2 dense caption;多模态方法保留原始视觉输入。检索方法默认 top-。
Models and metrics
Backbones 包括 Qwen3-VL-8B-Instruct、gpt-4.1-nano、gpt-5.4-mini、gemini-2.5-flash-lite。主表使用 gpt-5.4-mini;answer generation deterministic decoding,temperature ,主 gpt-5.4-mini config 的 max_new_tokens=128。MCQ 指标是四轮 answer rotation 的 EM;open-ended 以 LLM-as-a-Judge 为主,BLEU-1/F1/BERTScore 为辅助。LLM judge 用 gpt-5.2,自动 judge 与 human labels 的 agreement 为 97.2%(69/71,排除 1 个 borderline),Cohen’s 。
Validation and diagnostics
- Caption-Proof:比较 native-image memory 与 dense-caption memory,计算 。
- Oracle-Evidence:直接提供 gold clue rounds + original images,移除 retrieval 难度,检查 轴是否仍体现 reasoning depth。
- Retrieval diagnostics:对 top-10 retrieved rounds 统计 Any-Clue、Coverage、Full-Clue、Latest / Stale。
- Cross-topic scaling:把不同任务历史拼到更大的 conversation history 中,测试 memory mechanism 是否能过滤 unrelated histories。
5. Experimental Results (实验结果)
Main MemEye matrix results
Figure 6 解读:热力图展示 gpt-5.4-mini 下不同 memory method 在 cells 上的表现。左侧是 open-ended LLM-as-a-Judge,右侧是 MCQ EM。它直观显示没有方法在所有 cell 都稳定高分:低 与低 相对容易,高 与 暴露不同瓶颈。
主表中,gpt-5.4-mini 的 aggregate 最好方法是 SRAG(V):平均 MCQ EM 、平均 LLM-Judge 。第二名 aggregate:FC(V) 的 EM 、LLM-Judge 。对比可见,native visual retrieval 在整体上最强,但仍远未 saturate benchmark。
关键 cell 结果体现两个 stressors。第一,细粒度视觉证据:在 ,SRAG(V) 的 LLM-Judge 为 ,显著高于最佳文本方法 A-Mem 的 ;在 ,MMA 与 SRAG(V) 都达到 ,而最佳文本方法只有 。第二,evolving-state reasoning:到 后,系统不只是找相关证据,还要判断哪个状态有效;检索方法优势减弱,full-context 或具备状态/抽象机制的方法在部分低- 或更新场景中更有竞争力,但没有方法同时解决高 与高 。
Diagnostic findings
Figure 7 解读:四个 panel 分别诊断不同失败源。(a) 展示 region-level 表现;(b) 展示 Caption-Proof gain,说明 native images 在某些 cell 比 dense captions 保存更多信息;(c) 展示 SRAG(V) retrieval diagnostics 和 recency counterfactual,区分 evidence access 与 temporal-authority failure;(d) 展示 cross-topic memory scaling,说明 history 变长且主题混杂时,简单 full context 会受干扰。
Caption-Proof validation 支持 轴设计。按 — 聚合后,FC 在 的 LLM-Judge gain 为 ,SRAG 在 的 gain 为 ,SRAG 在 的 EM gain 为 。task-aware caption ablation 进一步说明:更强 captioner 会缩小 gap,但高 仍保留视觉优势;SRAG 的 high- native-over-task-aware caption gap 从 generic caption 的 缩到 , 从 缩到 ,说明 scene/region 信息可被详细 caption 弥补,但 instance/pixel-level 仍难完全文本化。
Figure 8 解读:完整 Caption-Proof heatmaps 展示不同 matched method families 中 的 cell-level 分布。重点不是“图像输入总是更好”,而是 native visual evidence 的价值随视觉瓶颈位置变化:scene/region 层有时 caption 足够甚至更稳,instance/pixel 层更依赖原图。
Oracle-Evidence diagnostics 说明 轴不是单纯检索难度。直接给 gold clue rounds + 原图后,gpt-5.4-mini 的 LLM-Judge 从 到 下降:。同时,gold-evidence 下视觉 granularity gap 从 的 增到 的 ,说明高 确实更依赖 native visual evidence。
Retrieval and evolving-state failures
检索诊断显示,“找相关”不等于“找当前有效”。SRAG(V) 在 的 Any-Clue Recall@10 为 ,高于 SRAG(T) 的 ,但 Full-Clue Recall@10 只有 ,Latest-Clue Recall@10 只有 ,Stale-Dominance 高达 。MMA 在 的 Any-Clue 为 、Coverage 、Full-Clue ,但 Stale-Dominance 仍有 。这说明多模态检索能找到主题相关图像,却常错过完整 update chain 或把 stale evidence 排在 latest update 前面。
Evolving visual-state probe 进一步隔离这个问题:在视觉状态更新 subset 上,oracle latest-only 的 LLM-Judge 为 ,all-clue oracle 为 ,stale-only 为 ;正常 memory systems 明显更低,FC(V) 、SRAG(V) 、MMA 、M2A 。结论是:最终状态通常可读,真正瓶颈是从长历史中恢复并优先选择 valid visual state。
Recency reranking 只能部分缓解。SRAG(V) baseline 在 的 Latest@10 为 、Latest-Miss 、Stale-Dom. 、Rank-Inv. 、Judge 。加入 recency 后, 把 Stale-Dom. 降到 、Rank-Inv. 降到 、Judge 提到 ; 把 Stale-Dom. 降到 、Rank-Inv. 降到 ,但 Judge 只有 。由于 Latest-Miss 不会因 reranking 变好,answer-quality 的 CI 也跨 0,recency 是诊断信号,不是完整解法。
Figure 9 解读:cross-topic scaling 把 answer-relevant evidence 固定,同时加入更多无关任务历史。FC(V) 随 scale 增大更容易被 unrelated visual-textual context 干扰;SRAG(V)、MMA 等 retrieval/structured memory 更平稳,说明长程多模态记忆不能只靠扩大 context window,还需要 evidence routing 和 state-aware selection。
Limitations and conclusions
作者明确把 MemEye 定位为 diagnostic benchmark,而不是所有真实 multimodal agent deployment 的完整模拟。限制包括:场景是 curated life-scenario tasks;模型面板、captioning pipeline 和 human validation sample 不能覆盖所有实际环境;不同 memory architecture 的 encoder 与实现差异会影响系统级比较,因此结果应解读为 design trade-off 诊断,而非永久排行榜。隐私(privacy)方面,更强的视觉记忆会保存用户图像、个人环境和状态变化,未来系统需要 consent、data minimization、deletion、access control 等机制。
总体结论:有效 multimodal agent memory 需要把三件事结合起来:保留 native image evidence 以覆盖 instance/pixel-level 细节;用 text/structured state records 组织 update、conflict、override;再用 temporal-validity-aware selection 过滤无关历史和 stale evidence。MemEye 的贡献是把这些失败模式变成可测坐标,而不是只给一个平均分。