Hermes 靠记忆系统、fast-jev-compaction 靠决策模型:上下文管理的两条路线谁走得更远?
【免费下载链接】fast-jev-compactionClaude Code plugin that replaces the compaction summary with Jev decisions: every tool call and result is scored in one fast request, stale ones are dropped or truncated, everything kept stays verbatim.项目地址: https://gitcode.com/gh_mirrors/fa/fast-jev-compaction
长会话 Agent 最贵的不是 API 账单,而是"记忆错位":模型忘了自己改过哪个文件、丢了一段报错堆栈、把src/generated的禁改约束在摘要里"优化"掉。2026 年,围绕上下文管理出现了两条针锋相对的技术路线——以 Nous Research Hermes Agent 为代表的记忆/检索体系(先记住,再按需召回),和以 TypeSafe AI 的 Jev 决策模型为底座、由 fast-jev-compaction 工程化的逐条决策压缩(不生成一个字,只做选择题,按需删除)。前者试图把上下文变成"外挂硬盘",后者试图把压缩变成"法官判决"。本文将以 fast-jev-compaction 仓库源码为第一手证据,对比两条路线的骨架、工程成本与适用场景,并讨论它们是否会殊途同归。
一、两条路线的骨架:把上下文"记住"还是"裁掉"
记忆/检索体系:上下文是资产,值得长期持有
Hermes Agent 走的是"记忆系统"路线:会话历史被结构化地存入长期记忆,通过向量检索与分层归档按需召回,配合上下文压缩与 MCP 工具集成,让 Agent 在长任务中"不丢事"。这套体系的核心假设是——过去的对话是有价值的资产,值得被索引、被持久化、被重新读取。它的代价也很明确:需要维护记忆的写入与召回策略,需要向量库或数据库做状态持久化,本质上是用"存储 + 检索"换"上下文窗口"。
决策压缩:上下文是消耗品,该删就删
fast-jev-compaction 走了完全相反的路。项目 README 的第一句话就划清了边界:"This library never rewrites anything. It only deletes tool calls and tool results Jev says are no longer needed."(README.md)——它不重写任何内容,只删除 Jev 判定为不再需要的工具调用与工具结果;用户和助手的文本逐字逐句、原序保留。
这套机制的核心假设是——大多数历史工具调用是消耗品:Read过 30 个文件、跑过 20 次测试,真正需要留给模型的只有最近几步。与其把历史"压缩成一段漂亮话",不如逐条问一个不写字的模型:这条调用还重要吗?这个结果还必须原样留着吗?
源码里的决策流水线
打开 src/compact.ts,compact()的主流程清晰可见:配对 → 钉选 → 拟合状态 → 分批提问 → 概率决策 → 重建消息。
- 配对:
collectToolCalls(src/state.ts)按tool_use_id把每条tool_use与其tool_result配对;没有结果的调用根本不是候选——"还没有可删的东西"。 - 钉选:
isPinned()规定index === 0 || index >= total - preserveRecentMessages——首条消息和最近preserveRecentMessages(默认 6)条消息永不触碰。 - 逐条提问:对每个非钉选调用,构造两个
noul问题(src/compact.ts 的questionsFor):call_xx问"知道这条调用被做出、且其输入仍然重要吗",result_xx问"完整输出是否仍需逐字保留(重跑工具不可行)"。 - 概率裁决:
decideCall把两个概率压到三个动作上——keepResult ≥ keepThreshold则整条保留;否则keepCall ≥ keepThreshold则保留调用、把结果截断;否则连调用带结果一起删。 - 无损重建:
applyDecisions重建消息列表,内容全失的消息整体移除,未触碰的消息原对象返回,"任何结果都不会脱离其调用而存在"。
这套流水线最反直觉的地方在于:给 Jev 看的是"省略版"历史,删的却是"原版"历史。决策模型看到的状态(fitState产物)里,工具结果一律被替换成一行注释ok, 4213 chars (omitted);而真正从会话中删除的,是未经任何改写、逐字逐句的原始消息。
二、工程对比:实现复杂度、模型依赖与成本
模型依赖:生成式 LLM vs 不生成文本的"哑巴模型"
记忆系统路线的压缩环节通常依赖通用 LLM 做摘要,而摘要恰恰是上下文管理里最不可控的一环——它会把变量名写丢、把逻辑"平滑"、把约束条件吞掉,且每次压缩都是新的幻觉风险源。社区对 Jev 的讨论几乎都围绕这一点展开:它是System One Model,不生成文本,只输出封闭空间内的结构化判断(noul概率、choice、score),官方口径是"速度快 193 倍、成本低 444 倍、输出 Token 免费"。在 src/types.ts 里可以直观看到这种"哑巴"的代价:Jev 的答案类型只有三种——NoulAnswer(一个概率)、ChoiceAnswer(一个选择 + 置信度)、ScoreAnswer(一个分数),仅此而已。
从工程视角看,这带来一个显著红利:响应可校验。src/request.ts 的parseJevResponse对响应做了严格的结构化校验——非 2xx 抛错、非法 JSON 抛错、缺answers抛错、noul缺失或非有限数抛错。生成式摘要的输出根本无法这样硬校验,而决策模型的输出天然是机器可消费的。
实现复杂度:规则层把"智能"降级为"工程"
记忆系统需要设计记忆 schema、写入时机、召回排序、过期策略,复杂度分布在系统各处。fast-jev-compaction 则把复杂度收敛进了三个"可调试"的规则层:
其一,无 tokenizer 的 token 估算。src/state.ts 的estimateTokens用正则把文本切成词/数字/符号,按"单词每 6 字母 1 token、数字半 token、符号 0.9"计价,并明确校准到比 Jev 实际报告值高出 2–18%——注释里写着"纯字符比会低估 JSON 密集状态最多 40%"。这避免了引入 tokenizer 依赖,换来的是可预期的预算余量。
其二,分级状态拟合。同一个文件里的fitState定义了七级"瘦身"阶梯,逐级施加、命中最先返回:工具输入截断至 1000 → 200 → 60 字符 → 长文本头尾摘录([… N chars omitted …])→ 旧消息折叠 → 旧调用压成单行(t12 Read file_path=src/a.ts → ok 480ch)→ 无调用的旧消息剔除 → 连续调用行合并;全部用尽仍超预算则直接抛错。每一级都返回stage标签(inputs<=200、texts abridged、old calls compacted…),压缩究竟发生在哪一步,一目了然。
其三,分批并发请求。batchCalls用maxRequestTokens(默认 30k,压在 Jev 32k 请求上限之下)减去状态与 20 token 请求开销算出预算,把问题拆成多批;每批都重发同一份完整状态,Promise.all并发执行后合并答案(src/compact.ts)。
成本账:毫秒级、零生成、可回退
决策路线的成本结构几乎全是"判断"成本:每批请求只输出几十个概率数字,没有生成文本的 token 费用,也没有二次摘要的级联开销。社区实测口径(如"Jev 不生成一个字,却干掉了 Agent 90% 的上下文"、91.5% 压缩率、压缩耗时 5–20ms)虽来自不同作者、数字口径不一,但方向一致:决策压缩的成本与延迟都低一个数量级。
fast-jev-compaction 还做了一层工程保险:压缩收益不足则回退。hooks/fast-jev.ts 中minReductionRatio默认 0.25——若 Jev 裁掉的字符不足 25%,插件 toast 提示fallback to built-in summary,把session.compact事件交给 Claude Code 内置摘要;Jev 请求失败、响应畸形、缺 API key、历史装不进状态预算,同样触发回退。决策路线因此不是"孤注一掷",而是"能删则删、删不动就退"。
三、场景对比:长会话编程、RAG、多工具编排各适合谁
长会话编程:决策路线的主场
fast-jev-compaction 从设计上就是为 Coding Agent 的长会话定制的,README 里那句"a file path, exact error, constraint, or command can disappear even when it matters later"直指编程场景的死穴。几个源码细节都为此服务:
- 钉选保护:首条消息与最近 6 条永远不删,用户的初始约束("Never edit src/generated")和正在进行的操作链不会误伤;
- 只删工具调用,不碰文本:README 的 Limitations 明确写着"Only tool calls and results are candidates; text messages are never removed or shortened in the output"——人类语言的语义完整性由规则保证,模型判断只作用于工具层;
- 截断留痕:结果被删时保留前 300 字符并追加
[fast-jev-compaction truncated N chars…; re-run the tool if needed](src/compact.ts),报错堆栈的头部、CLI 参数的签名都能留在视线里; - "重跑"兜底:决策指令中明说"whatever is not kept is deleted permanently, but the assistant can always re-run a tool or re-read a file"——编程 Agent 的工具具有可重入性,删错了代价有限,这正是决策路线敢删的底气。
RAG:记忆/检索体系的主场
决策路线在 RAG 场景几乎无用武之地。RAG 的核心矛盾是"语料在窗口之外",需要的是把知识索引、持久化、按查询召回——这是 Hermes 式记忆系统的能力圈。决策压缩解决的是"窗口之内的垃圾",而 RAG 解决的是"窗口之外的宝藏",两者解决的问题根本不同。想用"删调用"的思路管理知识库,等于用剪刀修水管。
多工具编排:中间地带
多工具编排里,决策路线的优势是"证据链完整"——社区情报中反复出现的 K/Q/V(Key/Query/Value)三元组描述,在源码里的对应物是STATE_CONTEXT与goal(src/state.ts):goal默认取最近三条用户指令,context明确告诉 Jev"这是一段编码助手对话正在被压缩,工具输出已替换为简短注释"。也就是说,Jev 是在"知道任务目标 + 看到全量历史骨架"的前提下逐条裁决的,这比无目标地批量摘要要精准得多。但代价也在 README 的 Limitations 里写着:完整状态随每个请求重复发送,历史接近状态上限时,一个问题批次就是一次完整重传——调用密度极高时,请求数与 token 消耗会同步上升。
四、融合猜想:记忆 + 决策会不会是终局
两条路线各自承认的边界
值得注意的细节是,fast-jev-compaction 自己并不声称"无损"——README 的 Limitations 写得很克制:"Calibration is at the request level; a probability is not a proof that a result is safe to delete."概率不是删除安全的证明。这与社区里 Redis 之父对 Jev 狂热的质疑("绝大多数开发者其实不需要它")遥相呼应:决策模型擅长高频、窄域、可回退的判断,但"这条历史值不值得留"在语义深处仍是一个生成问题,只是被工程手段降格成了判断问题。
每轮重新决定"模型该看什么"
社区情报中有一条值得玩味的线索:Jev 团队公开的 Coding Agent 设计草案提出"每轮重新决定模型该看什么"——这本质上已经不是"压缩历史"而是"动态选择视野"。把这条思路外推,决策模型完全可以嵌入记忆系统的召回环节:不是由规则或向量相似度决定召回什么,而是由决策模型对"当前任务 × 候选记忆"逐条裁决。届时记忆系统负责"存得住",决策模型负责"看得准",压缩从一次性的会话整理,变成每轮推理前的实时视野管理。
终局可能是分工而非取代
回到标题的问题:两条路线谁走得更远?从工程事实看,它们不是同一场比赛。决策路线把上下文管理从"昂贵的生成"变成"廉价的判断",在长会话编程这种高频率、可重入、证据敏感的场景里,成本和确定性优势是结构性的;记忆/检索路线则在知识持久化、跨会话复用场景里拥有不可替代的位置。真正的终局更可能是一种分工:记忆系统决定"什么值得长期拥有",决策模型决定"此刻该看什么"——一个管存量,一个管流量。fast-jev-compaction 已经把决策路线的工程范式(钉选、分级拟合、概率裁决、可回退)打磨成了可复用的开源积木(src/index.ts 导出了compactMessages、buildJevRequest、fitState、decideCall等全套构件),下一步被接进记忆检索链路,几乎是顺理成章的事。
上下文管理的下半场,赢家不会是"只记住"或"只删除"的一方,而是能把记忆的广度和决策的锋利组合起来的一方。
【免费下载链接】fast-jev-compactionClaude Code plugin that replaces the compaction summary with Jev decisions: every tool call and result is scored in one fast request, stale ones are dropped or truncated, everything kept stays verbatim.项目地址: https://gitcode.com/gh_mirrors/fa/fast-jev-compaction
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考