压缩管道
压缩管道负责「把长文本在进入模型前压到可承受的大小」:十个节点按固定顺序执行,算法优先、LLM 兜底,并且有一道硬性守卫——压缩结果只要没变短,就保留原文。它是上下文成本控制的第一层,与第二层「会话级自动压缩」配合使用。
节点顺序与「是否启用」由代码里的默认值决定,用户可以改启用状态;升级后新增节点会自动出现在配置里。
两个入口
| 入口 | 行为 | 用在哪 |
CompressAsync | 执行完整管道,允许 LLM 摘要节点参与 | 对话 / 编码会话的历史文本压缩 |
CompressAlgorithmicAsync | 只跑算法节点(allowLlm=false):即使配置成 llm / hybrid 也不触发模型调用 | 单轮任务:Wiki 生成、知识图谱提取等一次性输入 |
单轮任务为什么要区分?因为一次性的长输入只压缩一次,再花一次模型调用不划算;而对话历史会被反复送进模型,LLM 摘要摊薄之后才值得。
三种模式
| 模式 | 含义 |
algorithmic(默认) | 只跑算法节点,llm_summary 即使勾选也会被跳过(日志中会写明原因) |
llm | 算法节点 + LLM 摘要(满足长度阈值时) |
hybrid | 与 llm 相同:先算法后 LLM——算法先把明显冗余去掉,LLM 再处理语义级压缩 |
十个节点(按执行顺序)
| # | 节点 Key | 名称 | 做法 | 默认 |
| 1 | structured | 结构化折叠 | 折叠 base64 / HTML / JSON / 表格等长载荷,只留结构骨架与样本 | 启用 |
| 2 | dedup | 去重合并 | 去除重复段落、重复行与行内重复句,保留首次出现 | 启用 |
| 3 | whitespace | 格式压缩 | 去除多余空格、换行和缩进 | 启用 |
| 4 | log_dedup | 日志去重 | 识别并折叠重复的日志模式 | 启用 |
| 5 | near_dup | 近似重复 | SimHash 相似度去重,抓只有时间戳 / ID 不同的重复内容 | 启用 |
| 6 | number_normalize | 数字归一化 | 把数字替换成占位符,减少变化量 | 启用 |
| 7 | stopwords | 停用词过滤 | 移除中英文常见无意义词 | 关闭 |
| 8 | keywords | 关键行抽取 | 按信息量打分,保留错误 / 结论 / 路径等关键行,折叠其余流水行 | 启用 |
| 9 | headtail | 超长头尾保留 | 超长输出保留首尾、折叠中间(构建日志、大文件内容) | 启用 |
| 10 | llm_summary | LLM 摘要 | 调用模型做语义级摘要(按下面的门槛触发) | 关闭 |
节点顺序在代码里固定(Order 1–10),配置只决定「哪些节点启用」。顺序有讲究:先去结构噪声,再去重复,最后才做数字归一化与关键行抽取;LLM 摘要永远在最后。
LLM 摘要的四个门槛
llm_summary 要同时满足以下条件才会真正调用模型,任何一条不满足都会跳过并写日志:
| 门槛 | 取值 | 不满足时 |
| 入口允许 | allowLlm=true(CompressAsync) | 单轮任务直接跳过 |
| 模式 | llm 或 hybrid | algorithmic 下跳过 |
| 长度阈值 | LlmThreshold ≥ 500 字符(可配置) | 短文本跳过,省一次调用 |
| 可用模型 | 配置里指定的摘要模型可用,否则回落到默认对话模型 | 都没有则记 warning 并保留原文 |
摘要提示词默认要求:保留结论、数字、路径与文件名、命令、待办与约束,删除重复与寒暄,不编造事实,输出与原文同语言。
守卫与降级
- 未变短就保留原文:整条管道跑完后,如果结果长度 ≥ 原始长度,直接返回原文(
number_normalize、重复标注等节点在特定文本上确实会变长)。
- 空输入 / 管道关闭 / 无启用节点:原样返回,不做任何处理。
- LLM 失败:摘要模型不可用时只记 warning 返回原文,不阻断主流程。
- 每个节点执行前后都会记录字符数,最终记录压缩比(
ratio)。
配置存储与升级语义
| 项 | 说明 |
| 存储键 | 应用设置 CompressionConfig(JSON) |
| 总开关 | Enabled,默认关闭:关闭时管道整体跳过 |
| 合并策略 | 节点集合、顺序与文案以代码为准;只保留用户对「是否启用」的选择——所以升级后新增节点会自动出现在配置里,不会因为老配置而不可见 |
| 历史节点 | 配置里存在但代码已没有的节点会保留并排到末尾(Order + 100),便于回滚排查 |
| 自检 | DescribeAsync() 输出当前真正会执行的节点与模式,并明确写出 llm_summary 是否被跳过及原因(日志排查用) |
与「会话级自动压缩」的区别
| 维度 | 压缩管道(本页) | 会话级自动压缩 |
| 作用对象 | 单段文本(历史片段、工具输出) | 整个会话的历史消息序列 |
| 触发方式 | 调用方显式调用(每轮前、单轮任务前) | 上下文占用 ≥ 窗口 80% 时自动触发 |
| 结果落点 | 只替换送入模型的那段文本 | 摘要写回话题 / 会话的 ContextSummary 与 ContextSummaryThroughMessageId,原始消息不动 |
| 可调项 | 节点启停、模式、阈值、摘要模型与提示词 | 保留最近条数、摘要模型、自动触发比例 |
调优建议(基于实现)
- 先开总开关:管道默认是关闭的,设置里打开后即使只保留默认节点也有明显效果。
- 长日志 / 构建输出:确保
structured、log_dedup、headtail 开启;这三个对命令行噪音最有效。
- 只想降噪、不想动语义:保持
algorithmic,不要开 llm_summary。
- 长会话成本:开
llm / hybrid,阈值别设太小(默认 500 字符已经很激进),摘要模型选便宜的小模型。
- 谨慎开启:
number_normalize 会把数字换成占位符、stopwords 会删词,涉及精确数值或措辞的任务建议关闭。
- 排查:看后端日志里
[Compression] 前缀的行,能看到每个节点的前后字符数、跳过原因与最终压缩比。