Appearance
第18章 · 评估、可靠性、安全与本地部署门禁
离线 replay/dry-run 不等于 Google Cloud job、Service 或账单通过。
先修:第11章的 RAG 指标、第13章的工具状态机和第8章的 checkpoint。
本章目标
- 冻结版本化 eval manifest,固定样例、分母、终态、工具白名单和失败原因。
- 实现 task success、schema validity、citation correctness、unsupported claim rate、recovery 和 bypass 记账。
- 用人工复核校准 Judge,加入故障注入、trace、容器化和本地 artifact-chain dry-run。
公式与 shape
对冻结样例集合 E:
| 结构 | 关键字段 | 约束 |
|---|---|---|
| eval case | stable ID、category、input、expected terminal state | 冻结后 hash 不可静默改变 |
| report | numerators、denominators、failures、formulas | 分母不能因无调用而消失 |
| trace | event、state、tool、status、checkpoint | 只记录可诊断的结构化字段 |
| artifact chain | dataset/tokenizer/config/checkpoint/metrics/container hashes | descriptor、metrics、checkpoint 每段可回读;不可用 hello-world 替代 |
关键概念与论文绑定
| 概念 | 论文/规范 | 动手输出 / 口述题 | 通过边界 |
|---|---|---|---|
| holistic eval、固定分母与可复现报告 | HELM | 给每个 category 写 stable ID、分子/分母、失败原因和 manifest hash | 一个总分或一次 replay 不能代表全面质量 |
| Judge 只是辅助信号 | MT-Bench / LLM-as-a-Judge | 用固定人工标签计算一致率,列出分歧样例并由人类保留最终判断 | Judge 不能单独写入毕业或安全通过状态 |
| 威胁模型与安全回归 | OWASP GenAI LLM Top 10 2026 | 至少注入 prompt injection、越权、secret exfiltration、工具输出污染,并记录拒绝/失败状态 | 安全清单不是运行时 policy,也不替代副作用计数 |
| artifact chain 与部署可追溯性 | cloud_adapter / Cloud Run 官方文档 | 串起 dataset/config/tokenizer hash → execution → checkpoint → image digest → revision → authenticated generation | 任一段用 placeholder、fixture binding 或本地 revision 都不能升级为云通过 |
中文复习可参考 LLMs-from-scratch-CN 和 dive-into-llms 的评估/部署章节;只用于术语对照和问题清单,不能复制正文、图或代码,亦不能把中文材料的示例数字当成本仓库的 evidence。
数学桥接:第2章 → 第18章
第18章的评估框架和 artifact chain 建立在概率估计和信息论之上:
Eval 指标与 mle_bernoulli:第2章 §5 的 mle_bernoulli(trials) 用成功次数除以总试验数估计概率。第18章的 success = #achieved / |E| 和 schema = #valid / max(1, #attempts) 就是 MLE 在 Bernoulli 分布上的直接应用——每个 eval case 是一次独立的伯努利试验,分子计数是"成功"次数,分母是总试验次数。max(1, #attempts) 避免分母为零时的未定义行为,等价于 Laplace smoothing 的极端情况(α=1)。
Judge 与 cross_entropy:第2章 §6 的 cross_entropy(p_dist, q_dist) 衡量两个分布的差距。LLM-as-a-Judge 的"一致率"可以看作 Judge 输出分布和人类标签分布的"近似度"——如果 Judge 的预测和人类标签的 CE 很低,说明 Judge 的信号可靠;如果 CE 很高(分歧多),说明 Judge 需要校准。
Artifact chain hash 与确定性:第2章 §3 的 partial_derivative(f, x, x0, eps=1e-6) 用有限差分验证梯度——相同输入 + 相同 eps 必须给出相同结果。Artifact chain 的 hash 链(dataset → config → checkpoint → metrics)的语义是"相同训练配置 → 相同产物"——如果有人悄悄替换了 dataset 或 config,hash 会立即 detect 到变化。这不是"防止篡改",而是"让篡改可被检测"。
前端类比:eval manifest = npm lockfile——冻结所有依赖版本,保证 npm install 在不同机器上产出相同的 node_modules。Judge 校准 = A/B 测试中的显著性检验——人工标签是 ground truth,Judge 是一组预测器,一致率就是 accuracy。Artifact hash = Git 的 content-addressable storage——相同 blob 永远映射到相同 SHA-1。
交互观察
交互:OWASP LLM Top 10
点任意一张卡片,看「症状 → 修复」。把它当成 LLM 应用的威胁建模 checklist用。
点上面任意一张卡片查看详情
逐张点开卡片,把每条风险映射到本仓库已有的可观察防线(ACL 前置、批准 token、副作用前 checkpoint、离线 replay);映射不出来的项就是本章安全回归要补的 fixture。组件内卡片是教学快照(2025 版清单),规范条目以下方「论文与延伸」链接的 2026 版为准;浏览器导览不等于安全测试通过,注入样例仍须在 pytest 里真实失败再修复。
动手任务与验收(从零实践)
读取
eval/eval-spec-v1.yaml,确认稳定 ID、类别计数和 manifest hash;候选样例不得进入评分分母。用离线 replay 运行评估,检查失败计数、分母、ACL/HITL bypass 和公式是否可复算;每个工具证据必须含工具名、schema、允许工具归属和审批信号,不能只填
success=true。使用至少 30 条样例做人工复核;Judge 是辅助信号,不是唯一真相,必须报告分歧。
运行当前本地回归:
bashPYTHONPATH=python python -m pytest \ python/tests/test_eval_spec.py \ python/tests/test_judge_calibration.py -q PYTHONPATH=python python -m agent_core.eval \ --spec eval/eval-spec-v1.yaml --replay eval/fixtures PYTHONPATH=python python -m agent_core.judge --json本页只运行本地 bounded fixture/replay。仓库内置的是 30 条合成 calibration labels:27/30,一致率
0.9,显式报告 3 条分歧;报告将label_provenance=synthetic_fixture,不能称为人工复核。真实 annotator labels、容器 smoke、真实部署、IAM、账单和完整产品 gate 仍需独立 evidence;自动 Judge 仅为 advisory。用本地训练 Job 入口验证 artifact chain 的前半段,再用带有真实 image digest/service revision 的绑定 manifest启动服务。没有 Docker 时直接执行 Python 入口也足以验证训练、hash、metadata 和 fail-closed 检查;Dockerfile 只作为后续 Cloud Run 构建输入:
bashPYTHONPATH=python python cloud/train_job/entrypoint.py \ --config configs/tiny-cpu.json --text <local-fixture.txt> \ --output-dir <artifact-dir> --job-execution-id exec-local-001 \ --max-seconds 30 PYTHONPATH=python python -m pytest python/tests/test_cloud_artifacts.py -q仓库还提供统一入口
pnpm cloud:contract,会真实执行一次受限 CPU TinyGPT 训练、验证 checkpoint/metrics hash、认证 Service 和 loopback 生成;它属于 本地合同证据,不会触发 Google Cloud。cloud/service/app.py只接受完整的 dataset/tokenizer/config/metrics/checkpoint → job → image → revision 链,并要求认证 token;本地 fixture 的status=ok不等于 Cloud Run execution、IAM、费用或清理已通过。除了直接调用 Service 外,必须先通过 loopback HTTP handler 的最小契约:未带
Authorization的/health返回 401;带 token 的/health、/metadata、/generate分别返回健康状态、同一job_execution_id和确定长度的 token 序列。 这只证明本地 HTTP 边界与 artifact 回读连通,不证明公网 TLS、Cloud Run IAM、 真实 revision 或生产流量。为一个评估类别做“失败也入分母”的小报告:保留 stable ID、输入 hash、预期终态、实际终态、失败原因、引用/工具证据和人工复核栏;不得删除失败样例来提高分数。
只在获得对应授权后执行云门禁;没有授权时完成下面的证据矩阵并停在本地,不调用
gcloud、billing 或已登录控制台。
Google Cloud 小模型真实验证边界
与第1章的关系:第1章的云权益审计 定义三态能力审计(
eligible|unavailable|unverified)与一次性授权合同,回答「我现在被允许做什么」;本节是它的五阶段展开,回答「每个阶段必须回读什么证据才算过」。第1章中对应字段为unverified或授权为false时,本节相应阶段自动停在本地。
“真实验证”必须证明一条外部 artifact chain,而不是把本地训练或服务 fixture 换一个名字。每一阶段都是独立 gate:
| 阶段 | 必须回读的证据 | 这一阶段能证明 | 不能推出 |
|---|---|---|---|
| 0. 本地前置 | 第8章已验证的 config/data/tokenizer hash、训练更新、validation loss、checkpoint;第1章脱敏 capability 状态 | 云前置输入可复现,且本地模型链先通过 | 不证明 Google 资格、云 job 或云 checkpoint |
| 1. 当日资格 | 官方 UI 的脱敏 eligible、scope、expiry、billing/quota 状态和记录时间 | 当前账号/路线在 UI 层具备候选资格 | 会员名或 credit 文案不证明 billing 已开、quota 可用或费用为零 |
| 2. 受控 smoke | 一次性 smoke approval(绑定 action/route/region/资源形状/时长/预算/operation/resource 名)、单 task/重试限制、退出状态、训练 loss、checkpoint hash、实际 gross cost | Google Cloud Job 真正执行了受限的小模型训练 | 不证明 full run、Service 部署或学习者/Agent 质量 |
| 3. 独立 full run | 新的 full-run approval;同一数据/配置/tokenizer hash;Job execution、validation metrics、checkpoint 和费用回读 | 受批准的正式小模型训练闭环 | smoke 不能继承授权;本地 loss 不能代替 full run |
| 4. 私有服务 smoke | 独立 deploy approval;同一 checkpoint 的 image digest、Service revision、IAM/认证结果,以及 /health、/metadata、/generate 的脱敏回读 | 该 checkpoint 已在指定私有 Service 上可认证调用 | Job 成功不等于部署成功;一次生成不等于产品质量或安全通过 |
| 5. 清理与观察 | 同日 Job/Service/Artifact Registry/Storage/Vertex 资源清单为预期状态,48 小时 billing/usage 回读 | 资源生命周期和成本尾部已被观察 | 估算、credit 或本地 cleanup fixture 不是实际账单证据 |
本 checkout 当前只有本地 replay、dry-run 和本地 artifact-chain contract;没有 Google UI 资格、Cloud execution、IAM、真实 image digest/service revision、账单或 48 小时回读。因此当前状态必须保持 cloud_training_eligibility=unverified、cloud_execution=unverified、cloud_training_passed=false,不得把本地 status=ok 写成云端通过。任一阶段缺证据时,本地章节学习路径仍可继续,但第18章云门和 live_capstone_passed 保持阻塞。
官方执行日再核对 Cloud Run Jobs 创建/执行文档、任务超时、Cloud Run pricing 与 Vertex AI quotas;链接本身不构成授权或价格承诺。
故障注入与预期信号
| 注入 | 预期失败信号 | 修复后证据 |
|---|---|---|
| 修改 manifest bytes 不改版本 | hash/冻结测试失败 | 新版本、新 hash、完整重跑 |
| Judge 单独决定通过 | 与人工分歧被隐藏 | 人工抽样、一致率和分歧报告 |
| checkpoint/config hash 不匹配 | artifact load 被错误接受 | manifest mismatch fail closed |
| 依赖失败/超时返回成功 | trace 缺少失败原因 | non-zero/明确失败状态和 recovery 指标 |
论文与延伸
- Holistic Evaluation of Language Models(Liang 等,2022)
- Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena(Zheng 等,2023)
- 安全清单: OWASP GenAI LLM Top 10 2026。旧版 OWASP LLM Top 10 页面目前是历史入口,执行日以 2026 版本为准。
前端/Agent 迁移
评估报告像 CI quality gate:指标名称、分母、阈值和失败样例必须版本化,不能只显示一个总分。trace 像可回放的用户旅程;可靠性来自状态和证据,而不是模型自评。
- Eval manifest ≈ npm lockfile / package-lock.json:用例集 hash 化冻结,两次运行用同一个 lockfile 保证依赖一致——改动任何用例(相当于升级 package)必须产生新的 hash,不能悄悄替换。
- Judge 校准 ≈ A/B testing significance test:LLM Judge 和人类标注的一致率就是"两个评测者的 inter-annotator agreement"——低于阈值时不能直接用 Judge 分数代替人工,就像 A/B 测试样本不足时不能提前终止。
- Artifact hash ≈ Git content-addressable storage:checkpoint、config、eval trace 各自带 SHA-256,从结果可以一路回溯到产生它的全部输入——就像 Git 从 blob hash 找回文件内容。
- Replay ≈ Cypress / Playwright trace:固定 fixture 重放 eval 轨迹,就像 Playwright 录制用户旅程后重跑——每次运行的 trace 必须可比较,不能因为模型版本变了就改变评估条件。
口述与自测(不看资料,5–10 分钟)
- 对一个固定 eval category 写出分子、分母、失败终态和 manifest hash;解释为什么失败样例、无调用样例和
not-measured不能被删除或改写成零。 - 对照 HELM 与 LLM-as-a-Judge,说明人工标签、Judge 一致率和分歧样例各自的作用;再说明本地 artifact-chain dry-run 与真实 Cloud Run/IAM/账单回读之间缺少哪些证据。
- 用第2章的
mle_bernoulli解释 eval 指标success = #achieved / |E|:每个 eval case 是一次伯努利试验,MLE 用样本比例估计真实成功率;分母不能为零是因为 MLE 在 n=0 时未定义。 - 用第2章的
cross_entropy(p_dist, q_dist)解释 Judge 校准:如果 Judge 预测分布和人类标签分布的 CE 很低,说明 Judge 信号可靠;CE 高说明 Judge 需要更多校准或人工覆盖。
实验与参考
动手实验
把评估与安全防护的四道闸门钉死:评测用例 ID 与分母在评估期间冻结以保证可复现;Judge 与人工抽测分歧被显式记录;离线 replay 不访问外网;云端 dry-run 只产出计划与成本上限,不触发真实资源。
环境准备
bash
cd <仓库根>
export PYTHONPATH="$PWD/python"命令与预期输出
上方「动手任务与验收」第 4 步已跑过 test_eval_spec.py、test_judge_calibration.py、agent_core.eval、agent_core.judge;这里补充 cloud dry-run CLI 与 test_cloud_adapter.py:
bash
python -m cloud_adapter --route cloud_run_job_cpu \
--region us-central1 --eligibility unverified
python -m pytest python/tests/test_cloud_adapter.py -qtext
......................... [ 100% ]
4 passed in 6.74s
判定信号:
用例 ID 与分母在评估期间冻结、两次运行结果一致
Judge 与人工抽测分歧被记录到校准日志
离线 replay 模式下无任何出站网络请求
dry-run 只产出计划与成本上限、不调用真实云服务概念图
图:第18章 Eval 冻结规范 → 多路径执行 → 双门控毕业 — 冻结的 eval-spec 通过 hash 锁定后,执行路径分为三条:实时 eval 执行 + LLM Judge 打分、replay 离线回放分析、dry-run 零网络计划。三条路径的输出聚合为评估报告,但产品 gate(指标达标)和人类 gate(口述通过)是两个独立信号——自动化全绿不等于学习者真正掌握,就像 GitHub Actions 全绿不等于代码没有 bug。
OWASP LLM Top 10 对照
| 风险 | 仓库中的可观察防线 |
|---|---|
| 提示注入 | 工具返回标记为 data 而非 instruction、ACL 先于排序、检索结果回链到 chunk |
| 不安全输出处理 | 高风险工具批准 token 绑定参数与会话、副作用前写 checkpoint |
| 敏感信息泄漏 | 检索 ACL 过滤、评估集 hash 化、离线 replay 关闭出站网络 |
| 过度代理权限 | 工具 schema 校验前置、政策引擎拦截越权调用、批准 token 限时 |
| 供应链与插件风险 | MCP 适配器白名单、Judge 模型与被评估模型解耦、依赖固定版本 |
故障注入清单
| 故障 | 表现 | 修复 |
|---|---|---|
| 评估期间增删用例 | 分母变化、通过率虚高、结果无法复现 | 用例集 hash 化冻结、变更需走 PR 重新跑基线 |
| 用 Judge 输出训练 Judge | 模型自我确认偏置放大、指标虚高 | Judge 与被评估模型解耦、校准用人工标注作锚点 |
| 剔除提示注入样本 | 安全指标虚高、模型实际仍脆弱 | 注入样本属于必须保留的硬性反例并按维度独立统计 |
| dry-run 误配成真实提交 | 触发云资源、产生实际费用 | 二次确认 route 与 eligibility、dry-run 路径无写权限 |
资源 / 成本 / 隐私
本地 replay、local-engine harness、Cloud adapter dry-run 和容器配置检查不联网、不读凭据,预计 gross cost 为 0。真实 Google 训练/部署只有资格核验、预算和对应 approval 全部通过后才可进入;评估 trace 必须脱敏。
Evidence
仓库当前机器证据(只读快照)
evidence/module-manifest-v1.json 中 18.evidence 指向当前文件:evidence/18-runtime-v1.json。这是当前 checkout 的脱敏机器运行记录,只覆盖该 JSON 记录的命令、指标、产物和已知失败;它不是学习者提交,也不能推出学习者已完成本章。Judge 校准补充记录见 evidence/18-judge-calibration-v1.json,三次确定性离线 replay 见 evidence/eval-replay-local-v1.json,60-case local-engine 实际执行见 evidence/eval-harness-local-v1.json,本地 artifact chain 最新快照见 evidence/cloud-artifact-local-v2.json(v1 为历史快照);这些都不替代 live planner、云端执行、部署或学习者证据。
学习者提交模板(待填写,不是当前机器证据)
复制下面模板并填写自己的真实运行结果。所有 <...> 都是未填写状态;actual 和 artifacts 尤其不能被当作已运行或已通过。artifacts 必须替换为本次提交中真实存在的仓库相对路径。
yaml
schema: learn-llm.evidence.v1
module: 18-eval-reliability
commit: <learner-commit-sha>
verified_at: <iso-date>
environment: <sanitized-python-device>
seed: 11
commands:
- PYTHONPATH=python python -m pytest python/tests/test_eval_spec.py -q
- PYTHONPATH=python python -m agent_core.eval --spec eval/eval-spec-v1.yaml --replay eval/fixtures
metrics:
- name: eval_manifest_sha256
expected: <frozen-hash>
actual: <recorded-hash>
- name: acl_hitl_bypasses
expected: 0
actual: <recorded-value>
- name: judge_human_agreement
expected: <versioned-threshold>
actual: <recorded-value>
artifacts:
- <learner-repo-relative-artifact-path>
cost:
gross_usd: 0
credit_usd: 0
licenses:
- source: <source>
version: <version>
license: <license>
attribution: <attribution>
redistribution: <redistribution>
known_failures:
- <sanitized-failure-or-none>只展示总分、跳过失败、缺少人工复核或离线 dry-run 边界不明确时,第18章保持 gate;当前本地 Judge 报告不能替代人类最终审批。