惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
V2EX
Y
Y Combinator Blog
博客园_首页
V
Visual Studio Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
阮一峰的网络日志
阮一峰的网络日志
Hugging Face - Blog
Hugging Face - Blog
宝玉的分享
宝玉的分享
B
Blog
博客园 - 三生石上(FineUI控件)
小众软件
小众软件
WordPress大学
WordPress大学
L
LangChain Blog
爱范儿
爱范儿
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Proofpoint News Feed
Blog — PlanetScale
Blog — PlanetScale
C
Check Point Blog
博客园 - 聂微东
云风的 BLOG
云风的 BLOG
Microsoft Security Blog
Microsoft Security Blog
博客园 - 叶小钗
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Help Net Security

V2EX

我用 AI 写代码,但终端管理反而成了累赘——于是我做了 codux [调研] 各位在公司都用什么 ide 和 agent 写代码? 老运维 share 一个运维平台 看到有公司考核 token 指标,很好奇大家上个月的 AI 账单是多少 GLM-Coding 调用持续报错: z.ai 的 Lite 套餐几乎无法使用,官方 Pro/Max 是否稳定? 现在还有什么渠道可以稳定安全地使用 Claude 吗? 上海漕河泾内推,本组有 2 个 hc,一个后端,一个前端,预算都是 20k 左右,不打卡,氛围好 如果 V2EX 上有一组不永久保存聊天记录(比如只保存 7 天或者 24 小时)的聊天室,那么会开启哪些有用或者有趣的可能? gemini cli 貌似挂了,一直返回 403 第一次在自媒体上赚到钱 收集了最近在使用的低价 GPT, Gemini,邮箱等 AI 会员的小店合集 讨论个大实话:现在企业还在说 AI 编程提效 20%, 30%的,真的太落后,没用懂 AI。因为包括很多前沿公司,已经狂奔到提效 200%-500%的情况 [招聘][远程][币安] 前端/后端/QA/iOS/Android 至少 3 年以上经验 目前有大量 HC 欢迎投递 Chatgpt Pro 用量用不完的可以开这些设置 面试的时候好像遇到钓鱼了,给各位避个坑 cursor 年续费 22 号到期, 自动续费是否还是老的计次套餐呢 被两件破事毁掉的一下午,琐碎的内耗消磨人的精力 使用 Planet 存储 Codex 的会话或者重要信息 如果业务部门领导不要你开发功能,而是要求你教会它用 claude code 开发功能,你会怎么做? 分享一个 MacOS 接绿联 CM818 USB 转 DP 转接器使用感受 我的 HR 朋友 10 年老 Java ,非全大专,大家帮忙看看简历 开源了一个 AI 口语练习工具,音素级发音评分,完全免费可自部署 V2EX 上有哪些你觉得很有趣、印象深刻的妹纸? 字节为啥不出个国内版 Vercel? 有在大马的朋友吗? 问个运营商问题 你们在有领导的公司大群发过的最大胆的消息是什么 公司裁员,目前没有工作。想试试摆摊,做一个移动鲜啤打酒车 我的硬盘 Memblaze Pblaze 5 Linux 下不识别,给 Linux 内核提交了补丁, AI 说有望被合并 只有我一个人觉得 codex 不好用?
聊聊 opencode 上下文压缩: 如何做到单会话 1 亿 token 不爆...
ranxianglei · 2026-05-20 · via V2EX

潜水 10 年:)

可以先把话撂在这里,acp 这个插件出现其他上下文压缩方式就可以谢幕了,甚至尝试继续扩大模型上下文的行为也变得无意义。

先说说上下文压缩插件 acp 是啥,这是一个 opencode 中的插件。为什么需要上下文压缩?用过 AI coding 的都知道,模型上下文都是有限的,哪怕你有 100w 上下文也无济于事,面对旷日持久的大项目也捉襟见肘(尤其是可怜的 glm5.1 啊啊啊)。

所以 gpt 和你聊天实际上是假聊天,你和他每次说的消息,包括他的输出,都作为上下文,每次都全部发给 gpt 处理,久而久之你们就攒满几十万甚至 100w 上下文,就要删去一些。

作为程序员,显而易见想到的方式就是把上下文提炼总结,替换掉原会话冗余的上下文。现在大部分上下文压缩都是这么做的,只不过有一些做的很粗糙(大部分),有的很精细(比如 claude 多级级联),有一些还甚至想出做向量存储相关性搜索等等。

不过最终面临的问题还是压缩效果不好的问题。

想法很简单,实现很简单:模型自己决定要不要压缩,怎么压缩

说起来一肚子气,本来这个插件是要提给原作者dcp的,我修了几十个 bug ,增加了类似 jvm 的垃圾回收算法,结果他看都不看全给我关了!!!

废话不多说先看看效果:最近上下文几乎都没有超过 50%!

模型 GLM-5.1 ( 204K context window ),ACP 阈值 55%。

指标 修复前 (5/14 - 5/19) 修复后 (5/19 - 5/20)
采样数 2,749 362
峰值 context 74.2% 45.3%
平均 context 35.9% 25.3%
context <40% 的占比 64.5% 87.0%
context >55% 的次数 130 次 (4.7%) 0 次 (0%)

主:修复前之前还有,再之前会话超过几百条就上下文丢干净了。

这是最近几天这个会话的 token

指标 数值
总 Input Tokens 35,232,595(约 3520 万)
总 Output Tokens 616,525(约 62 万)
总 Tokens (输入+输出) 约 35,849,120(约 3585 万)
消息总数 3,762 条
会话时长 约 6 天( 5/14 - 5/20 )
模型 GLM-5.1 ( 204,800 token 上下文窗口)
ACP 压缩阈值 55%( 112,640 tokens )

原理:把上下文压缩当做一个 skill

是的,就这么简单。你不需要像 claude 一样搞多级压缩(都是人工定死的,哪有模型灵活?)也不需要搞外部 api 专门压缩(外部 api 才不了解你需要哪些信息)。也不需要专门训练模型,只需要交给模型一个 skill ,他自己决定什么时候调用即可。

重点说明一些基本特性:

  1. 每条消息模型都可以压缩,或者解压缩(这很重要)
  2. 模型可以把连续 N 条消息压缩成 1 条消息。
  3. 模型可以删除消息。
  4. 模型可以修改消息。

系统做什么?

  • 在模型启动的时候告诉模型可以压缩
  • 在上下文 45%的时候提示模型应该压缩
  • 在上下文 55%的时候提示模型必须压缩

仅此而已。

最后说说我改了啥?和原生 dcp 有啥区别

原始 DCP 有个致命问题:上下文状态全靠 msgId 列表追踪,但这些 ID 不持久化,一重启就丢,35 个压缩块全部作废,559K 字符的摘要变成废纸,3175 条原始消息全部涌回上下文,GLM-5.1 直接返回 model_context_window_exceeded

我从头重写了核心架构,主要改了这些:

1. 独立 Block 架构 — 不再有巨型摘要

DCP 原始设计有个脑残的地方:每次压缩会把旧 block 的摘要内联展开到新 block 中。打个比方,就像你每次整理抽屉,都把之前所有整理记录的完整版塞进新记录里。经过 23 次压缩后,最新 block 的摘要膨胀到 90K 字符 — 整个会话历史的递归摘要。这个巨型摘要无法再压缩(它本身就是摘要),占据了上下文的大部分空间,会话卡在 70% context 无法继续。

ACP 改成独立 Block 架构:每个 block 独立存在,摘要只覆盖自己的范围。多个 active block 在上下文中同时存在。不再自动嵌套,(bN) 引用保留为文本标签。模型需要显式用 bN 作为 boundary 才会消费旧 block 。

2. 压缩块状态机(类似 JVM 分代 GC )

每个压缩块有 young → old 代的概念。新压缩的块是 young generation ,经历多次压缩周期后晋升为 old generation 。Old generation 的摘要会被 GC 自动截断(保留头部 + 尾部引用标记),防止老摘要无限膨胀吃掉上下文。

JVM GC ACP 触发条件
Young Gen 新创建的压缩块 每次压缩产生
Minor GC 合并最近的 young 块 55% 阈值触发
Old Gen 存活超过 N 次压缩周期的块 survivedCount ≥ 5 自动晋升
Major GC 截断 old-gen 块摘要 超过阈值自动执行
Age-based deactivation 超龄块自动停用 age > 15

实测效果:126 个 active blocks ( 63K tokens 死重)→ GC 自动清理到 10 个。

3. 34 个 Bug 修复

fork 以来修了 34 个 bug( 4 CRITICAL ,15 HIGH )。每个都是真实踩到的坑,不是坐着想出来的:

最离谱的几个:

  • 状态不持久化:重启后所有压缩块丢失,几千条原始消息涌回上下文,API 直接返回 model_context_window_exceeded,会话当场暴毙。这是 DCP 最大的坑,我反复踩了 N 次。

  • prune summary 静默丢失:遇到一种边界情况,原始消息被删了但摘要没注入进去 — 也就是数据直接丢了,不是压缩质量不好,是真的没了。

  • 每轮 20-50 秒延迟:DCP 的 Logger 在 debug=false 时仍然执行 new Error() + Error.prepareStackTrace 来获取调用栈,每次 50-100ms 。syncToolCache 对每个 tool call 调一次 logger ,500 个 tool × 100ms = 50 秒。用户以为模型在思考,实际上是 DCP 在那做无用的堆栈追踪。( PS:大概原生 dcp 上下文没这么大过,所以不会复现这个 bug 吧哈哈)

  • 阈值计算错误:DCP 用 inputBudget(= context limit - output limit = 73K )代替 context limit( 204K )算百分比,导致 36% 就触发 CRITICAL WARNING ,模型疯狂压缩一个根本没满的上下文。

  • 压缩完模型罢工:compress 工具返回后,模型说"压缩完成,接下来你想做什么?"然后停下来。正在执行的多步任务被直接中断。

  • 前缀缓存被打破:DCP 把动态数据注入到对话中间的锚定消息里,GLM-5.1 的 cache 是前缀匹配,锚定消息内容每轮变化 → 后面所有内容都变成 cache miss ,命中率从 99% 持续下降到 82%。

  • npm 静默覆盖:opencode 自动安装 npm 原版 DCP ,原版缺少我的 bug fix ,加载会话时清空所有压缩块,1866 条消息未压缩直接发送。(好吧,这个不是 bug ,现在我改名了,再也不会有这个困扰了)

完整的 bug 列表太多了就不贴了,感兴趣的看 GitHub 。

增加了 300 个测试

凸(艹皿艹 ),原来 dcp bug 那么多,总计 15 个测试只有 5 个能跑,让 glm5.1 帮我写了 300 个基准测试,

竞品对比

ACP DCP 原版 Morph opencode 内置
压缩方式 模型自己决定 模型自己决定 外部专用压缩 API 被动全量摘要
额外 LLM 调用 idle 分析可选(费 token ) 需要 API Key 1 次摘要调用
触发时机 45% 建议,55% 必须 可配置 70% 95%(基本已经来不及了)

PS:实际上 glm5.1 本身就是压缩大师了:)。

安装

opencode plugin opencode-acp@latest --global

或者

{
  "plugin": ["opencode-acp@latest"]
}

配置文件 acp.jsonc

{
  "maxContextLimit": "55%",  // 触发压缩的阈值
  "gc": {
    "enabled": true,
    "interval": 300  // 每 5 分钟 GC 检查一次
  }
}

链接


吐槽归吐槽,DCP 原作者的设计思路我是认可的(好吧,这句话是模型给我加的,原作者思路是对的,只不过并没有发挥到登峰造极) — 让模型自己决定压缩,而不是搞一堆规则和外部 API 。只是在工程实现上踩了太多坑,我花了几周把这些坑都填上了。

如果你也在用 opencode 做大项目,试试看。 几周 session 不用重开。

遇到 bug 就提 github 吧,我自己高频用,应该还会发现很多 bug 。你发现了在 issue 说,直接提 pr 即可。