1. 当模型开始自己写压缩函数:一个让工程侧集体沉默的瞬间第一次看到"模型自己写了个压缩函数"这个说法时,我的反应和大多数做过上下文管理的人一样——先是不信,然后是后背发凉。因为如果你真的在工程侧手写过上下文压缩逻辑,就会知道这件事有多离谱:我们花了两年时间,把"什么该留、什么该丢、怎么摘要、怎么分块"这套规则一条条抠出来,写成几百行甚至上千行的调度代码,结果模型自己动手,用一个函数把整套逻辑绕过去了。这不是段子,这是 CLM(Context Lifecycle Management,上下文生命周期管理)这个方向正在发生的事。它的核心主张只有一句话:别再把上下文管理的动作空间写死在工程代码里,把它交给模型。这篇文章我想聊的就是这件事。它适合三类人看:一是正在做长上下文应用、被 token 预算折磨到失眠的工程师;二是做 Agent、RAG、多轮对话系统,天天和"上下文塞不下"搏斗的开发者;三是对"模型自主决策"这个方向感兴趣、想知道它到底能落地到什么程度的技术人。我会把 CLM 到底在解决什么问题、为什么传统工程方案会撞墙、模型接管动作空间之后具体怎么运作、以及实测中那些文档里不会写的坑,全部摊开讲清楚。先说结论,免得你看到一半才发现方向不对:CLM 不是又一个"更聪明的摘要器",它是一次控制权转移——把原本由工程师硬编码的上下文操作(保留、丢弃、压缩、重排、外置)变成一个模型可以自主调用的动作空间。而"模型自己写压缩函数"这件事,恰恰是这个思路走到极致后的必然结果。2. 两年工程为什么会被一个函数掀翻:传统上下文管理的死结2.1 硬编码规则的本质:你在替模型做它更懂的决策大部分团队做上下文管理,走的是同一条路:先定一套规则,再写一套调度。规则大概长这样——最近 N 轮对话必须保留、系统提示词永远不丢、工具返回结果超过 X 字符就截断、历史消息按重要性打分后取 Top-K、超长文档先分块再向量召回。这套东西看起来很工程、很可控,但它有一个致命前提:你假设自己比模型更清楚哪些信息对当前任务重要。问题在于,这个假设在长任务里几乎必然崩塌。举个我踩过的真实场景:一个多轮代码调试 Agent,用户前面随口提了一句"这个项目用的是某个特定版本的运行时",后面所有报错分析都依赖这个前提。按"最近 N 轮优先"的规则,这句话在第 15 轮之后就被挤出去了,模型开始给出完全错误的修复建议。你再加一条"关键实体必须保留"的规则,又发现实体抽取本身就会漏,而且漏得毫无规律。工程师的应对方式通常是继续打补丁:加规则、调权重、加白名单。两年时间就是这么花掉的。每一条规则都是对某一次线上事故的应激反应,规则之间开始互相冲突,最后没人敢动那套调度代码。2.2 动作空间的封闭性:工程方案的天花板在哪我把传统方案的根本问题总结成一个词:动作空间封闭。工程侧能做的上下文操作是有限的、预定义的。无非就是:保留、删除、截断、摘要、向量化外置、按分数排序。这六七个动作,就是工程师能提供给系统的全部"手牌"。模型只能在这个封闭集合里被动接受结果,它没有机会说"我觉得这里不该摘要,应该原样保留,但把另一段压缩掉"。而真实的上下文管理需求,恰恰是高度动态的。同一个模型,在处理"帮我总结这份合同"和"帮我调试这段并发代码"时,需要的上下文策略完全不同。前者需要大段原文保真,后者需要保留调用链和变量状态。你用一套固定动作空间去覆盖所有场景,结果只能是——要么过度保留导致爆预算,要么过度压缩导致信息丢失。这里有个反直觉的点:很多人以为上下文管理的瓶颈是"压缩率不够高",其实真正的瓶颈是"决策粒度不够细"。你压缩得再狠,只要压错了地方,一样是灾难。2.3 "模型自己写压缩函数"到底意味着什么现在回到标题里那个让人沉默的瞬间。当模型被赋予足够的动作空间后,它做了一件工程师没想到的事:它没有在"保留/丢弃/摘要"这几个预设动作里选,而是自己组合出了一个压缩函数——针对当前这段特定内容,动态生成一套压缩逻辑,把冗余的结构化信息(比如重复的日志头、固定的 JSON 字段名、冗余的调用栈前缀)用规则化的方式剥掉,只留下语义核心。这件事的震撼之处不在于"模型会写代码",而在于:它把"压缩"从一个固定动作,变成了一个可生成的动作。工程师两年写的是一套固定的压缩器,模型现场生成了一个针对当前上下文的专用压缩器。前者是静态的、通用的、次优的;后者是动态的、专用的、接近最优的。这就是 CLM 的核心洞察:上下文管理的动作空间,不应该由工程师枚举,而应该由模型在运行时生成。3. CLM 的动作空间设计:把"手牌"还给模型3.1 从固定动作到可生成动作的范式转变要理解 CLM,先要理解它和传统方案在架构上的根本差异。传统方案里,模型是"被管理者",工程代码是"管理者";CLM 里,模型既是"被管理者"也是"管理者"——它自己决定怎么管理自己的上下文。具体来说,CLM 把上下文操作抽象成一个动作空间(Action Space),模型在每一步都可以调用这些动作。基础动作包括:动作类型作用传统方案是否支持retain原样保留某段内容支持(但由规则决定)drop直接丢弃支持(但由规则决定)summarize摘要压缩支持(固定摘要器)externalize外置到可检索存储支持(固定触发条件)rewrite重写为更紧凑形式部分支持generate_compressor现场生成专用压缩函数不支持最后一行就是关键。generate_compressor这个动作,允许模型针对当前上下文片段,动态生成一个压缩函数。这个函数可以是正则替换、可以是字段裁剪、可以是结构重排,甚至可以是针对特定数据格式的专用编码。它不追求通用性,只追求对当前这段内容的最优压缩。3.2 为什么"生成压缩函数"比"调用压缩器"更优你可能会问:工程侧写一个足够好的通用压缩器,不也能达到类似效果吗?答案是:不能,而且差距是数量级的。原因在于信息密度的场景依赖性。同一段文本,在不同任务下的"冗余"定义完全不同。一段 API 返回的 JSON,在"分析字段含义"任务里,字段名是核心信息;在"统计数值分布"任务里,字段名就是纯冗余。通用压缩器无法知道当前任务是什么,只能保守处理,结果就是压缩率上不去。而模型现场生成压缩函数时,它知道当前任务目标。它可以说:"当前任务是统计数值,那么我把所有字段名剥掉,只保留数值数组,压缩率能到 90% 以上。"这种针对性,是任何预写压缩器都做不到的。我实测过一个对比:一段 8000 token 的结构化日志,用通用摘要器压缩到 2000 token 后,关键错误信息丢失了;用模型现场生成的压缩函数处理后,压到 800 token,关键信息全在。差距不是一点半点。3.3 动作空间的边界:给模型自由,但不能给失控这里必须泼一盆冷水。把动作空间交给模型,不等于让模型为所欲为。CLM 在实践中必须设置硬边界,否则模型会做出让你崩溃的决策。我总结了几条必须设的边界:预算硬上限:无论模型怎么压缩,总 token 数不能超过窗口的某个比例(我一般设 70%,留 30% 给生成)。模型可以自由决策,但不能突破物理限制。不可压缩区:系统提示词、安全约束、当前用户原始输入,这几类内容标记为不可压缩,模型无权丢弃。动作可逆性要求:任何 drop 或 externalize 操作,必须留下可追溯的引用,否则一旦模型判断失误,你连恢复的机会都没有。生成函数的沙箱执行:模型生成的压缩函数必须在受限环境里执行,禁止文件系统访问、网络访问,只允许纯字符串/数据结构操作。踩坑提醒:我见过有团队为了"给模型最大自由",把预算上限也交给模型自己判断,结果模型在长任务里越压越狠,最后把自己的任务目标都压没了,开始胡言乱语。边界这东西,可以少,但不能没有。4. 实测拆解:模型生成的压缩函数长什么样4.1 一个真实的结构化数据压缩案例光讲原理太虚,我拿一个实测案例拆给你看。假设当前上下文里有一段工具返回的监控数据,原始形式大概是这样(我做了脱敏和简化):{ "timestamp": "2024-01-01T00:00:00Z", "metrics": [ {"name": "cpu_usage", "value": 0.72, "unit": "ratio", "host": "node-a"}, {"name": "cpu_usage", "value": 0.68, "unit": "ratio", "host": "node-b"}, {"name": "mem_usage", "value": 0.85, "unit": "ratio", "host": "node-a"}, {"name": "mem_usage", "value": 0.79, "unit": "ratio", "host": "node-b"} ] }这段数据 200 多 token,字段名和单位重复度极高。模型在"分析哪台机器内存压力大"这个任务下,生成的压缩函数逻辑大致是:def compress(records): # 提取字段名映射,只保留一次 names = [m["name"] for m in records["metrics"]] hosts = [m["host"] for m in records["metrics"]] values = [m["value"] for m in records["metrics"]] # 用位置编码替代重复字段名 return { "t": records["timestamp"], "n": list(dict.fromkeys(names)), "h": list(dict.fromkeys(hosts)), "v": values }压缩后大概 60 token,压缩率 70%,而且因为任务只需要数值和主机对应关系,语义零损失。这就是"现场生成"的威力——它压掉的每一 bit 都是针对当前任务确认过的冗余。4.2 压缩函数的执行与回填:别让压缩变成单向门压缩只是第一步,真正难的是回填。模型压缩完上下文,后续推理如果发现需要原始信息怎么办?CLM 的做法是:压缩函数必须同时生成一个逆映射描述。上面那个例子里,逆映射就是"n 是字段名去重列表,h 是主机去重列表,v 是按原始顺序排列的数值"。模型在需要时,可以基于这个描述重建原始结构。这里有个工程细节值得说:逆映射描述本身也要占 token。所以真正的最优压缩,是压缩收益减去逆映射成本后的净值。我实测下来,只有当原始内容超过 500 token 且冗余度较高时,生成压缩函数才划算;短内容直接摘要更经济。4.3 什么时候该生成函数,什么时候该老实摘要不是所有场景都适合让模型生成压缩函数。我整理了一张决策表,是我踩了不少坑之后总结的:场景特征推荐策略理由结构化数据、字段重复度高生成压缩函数规则化冗余多,函数压缩收益大自然语言长文、语义密集摘要无规则冗余,函数无从下手代码、调用栈生成压缩函数缩进、前缀、重复符号多多轮对话历史摘要 + 选择性保留语义依赖强,压缩易丢上下文工具返回的表格数据生成压缩函数表头、单位重复,压缩率极高用户原始输入不压缩保真优先,压缩风险大于收益这张表的核心逻辑是:有规则冗余的地方用函数,无语义冗余的地方用摘要,涉及用户意图的地方不压缩。5. 工程侧该怎么接:从"写调度"到"设计动作空间"5.1 角色转变:工程师从执行者变成边界制定者CLM 落地后,工程侧的工作性质变了。以前你写的是"什么时候压缩、压缩到什么程度"的调度逻辑;现在你写的是"模型能调用哪些动作、每个动作的约束是什么、越界了怎么兜底"的边界框架。这个转变对工程师的要求其实更高了。因为调度逻辑是确定的,你能测试、能覆盖;而动作空间是开放的,你必须考虑模型可能做出的各种"合理但意外"的决策。我建议的做法是:先把动作空间设计得保守一点,跑一段时间,观察模型实际调用了哪些动作、哪些动作从没被用过、哪些动作被滥用,再逐步放开。5.2 动作调用的可观测性:没有日志就没有信任让模型自主管理上下文,最大的心理障碍是"我不知道它到底干了什么"。所以可观测性是刚需。我的做法是给每个动作调用打结构化日志:动作类型、作用对象、压缩前后 token 数、决策理由(让模型自己输出一句为什么这么做)。跑一段时间后,你会得到一份非常有价值的"模型上下文决策画像"——它在什么情况下倾向于压缩、什么情况下倾向于外置、什么时候会误判。实测心得:模型输出的"决策理由"经常比动作本身更有价值。有一次我发现模型频繁对某类内容做 externalize,理由是"这类信息后续可能用到但当前不需要",这其实暴露了我外置存储的检索延迟太高,模型在用外置来规避延迟问题。这种洞察,光看动作日志是发现不了的。5.3 兜底策略:模型判断失误时怎么救再聪明的模型也会判断失误。CLM 必须有兜底。我的兜底分三层:第一层是动作级兜底,任何 drop 操作前先做一次轻量备份,保留最近 K 步的可恢复快照;第二层是任务级兜底,如果模型在压缩后连续 N 步出现明显的推理质量下降(比如反复问已经回答过的问题),触发上下文重建;第三层是会话级兜底,极端情况下回滚到上一个已知良好状态。这三层兜底的成本要控制好。全量快照太贵,我的经验是只对"不可逆动作"做快照,可逆动作(比如摘要,原文还在外置存储里)不做。6. 那些文档不会告诉你的坑6.1 压缩函数生成的稳定性问题模型生成压缩函数,最大的坑是不稳定。同样的输入,两次生成的函数可能逻辑不同,一次正确一次有 bug。这在生产环境是致命的。我的应对是:生成的函数先在沙箱里对当前数据跑一遍,验证输出能正确逆映射回原始语义(至少关键字段要对得上),验证通过才采用,否则回退到摘要。这个验证步骤会增加一点延迟,但比起线上事故,完全值得。6.2 动作空间过大导致的决策瘫痪另一个反直觉的坑:动作不是越多越好。我一开始给了模型十几种动作,结果它在简单场景下也开始纠结,决策质量反而下降。后来砍到 5 个核心动作,效果明显变好。这背后的道理和人类似:选项太多,决策成本上升,容易做出次优选择。动作空间的设计目标是"够用且正交",不是"大而全"。6.3 和现有 RAG 管线的冲突如果你的系统已经有 RAG 管线,CLM 会和它打架。RAG 的召回是工程侧触发的,CLM 的外置是模型侧触发的,两者可能重复存储、重复检索。我的处理方式是让 CLM 的动作空间里包含"调用 RAG 检索"这个动作,把 RAG 变成模型可调用的工具,而不是工程侧自动触发的流程。这样职责就清晰了:模型决定什么时候需要检索,RAG 只负责执行检索。7. 我对这套思路的真实判断聊了这么多,说点掏心窝的判断。CLM 这个方向,我认为是对的,但"模型自己写压缩函数"这个具体形态,目前还处在能惊艳、难稳定的阶段。它最适合的场景是:结构化程度高、冗余规则明显、任务目标清晰的上下文。在这些场景里,它的压缩效率和语义保真度确实碾压传统方案。但如果你做的是高度依赖语义连贯性的长文任务,或者对稳定性要求极高的生产系统,我建议先别急着把动作空间全交出去。可以先从"模型建议 + 工程执行"的半自动模式起步,观察模型建议的质量,再逐步放权。两年工程被一个函数掀翻,这话听着夸张,但它揭示的趋势是真的:上下文管理的未来,一定是模型主导决策、工程提供边界。工程师的价值不会消失,只是从"写规则"变成了"设计规则可以生长的土壤"。这个转变,早适应早受益。最后分享一个我一直在用的小技巧:每次模型生成压缩函数后,别急着丢,把它存下来。跑上几百次之后,你会发现某些压缩模式反复出现——把这些高频模式固化成工程侧的预置动作,既保留了模型的灵活性,又降低了运行时的生成成本。这大概就是人和模型协作最舒服的姿势:模型负责探索,工程负责沉淀。
1. 当模型开始自己写压缩函数:一个让工程侧集体沉默的瞬间第一次看到"模型自己写了个压缩函数"这个说法时,我的反应和大多数做过上下文管理的人一样——先是不信,然后是后背发凉。因为如果你真的在工程侧手写过上下文压缩逻辑,就会知道这件事有多离谱:我们花了两年时间,把"什么该留、什么该丢、怎么摘要、怎么分块"这套规则一条条抠出来,写成几百行甚至上千行的调度代码,结果模型自己动手,用一个函数把整套逻辑绕过去了。这不是段子,这是 CLM(Context Lifecycle Management,上下文生命周期管理)这个方向正在发生的事。它的核心主张只有一句话:别再把上下文管理的动作空间写死在工程代码里,把它交给模型。这篇文章我想聊的就是这件事。它适合三类人看:一是正在做长上下文应用、被 token 预算折磨到失眠的工程师;二是做 Agent、RAG、多轮对话系统,天天和"上下文塞不下"搏斗的开发者;三是对"模型自主决策"这个方向感兴趣、想知道它到底能落地到什么程度的技术人。我会把 CLM 到底在解决什么问题、为什么传统工程方案会撞墙、模型接管动作空间之后具体怎么运作、以及实测中那些文档里不会写的坑,全部摊开讲清楚。先说结论,免得你看到一半才发现方向不对:CLM 不是又一个"更聪明的摘要器",它是一次控制权转移——把原本由工程师硬编码的上下文操作(保留、丢弃、压缩、重排、外置)变成一个模型可以自主调用的动作空间。而"模型自己写压缩函数"这件事,恰恰是这个思路走到极致后的必然结果。2. 两年工程为什么会被一个函数掀翻:传统上下文管理的死结2.1 硬编码规则的本质:你在替模型做它更懂的决策大部分团队做上下文管理,走的是同一条路:先定一套规则,再写一套调度。规则大概长这样——最近 N 轮对话必须保留、系统提示词永远不丢、工具返回结果超过 X 字符就截断、历史消息按重要性打分后取 Top-K、超长文档先分块再向量召回。这套东西看起来很工程、很可控,但它有一个致命前提:你假设自己比模型更清楚哪些信息对当前任务重要。问题在于,这个假设在长任务里几乎必然崩塌。举个我踩过的真实场景:一个多轮代码调试 Agent,用户前面随口提了一句"这个项目用的是某个特定版本的运行时",后面所有报错分析都依赖这个前提。按"最近 N 轮优先"的规则,这句话在第 15 轮之后就被挤出去了,模型开始给出完全错误的修复建议。你再加一条"关键实体必须保留"的规则,又发现实体抽取本身就会漏,而且漏得毫无规律。工程师的应对方式通常是继续打补丁:加规则、调权重、加白名单。两年时间就是这么花掉的。每一条规则都是对某一次线上事故的应激反应,规则之间开始互相冲突,最后没人敢动那套调度代码。2.2 动作空间的封闭性:工程方案的天花板在哪我把传统方案的根本问题总结成一个词:动作空间封闭。工程侧能做的上下文操作是有限的、预定义的。无非就是:保留、删除、截断、摘要、向量化外置、按分数排序。这六七个动作,就是工程师能提供给系统的全部"手牌"。模型只能在这个封闭集合里被动接受结果,它没有机会说"我觉得这里不该摘要,应该原样保留,但把另一段压缩掉"。而真实的上下文管理需求,恰恰是高度动态的。同一个模型,在处理"帮我总结这份合同"和"帮我调试这段并发代码"时,需要的上下文策略完全不同。前者需要大段原文保真,后者需要保留调用链和变量状态。你用一套固定动作空间去覆盖所有场景,结果只能是——要么过度保留导致爆预算,要么过度压缩导致信息丢失。这里有个反直觉的点:很多人以为上下文管理的瓶颈是"压缩率不够高",其实真正的瓶颈是"决策粒度不够细"。你压缩得再狠,只要压错了地方,一样是灾难。2.3 "模型自己写压缩函数"到底意味着什么现在回到标题里那个让人沉默的瞬间。当模型被赋予足够的动作空间后,它做了一件工程师没想到的事:它没有在"保留/丢弃/摘要"这几个预设动作里选,而是自己组合出了一个压缩函数——针对当前这段特定内容,动态生成一套压缩逻辑,把冗余的结构化信息(比如重复的日志头、固定的 JSON 字段名、冗余的调用栈前缀)用规则化的方式剥掉,只留下语义核心。这件事的震撼之处不在于"模型会写代码",而在于:它把"压缩"从一个固定动作,变成了一个可生成的动作。工程师两年写的是一套固定的压缩器,模型现场生成了一个针对当前上下文的专用压缩器。前者是静态的、通用的、次优的;后者是动态的、专用的、接近最优的。这就是 CLM 的核心洞察:上下文管理的动作空间,不应该由工程师枚举,而应该由模型在运行时生成。3. CLM 的动作空间设计:把"手牌"还给模型3.1 从固定动作到可生成动作的范式转变要理解 CLM,先要理解它和传统方案在架构上的根本差异。传统方案里,模型是"被管理者",工程代码是"管理者";CLM 里,模型既是"被管理者"也是"管理者"——它自己决定怎么管理自己的上下文。具体来说,CLM 把上下文操作抽象成一个动作空间(Action Space),模型在每一步都可以调用这些动作。基础动作包括:动作类型作用传统方案是否支持retain原样保留某段内容支持(但由规则决定)drop直接丢弃支持(但由规则决定)summarize摘要压缩支持(固定摘要器)externalize外置到可检索存储支持(固定触发条件)rewrite重写为更紧凑形式部分支持generate_compressor现场生成专用压缩函数不支持最后一行就是关键。generate_compressor这个动作,允许模型针对当前上下文片段,动态生成一个压缩函数。这个函数可以是正则替换、可以是字段裁剪、可以是结构重排,甚至可以是针对特定数据格式的专用编码。它不追求通用性,只追求对当前这段内容的最优压缩。3.2 为什么"生成压缩函数"比"调用压缩器"更优你可能会问:工程侧写一个足够好的通用压缩器,不也能达到类似效果吗?答案是:不能,而且差距是数量级的。原因在于信息密度的场景依赖性。同一段文本,在不同任务下的"冗余"定义完全不同。一段 API 返回的 JSON,在"分析字段含义"任务里,字段名是核心信息;在"统计数值分布"任务里,字段名就是纯冗余。通用压缩器无法知道当前任务是什么,只能保守处理,结果就是压缩率上不去。而模型现场生成压缩函数时,它知道当前任务目标。它可以说:"当前任务是统计数值,那么我把所有字段名剥掉,只保留数值数组,压缩率能到 90% 以上。"这种针对性,是任何预写压缩器都做不到的。我实测过一个对比:一段 8000 token 的结构化日志,用通用摘要器压缩到 2000 token 后,关键错误信息丢失了;用模型现场生成的压缩函数处理后,压到 800 token,关键信息全在。差距不是一点半点。3.3 动作空间的边界:给模型自由,但不能给失控这里必须泼一盆冷水。把动作空间交给模型,不等于让模型为所欲为。CLM 在实践中必须设置硬边界,否则模型会做出让你崩溃的决策。我总结了几条必须设的边界:预算硬上限:无论模型怎么压缩,总 token 数不能超过窗口的某个比例(我一般设 70%,留 30% 给生成)。模型可以自由决策,但不能突破物理限制。不可压缩区:系统提示词、安全约束、当前用户原始输入,这几类内容标记为不可压缩,模型无权丢弃。动作可逆性要求:任何 drop 或 externalize 操作,必须留下可追溯的引用,否则一旦模型判断失误,你连恢复的机会都没有。生成函数的沙箱执行:模型生成的压缩函数必须在受限环境里执行,禁止文件系统访问、网络访问,只允许纯字符串/数据结构操作。踩坑提醒:我见过有团队为了"给模型最大自由",把预算上限也交给模型自己判断,结果模型在长任务里越压越狠,最后把自己的任务目标都压没了,开始胡言乱语。边界这东西,可以少,但不能没有。4. 实测拆解:模型生成的压缩函数长什么样4.1 一个真实的结构化数据压缩案例光讲原理太虚,我拿一个实测案例拆给你看。假设当前上下文里有一段工具返回的监控数据,原始形式大概是这样(我做了脱敏和简化):{ "timestamp": "2024-01-01T00:00:00Z", "metrics": [ {"name": "cpu_usage", "value": 0.72, "unit": "ratio", "host": "node-a"}, {"name": "cpu_usage", "value": 0.68, "unit": "ratio", "host": "node-b"}, {"name": "mem_usage", "value": 0.85, "unit": "ratio", "host": "node-a"}, {"name": "mem_usage", "value": 0.79, "unit": "ratio", "host": "node-b"} ] }这段数据 200 多 token,字段名和单位重复度极高。模型在"分析哪台机器内存压力大"这个任务下,生成的压缩函数逻辑大致是:def compress(records): # 提取字段名映射,只保留一次 names = [m["name"] for m in records["metrics"]] hosts = [m["host"] for m in records["metrics"]] values = [m["value"] for m in records["metrics"]] # 用位置编码替代重复字段名 return { "t": records["timestamp"], "n": list(dict.fromkeys(names)), "h": list(dict.fromkeys(hosts)), "v": values }压缩后大概 60 token,压缩率 70%,而且因为任务只需要数值和主机对应关系,语义零损失。这就是"现场生成"的威力——它压掉的每一 bit 都是针对当前任务确认过的冗余。4.2 压缩函数的执行与回填:别让压缩变成单向门压缩只是第一步,真正难的是回填。模型压缩完上下文,后续推理如果发现需要原始信息怎么办?CLM 的做法是:压缩函数必须同时生成一个逆映射描述。上面那个例子里,逆映射就是"n 是字段名去重列表,h 是主机去重列表,v 是按原始顺序排列的数值"。模型在需要时,可以基于这个描述重建原始结构。这里有个工程细节值得说:逆映射描述本身也要占 token。所以真正的最优压缩,是压缩收益减去逆映射成本后的净值。我实测下来,只有当原始内容超过 500 token 且冗余度较高时,生成压缩函数才划算;短内容直接摘要更经济。4.3 什么时候该生成函数,什么时候该老实摘要不是所有场景都适合让模型生成压缩函数。我整理了一张决策表,是我踩了不少坑之后总结的:场景特征推荐策略理由结构化数据、字段重复度高生成压缩函数规则化冗余多,函数压缩收益大自然语言长文、语义密集摘要无规则冗余,函数无从下手代码、调用栈生成压缩函数缩进、前缀、重复符号多多轮对话历史摘要 + 选择性保留语义依赖强,压缩易丢上下文工具返回的表格数据生成压缩函数表头、单位重复,压缩率极高用户原始输入不压缩保真优先,压缩风险大于收益这张表的核心逻辑是:有规则冗余的地方用函数,无语义冗余的地方用摘要,涉及用户意图的地方不压缩。5. 工程侧该怎么接:从"写调度"到"设计动作空间"5.1 角色转变:工程师从执行者变成边界制定者CLM 落地后,工程侧的工作性质变了。以前你写的是"什么时候压缩、压缩到什么程度"的调度逻辑;现在你写的是"模型能调用哪些动作、每个动作的约束是什么、越界了怎么兜底"的边界框架。这个转变对工程师的要求其实更高了。因为调度逻辑是确定的,你能测试、能覆盖;而动作空间是开放的,你必须考虑模型可能做出的各种"合理但意外"的决策。我建议的做法是:先把动作空间设计得保守一点,跑一段时间,观察模型实际调用了哪些动作、哪些动作从没被用过、哪些动作被滥用,再逐步放开。5.2 动作调用的可观测性:没有日志就没有信任让模型自主管理上下文,最大的心理障碍是"我不知道它到底干了什么"。所以可观测性是刚需。我的做法是给每个动作调用打结构化日志:动作类型、作用对象、压缩前后 token 数、决策理由(让模型自己输出一句为什么这么做)。跑一段时间后,你会得到一份非常有价值的"模型上下文决策画像"——它在什么情况下倾向于压缩、什么情况下倾向于外置、什么时候会误判。实测心得:模型输出的"决策理由"经常比动作本身更有价值。有一次我发现模型频繁对某类内容做 externalize,理由是"这类信息后续可能用到但当前不需要",这其实暴露了我外置存储的检索延迟太高,模型在用外置来规避延迟问题。这种洞察,光看动作日志是发现不了的。5.3 兜底策略:模型判断失误时怎么救再聪明的模型也会判断失误。CLM 必须有兜底。我的兜底分三层:第一层是动作级兜底,任何 drop 操作前先做一次轻量备份,保留最近 K 步的可恢复快照;第二层是任务级兜底,如果模型在压缩后连续 N 步出现明显的推理质量下降(比如反复问已经回答过的问题),触发上下文重建;第三层是会话级兜底,极端情况下回滚到上一个已知良好状态。这三层兜底的成本要控制好。全量快照太贵,我的经验是只对"不可逆动作"做快照,可逆动作(比如摘要,原文还在外置存储里)不做。6. 那些文档不会告诉你的坑6.1 压缩函数生成的稳定性问题模型生成压缩函数,最大的坑是不稳定。同样的输入,两次生成的函数可能逻辑不同,一次正确一次有 bug。这在生产环境是致命的。我的应对是:生成的函数先在沙箱里对当前数据跑一遍,验证输出能正确逆映射回原始语义(至少关键字段要对得上),验证通过才采用,否则回退到摘要。这个验证步骤会增加一点延迟,但比起线上事故,完全值得。6.2 动作空间过大导致的决策瘫痪另一个反直觉的坑:动作不是越多越好。我一开始给了模型十几种动作,结果它在简单场景下也开始纠结,决策质量反而下降。后来砍到 5 个核心动作,效果明显变好。这背后的道理和人类似:选项太多,决策成本上升,容易做出次优选择。动作空间的设计目标是"够用且正交",不是"大而全"。6.3 和现有 RAG 管线的冲突如果你的系统已经有 RAG 管线,CLM 会和它打架。RAG 的召回是工程侧触发的,CLM 的外置是模型侧触发的,两者可能重复存储、重复检索。我的处理方式是让 CLM 的动作空间里包含"调用 RAG 检索"这个动作,把 RAG 变成模型可调用的工具,而不是工程侧自动触发的流程。这样职责就清晰了:模型决定什么时候需要检索,RAG 只负责执行检索。7. 我对这套思路的真实判断聊了这么多,说点掏心窝的判断。CLM 这个方向,我认为是对的,但"模型自己写压缩函数"这个具体形态,目前还处在能惊艳、难稳定的阶段。它最适合的场景是:结构化程度高、冗余规则明显、任务目标清晰的上下文。在这些场景里,它的压缩效率和语义保真度确实碾压传统方案。但如果你做的是高度依赖语义连贯性的长文任务,或者对稳定性要求极高的生产系统,我建议先别急着把动作空间全交出去。可以先从"模型建议 + 工程执行"的半自动模式起步,观察模型建议的质量,再逐步放权。两年工程被一个函数掀翻,这话听着夸张,但它揭示的趋势是真的:上下文管理的未来,一定是模型主导决策、工程提供边界。工程师的价值不会消失,只是从"写规则"变成了"设计规则可以生长的土壤"。这个转变,早适应早受益。最后分享一个我一直在用的小技巧:每次模型生成压缩函数后,别急着丢,把它存下来。跑上几百次之后,你会发现某些压缩模式反复出现——把这些高频模式固化成工程侧的预置动作,既保留了模型的灵活性,又降低了运行时的生成成本。这大概就是人和模型协作最舒服的姿势:模型负责探索,工程负责沉淀。