AI Hero Club

上下文工程 · 第 8 章

已自行标记完成0 / 8

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

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

CHAPTER 08 / 8建议学习 140 分钟

完整交付:从新目录运行与修改

把一份自己的新通知导入项目后,怎样核对预算、版本、引用和重开回放仍然一致?

本章要解决的 3 个问题
  • 从CLI重建资料到回答的完整链
  • 完成持久化、重开、引用与撤销闭环
  • 以冻结证据和独立包验收课程项目
课程项目 ZIP ↓

把章节接成一个可检查交付

本章不再增加新概念,而把前七章变成读者能从新目录运行、修改、解释的项目。入门边界是能运行 Python、读 JSON 和字典;不要求购买模型服务或下载权重。完成能力是:给定一组带版本资料与任务,导入事件、恢复状态、构造日期视图、检索、压缩、实际分词预算、生成带引用结果、验证支持、保存回执,并通过更新/撤销后的同一流程复验。它是受控字段资料编译器,不是开放域聊天机器人。

下载包中 context.py 是机制实现,run.py 是统一入口,tests.py 是验收,vendor/tokenizer.py 与 data/tokenizer.json 是随包分词器实现和冻结表,data/docs、events.json、tasks.jsonl 是原创资料与固定任务。evidence/final 是最终实验,development 系列只是历史。学生执行不读取网页源码或任何兄弟课程,作者章节审计也不属于运行依赖。学习网页是讲解载体,项目 ZIP 是可独立执行的产物,两者用清单关联而不互相偷偷依赖。

调用顺序从明确契约开始。query 提供问题,fields 指明要提取的字段,limit 和 reserve 给容量,as_of 决定事件前缀,at 决定业务日期,scope 决定记忆范围。应用 validate_task 后回放事件,派生 temporal_view,再得到 units 与压缩检查;rank 自动算字面分数,pack 用完整 wire 计数;answer 只发可见且有效 claim,并经全库同字段冲突门与实际输出计数。最终保存输入、输出、token_ids 和所有中间身份。每一步的输出都是下一步可审计的输入。

完整算例一:新目录运行到具体引用

先使用一个没有 memory.sqlite 的输出目录执行 demo。它从真实 Markdown 文件读取,而不是直接导入一组人工答案;每次 import 计算源文件 SHA,逐事件写入 SQLite。十八任务分别回放指定前缀,主配置 time-current 使用前十二事件和固定14日日期,输出 schedule@2:3 的时间。这个引用可回到 schedule-v2.md 第三行复核。正文开销、JSON 结构、出处和特殊标记都已进入实际编码,不拿人工写的“该段30token”当成本。

实际结果中的时间题输入958、输出89,预留240、容量1500。先检查 958+240=1198≤1500958+240=1198\leq1500,说明准入按最大允许输出预留成立;再检查 89≤24089\leq240,得实际总 958+89=1047≤1500958+89=1047\leq1500。这是一条精确容量推导,与是否引用正确分开。支持检查再按当前源版本、SHA、第三行逐字内容和可见集合验证。读者应在报告里分别看到容量真、支持真和覆盖一,不能只看“answered”这个状态。

终端命令解压项目后在项目目录运行。learner-run 与 learner-memory.sqlite 必须是新的;重复用已导入库会被拒绝。
python3 tests.py
python3 run.py demo --output learner-run
python3 run.py import --db learner-memory.sqlite
python3 run.py query --db learner-memory.sqlite --task-id time-current
python3 run.py query --db learner-memory.sqlite --task-id conflicting-time
python3 run.py replay --db learner-memory.sqlite --as-of 6

读自己的任务,而不是只能点固定演示

query 命令同时支持 task-id 与 task-file,二者互斥。最小自定义文件需 query、fields、limit、reserve;可以明确给 as_of=12 来查看未冲突通知。query 必须非空、最多4096字符,fields 非空且字段名无重复,预算是真整数而非 True/False。日期要能解析为 ISO 年月日,未知字段被拒绝,防止用户以为某个拼错参数已经生效。任务字段和业务数据分开,外部 quote 不会被当成任务参数覆盖。

direct CLI 遇到 schema 或数据库错误会显示异常,不伪装成正常答复;evaluate 只把 BudgetError 转成对应任务状态。开发者若把它包装成网页 API,应将 ContractError 与内部错误分成稳定响应,并添加认证、并发与输入大小控制;当前课程没有提供这种服务器,也不让“本地命令行能运行”替代真实服务测试。读者首先应能解释本地结果,再决定是否引入外部模型或网络。

在课程项目目录运行项目目录:真正写入自定义JSON,经子进程CLI进入同一管线,未绕过参数解析。
import json,pathlib,tempfile,subprocess,sys
from run import setup,ROOT
with tempfile.TemporaryDirectory() as d:
    d=pathlib.Path(d);db=d/'m.sqlite';repo=setup(db);repo.db.close()
    task={'query':'活动地点','fields':['活动地点'],'limit':1500,'reserve':240,'as_of':12}
    f=d/'task.json';f.write_text(json.dumps(task,ensure_ascii=False),encoding='utf-8')
    result=subprocess.run([sys.executable,str(ROOT/'run.py'),'query','--db',str(db),'--task-file',str(f)],capture_output=True,text=True,check=True)
    row=json.loads(result.stdout)
    assert row['compiled']['result']['coverage']==1
    assert row['compiled']['result']['claims'][0]['id']=='location@2:3'
print('custom task CLI checked')

完整算例二:一次批准、更新、撤销的闭环

初始完整库里表达偏好已撤销。读者在临时库追加 version=3、scope=club、approved=true 的记忆“先列证据,再解释预算”,关闭连接再重新打开。查询该 key 时 units 仅暴露当前范围内这条第三版记忆;它进入实际 wire、被抽取、通过 source 与 visible 检查,输出引用 memory/club/表达偏好@3。不是程序打印“记住了”就算持久化,必须重开数据库从日志恢复并查出。

随后追加 revoke_memory 指定相同 key、scope 与 version=3,再次查询应 abstain。旧v1与v2不会复活,历史事件仍可通过明确 as_of 查看。整个闭环包含批准意图、实际状态写入、重开回放、预算构建、来源验证与撤销后复测;只展示一个 Python 字典内容无法证明这些环节。这个程序也不把回答自动写成新记忆,避免模型从自己未经支持的文本制造“事实”再用它给自己引用。

在课程项目目录运行项目目录:完整持久化与撤销闭环,临时库不会污染冻结证据。
import pathlib,tempfile
from context import Repository,compile_context
from run import setup,load_tokenizer
t={'query':'表达偏好','fields':['表达偏好'],'limit':1500,'reserve':240}
with tempfile.TemporaryDirectory() as d:
    db=pathlib.Path(d)/'m.sqlite';r=setup(db)
    r.append({'type':'memory','key':'表达偏好','value':'先列证据,再解释预算。','scope':'club','version':3,'approved':True});r.db.close()
    r=Repository(db);a=compile_context(r.replay(),t,load_tokenizer())
    assert a['result']['claims'][0]['id']=='memory/club/表达偏好@3'
    r.append({'type':'revoke_memory','key':'表达偏好','scope':'club','version':3})
    assert compile_context(r.replay(),t,load_tokenizer())['result']['status']=='abstain'
    r.db.close()
print('persist, reopen, cite, revoke, abstain')

对照一条失败的修复流程

先在 final/evaluation.json 找到 head、compressed=true、task=project 的记录。固定所有源文件,改选择策略为 rank,只重跑同一任务:若目标行进入 selected 并恢复 coverage=1,可以把这次差异归因到已声明的选择规则,而不是“换了更聪明的模型”。再恢复 head 保持失败,作为负对照;不要把失败任务从任务表删除后宣布所有配置满分。完整十八题仍应重跑,确认局部修复没有在过期、冲突和范围题上回归。

若想修改资料本身,应导入新版本而非在 SQLite 里原地改 text。事件摘要绑定旧原文,直接替换会破坏链或让来源摘要不匹配。原 Markdown 文件改变但没有重新导入,也不会自动修改已存资料:这是快照外部输入的明确边界。复现时可新建库并导入新清单,保存新代码/数据摘要与逐题报告;旧实验仍留在旧目录,不能把新资料和旧模型/选择结果拼成“同一冻结成绩”。

何时才算这门课完成

先检查二十二项测试,包含非单调 BPE 前缀、Unicode切片、源行与可见支持、篡改摘要、历史撤销、过期、未来生效、冲突、schema及输出预留。再运行 demo 得到十八主任务和一百零八对照,检查 head 的既知失败仍保留、删除证据反事实仍1到0、截断实验仍三分之一。最后从新解压包运行同样验收,不借作者工作区的模块。源码正确与打包独立性是两个不同检查,学生缺一个文件就无法复现。

交付说明还应列出未验证项:远程 LLM NOT RUN、语义向量检索 NOT IMPLEMENTED、通用语义压缩未实现、真实来源认证未实现、多进程并发和断电故障未测。全库冲突门是精确字段文本比较,不推理任意逻辑矛盾;日期元数据由作者提供,不从“本周五”自动推算。完整性不是把系统说成无所不能,而是读者能从输入一路重建结论,并准确指出每条结论依赖哪条假设。

这一最终项目把上下文工程从措辞建议变成可检查的对象:允许状态决定资料域,实际编码决定容量,来源与可见交集决定可发声明,事件日志决定历史,固定任务决定当前验收结论。课程完成的标准是能修改其中一个环节并预测哪个正负对照应变化,再用新的逐题证据检验预测;不是再增加十条口号或把一个演示回答写得更华丽。

文件清单与行为复现的不同证据

最后的project-receipt绑定当前项目源码、数据、冻结输出与章节,每个条目用实际文件SHA计算。清单能检验下载后文件是否与已审计构建一致,但不能单凭摘要证明程序正确。行为复现仍要从干净目录运行测试与demo。反过来,行为输出相同也不代表所有文件都没变:不同注释或重构可能产生同样结果。课程因此同时保存来源清单和运行结果,不把二者混成一个“完全一样”的含糊断言。

修改实验应只变化一个明确环节。比如将rank的k常数从60改为30,保留资料、tokenizer与容量,再预测名次差距和selected是否可能改变;若只改常数却任务结果无变化,也应报告这个负结果,而不是继续换很多项直到找到一个成功案例。将所有修改累积后回头说某一项提高效果,会失去因果定位。小项目的优势就是成本低,可以保留每个候选的真实报告。

读者最终应能独立回答三个验收问题:某条回答具体源于哪一份文件哪一行;这一行为何在该日期与版本前缀可用;完整输入与实际输出各占多少冻结词元。如果任何答案只能诉诸“模型应该知道”,说明这条受控管线的链路还未闭合。能回答它们并不使系统自动成为通用助手,却给后续引入更强模型提供一组稳定接口与可反驳假设,避免效果只停留在一次漂亮演示。

TRY IT YOURSELF

基础:两道容量检查

输入958、预留240、实际输出89、容量1500,写出准入与实际总量检查。

提示 1
先分别写执行前的预留准入与执行后的实际输出限制。
提示 2
先验输入+R≤C,再验输出≤R,从两条不等式推实际总量;支持性与完整性另外检查。
对照参考解答
先958+240=1198≤1500,再89≤240,故实际958+89=1047≤1500。容量成立仍要另验来源支持与任务覆盖。

TRY IT YOURSELF

进阶:持久化证据

打印“已记住”后程序结束,为什么不足?

提示 1
打印消息与数据库提交回执有何不同?进程退出后还应能观察到什么?
提示 2
提交事件后关闭重开数据库并replay,查询同范围同版本记忆,再撤销检查不可见。
对照参考解答
打印不是落库回执。应通过受控append提交事件,重开SQLite并replay,再从units查询同范围同版本记忆,最后检查撤销后不可见。

TRY IT YOURSELF

挑战:项目独立性

学生ZIP里tests导入工作区另一课程的tokenizer,作者机器通过,合格吗?

提示 1
作者环境成功可能借用了压缩包外的哪些依赖?
提示 2
从新解压目录执行检查,确认tokenizer等必要源码与说明随包提供,且不读取兄弟课程或章节文件。
对照参考解答
不合格。必须把依赖随包复制并注明来源,测试从新解压目录执行;既不需要兄弟课程,也不需要作者章节文件。模型边界与分词器约定也应在README里明确。

CHECK YOUR UNDERSTANDING

检验理解

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

1. 自定义任务如何进入管线?

查看解析真实CLI读取同一schema,经完整编译流程。
2. “我记住了”能证明?

查看解析需持久化回执与重开回放检查。
3. 修改源资料正确方式?

查看解析保持历史与新构建的来源一致。
4. 学生验收需作者工作区吗?

查看解析这是标准库离线项目,独立解压可运行。

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