Appearance
16|预处理管线:调用前整理上下文
上一篇讲完继续工作,循环与控制设计的核心都到位了。但有两个执行细节要补,本篇讲第一个:每轮调 API 前,消息要先经过预处理。
第 10 篇讲过压缩策略——上下文太长时怎么办。本篇是另一个角度:不是"太长才压缩",而是"每轮调用前都过一遍管线,从轻到重处理,够用就停"。它和压缩策略用的是同一套手段,但定位不同:压缩是被动应对超长,预处理是主动的调用前流程。
为什么每轮都要预处理
循环每轮调 API 前,消息列表可能积累了各种问题:上一轮工具返回的大段日志还没折叠、早期对话已经过时但还留着、格式噪声没清理。如果不管直接发,token 浪费、模型注意力分散、甚至触发上下文超长。
预处理管线在调用前把这些处理掉。不是等到超长才动手,是每轮调用前过一遍,把上下文维持在健康状态。
从轻到重的管线
和第 10 篇的压缩策略同源,从轻到重三层:

python
def preprocess(messages, budget, client):
# 第一层:轻量整理(零成本)
messages = light_cleanup(messages)
if token_count(messages) < budget * 0.9:
return messages
# 第二层:上下文折叠(低成本)
messages = fold_messages(messages, budget)
if token_count(messages) < budget * 0.9:
return messages
# 第三层:AutoCompact(高成本,调模型)
messages = auto_compact(messages, client, budget)
return messages第一层轻量整理:去掉空消息、重复内容、过期时间戳标记。不改变实质信息,成本接近零。
第二层上下文折叠:把详细内容折叠成摘要,保留关键字段。工具返回的 500 行日志折叠成一行摘要,早期几轮对话折叠成"已确认事实"。靠规则或模板,不调模型。
第三层 AutoCompact:前两层不够时调模型做摘要。成本最高,放最后。
够用就停
这是预处理管线最关键的设计:够用就停,不每次走完三层。
固定流程——每次都先整理、再折叠、再摘要——违背管线核心设计。生产环境里多数请求只需要轻量整理,少数需要走到折叠,只有少数长会话才触发 AutoCompact。固定走完三层会让大部分请求多付不必要的成本。
每一层试完都检查够不够,够了就停。这个"够用"的判断是 token_count(messages) < budget * 0.9——留 10% 余量,不卡着上限。
管线顺序不能乱
三层顺序是按成本和破坏程度递增排的。轻量整理成本最低、破坏最小(不丢实质信息),先走。折叠成本中等、会丢细节,第二。AutoCompact 成本最高、会丢最多信息,最后。
如果反过来——先 AutoCompact,再折叠,再整理——会浪费高成本操作在不必要的地方。AutoCompact 一次调用模型的钱花了,结果轻量整理本来就能释放足够空间。顺序按成本递增,让贵的操作尽量不被触发。
压缩必须保留用户消息
和第 10 篇一样,预处理压缩时必须保留用户消息和用户约束。
"不要用某技术栈""只看最近一小时"这类约束最容易在摘要中丢失。一旦丢失,后续轮次就会破坏这些约束。预处理 prompt 要明确要求保留用户约束、已确认事实、待确认项,可以丢弃工具调用的中间过程和重复确认消息。
预处理不是每次请求都全走
这里要纠正一个常见做法:把预处理写成固定的三步流程,每次请求都走完。
预处理管线的核心是"按需触发"。轻量整理可以每轮都做(成本接近零),但折叠和 AutoCompact 应该只在轻量整理不够时才触发。判断条件是 token 是否接近预算——离预算远就只做轻量整理,接近了才往下走。
具体各层占比以本项目 eval 为准,不套用别人的统计数字。不同任务、不同对话长度,各层触发比例不同。
预处理之后
预处理管线让每轮调 API 前的上下文都是健康的。调用前的部分讲完了,接下来是调用后:模型一次可能返回多个工具调用,这些工具调用怎么执行——串行还是并行,怎么决定。
下一篇讲流式与并发。这是循环与控制设计的最后一篇执行细节。