Harness 工程 全部章节

第9章 长任务上下文——结果折叠、历史压缩与接续

第7章控制信息进入与驻留,第8章解决取得和复用。长任务还会积累已经取得的原文、调用结果、纠正和判断历史。它们的增长首先带来容量与重复输入成本,也可能增加干扰;但上下文长并不是全部判断错误的原因,输入变短也不自动使模型更正确。

本章继续第3章的串行摘录系统,说明如何在合法边界上改变输入表示。原 Harness 超出字节预算时停止,没有自动折叠或压缩。随书 practices.py 提供内存原文引用、有限展开及压缩候选的结构与版本检查,便于检验其中几项条件;这些局部函数尚未接入原循环,不构成持久结果存储、完整压缩服务或新会话接手续跑,也不以虚构调用和缓存数字证明收益。

9.1驱逐、折叠、压缩与删除

驱逐(eviction)是让某项内容不再进入后续模型输入。它不是持久删除,也不是直接释放提供方 GPU 缓存。最小形态是旧输入有一项材料,新输入没有它,而原记录的保存条件另行明确。无需再用的重复说明可以驱逐,但相关动作事实不会因此消失。

折叠(folding)是把详细内容移出当前输入,保留能够定位并按需展开的较短表示。它不是只在界面上收起正文,也不是生成一个无法回到原文的摘要。最小形态是原文保存、带范围和版本的引用,以及受控展开路径。当前输入不再有全文,宿主仍能取得需要的同版内容。

压缩(compression)是用较短的新表示替代一段历史的信息内容。它不是与折叠同义:即使旧记录仍保存,新表示也通常舍弃表达和细节,具有信息损失风险。最小形态是压缩候选、针对任务需要的校验,以及提交失败时保留旧表示的版本规则。

持久删除(deletion)是按保存与授权条件移除存储中的内容或副本。它不是模型不再看到,也不是撤回已发生的外部效果。最小形态要说明删哪个对象、哪些副本仍在、是否需要保留必要记录,以及后续引用如何失效。不能用“已经忘记”掩盖记录仍可被读取。

四种操作可以组合。全文外存、输入只留引用,是折叠并驱逐全文;把多次讨论重写成结构化接续材料,是压缩;旧档案是否删除则另作决定。建设时应分别记录作用对象和版本,否则输入已经缩短,仍可能没有可展开证据;存储还在,接口接续却可能已被破坏。

先选操作,再谈节省。第7章的局部后缀退出适合阶段整体结束,当前章处理不能整段退出的大结果和主线历史。无论采用哪一种,都不能改变授权、动作事实、调用配对和所选接口必须保留的字段。

9.2保留量与原文保存

重要性是某项信息对后续判断、动作和验收的必要程度,不是模型觉得哪段文字更精彩。最小判断包括它支持什么结论、丢失会改变哪项决定,以及是否涉及未完成动作或用户纠正。授权范围和精确来源顺序可能很短,却比大量背景说明更重要。

同版可恢复性是之后能否在当前许可下取得当时同一版本的必要内容。它不是“可以再查询一次”。最小依据是保存的不可变原文,或具备版本定位和有限读取契约的来源。内容 hash 能检查返回字节是否匹配,但 hash 本身不能恢复丢失的字节。

两个维度共同决定表示。重要且难以同版恢复的材料,应保存原文,并在输入中留下足够支持当前判断的内容;如果连持久保存都没有成立,不能删掉唯一证据。重要且能同版恢复的材料可以保留提纲与引用,需要时展开。暂时不重要但有核对价值的材料,可以留档、退出输入;没有复用与保留义务的内容,才进入删除判断。

提纲说明材料覆盖什么、何时应展开;引用提供准确来源、版本和范围;持久原文保住实际观察。三者不是互相排斥的存储等级。一份关键工具结果可以同时具有持久原文、输入中的短提纲和两个精确摘录,避免只能在“全文常驻”与“全部舍弃”间选择。

第3章的来源快照在运行内存中保持固定,工具内容随后进入消息和请求快照。诊断快照经过脱敏,不能未经核对就宣称它是任意原始字节的完整档案。若扩展为同版展开,需明确保存的是哪个内容对象、是否变换过,以及原文读取路径;不能把现有 hash 当作已建好通用结果仓库。

有些字段不参与一般重要性排序。未完成调用的关联信息、程序侧动作状态、有效目标与授权版本,以及接口要求的接续项,有各自保留条件。模型给它们打低分,也不能授权移除。先满足这些硬条件,再比较普通证据的驻留成本,避免用一项相关性分数代替多个建设责任。

保留判断做完,接着决定原文怎么留。折叠从保存开始,而不是先把正文清掉。原始结果的保存对象应明确:是工具返回的业务内容、完整协议消息,还是经脱敏的诊断副本。它们可能相互关联,但不是同一份字节。保存凭证或不允许留存的数据并非折叠的默认权力;应在获准范围内保存必要对象,并声明变换与缺口。

结果短引用(stub)是替代全文进入输入的定位表示。它不是内容真实性保证,也不是足以替代所有原文的摘要。最小形态包含对象引用、内容 hash、来源版本、覆盖范围、取得时间和发送范围,并说明能怎样有限展开。下面是字段关系示意,不是现有存储接口:

stub = {
    "result_ref": stored_result_ref,
    "content_hash": stored_content_hash,
    "source_version": source_version,
    "read_slice": stored_range,
    "retrieved_at": original_retrieval_time,
    "disclosure_scope": allowed_scope,
    "outline": coverage_and_limits,
}

retrieved_at 表示原观察的取得时间,不是之后展开的时间;read_slice 表示原结果覆盖的部分,不代表全文。outline 告诉模型这份材料能帮助回答什么以及没有覆盖什么。只有一个路径而没有这些含义,模型未必知道应当何时读取,也容易把局部结果当作完整来源。

保存成功需要能够确认写入对象和版本,并检查必要内容可读。确认以前保留当前全文;写入失败或结果未知时,不提交折叠。串行实现应在动作结束的控制边界安排这些步骤;第3章尚未实现这条保存与折叠路径。不能把进程内有一个字符串当作已经满足跨重启耐久条件。需要哪种耐久范围,要在存储契约中说明。

同一个业务结果中的原文与状态应分别处理。可以将大段来源正文折叠为引用,但创建动作的身份、目标、结果和未知标记仍由程序侧记录保留。短引用不得把“可能已创建”改成“已创建”,也不能让工具返回中的自述取代后续产物验收。

来源无法同版重取时,保留下来的原文尤其重要。唯一观察尚未保存,就不能用“以后再搜”作为清理依据。若预算已经不足而又没有合法保存或接续路径,应停止并保留现场,不要让模型编写一个概括来掩盖证据已经丢失。

9.3展开的边界与重查

展开(expansion)是根据短引用取得其中所指的必要内容并重新提供给模型。它不是把所有折叠材料全部重新加载。最小过程是选引用与范围、复查许可、读取同版片段、核对返回范围和版本,再计入新请求预算。调用展开能力时仍需遵守第2章的消息往返,不能凭空补写工具结果。

展开上限在读取前确定,可以限制区间、字节、条目数或分页数量。区间单位以工具契约为准;文本切片应避免破坏编码,并说明返回的是完整范围还是有标记的截取。返回以后再检查完整载荷与窗口条件,不能让展开接口的单项上限替代全请求预算。

先展开足以支持当前判断的部分。如果提纲说明来源包含多种规则,当前只核对摘录长度,就读取相关限制及必要上下文,而不是全文恢复。若局部片段无法排除限定条件,再有理由地扩大。反复展开同一段说明驻留可能过短,可在当前阶段保留它,不能机械追求每次最短输入。

同版读取失败应保留引用与失败状态。服务只返回当前版本时,可以发起一次新的查询或读取,但它形成的是新观察。即使文本碰巧一样,也应核对内容和范围,不能先把新结果的取得时间写成旧时间。版本变化会影响历史结论是否仍成立,不能静默替换原证据。

副作用更不能用于恢复输出。丢失 create_card 返回后,再创建一个产物不是展开旧结果,而是一个新的持久动作。应查询已有动作或产物,核对原记录;缺少这种能力时停下人工确认。重新执行发送、写入或修改,即使参数相同,也不能据此宣称恢复了之前那次观察。

第3章现有 read_source 只读取运行绑定的完整来源,并没有引用展开参数。本章扩展契约不意味着现在可用该工具读取任意档案。实践中应沿同一固定工具接入有限读取,不为取回一段证据增加通用 shell 或另建检索平台。

9.4摘要边界与接续项

有了可恢复原文,也还要检查接续结构。助手工具调用与匹配结果是接口中的关联对象,不能把其中一半随普通背景压缩后留下另一半。尚有调用未处理时,应保留原调用、参数和关联标识,按原契约完成处理或明确停止。不能用“上一轮读了材料”代替缺失的结果消息,也不能替模型补造一次从未发生的调用。

一个批次中部分结果已返回,也不能只留下成功部分并请求继续。第3章先保存助手调用消息,再逐项回传匹配结果;未知工具导致后续停止时也保留相应配对。这里的配对是合法协议关系,不证明所有业务动作成功。压缩不得为了形成整齐历史,把拒绝和未知改成正常结果。

状态账本(state ledger)是程序侧组件保存的动作与控制事实记录,不是模型写出的进展摘要。最小记录把动作身份、意图、确定结果或未知,以及当前条件关联起来。第3章的 Ledger 留下这些边界证据,但没有自动恢复协议。把它摘要成一句“可以继续”不会新增接手资格。

折叠可移出大正文,状态账本不能因模型不再需要阅读而丢弃必要事实。输入只需给出本次判断的准确投影,程序仍从程序侧对象核对动作。摘要中的 open_actions 用于提醒,不是权威状态;与账本冲突时,应停止核对,不能选比较简洁的那一份。

输入表示变换只在控制边界使用,不在模型请求、工具批次或效果提交途中改写输入版本。边界上要确认没有未处理调用,没有需要旧请求继续承担的动作,相关结果已可靠确认。窗口压力不能使在途操作突然变成可压缩对象;不足以合法继续时,停止比破坏配对更有限也更真实。

并非所有已完成历史都因此自由可删。接口可能要求保留完成轮次的特定字段,证据与发送契约也可能要求原记录。业务动作结束只是进入表示变换的必要条件,下一步还要检查模型接口是否允许保持原会话继续。

可恢复原文之外,还有模型侧的接续项要处理。可见思考(thinking)是接口提供的推理相关内容,可能位于独立字段。它不是已核验事实,也不保证等于模型内部全部计算。最小形态是与某条生成消息关联的可读内容,保留和回传规则由所选接口决定。不是所有供应商都返回它,不能用一个字段名代表全部模型。

推理摘要(reasoning summary)是对推理相关过程的较短表示,可能由服务产生。它不是完整原过程,也不是宿主普通历史摘要的同义词。最小形态是带明确类型与接口语义的摘要项;它能否接续、是否占输入和如何计费,应分别核对,不能从“更短”推导可自由编辑。

签名(signature)是某些接口附在特定内容上的校验或关联数据,用于按其契约识别内容与上下文的关系。它不是模型事实的可靠性证明,更不是一段摘要写上“已签名”就能获得的凭证。最小形态是原返回项与对应签名,是否必须配对、是否可跨模型使用由接口规定。

不透明接续项(opaque continuation)是宿主不能按普通文本解释的接续对象。它不是可随意总结的隐藏段落,也不是长期知识。最小形态是接口返回、要求按规定方式保留或回传的对象。它可能具有兼容性或完整性条件;未经契约允许,不能解包、改写,或用语义相似文本替换。

这些对象不是所有供应商共有的一套字段,有的接口只有可见推理,有的提供其他接续形态。适配器应保存真实返回的类型和关联规则,而不是要求所有响应都包含四项。普通压缩候选也不能冒充提供方的推理摘要、签名或原生压缩结果。

推理跨用户 turn 可能有任务价值。连续目标中的已比较方案、约束关系和未验证假设,可能帮助后续判断;目标变化或旧假设失效时,保留也可能增加干扰。任务价值要通过同一任务效果评估,协议要求则必须先满足。两者都不能推出“跨 turn 一律清空”,推理也不能作为唯一动作记录或永久事实。

9.5DeepSeek 的 thinking 保留与新会话交接

本书基础接口采用 DeepSeek Chat Completions,调用 deepseek-flash。按二〇二六年十一月一日核验的官方思考模式契约,思考内容通过与 content 同级的 reasoning_content 返回。这里说明的是该接口,不推广为所有提供方规则。

携带 tools 的后续请求必须完整回传历史 reasoning_content,即使某一轮模型没有实际发起工具调用。这里的历史包括原会话中跨用户 turn 的助手消息,不能按与当前问题的相关性筛选思考字段。官方示例在下一用户 turn 继续回传此前产生的字段。不能只保留最近工具调用前的思考,也不能因一条助手消息只有最终文本就清掉其推理字段。

未携带 tools 的请求不需要回传 reasoning_content,即使回传也会被忽略,不拼入上下文。这与上一条有不同前提。不能在任务仍需要工具时,为清理历史临时去掉 tools,再把省下输入当作保持原工具链的等价压缩;后续重新携带工具时,仍要具备该契约要求的历史,而不能已经永久删掉。

第3章显式设置 thinking.type = disabled,正常历史不含需要保存的非空思考字段;返回非空字段会按模式不匹配停止。这个基础选择不承担启用思考后的保留实现。若修改模式,需同时修改适配器、消息保存、预算和测试,不能只把开关改成 enabled 后继续沿用只保留文本与调用的解析器。

保持原会话并沿上述工具接口接续时,必须保留的历史字段不能用普通摘要替代。即使没有未完成调用,完整回传规则仍成立;业务结束边界不能单独授予删除资格。需要原生清理能力时,应先核对提供方是否支持相应路径;没有明确契约,就不能宣布任意删改后仍保持同等接续。

这也改变预算。携带工具的思考历史进入有效输入,后续再次提交会影响窗口和用量。生成上限按接口覆盖思考与答复,不能把可见文本当作全部输出。只记录任务真实返回的 usage,不为本章补造命中率、价格节省或思考保留收益。

保留规则之外,另一种接续方式是把任务挪到新会话。新会话交接是在合法结束后,用经过接受的任务材料初始化新的逻辑会话。它不是原会话内部把历史偷偷改成摘要,也不是自动恢复旧执行者。最小形态是保留原记录、接受交接材料、绑定当前条件和工具映射,再由新的调度检查决定是否可以推进。

先让旧动作结束。已经确定的效果保留动作与产物证据;未处理调用按原链完成处理或停止;存在未知效果时,先核对,不能把“尚不知道”写成“未发生”再让新会话重做。只把旧窗口关闭,不会取消后台效果,也不会证明没有旧执行者继续工作。

原会话记录按保存契约保留,包括完整调用关系和需要核对的接续项。新材料说明当前目标、全部有效纠正、精确字段、证据引用、已接受决定、未决点及限制。它作为当前任务输入进入新会话,不伪装成从旧模型返回的助手消息,不把人工摘要伪装成签名或不透明接续对象。

已接受交接(accepted transfer)是宿主校验并绑定版本的交接表示,不是模型说“交接完成”。它至少关联原记录、当前目标修订 goal_revision、采用的上下文版本、schema 与实现映射。旧工具名相同不证明新定义兼容;来源引用也需确认在新请求范围下可以读取和发送。

新调度检查当前授权、任务归属、旧动作状态以及是否还有旧更新者。复制消息不复制调度资格;交接也不自动恢复历史授权。第3章在目标变更时停止旧任务;读者另行启动 CLI 才会创建全新 run,并不接手旧动作。本章限定在单一协调者、旧动作已结束的场景;跨重启和多更新者的接收规则由第11章建设。

新会话可以减少协议历史负担,但不保证推理连续或语义完全等价。它可能需要重新判断,并增加模型调用与验证成本。只有在旧记录保留、必要信息可恢复且新任务条件成立时,才是一种明确取舍,不是绕过提供方原会话保留要求的字段技巧。

9.6压缩候选的验证与提交

允许压缩普通历史时,先提出候选,不直接替换。结构化候选(structured candidate)是按后续任务所需字段组织的较短历史表示。它不是程序侧账本,也不是“语义无损”的证明。最小字段包括目标、用户纠正、精确字段、证据、决定、未完成动作和未知,均关联原记录与来源版本。

目标保留当前有效要求,纠正保留哪些旧条件已失效。精确字段包括不能改写的来源标识、顺序、参数值、版本和必要原文;证据保留定位与核验范围。决定说明采用了什么及依据什么,不把已放弃方案保留为有效指令。未完成动作与未知由程序侧状态投影,候选不能自行归零。

验证先比较可精确检查的部分。可以对照目标修订、来源集合、摘录原文、调用关联和状态字段,发现丢失、变更或引入新事实。然后检查哪些必要依据无法由候选恢复、哪些表达弱化了限制,必要时回到原文。用另一个模型审阅可以增加发现遗漏的机会,但它不能证明所有语义都无损。

校验保证只到声明的有限字段和规则。hash 相同能绑定候选版本,不能证明候选含义完整;字段齐全也不证明概括保留了全部条件。对无法验证的关键判断,应保留精确原文或可展开引用,而不是用更强的成功措辞代替验证。候选不满足条件时,保留旧表示并报告原因。

提交在控制边界核对采用的旧上下文版本仍有效,再把通过检查的候选作为新版本使用,并保留回到旧记录的路径。生成候选以后收到用户纠正,不能把旧目标下的结果直接提交。串行实现可以在同一协调者边界检查;有并发更新者时,版本比较与提交必须满足第11章的接收规则,不能先检查后任意覆盖。

以下是组装器在单一协调者边界内应遵守的提交示意。候选已完成结构与证据检查,比较值来自程序侧快照;它不是随书 commit_compression 的源码。示意最后选择新输入,而该函数只检查条件并返回新修订,两者不能混作同一项已实现能力。这些检查也不证明语义无损。

if in_flight or unresolved_calls or not adapter_allows_rewrite:
    raise ValueError("当前边界不允许改写")
if (candidate["base_version"] != current_version
        or candidate["goal_revision"] != current_goal_revision):
    raise ValueError("候选基准已失效")
if candidate["exact_fields"] != required_exact_fields:
    raise ValueError("必留字段改变")
if (candidate["open_actions"] != state_projection["open_actions"]
        or candidate["unknowns"] != state_projection["unknowns"]):
    raise ValueError("状态投影不一致")
selected_context = (current_version + 1, candidate)

全部检查通过才选择新表示,失败不改旧选择。提交后仍须核对效果,缺信息时展开原证据,或在当前条件仍成立时回到旧表示;不重放动作。完整过程是“提出→校验损失与比较→版本提交→失败保留旧”。

9.7容量、成本与效果的比较

触发表示变换,应看当前完整输入、下一次预计增长和合法接续所需余量,不给所有任务统一的“达到某个百分比就压缩”配方。无法继续合法往返时应停止或走已支持的处理路径;阶段尚未结束,不是允许突破窗口的理由。

比较沿同一任务和同一验收条件进行。基线可保持第3章原有保留策略,候选分别采用有版本的折叠或允许的普通历史压缩。记录实际完整载荷、输入输出 tokens、请求次数、可取得的缓存细分、展开次数、耗时和最终验收;没有真实请求就只报告结构验证,不填实测缓存数字。

成本使用第2章日期化统一基线重算实际用量,调用时账单另核对。压缩请求、展开请求和外部存取费用都应进入总口径。一次输入变短而总请求增加,未必更便宜;中部改写损失前缀复用,也要作为实际条件观察,而不是预先承诺某个节省比例。

效果同时检查有效纠正是否保留、原文是否准确、拒绝与未知是否仍明确,以及后续是否重复副作用。窗口装得下只证明容量条件,不能证明所有必要材料都被正确利用。只有资源与任务结果一起比较,才能判断这种表示是否值得保留。

配套实践

随书 book/v2/practices.py 把本章几项可精确检查的条件做成小型函数,没有接管原 Harness.history。Material 保存的是进程内的原文字节;fold 生成 MaterialRef,引用包含整份原文的 hash、来源版本与 [start, end) 字节范围。expand 先核对同版与整份原文 hash,再由 read_slice 取得有限片段。原文仍只在内存里,没有持久结果库、跨重启取回或自动工具展开。

start、end 的单位是 bytes,不是字符。范围合法不保证落在 UTF-8 字符边界,切片可能截断一个中文字符。函数返回对应原始 bytes,能够核对字节,却没有保证任意片段可解码成完整文本。要将片段作为文本使用,调用方还须选择合法编码边界;不能把此例宣称为完整文本保真。test_read_slice_byte_offsets 与 test_fold_expand_reference 检查的是字节范围和同版展开,其他用例检查版本、hash、范围与输出上限。

Budget.check 真正测量并限制的是 bytes_limit:折叠时检查短引用的编码字节,展开时检查片段字节。它另将解码后字符数除以4并向上取整,得到 token_estimate;这只是粗略教学估计,对中文尤其不可靠。用于估计的替换解码不改变函数返回的原始 bytes,也不修复字符截断。token_estimate_limit 不是精确 token 额度、窗口保证或 KV 用量,单项字节检查也不能替代最终完整模型载荷的检查。

Snapshot.capture 固定 revision、goal、规范化的 fields_json 与 unknown。CompressionCandidate 带上这些条件和候选 summary;validate_compression 精确比较基准版本、目标、字段字节及未知项,只检查摘要是字符串。返回的 structure_verified 只到这些条件,semantic_lossless 明确为 unknown。字段相同不证明摘要重述了全部事实、纠正或限制,更不证明所有历史格式、签名与不透明接续项都能压缩。

commit_compression 再核对预期修订与候选条件,返回修订号加一的新 Snapshot,原对象不变。它不保存 summary,不自动选择新的模型输入,不替换 Harness.history,也不提供持久提交、分布式 CAS 或完整 compression service。test_compression_cas_one_coordinator 验证的是单一可信协调者下的版本检查与失败拒绝,不是并发平台或自动历史压缩已经建成。

源码与测试均在随书包内,从项目根目录可运行:

python3 -I -B book/v2/practices.py --demo
python3 -I -B book/v2/test_practices.py

--demo 只打印合成示意,不调用模型;测试入口会留下本地证据。本轮该局部实践套件39项通过,包含契约转换、引用、压缩结构、对账等检查,不能把总数当作本章所有历史与接续规则的验证。没有真实模型 usage、缓存或账单数据,不据此报告价格节省、性能提升或语义无损收益。

9.8本章判据

  • ☐是否分别定义输入驱逐、可展开折叠、有损压缩和持久删除,没有把它们都叫摘要?
  • ☐是否按重要性与同版可恢复性选择提纲、引用和持久原文,没有删除未保存的唯一证据?
  • ☐短引用是否关联原文、hash、来源版本、读取范围、原取得时间和发送范围?
  • ☐展开是否先限定范围、复查许可并核对同版,重查是否明确是新观察,副作用是否不能重做以取回输出?
  • ☐未完成调用与结果是否保持合法配对,状态账本是否独立,未知是否不能被摘要改成成功?
  • ☐是否区分可见思考、推理摘要、签名和不透明接续项,没有假定所有提供方具有相同字段?
  • ☐DeepSeek 携带 tools 的历史推理是否按契约完整回传,包括没有实际调用和跨用户 turn 的历史?
  • ☐原会话必留字段是否未被压缩替代,新会话是否在旧动作结束、记录保留、交接接受并通过新调度检查之后才开始?
  • ☐候选是否按有限字段校验并绑定版本,失败是否保留旧表示,并发提交是否留待可靠接收机制?
  • ☐变换是否仅在控制边界使用,比较是否同时报告同一任务的实际用量、基线成本和验收效果?

本章没有回答什么

本章没有实现提供方推理内核、原生压缩协议或签名机制,也不保证普通历史摘要语义无损。接口强制保留的字段按接口处理;方法示意不表示第3章已支持自动折叠、展开、思考模式或旧动作续跑。

本章没有处理并发更新者、跨重启认领和未知动作的自动恢复。这些不是压缩历史就能取得的资格,第11章专门建设。输入缩短解决的是容量、重复成本和信息组织的一部分,不代替执行边界、证据核验与完整任务评测。