第 1 卷
张嘉熙 · DeepSeek Harness 前沿工程实践



你好,我是张嘉熙。
上一讲我们把会话续接讲透了:日志怎么落盘、怎么分叉、崩了怎么修复、怎么读回来接着干。但那些讲的都是日志本身,有一个口子始终没碰——上下文本身会越滚越长。
一次请求能塞进去的量是有上限的(上下文窗口,连系统提示、工具定义都算在里面)。而会话每跑一轮,历史就长一截;工具返回一大段输出,上下文又涨一块。当上下文逼近上限但还
没超限时,就进入了“压力”状态,这个时候还来得及从容处理;真越过了界,模型会报“超出上下文窗口”的错误,直接拒绝这次请求,框架把这类失败归一成错误码
CONTEXT_WINDOW_EXCEEDED;没装压缩的话,这一次请求就是终点,整轮随之失败。这一讲我们就来讲讲“装不下了怎么办”,一节解决一个问题:
什么情况算装不下?先弄清问题
压缩与裁剪的关系不是并列的:压缩后端在框架的事件上注册了监听器,每一步开始前、请求失败后,它自己就会动手;裁剪服务不注册任何监听器,只会等人来调,而框架里会调它的,
只有自动压缩这一条路:判定“该管了”之后、挑范围之前,先调用裁剪服务,把超长的工具结果裁剪一下,再重新量一遍;量完如果够低了,就到此为止(裁了,但不压)。下面从最核心
的压缩讲起。
关于环境:本讲新增几个包,@deepseek-ai/dsh-compaction(压缩 seam 定义)、 @deepseek-ai/dsh-compaction-basic(压缩后端)、@deepseek-ai/dsh-
compaction-tool-result-pruner(工具结果裁剪)、@deepseek-ai/dshtoken-meter(token 计量),已加入本项目的 package.json,npm install --
legacy-peer-deps 装上即可。
关于示例:npm run start:ch10:compact 跑压缩,npm run start:ch10:prune 跑裁剪。
压力与溢出
第一个问题:什么情况算装不下?
上一讲讲过的会话,历史是只追加的,每一轮对话、每一次工具调用,都会在日志里留下记录;其中浮到模型眼前的那一层,就叫 surface(surface 就是哪些事件浮在模型眼前的那份
清单)。上一讲那条消息历史,正是把 surface 投影成消息算出来的。轮次越多,surface 越厚;工具输出越大,surface 越重。
而模型是有上下文窗口的:一次请求能塞进去的量是有限的。这个量的单位叫 token,是模型读文本时切出来的最小计数单位,你可以粗略理解成词块(英文里一个长词可能被切成好几
块,中文里一个字也不一定正好是一块)。窗口有多大,由当前路由到的那个模型决定。这两者一碰,就有两种“装不下”:
压力(pressure):历史自然累积,正在逼近窗口上限,但还没超。
具定义这些固定开销,再拿去跟目标模型的窗口比,占到窗口的一定比例就算有压力(这个比例归压缩后端自己配,thresholdRatio,默认 0.8,即八成)。溢出不用量,它不是预
测,而是请求被拒之后才确认的事实。

压缩和裁剪这两样都是“可选能力”,不在 Agent Loop 的主干上,Agent Loop 那边一行代码都没提它们;不装的话,Agent 照跑,只是上下文一满就报错停下。装上之后,才有人处理
“装不下”这件事(压缩得在场,裁剪自己不会动,它只等人来调)。
压缩:把旧历史压成一段摘要
第二个问题:旧历史怎么压短?
装不下最直接的解法,是把已经聊过的旧历史压成一小段摘要:那一大片 surface 节点被一个