想把 macpro 卖了换成 mac air 有无过来人分享一下? 现在每天通勤背着太累了,我也用不到那么多性能,纯 DevOps 现在用的 m3pro
想把 macpro 卖了换成 mac air 有无过来人分享一下? 现在每天通勤背着太累了,我也用不到那么多性能,纯 DevOps 现在用的 m3pro
想把 macpro 卖了换成 mac air 有无过来人分享一下? 现在每天通勤背着太累了,我也用不到那么多性能,纯 DevOps 现在用的 m3pro
想把 macpro 卖了换成 mac air 有无过来人分享一下? 现在每天通勤背着太累了,我也用不到那么多性能,纯 DevOps 现在用的 m3pro
想把 macpro 卖了换成 mac air 有无过来人分享一下? 现在每天通勤背着太累了,我也用不到那么多性能,纯 DevOps 现在用的 m3pro
想把 macpro 卖了换成 mac air 有无过来人分享一下? 现在每天通勤背着太累了,我也用不到那么多性能,纯 DevOps 现在用的 m3pro
本帖使用社区开源推广,符合推广要求。我申明并遵循社区要求的以下内容: 我的帖子已经打上 开源推广 标签: 是 我的开源项目完整开源,无未开源部分: 是 我的开源项目已链接认可 LINUX DO 社区: 是 我帖子内的项目介绍,AI生成、润色内容部分已截图发出: 是 以上选择我承诺是永久有效的,接受社区和佬友监督: 是 以下为项目介绍正文内容,AI生成、润色内容已使用截图方式发出 github.com GitHub - ApliNi/IpacPanel: 一个轻量好用且专业的终端程序管理面板 一个轻量好用且专业的终端程序管理面板 历时 4 个月开发的最新力作, 终端程序管理面板. 对于单台主机管理大量终端程序, 苦于找不到一个合适好用的面板, 于是开发了这个软件. 它与 MCSManager 类似, 但在使用体验和性能上做了大量改进. 已在自己的生产服务器上测试了两个月的时间, 运行稳定, 达到预期. 原生开发, 无前后端框架, 轻量稳定, 操作流畅, 没有圆角. 支持不停机更新, 内置 vscode 同款文本编辑器和中文等宽字体. 目前正在 windows 和 linux 平台积极维护. 欢迎提出建议和需求 (。・̀ᴗ-)✧ 3 个帖子 - 2 位参与者 阅读完整话题
基础准备 1、本地安装好ClaudeCode。 2、idea安装好AI Assistant(或者使用高版本的idea,自带AI Assistant)。 环境配置 1、在 C:\Users\【你的用户名】\.claude\settings.json添加如下配置(env配置根据自己选择的中转站来配置),推荐使用ccswitch更加方便。 { "hasCompletedOnboarding": true, "env": { "ANTHROPIC_BASE_URL": "https://***", "ANTHROPIC_AUTH_TOKEN": "sk-cbfX7poXE5mjLl**************", "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1" } } 2、idea添加ACP配置 点击AI Assistant对话框右上角的option按钮(三个竖直的点) 选择Add customer Agent,进入acp.json配置界面 添加以下acp.json配置; 重启IDEA后生效; { "default_mcp_settings":{}, "agent_servers": { "Claude Code Local": { "command": "npx.cmd", "args": [ "@agentclientprotocol/claude-agent-acp" ], "env": { "ACP_PERMISSION_MODE": "bypassPermissions" }, "use_idea_mcp": true, "use_custom_mcp": true } } } 3、切换到Claude Code Local,即可使用本地Claude Code配置,在idea的AI Assistant实现vibe coding。 1 个帖子 - 1 位参与者 阅读完整话题
大家都知道的,claude code 2.1.156版本有 “system”的问题。cli我通过回退版本解决了,但是zed里面的这个直接更新到最新的版本了,也开始报这个问题 7 个帖子 - 3 位参与者 阅读完整话题
ricky@archlinux ~> sudo dmesg | grep -i i2c [sudo] password for ricky: [ 0.211745] ACPI BIOS Error (bug): Could not resolve symbol [_SB.PC00.I2C3.TPD0], AE_NOT_FOUND (20251212/dswload2-162) [ 0.211891] ACPI BIOS Error (bug): Could not resolve symbol [_SB.PC00.I2C4.TPL1], AE_NOT_FOUND (20251212/dswload2-162) [ 0.212028] ACPI BIOS Error (bug): Could not resolve symbol [_SB.PC00.I2C5.TPL1], AE_NOT_FOUND (20251212/dswload2-162) [ 0.237528] ACPI: _SB_.PC00.I2C3.PXTC: New power resource [ 0.238649] ACPI: _SB_.PC00.I2C4.PTPL: New power resource [ 0.239054] ACPI: _SB_.PC00.I2C5.PTPL: New power resource [ 1.207616] Modules linked in: i915(+) i2c_algo_bit drm_buddy ttm nvme intel_gtt nvme_core intel_lpss_pci serio_raw video nvme_keyring spi_intel_pci drm_display_helper nvme_auth intel_lpss hkdf spi_intel idma64 wmi cec intel_vsec [ 3.815849] i2c_dev: i2c /dev entries driver [ 4.195336] input: FTSC1000:00 2808:5662 as /devices/pci0000:00/0000:00:15.0/i2c_designware.0/i2c-0/i2c-FTSC1000:00/0018:2808:5662.0008/input/input18 [ 4.195401] input: FTSC1000:00 2808:5662 UNKNOWN as /devices/pci0000:00/0000:00:15.0/i2c_designware.0/i2c-0/i2c-FTSC1000:00/0018:2808:5662.0008/input/input20 [ 4.195467] hid-multitouch 0018:2808:5662.0008: input,hidraw7: I2C HID v1.00 Device [FTSC1000:00 2808:5662] on i2c-FTSC1000:00 [ 4.203661] input: TOPS0102:00 35CC:0104 Consumer Control as /devices/pci0000:00/0000:00:15.1/i2c_designware.1/i2c-1/i2c-TOPS0102:00/0018:35CC:0104.0009/input/input22 [ 4.205224] input: TOPS0102:00 35CC:0104 Touchpad as /devices/pci0000:00/0000:00:15.1/i2c_designware.1/i2c-1i2c-TOPS0102:00/0018:35CC:0104.0009/input/input23 [ 4.205278] hid-multitouch 0018:35CC:0104.0009: input,hidraw8: I2C HID v1.00 Mouse [TOPS0102:00 35CC:0104] on i2c-TOPS0102:00 libinput list-devices 识别为两个设备 Device: TOPS0102:00 35CC:0104 Consumer Control Kernel: /dev/input/event12 Id: i2c:35cc:0104 Group: 5 Seat: seat0, default Capabilities: keyboard pointer Tap-to-click: n/a Tap-and-drag: n/a Tap button map: n/a Tap drag lock: n/a Left-handed: n/a Nat.scrolling: disabled Middle emulation: n/a Calibration: n/a Scroll methods: none Scroll button: n/a Scroll button lock: n/a Click methods: none Clickfinger button map: n/a Disable-w-typing: n/a Disable-w-trackpointing: n/a Accel profiles: n/a Rotation: 0.0 Area rectangle: n/a Device: TOPS0102:00 35CC:0104 Touchpad Kernel: /dev/input/event13 Id: i2c:35cc:0104 Group: 5 Seat: seat0, default Size: 130x92mm Capabilities: pointer gesture Tap-to-click: disabled Tap-and-drag: enabled Tap button map: left/right/middle Tap drag lock: disabled Left-handed: disabled Nat.scrolling: disabled Middle emulation: disabled Calibration: n/a Scroll methods: *two-finger edge Scroll button: n/a Scroll button lock: n/a Click methods: *button-areas clickfinger Clickfinger button map: left/right/middle Disable-w-typing: enabled Disable-w-trackpointing: enabled Accel profiles: flat *adaptive custom Rotation: n/a Area rectangle: n/a 尝试过修改启动内核参数 i2c_hid.reset_suspended=1 还有 ignore dmi ,都没用 偶尔冷启动能用手势,重启就没了,监听输入设备事件就只有左键触发,没有手势
想在idea中用codex,试了试发现idea的agent里面的codex要登录,自己装了zed的codx acp,发现配置是跟着系统里面的走的,想在idea里面可以设置url和key,这样可以很容易的分发给别人,类似.codebuddy配置那样。 看了看codex-acp的仓库也没有详细的文档,就研究了下怎么配置。 { "default_mcp_settings": { "use_idea_mcp": true, "use_custom_mcp": true }, "agent_servers": { "codex-acp-custom": { "command": "npx.cmd", "args": [ "-y", "@zed-industries/codex-acp", "-c", "model_provider='custom'", "-c", "model='gpt-5.3-codex'", "-c", "model_providers.custom.wire_api='responses'", "-c", "model_providers.custom.name='custom'", "-c", "model_providers.custom.base_url='https://xxxxxxxxxxx/v1'", "-c", "model_providers.custom.env_key='OPENAI_API_KEY'" ], "env": { "OPENAI_API_KEY": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } } } } 发现问题的关键是要加上 “-c”, “model_providers.custom.env_key=‘OPENAI_API_KEY’” 然后key配置在env中, 确定是走的 acp.json中,在key中故意多一个字符会显示一个当前中转地址的报错 另外这个agent的acp有时候要关掉重新打开才会重新加载配置 2 个帖子 - 1 位参与者 阅读完整话题
潜水 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 ,他自己决定什么时候调用即可。 重点说明一些基本特性: 每条消息模型都可以压缩,或者解压缩(这很重要) 模型可以把连续 N 条消息压缩成 1 条消息。 模型可以删除消息。 模型可以修改消息。 系统做什么? 在模型启动的时候告诉模型可以压缩 在上下文 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 检查一次 } } 链接 GitHub: https://github.com/ranxianglei/opencode-acp npm: https://www.npmjs.com/package/opencode-acp 吐槽归吐槽,DCP 原作者的设计思路我是认可的(好吧,这句话是模型给我加的,原作者思路是对的,只不过并没有发挥到登峰造极) — 让模型自己决定压缩,而不是搞一堆规则和外部 API 。只是在工程实现上踩了太多坑,我花了几周把这些坑都填上了。 如果你也在用 opencode 做大项目,试试看。 几周 session 不用重开。 遇到 bug 就提 github 吧,我自己高频用,应该还会发现很多 bug 。你发现了在 issue 说,直接提 pr 即可。
潜水 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 ,他自己决定什么时候调用即可。 重点说明一些基本特性: 每条消息模型都可以压缩,或者解压缩(这很重要) 模型可以把连续 N 条消息压缩成 1 条消息。 模型可以删除消息。 模型可以修改消息。 系统做什么? 在模型启动的时候告诉模型可以压缩 在上下文 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 检查一次 } } 链接 GitHub: https://github.com/ranxianglei/opencode-acp npm: https://www.npmjs.com/package/opencode-acp 吐槽归吐槽,DCP 原作者的设计思路我是认可的(好吧,这句话是模型给我加的,原作者思路是对的,只不过并没有发挥到登峰造极) — 让模型自己决定压缩,而不是搞一堆规则和外部 API 。只是在工程实现上踩了太多坑,我花了几周把这些坑都填上了。 如果你也在用 opencode 做大项目,试试看。 几周 session 不用重开。 遇到 bug 就提 github 吧,我自己高频用,应该还会发现很多 bug 。你发现了在 issue 说,直接提 pr 即可。
潜水 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 ,他自己决定什么时候调用即可。 重点说明一些基本特性: 每条消息模型都可以压缩,或者解压缩(这很重要) 模型可以把连续 N 条消息压缩成 1 条消息。 模型可以删除消息。 模型可以修改消息。 系统做什么? 在模型启动的时候告诉模型可以压缩 在上下文 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 检查一次 } } 链接 GitHub: https://github.com/ranxianglei/opencode-acp npm: https://www.npmjs.com/package/opencode-acp 吐槽归吐槽,DCP 原作者的设计思路我是认可的(好吧,这句话是模型给我加的,原作者思路是对的,只不过并没有发挥到登峰造极) — 让模型自己决定压缩,而不是搞一堆规则和外部 API 。只是在工程实现上踩了太多坑,我花了几周把这些坑都填上了。 如果你也在用 opencode 做大项目,试试看。 几周 session 不用重开。 遇到 bug 就提 github 吧,我自己高频用,应该还会发现很多 bug 。你发现了在 issue 说,直接提 pr 即可。
潜水 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 ,他自己决定什么时候调用即可。 重点说明一些基本特性: 每条消息模型都可以压缩,或者解压缩(这很重要) 模型可以把连续 N 条消息压缩成 1 条消息。 模型可以删除消息。 模型可以修改消息。 系统做什么? 在模型启动的时候告诉模型可以压缩 在上下文 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 检查一次 } } 链接 GitHub: https://github.com/ranxianglei/opencode-acp npm: https://www.npmjs.com/package/opencode-acp 吐槽归吐槽,DCP 原作者的设计思路我是认可的(好吧,这句话是模型给我加的,原作者思路是对的,只不过并没有发挥到登峰造极) — 让模型自己决定压缩,而不是搞一堆规则和外部 API 。只是在工程实现上踩了太多坑,我花了几周把这些坑都填上了。 如果你也在用 opencode 做大项目,试试看。 几周 session 不用重开。 遇到 bug 就提 github 吧,我自己高频用,应该还会发现很多 bug 。你发现了在 issue 说,直接提 pr 即可。
潜水 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 ,他自己决定什么时候调用即可。 重点说明一些基本特性: 每条消息模型都可以压缩,或者解压缩(这很重要) 模型可以把连续 N 条消息压缩成 1 条消息。 模型可以删除消息。 模型可以修改消息。 系统做什么? 在模型启动的时候告诉模型可以压缩 在上下文 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 检查一次 } } 链接 GitHub: https://github.com/ranxianglei/opencode-acp npm: https://www.npmjs.com/package/opencode-acp 吐槽归吐槽,DCP 原作者的设计思路我是认可的(好吧,这句话是模型给我加的,原作者思路是对的,只不过并没有发挥到登峰造极) — 让模型自己决定压缩,而不是搞一堆规则和外部 API 。只是在工程实现上踩了太多坑,我花了几周把这些坑都填上了。 如果你也在用 opencode 做大项目,试试看。 几周 session 不用重开。 遇到 bug 就提 github 吧,我自己高频用,应该还会发现很多 bug 。你发现了在 issue 说,直接提 pr 即可。
潜水 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 ,他自己决定什么时候调用即可。 重点说明一些基本特性: 每条消息模型都可以压缩,或者解压缩(这很重要) 模型可以把连续 N 条消息压缩成 1 条消息。 模型可以删除消息。 模型可以修改消息。 系统做什么? 在模型启动的时候告诉模型可以压缩 在上下文 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 检查一次 } } 链接 GitHub: https://github.com/ranxianglei/opencode-acp npm: https://www.npmjs.com/package/opencode-acp 吐槽归吐槽,DCP 原作者的设计思路我是认可的(好吧,这句话是模型给我加的,原作者思路是对的,只不过并没有发挥到登峰造极) — 让模型自己决定压缩,而不是搞一堆规则和外部 API 。只是在工程实现上踩了太多坑,我花了几周把这些坑都填上了。 如果你也在用 opencode 做大项目,试试看。 几周 session 不用重开。 遇到 bug 就提 github 吧,我自己高频用,应该还会发现很多 bug 。你发现了在 issue 说,直接提 pr 即可。
潜水 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 ,他自己决定什么时候调用即可。 重点说明一些基本特性: 每条消息模型都可以压缩,或者解压缩(这很重要) 模型可以把连续 N 条消息压缩成 1 条消息。 模型可以删除消息。 模型可以修改消息。 系统做什么? 在模型启动的时候告诉模型可以压缩 在上下文 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 检查一次 } } 链接 GitHub: https://github.com/ranxianglei/opencode-acp npm: https://www.npmjs.com/package/opencode-acp 吐槽归吐槽,DCP 原作者的设计思路我是认可的(好吧,这句话是模型给我加的,原作者思路是对的,只不过并没有发挥到登峰造极) — 让模型自己决定压缩,而不是搞一堆规则和外部 API 。只是在工程实现上踩了太多坑,我花了几周把这些坑都填上了。 如果你也在用 opencode 做大项目,试试看。 几周 session 不用重开。 遇到 bug 就提 github 吧,我自己高频用,应该还会发现很多 bug 。你发现了在 issue 说,直接提 pr 即可。
潜水 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 ,他自己决定什么时候调用即可。 重点说明一些基本特性: 每条消息模型都可以压缩,或者解压缩(这很重要) 模型可以把连续 N 条消息压缩成 1 条消息。 模型可以删除消息。 模型可以修改消息。 系统做什么? 在模型启动的时候告诉模型可以压缩 在上下文 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 检查一次 } } 链接 GitHub: https://github.com/ranxianglei/opencode-acp npm: https://www.npmjs.com/package/opencode-acp 吐槽归吐槽,DCP 原作者的设计思路我是认可的(好吧,这句话是模型给我加的,原作者思路是对的,只不过并没有发挥到登峰造极) — 让模型自己决定压缩,而不是搞一堆规则和外部 API 。只是在工程实现上踩了太多坑,我花了几周把这些坑都填上了。 如果你也在用 opencode 做大项目,试试看。 几周 session 不用重开。 遇到 bug 就提 github 吧,我自己高频用,应该还会发现很多 bug 。你发现了在 issue 说,直接提 pr 即可。
潜水 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 ,他自己决定什么时候调用即可。 重点说明一些基本特性: 每条消息模型都可以压缩,或者解压缩(这很重要) 模型可以把连续 N 条消息压缩成 1 条消息。 模型可以删除消息。 模型可以修改消息。 系统做什么? 在模型启动的时候告诉模型可以压缩 在上下文 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 检查一次 } } 链接 GitHub: https://github.com/ranxianglei/opencode-acp npm: https://www.npmjs.com/package/opencode-acp 吐槽归吐槽,DCP 原作者的设计思路我是认可的(好吧,这句话是模型给我加的,原作者思路是对的,只不过并没有发挥到登峰造极) — 让模型自己决定压缩,而不是搞一堆规则和外部 API 。只是在工程实现上踩了太多坑,我花了几周把这些坑都填上了。 如果你也在用 opencode 做大项目,试试看。 几周 session 不用重开。 遇到 bug 就提 github 吧,我自己高频用,应该还会发现很多 bug 。你发现了在 issue 说,直接提 pr 即可。