AI Hero Club

上下文工程 · 第 3 章

已自行标记完成0 / 8

仅保存在当前浏览器;完成标记不代表通过项目验收。

本章提纲 6 个小节
全课目录 8 章
完整课程计划 ↗
上下文工程 / 课程计划 ↗

CHAPTER 03 / 8建议学习 140 分钟

保真压缩:原文、限定条件与回退

压缩把一条事实的限定条件删掉了,怎样发现损失并回到原文?

本章要解决的 3 个问题
  • 推导源声明集合相等的局部保真条件
  • 保留原行号与摘要而不虚构通用语义保证
  • 用限定语遗漏触发真实全文回退
课程项目 ZIP ↓

压缩到底必须保留什么

前两章把容量约束变成真实编码长度,也证明裁剪可能留下合法文本却丢掉答案。本章研究更早的一步:资料还没进入选择器时,可否改成更短表示。读者只需会列表、集合和字符串,新增的“保真”先定义为一组可检查的源声明完全保留,而不是任意读者的心理感受相同。最终能力是写出压缩前后对应表,指出哪些信息不可删,并在证明条件不成立时回退原文。

项目把一份文档表示为身份、版本、原始正文与摘要。facts 函数按原始行号扫描,忽略空行和左侧去空白后以井号开头的标题,把剩余每一行都当作待保留声明。这是人为定义的文档语言。它适合本课受控的短通知:标题只是标签,正文完整承载事实;如果真实材料的标题写“仅限未成年人”而正文没写,该假设不成立,必须修改语言与验证器,不能沿用本课证明声称保真。

这里需要三个不同对象。源文档是不可变文本;压缩提案是想留下的表示;用于检索的证据单元是含来源身份、原行号和逐字引文的记录。压缩器提出只保留以“- ”开头的行,验证器却遍历所有非标题行。若提案漏掉其中任何一行,验证不通过,证据单元使用全文。先有完整判据再做短提案,避免让压缩器自己定义“重要信息”并给自己打满分。

一个可推导的保真条件

定义 F(d)F(d) 为文档 d 的非空、非标题原始行集合,每项同时含原行号和文本。提案 P(d)P(d) 是其中以项目符号开头的子集。因为 P 从 F 筛选,天然满足 P 是 F 的子集;再检查差集 F 减 P 为空,便得到 F 等于 P。验证器不是看压缩后词数有多短,而是逐项核对这个集合等式。相同行文在不同行号仍是不同来源位置,不能因为文字重复便误删一个有独立证据身份的条目。

从集合等式可推导下游支持集合相同,但须加条件:source_claims 只按这些完整行生成事实,不跨行做语义推断;版本和日期视图相同;压缩记录仍指向原始摘要与原行号。给定这些条件,全文中每条可抽取事实在压缩单元中都有相同身份、文本和摘要,反向也没有新条目。两边逐条建立一一对应,故可抽取支持集合相同。这是当前数据语言内的精确命题,并不是自然语言摘要普遍无损的定理。

P(d)⊆F(d),F(d)∖P(d)=∅ ⟹ P(d)=F(d)P(d)\subseteq F(d),\quad F(d)\setminus P(d)=\varnothing\ \Longrightarrow\ P(d)=F(d)
d 是固定版本文档,F 为全部待保留原行,P 为压缩提案中的原行。

完整算例一:活动安排保真抽取

schedule 第二版原文包含标题、空行、三个项目符号事实,行号分别为三、四、五。F 含活动时间、活动时长、集合要求三项;P 也含这三项,差集为空。提案正文去掉标题与空行,冻结 BPE 计数从七十三降到五十七,减少十六,正文层压缩比例为五十七除七十三约零点七八。这一比例只是文档文本,不含每个证据单元的来源字段;不要直接拿它宣称整个 JSON 上下文省百分之二十二。

原文行号三的“活动时间:周四16:30。”生成身份 schedule@2:3。抽取后即使它成了压缩表示的第一条,也仍用原行号三。原 SHA 指向整份源文件,不能换成缩短后正文的摘要却继续声称同一源身份。检查时从源版本取第三行,与 quote 逐字比较;读者由引用回到原文件即可复核,不需要相信摘要器的解释。下一章的事件历史会决定这条身份此刻能否使用。

在课程项目目录运行项目目录:用真实函数检查压缩保留原行号。
from context import compress_document,sha
text='# 安排\n\n- 时间:16:30。\n- 地点:B室。\n'
row={'doc_id':'d','version':1,'text':text,'sha256':sha(text)}
c=compress_document(row)
assert c['faithful'] and c['retained_facts']==2
assert c['lines'][0][0]==3
print(c['lines'])

完整算例二:最短的一行可能最关键

access 文件两条项目符号写开放对象与开放方式,最后一行没有项目符号:“有效限制:只在本周五之前有效。”F 有三项,P 只有两项,差集恰是行号五的期限。若盲删这行,程序会把一次临时开放误表示为长期许可。实际提案从一百零四词元降为六十七,看起来更短,但验证失败,units 返回全文。报告把 faithful 标为 false 并列出漏行,使用状态写 full document fallback;没有把未采用的六十七当实际压缩收益。

这个反例同时暴露两个边界。第一,程序不懂周五是哪一天,所以事件元数据还要给明确的日期区间,第四章再计算。第二,保留原行不等于选入模型窗口:第二章的预算器仍可能不选 access 全文。压缩前后源事实集合相等只控制第一种损失,选择后的可见集合检查控制第二种损失。如果把两个阶段合在一个“摘要质量分”里,就难以定位究竟是资料被压坏,还是好资料没装进去。

再考虑一份条件句跨行书写的通知:“可借用相机”下一行“仅限老师确认后”。本课验证器会把两行都视作事实并保留,但下游按字段抽取可能无法理解条件依附关系。因此本课数据约定每行是一条完整、带限定的字段声明,源文档由作者按此约定编写。真实文档迁移应在单元形成时保留完整句群或依赖边,不是只扩大上下文就默认逻辑条件自动关联。

在课程项目目录运行项目目录:删除限定语必须真实触发失败与全文回退。
from context import compress_document,sha
text='# 临时通知\n\n- 开放对象:成员。\n有效限制:仅今天。\n'
c=compress_document({'doc_id':'a','version':1,'text':text,'sha256':sha(text)})
assert not c['faithful']
assert c['missing']==[{'line':4,'quote':'有效限制:仅今天。'}]
print('fallback required',c['missing'])

从同一原文独立检查两种表示

独立检查不复用压缩器的 faithful 布尔值作为答案。测试分别调用 units 的全文模式和压缩模式,经 source_claims 构造三元组集合:来源身份、逐字引文、原文摘要,再比较相等。若压缩器错报成功却漏行,两个集合会不同;若只改原行号或摘要也会失败。这比“函数返回 true”多检查了表示到实际引用的整条路径,但仍共享 facts 的文档语言定义,所以不是对任意语义的独立裁判。

复杂度按本课成本模型计:N 为文档 Unicode 字符数,L 为非标题行数,splitlines 与逐行筛选扫描 O(N)O(N) 字符,保存源行与缺失列表占 O(N)O(N) 空间。实际上下文打包会重复 JSON 序列化和 BPE 编码,其成本单独计算,不能把压缩器线性复杂度误写成全管线线性。我们的受控短材料很小,优先选择容易审计的实现;长材料需要缓存不可变片段、增量索引和重新证明失效规则。

如果把 extractive 替换成 LLM 摘要,应保留提案/验证分离的接口。让模型生成短文本只是新提案机制;还要问每条期限、否定、条件、数值和出处是否存在对应支持。逐字集合相等会过于保守,语义蕴含判据又依赖模型与评估,需要新的正负对照,不能借用这里的集合证明。工程文章中 compaction 的建议是动机输入,本章只对已定义的行式语言给出精确局部保证。

从这一章开始,读者应保留每个失败的最早位置。若候选构造后事实已缺,错误归压缩;若完整候选存在而 pack 没选,归选择;若选中了却答案漏引,归生成或引用校验。阶段分开不是为了给系统找借口,而是让一次改动可以对一个机制提出可证伪的预测。最终评测会保存每个阶段的身份列表,而非只留下漂亮的回答。

证据粒度与排列不是同一保真命题

集合保真有意忽略顺序,因此只能支持本课按字段独立抽取的机制。若资料说“先登记再取走器材”,把两条短句颠倒可能改变执行流程,原集合虽然相同也不能保证行动等价。我们的受控通知把顺序条件写在同一完整原行,不从条目排列推导额外约束。迁移到流程文档时,应把顺序边、条件作用域与否定范围纳入待保留对象,重新定义F,而不是复用一个只验集合的函数。

另一差异是存储保真与呈现保真。源文件不变,抽取后证据单元含逐字quote,源内容可回查;但模型看到的排列、来源头部和重复开销可能变了。因此本课保真压缩不是保证视觉页面毫无变化,也不是保证LLM输出分布不变。它精确保证的是特定抽取关系下支持集合不丢不增。实际选择效果已经单列比较,head在主任务中的失败正提醒我们:一个局部正确性命题不能自动升级成端到端质量提升。

对任意新增正文行,最保守的行为是完整保存并让新模板经过检查。验证器拒绝并不意味着原文不可用,而是当前压缩提案不足以证明可用,所以返回全文。程序宁可在预算阶段明确拒绝装入,也不静默删掉未理解的条件。若未来增加可靠的结构解析器,应同时构造有条件与无条件、否定与肯定、数值改动等成对反例,让“保留同一事实”成为可测试对象,而不是用摘要读起来顺畅当证据。

TRY IT YOURSELF

基础:集合证明

F 有三条原行,P 从中筛出两条。P⊆F 能证明保真吗?

提示 1
P⊆F只排除了新增事实,还缺少检查哪个方向的差集?
提示 2
分别列P−F与F−P,题设丢了一条原行时哪个非空?据此决定拒绝或全文回退。
对照参考解答
不能。子集只保证没引入集合外条目,不保证全部保留;还需 F−P 为空。本例差集有一条,必须拒绝提案或回退全文。

TRY IT YOURSELF

进阶:压缩比例

正文73→57词元,能否宣称全 wire 同比缩短?

提示 1
先将正文成本与包含身份/摘要/字段的完整wire成本分账。
提示 2
正文节省可直接相减,但总比率需分别渲染并编码两版wire;不能把局部比例套到固定包装。
对照参考解答
不能。正文节省16,约21.9%,但证据身份、摘要、JSON 字段开销会重复;必须分别渲染完整 wire 并编码后比较。正文比率不等于总输入比率。

TRY IT YOURSELF

挑战:标题带限制

标题写“仅限周五”,正文两行都保留。当前事实集合检查通过,能否保证真实语义保真?

提示 1
当前facts函数把标题当事实来源吗?先核对形式化范围。
提示 2
给标题加入决定性限制,再比较受控事实集合保持与真实语义保持两个命题;修复需扩解析并回归。
对照参考解答
不能。facts 明确排除标题,保证只对这种受控文档语言成立;应把带事实标题纳入解析与支持检查并补回归例,再重新验证。不能把模型定义遗漏掩盖成现实无损。

CHECK YOUR UNDERSTANDING

检验理解

先作答,再决定是否展开解析。选择题用于发现理解缺口;独立实现与迁移任务仍需另行检验。

1. 压缩保真首先相对什么定义?

查看解析没有明确保留对象,保真无法检查。
2. access 的正文漏行后如何处理?

查看解析实际缺失限定语,必须拒绝该提案。
3. 73→57描述的是?

查看解析来源与 wire 格式的成本另算。
4. 源集合相等仍可能在哪一步丢答案?

查看解析完整候选池不等于被选择的可见子集。

自行标记用于记录学习进度,不代表通过项目验收。