第 57 章 毕业项目:交付一个可评测的个人知识助手
米拉正在安排一次虚构的北京差旅。她要查出行日期适用的住宿限额,看到规定这个限额的原文,再确认自己的订单状态。回答流畅当然有帮助,前提是它能支持正确的判断。如果助手信心十足地引用旧制度、泄露同事的订单,或悄悄重复执行取消操作,文笔再好也不能算完成了任务。
我们已经有了能回答其中一些问题的服务。毕业项目要解决的是:现有证据究竟支持它作出哪些承诺。本章沿正常请求和异常请求验收同一个助手,不再另起一个聊天程序。前置包括第 33 章的选型实验、第 38 章的回答契约、第 46 章的 RAG、第 49 章的恢复机制,以及第 50—56 章的评测、治理、安全与服务实践。动手前先完成 HTTP Primer。默认实践路径使用 CPU,不需要模型账号。
57.1 先决定助手可以作出什么承诺
Section titled “57.1 先决定助手可以作出什么承诺”需求要写成用户能够判断的条件,不能只写组件名称。“使用 RAG”并没有告诉米拉究竟适用 600 元还是 750 元。本项目的要求是:给定明确日期,从有效的虚构制度中回答,显示单位和准确的来源行;支持结论所需的信息缺失时,不作答。2025 年的规定是每间每晚 600 元,从 2026 年 1 月 1 日起替换为 750 元。更新后,查询历史日期仍须得到正确结果。
订单另有要求。读者通过身份验证后,只有订单的租户和所有者都与宿主确认的身份一致,才能读取。两个租户都可能有一张叫 A-104 的订单;知道编号不等于有权查看。网页服务只提供读取操作,没有取消订单的接口。前面实现的审批后取消仍作为独立的本地恢复练习,保留其审核人、具体动作、对象版本和回执。读到审批制度,不等于获得了批准。
表 57.1——需求、威胁与人工责任。 这里的人物、订单和制度均为虚构。
| 用户需求 | 什么可能使它落空? | 验收证据 | 人工责任 |
|---|---|---|---|
| 日期、金额和单位与引用原文一致 | 上下文过期、适用范围缺失、来源文字误导 | 当前日期、生效边界和历史日期案例;逐项核对引用 | 制度负责人批准来源变更 |
| 只能查看自己的订单 | 猜编号、在问题中指定租户、凭据被盗 | 拒绝跨所有者和跨租户读取;身份由宿主确定 | 权限管理员发放和撤销凭据 |
| 停止提示和错误提示符合实际状态 | 取消后又显示迟到的结果;写入回执丢失后重复操作 | 终态测试、工作进程停止记录、回执恢复 | 运行负责人调查尚不确定的副作用 |
| 能撤回有问题的候选版本 | 评测没有绑定版本、数据不兼容、在途工作被遗漏 | 候选摘要、评测门拒绝记录、切换与回滚日志 | 发布负责人决定使用范围和回滚条件 |
| 反馈能改进后续测试,又不泄露用户信息 | 报告者自行选择是否反馈;原始私密内容被复制进测试集 | 隔离待审、明确审核、删除和独立回归案例 | 审核人判断报告究竟支持什么结论 |
这张表就是一个小型的威胁模型(threat model):列出要保护的对象、可能受损的方式、限制操作的边界,以及仍然掌握决定权的人。威胁不只来自用户提问。检索文档、工具结果和 Skill 引用材料也包含文字。这些文字可以作为证据,不能变成新的授权。本演示信任本地进程、运行者和已经审核的仓库文件;恶意的本地管理员不在这条防护边界内。公开的演示凭据也不是生产环境的秘密凭据。
因此,本项目的验收范围很明确:在本地运行,支持两种语言,处理一个小型、带日期的制度集合,并只读查询虚构的本人订单。广泛的同义表达覆盖、任意私有文档导入、公开的多用户托管和自主修改订单,都不在已接受的需求内。这个范围必须写进 System Card,不能成为掩盖失败样例的借口。
57.2 把一个回答追到证据源头
Section titled “57.2 把一个回答追到证据源头”例 57.1——验收一条 750 元的回答。 输入如下:北区租户的演示读者提出“Beijing lodging”,日期为 2026-09-14,主题为 travel,语言为 en。固定集合有五张来源卡,保留最初的 A—E 顺序。两份住宿制度各有不同的有效区间。现在要判断的,不只是响应里有没有 750,而是需求经过每一道边界后是否仍然成立。
HTTP 处理程序先把演示凭据映射成宿主掌握的身份。请求正文不能选择租户。业务层检查四个请求字段、该用户的限流额度和全局工作上限,再为这次请求保存一份发布清单快照。响应 202 分配了请求 ID,此时还没有答案。有了这个 ID,米拉的界面可以读取进度,再获取结果,无须重复提交任务。
缓存未命中时,工作进程复用已有的 RAG 实现。对于当前日期,先按有效期排除 2025 年的住宿来源,再用保留的 BM25 规则排列其余有效卡片。排序用于选择证据,分数本身不能证明事实。上下文带入来源的三行原文:范围与单位、生效日期、金额。本地回答程序抽取这些原文,构造回答对象。这条默认路径不运行神经模型。
结构化输出检查负责核对字段和允许的状态。支持性检查还要核对来源、版本、行范围、逐字引文、适用日期、完整范围和金额是否一致。经过审核的来源核验 Skill 会运行辅助程序,报告证据是否支持回答。全部通过后,工作进程才提交最终结果。界面把答案和引文当作文本显示,并给米拉看来源版本和日期。服务为运行者记录清单身份、各阶段和最终结果,不把内部实现检查表搬进用户界面。
- 应用保存的记录宿主:北区租户 / 米拉
- 模型之外有效来源:travel-v2,第 1—3 行
- 处理步骤结构、支持性与 Skill 核验
- 应用保存的记录每间每晚 750 元,附引文
默认抽取路径的神经模型调用为零。通过的 trace 解释这次回答,不能证明所有问题都能答对。
- 应用保存的记录所有者不符 → 拒绝
- 应用保存的记录词法未匹配 → 不作答;保留漏检
- 处理步骤旧规则候选 → 拒绝;本地回滚 600 → 750
同时保留独立预期、实际结果与人工负责人。平均分不能抵偿权限违规。
图 57.1 把请求连接到两类不同的证据。上方说明某个答案为什么被接受,下方检查边界受到挑战时,服务是否仍符合要求。上方跑通一次,不能代替下方的验证。
实际 HTTP 记录中,这个输入得到 answered、750 和 travel-v2,对应的中文请求也是如此。只把日期改到 2025 年,结果就变为 travel-v1 中的 600。询问火山时,结果是 abstained,没有引文。这些是 data/part-ix/service-run.json 保存的本地实测,不是语言模型通识能力的测量。完整请求、事件和结果均已保留;影响判断的关键事实也直接写在正文中。
第四个请求暴露了局限:“overnight accommodation ceiling”同样得到 abstained。语料里有相关制度,但这个范围较窄的词法检索路径不能从这种问法找回它。不作答避免了编造金额,却仍未满足用户查询已有信息的需求。我们保留这个样例,不把同义词补进词典后悄悄替换测量。若要增加改写规则,就应给规则一个新版本,用成对案例比较,并检查它是否把历史问题变成了当前问题。
57.3 系统长大以后,对照仍要公平
Section titled “57.3 系统长大以后,对照仍要公平”项目从检索起步,所以最早的对照仍然保留。KA-0 的每种方法都使用同样的九个问题、五张卡、候选顺序和成功标准。首选来源符合预期就算成功;对于范围外的问题,按规定返回空结果也算成功。这衡量的是来源选择,不是后来服务中的回答与权限任务。
表 57.2——重新运行未改动的词法对照。 每种语言都以九个问题为分母,表内为成功个数。
| 方法 | 英文 | 中文 | 与上一行相比,改变了什么? |
|---|---|---|---|
| Keyword 关键词重合 | 5/9 | 5/9 | 统计匹配的不同词项 |
| BoW Count 与余弦 | 6/9 | 6/9 | 保留重复次数,并归一化向量长度 |
| TF-IDF 与余弦 | 7/9 | 7/9 | 进一步降低常见词的影响 |
例如,七次成功、两次失败,得到 。分母是九个问题,不是五篇文档,也不是词数。两种语言使用各自对应的固定内容资源。本次实际复跑仍得到 5、6、7 次成功。后来的系统即使用了日期筛选和 BM25,这份范围有限的同集对照仍然有价值。不能把十个案例的发布门说成从 7/9 提升到 10/10:任务和分母已经不同。
模型选型也保留了不利结果。第 33 章训练的两个 Mini GPT 候选没有满足声明的双语 KA-1 回答契约。第 38 章则把格式适配与事实正确分开检查。它们的运行记录和检查点来源继续进入证据包;本部分没有重新训练。当前服务选择抽取式回答,是因为这个小范围内的答案能够直接核验,代价是放弃流畅的通用综合回答和广泛的同义表达覆盖。这不证明所有个人助手都应该选择抽取式方案。
第 47、50 章的可选 Qwen3 模型运行仍作为历史证据,分别支持受限的决策适配器与裁判实验。后一个实验在作者编写的差旅校准材料上匹配了 8/8 次呈现,却在另一组公开人工判断对照中只一致了 0/4。四个差旅案例的重复呈现,不等于八份独立人工判断。这两种结果都不足以让该裁判掌握毕业验收的决定权。默认发布门使用独立编写的预期状态、金额和来源,本次不新增神经模型调用。
例 57.2——为什么一个“毕业总分”会误导。 假设某份报告把 TF-IDF 的成功数、好候选的发布案例成功数和拦下的攻击数相加,得到 ;再除以 ,宣布质量达到 。算术没有错,这个量却没有约定好的含义。选对来源、给出符合日期的答案、拒绝一个恶意提议,是三种不同事件。攻击案例由作者刻意构造,发布案例又反复使用同一个很小的制度集合。多复制一些容易的案例,就能提高总分,却未必改善米拉的体验。
这些分母应分别保留。第 50 章注入故障的两个变体,端到端都通过了 3/4,但一个最先在检索处失败,另一个最先在回答生成处失败。本次毕业复跑仍保留这两种不同的首个失败位置。要尝试什么改动,取决于诊断,不取决于最后那个百分比。即使几千个简单的制度问题全部通过,一次越权也仍然可以成为停止发布的条件。
57.4 挑战权限和恢复边界
Section titled “57.4 挑战权限和恢复边界”例 57.3——相同的订单编号,不代表同一张订单。 北区租户的米拉查询 A-104,得到 processing;南区租户的里奥查询 A-104,得到 shipped。这是两个不同虚构租户记录的本地实测结果,不是模型自相矛盾。宿主先把身份与对象编号结合起来,再读取存储。米拉尝试查询别人的订单时会被拒绝。若在原本只有四个字段的 HTTP 请求中额外加入 tenant: "south",则会因正文不符合契约而被拒绝。
服务不缓存订单读取。制度回答的缓存键包含租户、用户、权限范围、完整请求和发布摘要;使用缓存前还要重新鉴权。CPU 回归也检查了另一租户不能读取已知的任务 ID。把订单按钮藏起来,并不能建立这些性质:直接发送 HTTP 请求时,检查也必须成立。
毕业验收还通过真实子进程,重新运行了前面的只读 MCP 交换。程序发现唯一的读取工具,读取属于该用户的 A-104 快照,拒绝 B-205,并把 cancel_order 当作未知工具拒绝。这条教学传输使用较早的 KA-3 快照;HTTP 服务使用后来加入租户检查的 KA-6 存储。不能把两套快照说成同一个实时外部订单系统。记录中明确保留了协议子集、版本和交换内容。工具注解描述预期用途,宿主的强制检查才建立权限边界。
随后,六个固定攻击案例比较了故意不设防的样例路径与受保护路径。它们分别尝试给出错误的当前金额、借文档要求外传数据、在工具结果中夹带取消指令、在 Skill 引用中指定租户、输出受禁止的虚构秘密,以及把输出当作活动 HTML 执行。六个案例都突破了不设防的本地样例,本次没有一个突破受保护路径,也没有发出外部请求。这说明列明的控制挡住了这些提议,不能用来估计它们面对适应性攻击者的成功率,更不能为任意模型 Agent 认证。
例 57.4——响应丢失,不会抹掉已经执行的取消。 独立的审批写入练习先提交一次虚构的取消,再注入响应丢失。请求进入 UNCERTAIN,订单却已经发生一次副作用。重新打开 SQLite 存储,恢复同一个已批准的意图,会复用原回执。最终副作用计数仍为 1,请求进入 DONE。读取保存的 trace 新增 0 次修改。补偿仍停留在 manual_review,自动业务写入为 0 次。
这里有三种不同观察:调用方尚不确定、业务存储已经提交、旧记录正在被回放。它们都不是第二次授权。新的幂等键可能表示一个新意图,从而绕开重复抑制;超时后随手生成新键,不叫恢复。HTTP 演示完全不开放这条写入路径,同时把它已有的恢复证据保留在项目中。
57.5 让验收决定能够复核
Section titled “57.5 让验收决定能够复核”表 57.3——毕业项目证据表。 “本次”表示本部分实际执行;“保留”表示核对文件哈希后的早期实测证据。
| 需求或主张 | 证据与观察结果 | 决定及剩余边界 |
|---|---|---|
| 复现基线 | 本次同集对照:两种语言均为 5/9、6/9、7/9 | 保留原始语料和漏检 |
| 选择回答程序 | 保留 Mini GPT 选型失败;本次运行来源核验后的抽取回答 | 接受小范围回答程序;不声称通用模型质量 |
| 按日期返回结构正确、带引用的答案 | 本次当前、历史、生效边界及证据缺失案例 | 接受这些案例;同义问法漏检仍未解决 |
| 强制只读权限并恢复已审批写入 | 本次 20 项权限矩阵、只读 MCP 交换、一次副作用的回执恢复 | 接受已测试边界;网页仍无写入功能 |
| 抵挡固定攻击提议 | 本次 6 个受保护案例;同时保留不设防对照 | 接受这组回归;适应性攻击覆盖仍有限 |
| 让服务可用 | 实际 HTTP 取消与错误记录,双语键盘和浏览器检查 | 本地演示;不声称完成全部辅助技术合规验证 |
| 控制发布和故障 | 发布门 10/10、10/10、4/10;拒绝旧规则候选;600 → 750 回滚;熔断后恢复 | 本地配置演练;不声称验证了可执行文件或数据迁移回滚 |
| 治理报告与运行观察 | 分类报告隔离待审、维护者审核后加入回归、删除;明确 SLO 窗口 | 小型内存监控;不估计生产可用性 |
在表 57.1 的范围内,可以演示本地候选:必要边界已有可执行证据,失败也有负责人。强制使用旧日期的候选未通过发布门,应被拒绝。回滚演练只在受控本地环境中刻意绕过这道门,随后记录错误的 600 元回答、恢复后的 750 元回答,以及仍返回 600 的旧在途请求。决定回滚时,必须考虑已经按错误快照接受的工作。
故障演练还说明,不能凭表面表现宣布毕业。在刻意损坏的窗口里,五个符合条件的任务只有两个好结果,比例为 40%。半开探测成功,使后续调用恢复,却不会抹去先前的三个坏结果。这验证了监控和恢复路径能暴露注入的事故,不是说 40% 可以成为面向用户的 SLO,也不是说随后短暂成功就证明了生产就绪。
本部分开发过程中实际发现的失败也留下了记录。一次取消最初被记成了下游故障,因为 Python 的 InterruptedError 落入了范围更大的 OSError 处理分支。行为断言暴露了这种误分类;修正后的 trace 记录工作进程停止,不再多出那条故障事件。首次服务浏览器测试中,四项检查失败,原因是界面期待 order_id,存储却提供 id。现在由服务边界把存储字段映射成公开结果,复跑后六项服务浏览器检查全部通过。这些修复有明确的代码原因和可重复的触发条件,不是从监控趋势推断出来的因果结论。
57.6 交接能运行的项目,也交接尚未解决的问题
Section titled “57.6 交接能运行的项目,也交接尚未解决的问题”证据包围绕同一个共享助手组织。实现放在 code/knowledge-assistant/,不会每个部分再复制一套。code/part-ix/README.md 给出干净 CPU 环境的配置、测试和 Notebook 命令。data/part-ix/ 保存独立预期、实际请求与故障和发布记录、候选清单及执行哈希。两份已执行的 Notebook 让实践读者不借助付费 API,也能重建服务与运维观察。打印出的结果证明代码执行过,不能仅以 Notebook 可以打开作为验收。
英文交接文件 docs/part-ix-capstone.md 把需求对应到这些材料,并记录评测决定。配套运行手册说明启动、健康检查、故障诊断、切换和回滚。Data Card 记录虚构来源、不可覆盖的旧版本、允许用途和删除范围。System Card 记录默认抽取路径、宿主权限、资源上限和不接受的主张。Risk Register 为每项风险列出负责人、缓解办法、证据与尚未解决的条件。许可和依赖清单分别列明原创 CC BY-SA 4.0 正文、数据和图示,Apache-2.0 代码,以及第三方组件。哈希能标识字节,不能赋予许可,也不能证明文件安全。
运行者应当能借助这套材料回答具体的事故问题:哪个请求失败了,它保存了哪份清单,最先在哪道边界出错,副作用有没有提交,还有哪些请求在途,以及恢复判断由什么证据支持。如果必须依赖原作者回忆某个没有记录的步骤,交接就没有完成。仅有候选文件,不能恢复已经修改的可执行文件,也不能逆转数据库迁移。本地演练切换的是兼容配置,这项限制已经明确记录。
一些责任仍然属于人。制度负责人批准未来的来源版本;考虑服务真实用户前,权限管理员建立真实身份管理;维护者审核反馈和回归变更;发布负责人取得新的负载、安全和无障碍证据后,才决定是否扩大使用范围。当前的标准库 HTTP 服务器、公开演示凭据、有界内存任务存储和单机测试没有提供这些缺失能力。它们足以完成声明的本地练习,不能暗中充当工业部署模板。
本章之后独立的多模态选修不是毕业验收缺项。加入多模态也不能修复同义问法漏检、权限缺陷或未经验证的回滚。下一步该做什么,应由证据决定:选定一个尚未满足的需求,保留基线,提出范围明确的改动,再同时检验新案例和旧责任。
57.7 本章小结
Section titled “57.7 本章小结”一个完成的助手,意味着它作出的承诺有证据支撑。我们从身份、证据与验证追踪了一条带日期的回答,用异常请求挑战权限边界,并区分旧记录回放与已提交副作用的恢复。未改动的词法基线、被拒绝的模型候选、实际服务观察和本地发布及故障演练,各自保留了自己的含义。毕业验收接受已经演示的小范围能力,同时保留漏检、风险和必须由人作出的决定;它不能把一组通过的检查变成普遍可靠性的证明。
57.8 习题
Section titled “57.8 习题”- 一份拟加入的 2027 年住宿制度把限额改为 800 元。接受它之前,需要哪些历史、生效边界和当前日期案例,哪些缓存与版本变更,以及谁的来源批准?为什么不宜直接改写
travel-v2? - 一份报告把 20 次检索中的 18 次成功,与同一个攻击重复 100 次且全部被拦下的结果相加,宣传质量为 118/120。计算这个比例,再指出它不能代替发布决定的两个原因。
- 已批准的取消操作丢失了响应,界面显示“请重试”。宿主必须保留哪些信息?此时可以怎样准确告知用户?为什么生成新的意图键很危险?
- 加入改写规则后,同集的同义问法回归有所改善,但一个历史问题开始得到 750。候选应该通过吗?说明决定性的需求、应保留的对照,以及下一项范围明确的实验。
- 维护者拿出六项浏览器检查、十个发布案例和一次成功恢复探测,认为可以把服务公开托管。指出三类仍缺少的证据或能力,并区分“能力尚未具备”与“本地测试已经观察到失败”。
57.9 参考解答
Section titled “57.9 参考解答”- 保留新生效日期之前、恰好生效当天、之后的案例,并继续运行原来的 2025 和 2026 年查询。若新制度从 2027 年 1 月 1 日生效,2026 年 12 月 31 日仍应返回 750,2027 年 1 月 1 日及之后的日期则应返回 800,并引用新来源、单位和行范围。由制度负责人批准虚构规则及其有效区间。新增带版本的来源,更新有效性筛选、索引和发布哈希,把缓存项绑定到该版本,不能让旧回答覆盖新时段。直接改写旧来源会破坏基线,还可能使过去的回答无法核验。除了新案例,还要运行权限、支持性和故障回归。
- 。检索正确与拦下攻击提议采用不同的评价单位,相加后没有声明好的用户含义。同一个攻击重复 100 次,也没有增加 100 个独立威胁条件,反而让这个容易的案例主导数字。应单列 18/20 的检索结果,另行说明那一个攻击条件及重复次数。无论总分多高,权限违规仍可能阻止发布。
- 保留已经验证的身份、获批的具体动作、对象版本、原意图及幂等键、有效期、尝试与截止时间预算,以及持久回执查询信息。告诉用户系统正在确认是否完成;没有收到响应,不能说明操作失败。先用原意图核对回执,再判断是否允许重试。新键可能被理解为新的已授权意图,从而允许再产生一次副作用。单纯读取 trace 不会修改业务,也不能解决业务回执缺失的不确定状态。
- 不应该。按日期回答是必须通过的门槛,同义问法的改善不能抵偿错误的历史金额。保留旧规则、完全对应的输入、预期来源和两种结果。下一项实验可以检查改写是否在检索前保留了明确日期和主题:用只在日期条件上不同的当前与历史改述来测试。候选恢复日期正确性后,再用同样的新旧案例比较。
- 例如,真实凭据的发放与撤销及租户管理;合适的加固服务栈和独立权限审查;具有代表性的持续负载与恢复测试,以及持久监控;超出当前键盘和浏览器检查范围的辅助技术与用户测试。这些属于缺失能力或尚未测试的场景,不说明已经记录的本地案例失败。同义问法漏检则是实际观察到的功能局限。一次探测成功只说明一次调用恢复了,既不会补齐这些能力,也不能估计长期可用性。
本部分概念检查点。 用一个正常请求和一个异常请求向同事解释服务:谁掌握身份,为什么 202 不代表完成,什么时候可以展示引用,取消确认说明了什么,评测怎样绑定发布,回滚留下哪些在途请求,缓存命中为什么还要检查范围,SLO 分母应该包含什么,以及谁能把反馈变成回归案例。最后指出一项本项目尚无资格作出的承诺。
本部分检查点解答。 宿主对每个请求验证身份并检查权限;202 是完成之前对工作的接受。默认工作进程抽取有效证据,检查结构与支持性后,界面才展示最终引文。取消请求被接受,说明服务收到停止要求;进入取消终态并停止工作进程,才构成已观察到的结果。清单摘要把候选字节和配置绑定到评测门。回滚改变新请求的去向,旧请求可能继续使用原快照。鉴权之后,缓存键仍须保留身份、日期、请求和发布范围。声明的统计窗口按明确的延迟规则计入符合条件的好坏结果,不能悄悄排除过载,也不能抹去事故。反馈先隔离,由维护者审核独立、经过最小化处理的回归案例后才纳入回归。面向公众的生产服务已经就绪和广泛的同义表达覆盖都尚无依据;保留的同义问法漏检,正是后一项的具体反证。
57.10 参考文献
Section titled “57.10 参考文献”- NIST,Artificial Intelligence Risk Management Framework: Generative AI Profile,NIST AI 600-1(2024)。MEASURE 2.3—2.6 与 MANAGE 4.1—4.3 支持结合使用场景评测、记录局限、处理反馈及明确事故责任。本项目并未获得 NIST 认证。
- Google,The Site Reliability Workbook: Canarying Releases(2018)。解释有限范围试用、对照与回滚需要考虑的问题。本地兼容配置演练没有验证分布式部署。
- Google,The Site Reliability Workbook: Implementing SLOs(2018)。支持明确与用户相关的指标、窗口和错误预算规则;注入故障的短时演练不能估计生产可靠性。
- OWASP,LLM09:2025 Misinformation。支持来源核验与适当的人工审核。仅仅显示引用,不能证明回答正确。
- W3C,Web Content Accessibility Guidelines 2.2。提供标签、焦点和状态检查所依据的无障碍准则。这组小型浏览器测试通过,不等于取得完整的符合性证据。