ICLR 2026 | 32倍压缩率下性能反超25个点!用TaoToken统一Key通道复现长文本压缩「翻车」修复实验

1. 为什么32倍压缩率下模型会「翻车」

长文本压缩这件事,很多人第一反应是「删减」——把32K的上下文砍到1K,只要保留和问题相关的片段就行了。但真跑过实验就会发现,压缩率一上去,性能不是缓慢下降,而是断崖式下跌。我在复现ICLR 2026那篇COMI论文时,第一次跑32倍压缩,Exact Match直接从40多掉到个位数,当时以为是脚本写错了,排查了半天才发现问题出在压缩策略本身。

核心矛盾在于:现有方法只盯着「相关性」,谁和query像就留谁。结果就是一堆语义高度相似的token被同时保留,看起来每个都相关,实际上信息高度重复。模型拿到这种压缩结果,等于在一堆同义反复里找答案,反而比看原文更容易迷失。论文里把这个现象叫「信息内卷」——token之间相互干扰,相关不等于正确。

COMI提出的解法是引入「边际信息增益」(Marginal Information Gain,MIG),把压缩决策从单维度相关性升级为「相关性减冗余性」的双维度权衡。公式很简洁:MIG = 本单元与查询的相关性 - 与其他已选单元的最大相似度。高MIG的token既相关又独特,低MIG的token要么不相关,要么和别的内容重复。压缩时优先保留高MIG单元,32倍压缩下NaturalQuestions的EM能到49.15,比次优基线高出近25个点。

这篇要交付的不是论文解读,而是工程复现路径:怎么用TaoToken统一Key通道把COMI的推理链路跑通,怎么配置config.toml和settings.json,怎么验证压缩率-性能曲线,以及压缩过程中边际信息增益衰减怎么排查。适合已经在做长上下文推理优化、想复现高压缩率实验的工程师。

2. TaoToken前置:统一Key通道与COMI复现的关系

COMI的复现涉及多个模型调用环节:压缩阶段需要调用基座模型做token级打分,生成阶段需要调用Qwen2-7B或Qwen3-4B做下游任务推理,验证阶段还要跑多个数据集的对照实验。如果每个环节单独配Key、单独管额度,调试成本会非常高。TaoToken在这里的角色是统一Key/API通道——一个Key覆盖多个模型的调用,config.toml里改模型名就行,不用来回切换账号。

具体来说,COMI的压缩流程分两阶段。第一阶段粗粒度组重分配,需要计算每个片段的组间MIG,这步可以离线做,用模型对片段做相关性打分。第二阶段细粒度token融合,需要token级MIG加权,这步对延迟敏感,因为要在推理时动态计算。TaoToken的API通道支持流式和批量两种模式,压缩阶段用批量打分,生成阶段用流式输出,配置上只需要在settings.json里区分两个endpoint。

另外,COMI论文里提到压缩阶段仅引入轻量级开销,NarrativeQA任务中压缩耗时2.76秒,生成仅0.50秒。这个数据是在单次训练后推理得到的,复现时如果压缩耗时远超这个量级,大概率是MIG计算没有做缓存,或者token相似度矩阵重复计算了。TaoToken的console里可以看每次请求的耗时分布,方便定位是压缩阶段慢还是生成阶段慢。

需要提前准备的东西:TaoToken的API Key(在console的api-keys页面创建),Python 3.10+环境,以及COMI的代码仓库。模型方面,压缩阶段建议用Qwen2-7B做打分,生成阶段可以用Qwen3-4B验证「压缩后反超原生长上下文」的结论。

3. 可复制配置:config.toml与settings.json骨架

COMI的代码仓库默认用环境变量传Key,但复现时经常要切换模型和endpoint,硬编码在环境变量里不好管理。我改成用config.toml管模型配置,settings.json管运行时参数,两个文件分离,改起来清楚。

先看config.toml。这个文件放在项目根目录,主要定义模型别名、API base、超时和重试策略:

# config.toml - 模型与通道配置 [default] api_base = "https://taotoken.net/api" api_key_env = "TAOTOKEN_API_KEY" timeout = 120 max_retries = 3 [models.compressor] name = "qwen2-7b" endpoint = "/v1/chat/completions" temperature = 0.0 max_tokens = 2048 batch_size = 16 [models.generator] name = "qwen3-4b" endpoint = "/v1/chat/completions" temperature = 0.1 max_tokens = 512 stream = true [compression] target_ratio = 32 mig_threshold = 0.15 group_size = 512 token_fusion = "weighted"

几个关键参数说明。target_ratio = 32对应32倍压缩,mig_threshold是MIG筛选阈值,低于这个值的token在细粒度融合时权重会被压低。group_size = 512是粗粒度分组的片段长度,论文里用的是等长划分,512是Qwen2-7B的常见窗口粒度。token_fusion = "weighted"对应论文里的加权融合,如果改成"mean"就是传统平均池化,用来做对照实验。

再看settings.json。这个文件管运行时行为,包括数据集路径、评估指标、日志级别:

{ "runtime": { "device": "cuda:0", "dtype": "bfloat16", "seed": 42 }, "datasets": { "natural_questions": { "path": "./data/nq", "max_context_len": 32768, "eval_metric": "exact_match" }, "hotpot_qa": { "path": "./data/hotpotqa", "max_context_len": 32768, "eval_metric": "f1" }, "narrative_qa": { "path": "./data/narrativeqa", "max_context_len": 32768, "eval_metric": "rouge_l" } }, "compression": { "ratios": [4, 8, 16, 32], "save_intermediate": true, "mig_log_interval": 100 }, "logging": { "level": "INFO", "log_dir": "./logs", "save_mig_curve": true } }

ratios数组定义要跑的压缩率梯度,从4倍到32倍,用来画压缩率-性能曲线。save_mig_curve = true会把每个片段的MIG分布存下来,排查边际信息增益衰减时直接看这个文件。mig_log_interval = 100是每处理100个片段打一次日志,避免日志刷屏。

两个文件配好后,在代码里这样加载:

import tomllib import json import os with open("config.toml", "rb") as f: config = tomllib.load(f) with open("settings.json", "r") as f: settings = json.load(f) api_key = os.environ.get(config["default"]["api_key_env"]) api_base = config["default"]["api_base"]

API Key不要写进文件,用环境变量传。在终端里执行export TAOTOKEN_API_KEY="你的Key",或者写进.env文件用python-dotenv加载。Key在TaoToken的console里创建,api-keys页面能看到所有已创建的Key和额度使用情况。

4. 验证请求:压缩率-性能曲线脚本与对照实验

配置就绪后,先跑一个最小验证请求,确认通道通、模型能调通。用curl测一下:

curl -X POST "https://taotoken.net/api/v1/chat/completions" \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "qwen2-7b", "messages": [{"role": "user", "content": "计算以下文本的边际信息增益:..."}], "temperature": 0.0, "max_tokens": 64 }'

返回正常的话,说明Key和endpoint都没问题。接下来跑压缩率-性能曲线的验证脚本。这个脚本的核心逻辑是:对每个压缩率,跑一遍COMI压缩,再跑下游任务评估,记录EM/F1分数。

import json import tomllib import os from comi import COMICompressor, Evaluator with open("config.toml", "rb") as f: config = tomllib.load(f) with open("settings.json", "r") as f: settings = json.load(f) compressor = COMICompressor( model=config["models"]["compressor"]["name"], api_base=config["default"]["api_base"], api_key=os.environ["TAOTOKEN_API_KEY"], target_ratio=config["compression"]["target_ratio"], mig_threshold=config["compression"]["mig_threshold"], group_size=config["compression"]["group_size"] ) evaluator = Evaluator( model=config["models"]["generator"]["name"], api_base=config["default"]["api_base"], api_key=os.environ["TAOTOKEN_API_KEY"] ) results = {} for ratio in settings["compression"]["ratios"]: compressor.target_ratio = ratio scores = [] for sample in evaluator.load_dataset("natural_questions"): compressed = compressor.compress(sample["context"], sample["query"]) answer = evaluator.generate(compressed, sample["query"]) score = evaluator.score(answer, sample["answers"], metric="exact_match") scores.append(score) results[ratio] = sum(scores) / len(scores) print(f"ratio={ratio}x, EM={results[ratio]:.2f}") with open("./logs/compression_curve.json", "w") as f: json.dump(results, f, indent=2)

跑完这个脚本,你会得到一条压缩率-性能曲线。正常情况下,COMI在4倍到16倍压缩率下性能下降平缓,32倍时仍能保持较高水平。如果32倍时EM掉到20以下,说明MIG计算或token融合环节有问题,需要排查。

对照实验的关键是跑两组:一组用COMI的加权融合,一组用传统平均池化。把config.toml里的token_fusion改成"mean",重跑一遍,对比两条曲线。论文里COMI在32倍压缩下比次优基线高25个点,这个差距在对照实验里应该能复现出来。

另外,验证「压缩后反超原生长上下文」这个结论,需要额外跑一组不压缩、直接输入完整32K上下文的baseline。用Qwen3-4B做生成模型,对比压缩后和未压缩的F1分数。论文里32倍压缩后F1是28.89,未压缩是16.90,差距明显。如果复现时压缩后反而更低,检查压缩阶段是否把关键证据链的token也压掉了。

5. 本篇常见错排查

复现COMI时踩过的坑主要集中在几个地方。第一个是MIG计算时的相似度矩阵维度对不上。COMI的MIG公式里,与其他单元的最大相似度需要遍历已选单元,如果实现时用了全量相似度矩阵而不是增量更新,32K上下文下显存会直接爆掉。正确做法是维护一个已选token的相似度缓存,每选一个新token就更新一次,而不是每次重新算全量。

第二个是压缩率设置和实际压缩比不一致。target_ratio = 32是目标压缩率,但实际压缩后token数可能因为MIG阈值过滤而偏离。如果mig_threshold设得太高,大量token被过滤,实际压缩率可能到40倍以上,性能自然崩。排查方法是打印压缩前后的token数,算实际压缩比,和target_ratio对比。偏差超过10%就调低mig_threshold。

第三个是边际信息增益衰减的误判。MIG衰减指的是随着压缩进行,后续token的MIG值普遍下降,因为高价值token已经被选走了。这是正常现象,但如果衰减过快,比如前10%的token就消耗了90%的MIG总量,说明分组策略有问题。group_size设得太小会导致组间MIG差异被放大,建议从512开始调,逐步试256和1024。

第四个是API调用超时。压缩阶段如果对每个片段单独发请求,32K上下文分成64个512片段,就是64次请求,每次都走网络往返,耗时很容易超过2.76秒的基准。优化方法是把多个片段打包成一个batch请求,config.toml里的batch_size = 16就是干这个的。如果还是慢,检查TaoToken的console里请求耗时分布,看是网络延迟还是模型推理慢。

第五个是生成阶段流式输出和评估脚本的兼容问题。settings.json里stream = true时,评估脚本要改成逐chunk接收,不能等完整响应。如果评估脚本用的是非流式接口,把stream改成false,或者改用流式接收的评估逻辑。

6. 接入路径与后续实验建议

跑通基础复现后,下一步可以做的实验有几个方向。一是换基座模型,论文用的是Qwen2-7B和Qwen3-4B,你可以换成其他支持长上下文的模型,验证COMI的压缩策略是否跨模型通用。二是换数据集,除了NaturalQuestions和HotpotQA,NarrativeQA的32K超长文本场景更能体现压缩鲁棒性。三是调MIG阈值和分组粒度,画一张超参数敏感性热力图,看哪些参数组合下32倍压缩仍能保持性能。

接入方面,TaoToken的API通道配置在config.toml里改api_base和模型名就行,不需要改代码逻辑。如果要做长期编码或Agent场景的压缩,建议用Coding Plan,额度更充裕,适合跑大批量对照实验。模型对话功能可以用来快速验证单个样本的压缩效果,不用每次都跑完整脚本。API Key在console的api-keys页面管理,接入文档在doc页面有详细的endpoint说明和参数列表。

复现过程中如果遇到压缩后性能异常,优先排查MIG计算的增量更新逻辑和实际压缩比,这两个是最容易出问题的地方。压缩率-性能曲线的脚本跑通后,建议把每次实验的config和settings存档,方便回溯对比。