《Holistic Context》写了三个机制,我去开源代码里挨个找了一遍。

@RealYDT
阿良|AI 工作流@RealYDT
42 views Sep 04, 2026 ~4 min read
Advertisement

兄弟们,大部分技术报告,你只能选择信或者不信。

Media image

因为你看不到它跑的东西,论文说"我们设计了一套记忆机制",配一张架构图、一组分数,然后就没有然后了

图里那些方框对应什么代码,没人知道。

MelandLabs 这份《Holistic Context》不一样,它在摘要第一段就写了一句可以被检验的话:

我们提出 Holistic Context,一套在 OpenContext 开源 AI 同事中实现的跨会话上下文框架。

这句话是可验的。melandlabs/opencontext 是公开仓库,Apache 2.0,clone 下来就能读。

那这件事就变得可以做了:论文说它用了三个机制,我去代码里一个个找,看看在不在、叫什么名字、参数是多少。

先把话说死

我核的是「机制在不在代码里」,不是「benchmark 数字对不对」。

这两件事完全不同。97.6% 我没有复现,也复现不了:那需要 LongMemEval-S 全量数据、同样的骨干模型、同样的评审配置,我一样都没有。

我能做的只有一件事:论文说它用了某个机制,我去确认这个机制真的在代码里,参数写的是多少。

这篇就是这件事的记录。

Alloomi 的技术路线分三层—全域上下文、自进化、专业交付。这篇核的是第一层,最后几节会说清楚它在整体里的位置,以及为什么另外两层我核不了。

(版本说明,免得你对不上:两份报告读的都是 2026 年 8 月 12 日的版本,代码核的是 melandlabs/opencontext 的 commit 63a5f63。下面每一处引用都带文件名和行号,你可以自己去查。)

这两件事完全不同。97.6% 我没有复现,也复现不了:那需要 LongMemEval-S 全量数据、同样的骨干模型、同样的评审配置,我一样都没有。

我能做的只有一件事:论文说它用了某个机制,我去确认这个机制真的在代码里,参数写的是多少。

这篇就是这件事的记录。

Alloomi 的技术路线分三层——全域上下文、自进化、专业交付。这篇核的是第一层,最后几节会说清楚它在整体里的位置,以及为什么另外两层我核不了。

(版本说明,免得你对不上:两份报告读的都是 2026 年 8 月 12 日的版本,代码核的是 melandlabs/opencontext 的 commit 63a5f63。下面每一处引用都带文件名和行号,你可以自己去查。)

一、先看报告说了什么

《Holistic Context: A Unified Cross-Session Context Retention Framework for Long-Horizon Autonomous Agents》,MelandLabs。

它要解决的问题用一句话说得清:AI Agent 干活跨天、跨会话、跨平台,而上下文窗口是固定的。窗口外的信息直接消失,窗口内的信息也只是一堆没组织过的 token。

它的主张是:上下文不该被当成一段会过期的 token 序列,而该被当成一份持续维护的状态。

三个基准的成绩:

▍LongMemEval-S (n=500)
  Holistic Context:97.6%
  主要对照:长上下文基线 43.8%、MemGPT 48.7%、Mem0 52.0%、Hindsight 91.4%、Mem0 V3 94.4%
▍LoCoMo (n=10)
  Holistic Context:97.4%
  主要对照:A-MEM 51.29%、Mem0 66.88%、TiMem 75.30%、Hindsight 85.67%、Mem0 V3 92.5%
▍BEAM(128K / 500K / 1M / 10M)
  Holistic Context:72.8 / 75.7 / 76.5 / 67.0%
  主要对照:Hindsight 73.4 / 71.1 / 73.9 / 64.1

BEAM(128K / 500K / 1M / 10M) | 72.8 / 75.7 / 76.5 / 67.0% | Hindsight 73.4 / 71.1 / 73.9 / 64.1数字很好看。但让我愿意继续往下读的,是紧接着的这段—它自己写的限定(摘要原文,以下为我的翻译):

所有 Holistic Context 的格子都是单种子、单骨干(Claude Sonnet 4.5)的点估计;BEAM-128K 那一格跑的是 100K token 子集;LoCoMo 那一格只覆盖十段对话;跨论文的基线行,是那些在不同骨干、不同评审配置下运行的系统已发表的数字。

因此,表头数字应当被读作可行性演示(feasibility demonstration)。

这不是我从角落里挖出来的免责声明—它就写在摘要里,紧挨着那几个漂亮数字。

正文里它又把这句说了一遍:这个比较「不是受控的一对一对照」。BEAM 那一节甚至主动写明,自己在 128K 上比 Hindsight 低 0.6 个百分点。

一份把自己的限定写到这个程度的报告,比只贴分数的可信。它主动告诉你:这些数字能证明什么、不能证明什么。

(同一团队的另一份报告《Self-Evolving Agent》里也是同样的态度—它把自己在公开榜单上的名次标注为「仅作外部参照,不构成框架贡献声明」,理由是榜单第一名的模型在骨干、参数量、训练数据、推理预算上同时不同,不是同类比较。能忍住不用榜单名次做宣传的技术团队,不多。)

所以这篇文章不会去争论 97.6% 是高是低。我想知道的是:撑起这个数字的三个机制,代码里到底怎么写的。

二、这三个机制,用大白话是什么

论文的三个机制名字都挺学术,先翻译一遍。

机制一:applicability-scoped attribution(可适用范围的归属)

大白话:不光记住"张三说预算是 50 万",还要记住"这是他在 3 月那个项目会上说的,只对那个项目有效"。散落在邮件、会议、文档里的碎片,要归到同一个实体上,并且各自带着适用范围。

机制二:tiered forgetting with evidence-preserving deprecation(分层遗忘 + 保留证据的退役)

大白话:过期的东西要能忘掉,但得留个存根——将来还能回答"你当时为什么那么认为"。

机制三:Hebbian relation learning with competition(带竞争的赫布关系学习)

大白话:经常一起出现的东西会互相绑定,久了不用的连接会松掉。名字来自神经科学里那句"一起激发的神经元会连在一起"。

论文自己给了这个机制的工程对应物:Personalized PageRank over co-activation graphs——在共同激活图上跑个性化 PageRank。

记住这句,第五节全靠它。

三、机制一:一处一字不差,一处形状不同

代码里 applicability 这个词出现了 177 处,核心定义在:

代码里 applicability 这个词出现了 177 处,核心定义在:

packages/ai/memory-consolidation/src/graph-contracts.ts

先说对上的

论文说,有一条 scope isolation 不变式:每张记忆图都绑定在一个 (userId, workspaceId, tenantId) 三元组上,跨范围的归属只能走显式关系,绝不默认共享—目的是防止一个私有工作区的事实悄悄泄进另一个的检索结果。

代码第 1 到 5 行:

export interface OwnerScope {	
userId: string;	
workspaceId?: string;	
tenantId?: string;
}

一字不差,一字不差。

这个不用多解释:论文说了个数据隔离的承诺,代码里有个同名同结构的类型在承载它。

再说没对上的

论文把 Applicability Context 定义成一个五元组:

A(f) = ( task(f), conversation(f), channel(f), person(f), [有效区间] )

五个并列的轴,一条记忆同时带这五个属性。

代码第 7 到 15 行:

export type MemoryApplicabilityScope =	
"global" | "task" | "conversation" | "channel" | "project" | "custom";
export interface MemoryApplicabilityContext {	
scope: MemoryApplicabilityScope;	
key?: string;	
validFrom?: number;	
validUntil?: number;	
metadata?: Record<string, unknown>;
}

形状不一样。

不是五个并列的轴,是一个六选一的枚举,选完再用 key 指定具体是哪个任务、哪场对话。而且:

  • 论文里的 person 不在这个枚举里
  • 代码里多了论文没提的 global、project、custom
  • 这说明论文造假了吗?没有,我不这么认为。

    person 完全可能由上面那个 OwnerScope.userId 承载,或者用 key 字段装。论文写的是概念模型,代码是它的一种落地形式,两者本来就不需要一一对应。

    但形状确实不同,而这件事只有把两边摆在一起才看得见。我的结论只到这儿为止,再往前推就是过度解读,我没有证据。

    四、机制二:论文只说了方向,代码给了数字

    分层遗忘的核心在:

    packages/ai/memory-consolidation/src/plan.ts

    先说三层

    论文说记忆分短、中、长三层。这个在代码里是一个独立的类型,在隔壁文件(evidence-cluster.ts 第 18 行):

    export type MemoryEvidenceTier = "short" | "mid" | "long";

    短、中、长。用词和论文一模一样,而且有默认值(adapter.ts:193):

    const DEFAULT_TIER: MemoryEvidenceTier = "short";

    一条新证据进来,默认落在短期层。

    分层之外,还有一套动作

    plan.ts 第 7 行定义了四个生命周期动作:

    export type MemoryConsolidationAction =	
    "preserve" | "observe" | "decay" | "deprecate";

    保留、观察、衰减、退役。

    这四个动作和上面那三层是两回事,别混——三层说的是"这条记忆存在哪一层",四个动作说的是"这一轮整理该拿它怎么办"。论文把两者写在同一段里,代码把它们放在两个文件、两个类型里。

    决定动作的那组数字,论文里没有

    plan.ts 第 64 到 70 行:

    const DEFAULT_THRESHOLDS: MemoryConsolidationPlanThresholds = {	
    preserveScore: 0.6,	
    preserveEvidence: 3,	
    decayScore: 0.55,	
    decayEvidence: 1,	
    competitionMargin: 0.12,
    };

    翻译一下:

    参数 | 值 | 意思

    preserveScore  |  0.6  | 想被保留,分数得过 0.6

    preserveEvidence  |  3  | 而且得有 3 条证据

    decayScore  | 0.55 | 掉到 0.55 就进入衰减

    decayEvidence  |  1  | 衰减只需要 1 条证据

    competitionMargin | 0.12  | 分差超过 0.12 才算竞争分出胜负

    光看阈值容易看岔—我第一遍就看岔了。以为保留要 3 条证据、衰减只要 1 条,是"系统更愿意让东西退役"。

    把判定逻辑读完,结论是反的。

    plan.ts 第 145 到 196 行,一共六个分支:

    Media image

    图 1|plan.ts 里六个分支各自的去向。这是我照着代码画的示意图,不是截图——条件、阈值、行号都印在图里,可以对着仓库自己核。

    六个分支,三个落在 observe,包括最后那个兜底的。

    preserve 要四个条件同时成立—是个高门槛。decay 要求"又弱又孤立"是个窄口子。中间那一大片,全部挂进"再看看"。

    所以这套默认值真正的倾向不是保留、也不是退役,而是先不做决定。

    对一个记忆系统来说,这是个挺明确的立场:既不囤积,也不过早遗忘,把拿不准的都挂着。

    而这件事,论文里读不出来。论文告诉你有分层遗忘这个机制;代码告诉你它在犹豫的时候会怎么办,而真实系统里,大部分时候都是拿不准的时候。

    退役之后去哪了

    论文强调 evidence-preserving——退役的信念要归档、可审计。

    代码里生命周期状态的定义(graph-contracts.ts):

    export type MemoryClusterLifecycleStatus =
     "forming"    | "active"           | "stable"
     "decaying" | "superseded" | "audit-only";

    最后那个 audit-only:已经不参与检索了,但还在,还能查。

    论文说的"归档可审计",落地就是这个终态。对上了。

    一个要提醒的地方

    ebbinghaus 这个词,在整个代码库里出现 0 次。

    论文说衰减是「Ebbinghaus 形状的重要性衰减」,代码里对应的是 decay(95 处)和 halfLife(7 处)。

    这不是问题。学术论文用学术名,工程代码用工程名,本来就是两套词汇。但如果你拿着论文去代码里搜关键词,会一无所获—得知道该搜什么。

    五、机制三:论文说的规矩,代码用类型钉死了

    这一节是我最想写的。

    四类边,一字不差

    论文说关系有四种:support(支持)、compete(竞争)、related(相关)、supersede(取代)。

    graph-contracts.ts 第 19 行:

    graph-contracts.ts 第 19 行:

    export type MemoryGraphRelationKind =

    "support" | "compete" | "related" | "supersede";

    四个,同名,连顺序都一样。

    但这只是名词对上了。真正让我坐直的是下面这个。

    「先竞争,后取代」这条规矩是被类型强制的

    论文里有一段讲它怎么处理信念冲突。大意是:

    当新信息和已有信念矛盾时,先建一条 compete 边(竞争关系),只有当新信念被证明证据更强之后,才关闭旧信念的有效区间,形成取代。

    翻译成大白话:不许一上来就宣布旧的错了。得先并列摆着,等证据分出胜负,才允许替换。

    这是个很克制的设计。问题是——代码里真的这么做了吗?

    我去找负责判断关系的那段。LLM 读完两条记忆,要输出它们是什么关系。adapter.ts 第 319 行:

    relation: "support" | "compete" | "related",三种。没有 supersede。

    graph-evolution.ts 第 419 行,同一处约束再写了一遍:

    const kind = judgment.relation as "support" | "compete" | "related";

    那 supersede 边从哪来?在另一个文件里,graph-lifecycle.ts 第 451 行:

    kind: "supersede",

    生命周期阶段。

    这件事为什么重要

    论文提出一个原则,代码不是"大致遵守",而是把它编码进了类型系统。

    模型判断那一步,根本拿不到 supersede 这个选项。不是靠提示词叮嘱它别乱用,不是靠事后检查兜底—是类型上就没有,想违反都违反不了。

    Media image

    图 2|同样是我照着代码画的示意图。三处引用的行号都标在图里,可以对着仓库自己核。

    这才是"论文和实现对得上"的真正含义。

    名词对得上,只能说明写论文的人和写代码的人用了同一份词汇表。约束对得上,才说明论文里那句设计原则是真的在管事。

    然后是那个 PageRank

    论文说 Hebbian 机制的工程对应物是「Personalized PageRank over co-activation graphs」。

    代码里就是这个文件:

    packages/insights/src/event-rank.ts

    它的几个关键参数:

    Media image

    阻尼系数 0.8 意味着:一个节点的分数里,八成来自邻居传过来的,两成来自它自己。这是个偏向"关系"的配置——原始 PageRank 常用 0.85,思路一致。

    人物边 0.7、关键词边 0.3,也就是说:「同一个人」这条线索的权重,是「同一个关键词」的两倍多。这是个产品判断,不是数学结论。

    一条论文里没有的:超过 200 个节点,图就不跑了

    event-rank.ts 第 368 到 381 行:

    Media image

    第 394 行,归零之后发生什么:

    if (n > 200 || maxIterations === 0) {

    // 直接返回基础分,eventRank: 0

    节点超过 200,图传播整个跳过,直接返回基础分。

    这不是 bug,是明摆着的性能取舍——注释里写得清清楚楚。迭代次数随规模递减:不到 50 个跑 20 轮,50 到 100 跑 10 轮,100 到 200 跑 5 轮,超过 200 一轮都不跑。

    但这条信息,论文里一个字都没有。

    论文讲的是机制在概念上怎么工作;代码讲的是它在什么规模下、按什么强度工作。两个都读,你才知道这套东西真实的样子。

    如果你的场景里活跃记忆常年在几十条,那 Hebbian 关系学习是完整跑的。如果你打算喂给它几千条,那你拿到的就是基础分排序,图那部分是关着的。

    这个边界只有读代码才知道。

    六、核对下来的全貌

    Media image

    五个对上,三个是命名或形状差异,三个是论文里没有、只能从代码里拿到的。

    三处 ⚠️ 里没有一处是"论文说了假话"。命名差异是学术圈和工程圈的常态;五元组那处是概念模型和落地结构的正常距离。

    这张表本身就是这篇文章的结论:这份报告描述的东西,可以被外部独立核对到这个颗粒度。大部分技术报告做不到,不是因为不想,是因为代码不公开。

    七、我核的这一层,是三层里的第一层

    写到这儿要说清楚一件事:上面所有内容,都只是 Alloomi 技术路线的三分之一。

    它的路线分三层,九个公开 benchmark,每层三个:

    第一层:全域上下文(记得住)

    长期记忆和全域上下文—也就是这篇文章从头核到尾的那一层。

    基准 | Holistic Context | 对照

    LongMemEval-S| 97.6% | 长上下文基线 43.8%、Mem0 V3 94.4%

    LoCoMo  | 97.4% | Mem0 66.88%、Mem0 V3 92.5%

    BEAM 10M  | 67.0% | Hindsight 64.1%

    第二层:自进化(学得会)

    从上下文和反馈里持续学到新东西,这一层在另一份报告《Self-Evolving Agent》里,跑的是 Self-Evolving Agent-mini(Qwen3.6-35B-A3B,35B 参数 / 3B 激活的 MoE)。

    数字出自该报告的 Table 3:

    ▍CL-bench

    测的是什么能力:从复杂上下文里学会新规则

    对照:21.5(GPT-5.6 SOL)

    SEA-mini:47.6%(+26.1,2.21 倍)

    ▍CL-bench Life

    测的是什么能力:跨会话累积经验

    对照:22.2(GPT-5.5 High)

    SEA-mini:32.1%(+9.9,相对 +44.6%)

    ▍Cont.L.Bench

    测的是什么能力:跨任务迁移、抵抗遗忘

    对照:22.3(Claude Sonnet 4.6)

    SEA-mini:32.6%(+10.3,相对 +46.2%)

    这张表自己带了一条提醒,我照抄过来:这六行「不是严格的同类比较」每一行走的是各自榜单的协议。它还明说,真正代表框架贡献的是同骨干那组对照,不是榜单排名。

    又是同一种克制。跟第一节里 Holistic Context 那句「应当被读作可行性演示」是一个路数,把自己数字的适用边界写在数字旁边。

    第三层:专业交付(做得成)

    学到的东西能不能变成真实交付。

    ▍SWE-Bench-CL

    测的是什么能力:多文件软件工程(273 个任务的时序序列)

    对照:73.3(OpenCode + Kimi-K3 + FAISS)

    SEA-mini:80.6%(+7.3)

    ▍GDPval

    测的是什么能力:44 种职业的真实经济价值任务

    对照:67.3(Claude Opus 5,榜单第一)

    SEA-mini:74.2%(+6.9)

    ▍JobBench†

    测的是什么能力:真实专业工作流交付

    对照:54.7(Kimi-K3)

    SEA-mini:57.5%

    这三行,论文给每一行都挂了一个"别这么读"的标签。我一条条搬过来:

    · JobBench 那个 †:它用的评审跟官方 JobBench 榜单不同,脚注写明「这个符号是给读者的信号,说明该行不是同类比较」。

    · SWE-Bench-CL:作为对照的五行 OpenCode 基线,跟 SEA-mini 同时差着两件事,骨干模型不同,而且没有那套飞轮。真正能把框架贡献单独摘出来的同骨干实验,被论文自己列进了"待办"。它还主动补了一句:+7.3 是对 Kimi-K3 的,要是对最强的那行(Qwen3.8-max,76.4%),只领先 4.2 个点。

    · GDPval:两边压根不是一套计分,74.2% 是 OpenAI / Anthropic / Scale 的官方加权评分,67.3% 是榜单快照的归一化百分比。表格标题里直接写着 "different scoring, not directly comparable"。

    顺带说一件我注意到的事

    从第一节到这里,同一种做法出现了四次:

    出处 | 它自己写的限定

    Holistic Context 摘要| 表头数字「应当被读作可行性演示」

    SEA Table 3  | 这六行「不是严格的同类比较」

    SWE-Bench-CL | 隔离框架贡献的那个实验「是待办」,且主动给出更保守的 +4.2

    GDPval  | 「不同计分方式,不可直接比较」

    每给一个数,旁边就标一次这个数不能拿去干什么。

    这在技术宣传材料里不常见,我核不了那些分数,但我能看出报数字的人有没有在藏东西,这四处说明它没有。

    三层串起来是一个闭环

    真实任务轨迹 → 质量筛选 → 专家锚定 → 后训练 → 评测准入 → 版本回滚。

    一句话:让 AI 每完成一次交付,就获得一次成长。

    但有件事我必须说明

    这三层里,我只核验了第一层。

    不是我偷懒,是只有第一层有开源实现可查,上下文这一层,机制写在论文里、代码摆在 GitHub 上,我能一行一行对;后两层是模型后训练,没有对应的开源代码,我能做的只有转述它报告里的数字和它自己标的限定。

    所以请这样读这篇文章:第一层的判断,是我核过的;后两层的数字,是它自己公布的,我只是把它们和边界一起搬了过来。

    八、你想自己核对的话

    代码在 github.com/melandlabs/opencontext,Apache 2.0。我跑通的路径:

    Media image

    两个坑先说在前面,都是我撞过的:

  • Windows 需要 Visual Studio Build Tools(C++ workload),否则 better-sqlite3 编译失败。README 里没写。
  • 别用官方的 build:packages:它的过滤器 ./packages/* 不跨目录分隔符,会漏掉嵌套在 packages/ai/ 里的包,构建挂在 indexeddb。用 pnpm -r build。
  • 跑通之后 pnpm test 会出 97 项通过、3 项跳过、0 项失败,和 README 写的一致。

    Media image

    图 3|examples 的检查结果,与 README 承诺的 97/3/0 逐字一致。这张是终端截图,不是示意图。

    本文引用的所有文件都在 packages/ai/memory-consolidation/src/ 和 packages/insights/src/ 下,行号基于 commit 63a5f63。

    九、最后

    再说一遍开头那句,因为它决定这篇能算什么:

    我核的是机制在不在代码里,不是 benchmark 数字对不对。

    97.6% 我没复现。这篇文章不能用来证明那个数字成立,也不能用来证明它不成立。它只能证明一件事:论文描述的那套机制,确实有一份可以打开来读的实现。

    对一份技术报告来说,这已经比大多数同类多了一层。

    如果你真的复现了那三个基准,无论结果是什么,欢迎发出来打我的脸,我这篇能验的部分只到代码为止。

    论文和代码:

  • 技术报告 https://alloomi.ai/reports/hc.pdf
  • 开源仓库 https://github.com/melandlabs/opencontext
  • 在代码生成场景,Cursor或Devin这类工具通过会话历史和规则文件已能部分记住项目偏好,但跨项目迁移仍弱。真正的经验复利可能需要比当前post-training更细粒度的持续对齐。

    Actions
    What You Can Do
    • Export as PDF or Markdown
    • Batch Export to Notion
    • Bookmark & Highlight
    • Screenshot Tweet
    Create Free Account

    Includes 7-day Premium trial

    Advertisement