PACMS:用次模选择替换 recency 截断,把 LLM Agent 的上下文工程从"丢东西"升级成"选东西"

  • 关联论文:2606.20047
  • 作者:flyP
  • 更新:2026-07-22

一句话结论

长会话 LLM Agent 的上下文窗口被对话轮次、持久 memory、工具输出同时填满,主流的 recency 截断(即按时间顺序只保留最近的 N 条)"topic-blind",会丢老但相关的关键事实、留新但无关的冗余。PACMS 把上下文装配从"丢东西"重新定义为"在统一候选池上做 budget-aware 次模选择",以 facility-location objective 最大化查询相关覆盖;在 LongMemEval 的 100 题样本上,对比 LangChain 的生产级 MMR(Maximal Marginal Relevance,一种经典的相关性-多样性折中打分),证据轮 recall 打平、端到端 QA 准确率领先 +8 到 +12 个百分点。

解决的真问题

长跑 Agent 累积的上下文同时从三个方向涌来:

  1. 对话轮次:用户/助手的历史 turn
  2. 持久 memory:从长期存储里召回的事实、偏好
  3. 工具输出:文件读取、搜索结果、API 响应——往往单条就 5000 token

一旦总和超 token 预算,框架必须做选择。今天的默认是 recency 截断(保留最近的 N 条),配以周期性 summarization。这套机制在两类场景必然失败:

  • memory 场景的本质失败:用户问的是会话早期建立的事实,recency 截断已经把它丢了
  • 工具输出污染:一个 5000 token 的搜索结果挤掉了 4 个关键事实 token,因为后者"老"

本文的核心判断:这是"上下文装配"层面的问题,不该让"上下文压缩"或"RAG 召回"来解决。压缩(如 LLMLingua)query-blind、有损;RAG 召回解决"外部文档进入 prompt",不解决"已经在 prompt 池里的候选怎么选"。两者都在装配步骤之外。PACMS 把选择权收到装配步骤里。

核心方法:budget-aware facility-location submodular selection

选择目标

设 C = {c_1, ..., c_n} 为所有候选(memory、turns、tool outputs),q 为当前查询,B 为 token 预算,M ⊆ C 为必选集(系统消息等)。定义:

rel(i, q)   = max(0, cos(e_i, e_q))
w_ij        = rel(i, q) · max(0, cos(e_i, e_j))

F(S)        = Σ_i max_{j∈S} w_ij     # facility-location 目标

优化问题:

max F(S)    s.t.   Σ_{j∈S} tok(j) ≤ B,  M ⊆ S

这是一个 monotone submodular maximization under a knapsack constraint 的标准问题。贪心给出 (1 - 1/e) 近似 ≈ 63% 界;用 CELF lazy-greedy(一种利用次模函数边际增益单调递减的剪枝加速算法)实操,论文给出常数因子近似保证(具体常数由 Khuller 等的 budgeted maximum coverage 给出,原文未列出具体数值)。

与 MMR 的三处本质差异

维度 MMR PACMS
冗余定义 看已选集的最大相似(max_i∈S) 看候选池的全集覆盖(Σ_i)
相关性加权 纯相似,relevance-blind 权重含 rel(i, q),只计"覆盖相关区域"
理论保证 启发式,无近似界 monotone submodular,常数因子近似保证

最后一项差异是 PACMS 工业友好的关键:可证明的近似界让 QA 系统的延迟/质量预算有了理论依据,而不是"试试看"。

引擎集成

PACMS 实现为 OpenClaw Agent 框架的一个可插拔上下文引擎,暴露标准 hook:

  • ingest():候选进入上下文池
  • assemble()核心——按当前 query 与预算跑次模选择
  • compact()故意不实现——设 ownsCompaction=false,把压缩委托给宿主 runtime

这个"让选择归选择、压缩归压缩"的拆分是关键架构决策:PACMS 只负责"留谁",不负责"压谁"。两种能力各司其职。

selector 是一个 Python 类,dispatch 五种策略(pacms / top-k / last-k / rag / mmr),共用同一组 embedding 和同一 token 估算器——观察到的差异是策略差异,不是实现漂移。FastAPI 服务暴露 /select/select_debug,前者生产、后者给 demo UI 实时回显。整服务跑在 127.0.0.1:8077,单例长驻——embedding 缓存跨轮保持温热,因为选择在 agent 热路径上。

优雅降级:服务不可达时,OpenClaw 回退到 recency 截断,绝不卡住。这条 fallback 路径让 PACMS 可以"开关式"上线,不阻塞 Agent 整体可用性。

关键实验与数据

评估设置

  • 数据集:LongMemEval 100 题,按六类问题均匀采样
  • embedding:nomic-embed-text,本地 Ollama
  • 预算:相对总上下文 token 的 20%/45%/70%
  • 冗余注入:R ∈ {0, 2, 4, 8},模板化 paraphrase 注入填充轮
  • 两个 reader:GPT-5-mini(reasoning_effort=minimal)、GPT-5.4-mini(reasoning_effort=low)
  • judge:GPT-4o-mini 用官方 LongMemEval CORRECT/WRONG prompt

1. 证据轮 recall(R=2, 45% 预算)

选择器 recall
top-k cosine 0.933
PACMS 0.909
lc-mmr 0.895
last-k 接近 0(随 R 增长崩盘)

关键发现:PACMS 和 lc-mmr 在 recall 上打平,top-k 在 R=0 时领先但随 R 增长被 PACMS/MMR 反超。原文明确"我们不声称在 recall 上优于 MMR"——这是一个诚实的 negative claim。

2. 端到端 QA 准确率(R=2, 45% 预算)

选择器 GPT-5-mini GPT-5.4-mini
PACMS 52.0% 68.0%
top-k 50.0% 64.0%
lc-mmr 44.0% 56.0%
last-k 44.0% 42.0%

核心反直觉:PACMS 在 recall 上落后 top-k(0.909 vs 0.933),但 QA 上反超(+2 / +4 pts);PACMS 在 recall 上略赢 MMR(0.909 vs 0.895),QA 上大幅领先(+8 / +12 pts)。

3. 中心发现:recall 与 extractability 的解耦

作者把 recall 定义为"证据轮被保留的比例",把 QA 定义为"从装配好的 prompt 中能抽出正确答案的比例"。两者在本实验里显著解耦

  • PACMS 的 facility-location 目标保留了"更多样的查询相关覆盖"——即使个别证据轮没进 prompt,被覆盖区域里仍有可用线索。
  • MMR 的成对去重保留了"更少但更不相似"——但因为不去覆盖全相关区域,关键线索容易整片丢失。
  • top-k 在低冗余时召回强,但冗余一上来就掉。

含义:衡量上下文选择的 metric 应该是 QA 准确率,不是 recall。这条结论对所有做 RAG / memory 的人都有方法论意义。

4. 强 reader 上差距放大

  • GPT-5.4-mini 上 PACMS 对 MMR 的领先 +12,比 GPT-5-mini 上的 +8 大。
  • 解释:能力越强的 reader 越能从 facility-location 的"覆盖广"中受益——它能自己定位、合成、推理;弱 reader 反而需要 top-k 的"直接命中"。

5. last-k 全面崩盘

无论什么 reader、什么预算,last-k 在 QA 上 42-44%,R≥4 时 recall 接近 0。再次实证 recency 截断是 memory 场景的错误默认。

亮点与局限

亮点

  1. 架构层面贡献大于算法:把"上下文装配"从 implicit 的 hardcoded 行为变成可插拔的引擎,是 OpenClaw 生态的系统级贡献。
  2. 诚实报告负结果:明确说"recall 上不赢 MMR"——这条 negative claim 让 QA 主导结论更可信。
  3. 强可复现性:五策略共用同一 embedding/token 估算器、同一数据集;排除实现差异。FastAPI + Ollama 本地部署,CPU 友好。
  4. 优雅降级 + 服务发现:插件挂了不影响 Agent 整体,对工业部署关键。
  5. 可视化 demo:保留/丢弃网格、token meter、预算预算滑块——把抽象指标变成可观察行为。

局限

  1. 100 题样本:LongMemEval 100 题均匀采样,统计功效受限。原文承认这是 compute constraint(约 1600 API calls 的预算上限)。
  2. GPT-5 系 reader 的 bias:两个 reader 都来自同一家族,且都是偏弱推理档;其他模型家族(Claude、Gemini、Llama)上的相对排名未明确。
  3. embedding 模型单一:只测了 nomic-embed-text。不同 embedding 下的 facility-location 目标效果差异未量化。
  4. 实验性系统的局限:很多引文条目(bib.bib6 / bib.bib7 等)的具体出处被 anonymized 占位,复现需要去查证完整文献。
  5. 未测多模态候选:候选都是文本,多模态 Agent(图像、音频)的工具输出未被建模。
  6. 论文标题与会议:形态标注为 method,但内容里包含 demo、benchmark、系统贡献——三者权重不均,读者期待会不一致。

对工程落地的启发

  1. 替换 Agent 框架默认 recency 截断:所有长跑 Agent 框架(LangChain、LlamaIndex、OpenHands、OpenClaw)的默认上下文策略都该升级为 facility-location 或类似 relevance-aware 选择器。这是一行 import 的 ROI。
  2. retrieval 与 selection 分层:retrieval 决定"哪些文档从外部进 prompt"(fetches from outside),selection 决定"已经在池里的留谁"(arbitrates the present pool)。两者不能合并。PACMS 这条边界值得在自己的系统里显式画出来。
  3. QA 而不是 recall 作为生产指标:所有 RAG / memory 系统的离线和在线评估都应该以 QA 准确率为第一指标,recall 是辅助诊断指标。
  4. embedding 缓存预热:selection 在 agent 热路径上,单例长驻 + 缓存跨轮温热,是性能保证的关键工程决策。
  5. 预算作为可观测控制:暴露 budget slider 给上游调用方,根据任务复杂度动态调整(简单 QA 用 20%,多跳推理用 70%)。
  6. reader 能力决定选择策略收益:如果底座 reader 偏弱,top-k 的"高 recall 直接命中"反而更划算;reader 越强,PACMS 类覆盖式选择器优势越大。选型要按 reader 能力分级。

与同方向工作的关系

  • vs LLMLingua / RECOMP 等上下文压缩:压缩 rewrite/prune 文本、query-blind、有损;PACMS 整段保留、query-conditional、无损。两者正交——PACMS 选完谁之后,可以再让压缩对单条做无损冗余消除。
  • vs MemGPT / mem0 等 memory 框架:它们管理"持久存储",PACMS 管理"装配时的选择"。PACMS 是它们的客户端选择器。
  • vs LongMemEval / LoCoMo / MemoryAgentBench:这些是评测基准,PACMS 是被评测对象之一(且显然会跑分很高)。
  • vs LangChain MMR:MMR 是 pairwise 去重启发式;PACMS 是 monotone submodular 带近似保证。两者都是 retrieval 社区里的 redundancy control 文献,但 PACMS 是 agent 上下文工程的工程实现。
  • vs 经典 IR search-result diversification(Santos、Lin & Bilmes 等):理论上同源;应用上从"搜索结果列表"迁移到"上下文候选池",跨越到 Agent 系统层。

适合谁读

  • Agent 框架架构师:在设计上下文管理子系统、想替换 recency 默认值的人。
  • 长会话产品 PM:chatbot / copilot / 客服 Agent 的 memory 表现总差一口气的根因排查者。
  • RAG 研究者:对 "retrieval ≠ selection" 这条边界感兴趣的人。
  • OpenClaw 生态贡献者:想给 OpenClaw 加可插拔引擎、follow 现有 hook 协议的人。
  • 评估方法论研究者:对"recall 与 QA 准确率解耦"这一发现想深入挖掘的人。

阅读提示:第 3.1 节的选择目标是核心;第 5.2 节 QA 表是说服力最强的反直觉证据;如果关心落地,看第 3.2 节引擎集成——ownsCompaction=false 的设计哲学和 FastAPI fallback 路径值得抄。demo 在第 4 节,是把抽象指标"可视化"的好范例。

工程落地与核查(Jay)

事实核查笔记

  • 100 题样本规模:原文承认受 compute budget 限制(~1600 API calls),100 题均匀采样。解读引用"p<0.001"存疑——100 题样本做独立trial比较,p 值不应如此极端,建议以原文为准;此处解读文字未注 p 值,引用本身是安全的。
  • GPT-5-mini / GPT-5.4-mini:均为假设名称,非 2026 年 7 月已发布模型。实验数据系合成/假设可能性高,不应用于正式引用或生产决策依据
  • nomic-embed-text + Ollama 本地部署:组合方式可行,但 nomic-embed-text 在不同任务类型上的 recall 表现差异显著;换 embedding 模型(如 bge、e5)可能导致 PACMS vs MMR 的胜负反转。
  • CELF lazy-greedy 近似常数:Khuller et al. 的 budgeted maximum coverage 贪心近似比是 (1 - 1/e) ≈ 0.632,但该常数适用于 set cover 变体;facility-location 在 knapsack 约束下的常数界需查 Khuller et al. 原文,解读中"具体常数由 Khuller 等给出,原文未列出具体数值"表述准确。

实际系统怎么用

集成路径(以 Python + FastAPI 为例)

# 最简集成:替换 LangChain 的 ConversationBufferMemory
from pacms import PACMSSelector

selector = PACMSSelector(
    budget_tokens=8192,        # 按模型 context 余量设
    embedding_model="nomic",    # 或 bge-large、e5-large
    fallback="last-k"           # 服务挂时自动切
)

# 每轮 assemble() 走热路径,embedding 缓存跨轮复用
selected = selector.assemble(query=current_turn, candidates=context_pool)

部署 checklist - embedding 服务(Ollama)与 selector 服务解耦,各自独立扩容 - budget_tokens 应与 max_context - system_prompt - reserved 联动,设成硬参而非 magic number - 单例长驻时注意内存:embedding 缓存随候选池膨胀,建议加 LRU eviction 或定期 selector.reset()

坑与经验

描述 解法
embedding 模型选错导致 coverage 退化 nomic-embed-text 对中文代码、专有名词嵌入偏弱,导致 facility-location 选了语义相似但实际无关的候选 上线前在自己业务 QA 上测 recall@K;换 bge-m3 或 e5-large 重新跑对比
budget 设太大等于没选 budget 接近总 context 时,selector 几乎把全部候选放入,facility-location 的边际收益消失 经验法则:budget 设为主 context 的 30-50%,具体按任务类型 A/B 测
候选池含 system prompt / few-shot 示例时误选 selector 把高相关性的 system prompt 当成普通候选压掉 通过 required_set 参数把必选集传入(PACMS 原生支持 M ⊆ S
冷启动缓存 miss 每轮 assemble() 第一次调用时 embedding cache 为空,P99 延迟翻倍 agent 启动时预热:把 memory pool 里候选预先 embed 一次
与 RAG 召回路径打架 有外部 RAG 管线时,retrieved docs 和 memory candidates 被放进同一候选池,但 embedding 空间不同(dense vs 稀疏词法) 两条流分开:RAG docs 走 retrieval 路由进 prompt;PACMS 只管 memory + turns

监控与可观测

  • 上线后新增指标:pacms_selection_recall_estimate(在保留候选上回刷 recall)
  • 每日抽 5% 请求打 assemble_debug 日志,看被丢的候选是否包含用户后续引用的信息(回刷验证)
  • 告警:pacms_fallback_rate > 5% → 服务健康或 embedding 服务抖动

总结

PACMS 的核心工程价值不是"次模算法",而是把"上下文选择"从隐式默认变成显式可插拔引擎。facility-location 的具体近似界在 0.63 附近,实际收益更多来自 query-conditional 覆盖这一直觉的正确实现。在生产落地前建议先跑自己业务的 recall 基线,确认 top-k 确实不够用再上 PACMS——对简单 QA 场景,top-k + budget 控制可能已经足够。