首页
/ agentmemory 评测体系完全指南:用 LongMemEval 与 coding-agent-life-v1 量化混合记忆检索栈

agentmemory 评测体系完全指南:用 LongMemEval 与 coding-agent-life-v1 量化混合记忆检索栈

2026-09-10 13:06:48作者:平淮齐Percy

agentmemory 的评测框架(eval/)为混合记忆检索栈(BM25 + 向量嵌入 + consolidation 记忆整合 + 图检索)提供了一套可复现、可比较的量化基准:一条基于公开 LongMemEval 500 问检索基准的"公共对比轴",一条基于 15 个虚构 Claude Code 会话语料的"内部快速迭代轴"。读完本文,你将掌握如何安装沙箱、运行两类评测、解读 P@K / R@K / 命中率等指标、对照 grep 与 OpenAI 向量基线验证每一层检索的价值,并学会为自定义后端编写新的 Adapter。

评测框架的定位:为什么 agentmemory 需要一套基准

agentmemory 的记忆栈不是单一检索器,而是由多层级联组成:BM25 词法检索、嵌入向量检索、consolidation 记忆整合以及图检索(graph retrieval)共同服务于 smart-search 端点。正如 eval/README.md 所陈述的,这些层级带来的数值提升必须能被证明——将整个栈与 grep 字符串匹配、OpenAI 向量检索这两种基线对比,每个组件对最终召回率的贡献才可量化,而不是停留在"感觉更好"的层面。

因此仓库提供两套互为补充的评测族,且都强调可复现(reproducible):

  • LongMemEval:公开的 500 问多会话聊天检索基准,负责对外部公开结果的横向对比;
  • coding-agent-life-v1:仓库内置的虚构语料,覆盖单会话、多会话因果推理、用户偏好与时间线问题,用于在不花费外部 API 费用的情况下快速迭代。

两套评测共用同一套 Runner 与打分逻辑,差异仅在于数据来源(见 eval/runner/coding-life.tseval/runner/longmemeval.ts)。

三个 Adapter:基线、向量与完整记忆栈

评测通过统一接口比较不同检索后端,接口定义在 eval/runner/types.ts

export interface Adapter<State = unknown> {
  name: string;
  init(sessions: Session[], config?: Record<string, unknown>): Promise<State>;
  query(q: string, state: State, k: number): Promise<RankedDoc[]>;
  teardown?(state: State): Promise<void>;
}

三个内置 Adapter 由 eval/runner/longmemeval.tseval/runner/coding-life.ts 中的 ADAPTERS 映射表注册:

Adapter 后端 所需 API Key 说明
grep 分词子串匹配 纯词法基线,零成本、零外部依赖
vector OpenAI text-embedding-3-small + 余弦相似度 OPENAI_API_KEY 纯向量基线,用于衡量语义检索相对词法匹配的提升
agentmemory 运行中的 agentmemory 服务,走 smart-search 端点 无(可选 AGENTMEMORY_SECRET 完整的混合记忆栈,实际评测名称是 agentmemory-hybrid

grep:最简单的词法基线

grep.ts 的实现非常直白:将查询串小写化、过滤掉长度 ≤2 的 token,然后在每个会话正文中统计命中的词项数并据此排序。它的价值在于给出"只做词法匹配、零语义理解"时的下限,任何声称有价值的记忆层都应稳定超越它。

vector:OpenAI 嵌入 + 余弦相似度

vector.ts 使用 text-embedding-3-small(维度 1536),init 阶段按每批 50 条会话批量编码(每条内容截断至 8000 字符),查询阶段对问题单独编码后与全部会话向量计算余弦相似度排序。注意 init 会立即抛出 OPENAI_API_KEY required 错误,因此运行 vector Adapter 必须显式提供密钥。

agentmemory:走生产级 smart-search 端点

agentmemory.ts 是最接近真实使用路径的 Adapter:init 阶段逐条调用 POST /agentmemory/remember 将每个会话写入记忆存储(type: "eval-session",并以会话 ID 作为 concept),同时建立"记忆条目 ID → 会话 ID"的映射;query 阶段调用 POST /agentmemory/smart-searchlimitmax(k*10, 50)),把返回的观测结果去重后映射回会话 ID。由于走的是生产端点,它实际锻炼的是 BM25 + 嵌入 + 重排的完整链路。

该 Adapter 默认连接 http://localhost:3111,可通过 AGENTMEMORY_BASE_URL 环境变量或 config.baseUrl 覆盖;可选 AGENTMEMORY_SECRET 以 Bearer 方式鉴权。

先沙箱后评测:隔离你的真实记忆库

运行 agentmemory Adapter 会向运行中的服务写入 15 个(或 LongMemEval 的数百个)评测会话——如果直接连你的真实 ~/.agentmemory,会同时造成两个方向的污染:评测结果被既有记忆干扰,真实记忆库被评测数据污染。因此官方文档明确要求:Always sandbox(始终沙箱化)

仓库提供了 eval/scripts/sandbox.sh 一键完成隔离:

  • 3411/3412 端口启动干净的 agentmemory + iii-engine;
  • 状态存放在 /tmp/agentmemory-eval-sandbox/ 下(该脚本强制要求 SANDBOX_ROOT 非空且位于 /tmp/ 下,否则拒绝执行);
  • 自动导出 AGENTMEMORY_BASE_URL 指向沙箱;
  • 脚本退出(EXIT trap)时自动销毁。
source eval/scripts/sandbox.sh
npm run eval:coding-life -- --adapters grep,agentmemory

脚本要求 iii v0.11.2 位于 PATH 上(agentmemory 的固定版本),且要求仓库已构建(缺少 dist/index.mjs 时会提示先执行 npm run build)。如果你已安装其他版本,可将固定版本装入 ~/.local/bin 并确保该目录在 PATH 最前:

mkdir -p ~/.local/bin
curl -fsSL https://github.com/iii-hq/iii/releases/download/iii/v0.11.2/iii-aarch64-apple-darwin.tar.gz | tar -xz -C ~/.local/bin
export PATH="$HOME/.local/bin:$PATH"  # 持久化可加入 ~/.zshrc 或 ~/.bashrc

从源码看,沙箱通过生成的 iii-config.yaml 配置了 iii-http(HTTP 端口 3411)、iii-state(基于文件的 KV 存储)、iii-queueiii-pubsubiii-croniii-stream(流端口 3412)与 iii-exec(启动 node dist/index.mjs)等 worker,并轮询 /agentmemory/livez 等待就绪,30 秒内未就绪则打印日志尾部并退出。

快速上手:两条评测路径

coding-agent-life-v1:内置语料,无需下载

# 仅跑 grep 基线,不需要沙箱
npm run eval:coding-life -- --adapters grep

# 叠加 agentmemory 与 vector(需要沙箱 + OpenAI Key)
source eval/scripts/sandbox.sh
OPENAI_API_KEY=sk-... npm run eval:coding-life -- --adapters grep,vector,agentmemory

该语料位于 eval/data/coding-agent-life-v1/,包含:

  • sessions.json:15 个虚构的 Claude Code 会话(约 6KB),主题是一个名为 shipctl 的 Rust CLI 项目;
  • queries.json:15 条人工评分的问题,每条带 goldSessionIds(正确答案所在会话 ID)。

queries.json 可以看到问题类型覆盖相当全面:single-session-bug(如 q-001 认证环境变量优先级修复)、single-session-infrasingle-session-refactorsingle-session-featuresingle-session-testsingle-session-perfsingle-session-apisingle-session-dbsingle-session-releasemulti-session-causal(如 q-011 追查 staging 事故根因需横跨 sess-001 与 sess-014)、preference(如 q-013 用户的格式化偏好)、multi-session-reviewtemporal(如 q-015 2026 年 4 月 8 日发布了什么)。

Runner 支持三个额外参数(见 coding-life.ts 的 CLI 解析):--data(数据目录,默认 eval/data/coding-agent-life-v1)、--k(截断深度,默认 5)、--out(报告输出目录,默认 eval/reports/coding-life)。

LongMemEval _s:公开基准(278MB 下载)

mkdir -p ~/datasets/longmemeval
curl -Lo ~/datasets/longmemeval/longmemeval_s.json \
  https://huggingface.co/datasets/xiaowu0162/longmemeval/resolve/main/longmemeval_s

source eval/scripts/sandbox.sh

# 每类分层抽样 10 条(快速迭代,OpenAI 花费约 $0.20)
OPENAI_API_KEY=sk-... LONGMEMEVAL_PATH=~/datasets/longmemeval/longmemeval_s.json \
  npm run eval:longmemeval -- --stratify 10

# 完整 500 问 × 3 个 Adapter(OpenAI 花费约 $2)
OPENAI_API_KEY=sk-... LONGMEMEVAL_PATH=~/datasets/longmemeval/longmemeval_s.json \
  npm run eval:longmemeval

load.ts 负责把 LongMemEval 原始 JSON 转换为内部 Question 结构:每个会话的 [{role, content}] 轮次被扁平化为 [role] content 文本,并校验 haystack_session_idshaystack_sessions 长度一致;stratifySample 则按问题类型分桶后每类取前 N 条,保证快速迭代时覆盖所有题型。Runner 额外支持 --limit(截断问题总数)与 --stratify(每类抽样数),--data 缺省时直接读取 LONGMEMEVAL_PATH

打分与指标解读:P@K、R@K、命中率与 p50 延迟

打分逻辑集中在 score.ts

  • P@K(Precision@K):取前 K 个检索结果,其中命中 gold 会话的比例(hits / k),逐问平均;
  • R@K(Recall@K):前 K 个结果覆盖全部 gold 会话的比例(hits / gold.size),逐问平均;
  • Hit(命中率):是否至少有一个 gold 会话进入前 K;
  • topGoldRank:第一个 gold 会话在完整排序中的位次(1-based),用于观察 gold 是否被排到很后面;
  • latencyMs:单次查询耗时,聚合时按 Adapter 计算 p50 延迟

每条问题的逐行结果以 NDJSON 写入 scores.ndjson(字段含 questionIdquestionTypeadapterkprecisionAtKrecallAtKhittopGoldRanklatencyMs),聚合结果写入 summary.json,包含按 Adapter 与按问题类型的 P/R/hit 汇总。

理解 P@K 的数学上限很重要:以 coding-agent-life-v1 为例,15 问中 12 问只有 1 个 gold 会话、3 问有 2 个,因此 P@5 的理论上限是 (12×1/5 + 3×2/5)/15 = 0.240。正如已发布的记分卡 docs/benchmarks/2026-05-20-coding-agent-life-v1.md 指出的,该语料刻意设计得小而 gold 稀疏,目的是快速迭代检索栈而非比拼 P@K 头条数字,核心信号是 Recall 与按题型拆分的 P@5;而 LongMemEval 提供的就是那个"公共对比轴"。

报告落盘位置:eval/reports/<bench>/(已被 gitignore),即 scores.ndjson + summary.json;正式发布的记分卡则放入 docs/benchmarks/YYYY-MM-DD-<bench>.md

写入与复现:一份已发布的记分卡样本

仓库已发布基于上述框架产出的示例记分卡 docs/benchmarks/2026-05-20-coding-agent-life-v1.md,其运行环境为 agentmemory v0.9.26 + iii-engine v0.11.2,本地默认嵌入提供方,沙箱端口 3411/3412。结果摘要(K=5):

Adapter P@5 R@5 命中率 p50 延迟
grep(分词子串) 0.227 0.967 15/15 0 ms
agentmemory-hybrid 0.240 1.000 15/15 14 ms

解读要点:agentmemory-hybrid 的 R@5 达到 1.000,P@5 = 0.240 恰好处于该数据集的数学上限(所有 gold 会话均进入 top-5);grep 基线的 R@5 = 0.967,在某道多 gold 问题上漏掉了 1 个会话。提升体现在召回而非聚合精度——这正是该评测体系想展示的效果:完整的混合记忆栈相对纯词法基线,主要价值在于更稳地把正确答案捞回 top-K。该记分卡也明确提示:此基准体量小(15 问)、gold 稀疏,不应拿来做头条 P@K 对比。

编写新 Adapter:三步接入自己的检索后端

任何自定义检索后端都能以 Adapter 形式接入评测,官方文档给出完整模板:

import type { Adapter } from "../types.js";
export const myAdapter: Adapter<MyState> = {
  name: "my-adapter",
  async init(sessions, config) { /* index */ return state; },
  async query(q, state, k) { /* search */ return ranked; },
};

接入步骤:

  1. eval/runner/adapters/ 下按 Adapter<State> 接口实现,query 返回按相关性降序的 RankedDoc[]{ sessionId, score });
  2. eval/runner/longmemeval.tseval/runner/coding-life.tsADAPTERS 映射表中注册,即可通过 --adapters 指定;
  3. 先在 coding-agent-life-v1 上冒烟验证正确性,再投入 OpenAI 花费跑 LongMemEval。

从源码看可复用的细节:vector 展示了带批处理与维度校验的 init 写法;agentmemory 展示了"写入索引 + 记录 ID 映射 + 查询去重映射回会话"的完整状态机模式;scoreQuestion 对空 gold 集返回 R@K = 0 的边界处理也可作为实现参考。另外仓库在 test/eval-adapters.test.tstest/eval.test.ts 中对适配器与评测流程有对应测试,可作为行为契约参考。

评测体系仓库结构速览

eval/
├── README.md
├── runner/
│   ├── types.ts                   Adapter、Question、RankedDoc、ScoreRow 类型
│   ├── score.ts                   P@K、R@K 计算与聚合
│   ├── load.ts                    LongMemEval JSON → Question[]
│   ├── adapters/
│   │   ├── grep.ts                分词子串匹配基线
│   │   ├── vector.ts              OpenAI 嵌入 + 余弦
│   │   └── agentmemory.ts         POST /agentmemory/{remember,smart-search}
│   ├── longmemeval.ts             公开基准 Runner
│   └── coding-life.ts             内部基准 Runner
├── scripts/
│   └── sandbox.sh                 沙箱化启动与销毁
└── data/
    └── coding-agent-life-v1/
        ├── sessions.json          15 个虚构会话(约 6KB)
        └── queries.json           15 条带 gold 会话 ID 的问题

两条 npm 脚本(见 package.json)对应两个 Runner:npm run eval:coding-lifenpm run eval:longmemeval,均通过 tsx 直接执行 TypeScript。

总结:如何用这套框架量化你的记忆层

agentmemory 评测体系的设计哲学是"每层价值可证明":grep 给出词法下限,vector 给出纯语义基线,agentmemory 给出完整生产链路,三者在同一批问题上、以同一套 P@K / R@K / hit / 延迟指标横向对比。内部语料小到几秒跑完、免费可复现,适合开发期快速迭代;LongMemEval 体量大、题型全,适合发布前产出可与公开结果对照的记分卡。任何想接入的检索后端,遵循 Adapter 接口三步即可纳入这套评测体系。

热门项目推荐
相关项目推荐

项目优选

收起
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.15 K
2.77 K
kernelkernel
deepin linux kernel
C
34
18
docsdocs
暂无描述
Markdown
900
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
929
1.85 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.36 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.94 K
1.03 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.47 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
534
603
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
398
leetcodeleetcode
🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解
Markdown
77
23