人工智能工作方法与实践

第一版完整稿

面向高职、中职和技工教育各专业学生

目录

前言

人工智能正在改变工作的入口。过去,完成一个数据分析、识别模型、专业小工具或设备连接项目,往往要先掌握软件、编程和工程环境;现在,学生可以先用自然语言说明任务,让大语言模型协助分析材料、生成完整代码、解释日志并提出修改。这降低了开始实践的门槛,却没有取消人的责任。任务是否值得做,材料能否使用,模型为什么失败,系统能否重复运行,成果是否可以交给别人继续维护,仍然需要人来判断和负责。

本书主要面向高职、中职和技工教育各专业学生,尤其适合没有人工智能和编程基础的学习者。它不是Python语法课,也不是把若干聊天、文案和图片功能排列成工具清单。全书从真实工作的生命周期出发,依次学习怎样定义任务,怎样建立可靠的数据和证据,怎样用生成、预测与优化形成专业方案,怎样训练视觉、声音和传感小模型并让它们在本地运行,最后怎样把模型、规则、程序、设备和人连接成可验收、可交接、可维护的工作成果。

学生在每章都会完成一个有明确输入、输出、测试和交付物的公共核心项目,并遇到两种人工智能。“应用中的AI”承担识别、检索、生成、预测或异常发现等专业任务;“协助开发的AI”帮助学生追问需求、规划文件、生成和解释完整实现、分析错误并补充测试。学生不用从空白手写所有程序,但必须提供真实上下文,亲自运行和观察,修改一个关键变量,审查AI改动的文件差异,并用固定样例决定成果应当采用、限用、退回还是停止。

本书为商业贸易、设计、数字媒体、智能制造、交通、生物和风景园林等专业提供迁移方向。各专业共享人工智能的基本机制,却会因材料、规范、错误后果和交付责任不同而形成不同应用。书中的公共项目用于看清本质,迁移任务则把创造空间留给学生和教师。

人工智能技术仍在快速变化,因此纸书不把某个模型、平台或编辑器当作学习目标。我们更关心相对稳定的内容:问题怎样表示,数据怎样进入模型,模型怎样产生输出,规则怎样守住边界,人怎样测试、接管和交付。具体产品、版本、安装方法与完整工程将由配套数字资源持续更新。

希望读者学完本书后,不只是“用过AI”,而是能够与AI一起接住一项工作,把它做出来、测清楚,并负责任地交给下一位使用者。

学习指南

一、你将怎样学习

本书不要求先背完术语或语法。每章从一个公共核心项目开始,你先用自然语言说明任务、输入、输出和限制,再让协助开发的AI提出问题和实现方案。AI生成的代码、Notebook或配置必须完整可见;你要亲自运行,观察中间结果和错误,带着证据继续研讨,而不是只复制最终答案。

全书使用同一条协同开发证据链:

任务与验收合同 → 项目上下文 → AI生成完整最小版本 → 运行观察 → 亲手调整一个变量 → 限定AI修改 → 审查文件差异 → 固定样例回归 → 验收 → 交接与维护。

十二章都会形成完整项目,但工程复杂度逐步增加。前几章以结构化材料、小型程序、Notebook或本地观察页完成一条可验收主链;现场章节逐步加入模型和设备;最后三章才集中使用多文件项目、工作流、版本和交接包。完整项目不等于功能很多,而是输入、AI机制、输出、测试和责任能够闭合。

二、每章的五类角色

学习时要持续区分五类角色:

  1. 大语言模型:理解模糊文字、协助规划、综合材料、生成和解释。
  2. 专业小模型:完成视觉、声音、时序、分类或异常识别等具体任务。
  3. 规则和普通程序:完成精确计算、格式校验、权限、阈值、安全停止和稳定执行。
  4. 协助开发的AI:在授权项目内读取材料、生成或修改代码、运行测试并报告差异。
  5. 学生与专业人员:确定目标,提供上下文,检查事实和结果,批准边界,承担验收和接管责任。

当模型输出流畅而规则检查失败时,应以规则和证据为准;当专业资料相互冲突时,应交给相应责任人,而不是让语言模型猜测;当人工或简单规则已经稳定完成任务时,不增加复杂模型也是合格选择。

三、怎样向AI说明任务

高质量协同不等于写一条很长的“万能提示词”。开始时先给出可核对的项目上下文:

要求AI在动手前列出缺失条件;生成代码时要求给出文件清单、运行入口和测试方法;修改时限定文件与目标;完成后要求解释差异和可能影响。不要把真实账号、密钥、未授权资料或个人隐私直接交给模型。

四、怎样阅读AI生成的代码

你不需要逐字背诵语法,但要能沿着“输入—处理—输出”追踪程序:数据从哪里读入,经过了哪些转换,哪一步调用模型,输出在哪里校验和保存,失败时怎样停止。每章至少挑一个关键变量亲手调整,例如时间窗口、相似度阈值、训练轮数、约束权重或置信度门槛,并用同一测试集比较前后结果。

遇到报错时,不要只把一句错误信息发给AI。应同时提供运行命令、环境说明、相关文件、完整报错、预期结果和已经尝试的修改。AI提出修复后,先查看它准备修改哪些文件,再小步执行并回归,不要一次接受与问题无关的大范围重写。

五、怎样完成测试和判断

一次成功演示不能证明系统可用。每章至少准备四类样例:

测试后不能只写“准确率较高”。要记录实际样例数、典型错误、误报与漏报的后果、响应时间、费用、隐私和人工复核量。最终作出四种结论之一:采用;限定范围使用;退回修改;停止使用。结论必须能从证据中找到依据。

六、专业迁移怎样开展

每章先完成公共核心项目,再从专业迁移卡中选择一个方向。迁移不能只替换名称,至少要重新确定材料或数据、专业规范、高代价错误、交付物和责任人。例如,同样是视觉分类,商品包装项目关心批次与误放,零件检查关心漏检后果,植物状态项目关心季节和拍摄条件,媒体素材项目关心授权和版本。

综合项目不要求堆叠全书所有技术。选择真正需要的一个模型模块和一个完整工作闭环,比把多个热门模型连在一起更有价值。

七、设备条件不足时怎样学习

现场章节提供三级路径。H0使用预录数据、设备视频和虚拟接口,所有学生都能完成核心机制和故障测试;H1使用电脑摄像头、麦克风或小组共享传感器;H2把模型部署到边缘设备。三条路径学习目标相同,设备只是输入与运行位置不同。

本书不允许模型直接控制市电、燃气、压力、加热、高速运动、门锁、交通工具或医疗设备。低置信度、证据冲突、输入超范围、传感器失效或网络中断时,系统默认不行动,并显示人工接管原因。

八、学习成果怎样保存

建议每章保留以下最小证据:任务合同或任务说明、项目上下文、AI追问与方案、完整首版、运行记录、一次变量实验、一次限定修改及差异、固定测试结果和最终判断。第12章再把这些材料整理为任务合同、项目代码库、数据卡、模型卡、测试报告、用户说明、交接清单和维护计划。

如果另一位同学不能按照你的说明运行项目,或者无法知道模型什么时候不应使用,成果就还没有真正完成。

每章正式配套工程位于resources/chXX/project/。进入目录后先阅读README,再运行python acceptance.py;它会检查该项目声明的文件、测试和参考结果。验收脚本通过只说明已覆盖的检查通过,不能替代你阅读失败样例、模型卡和最终采用判断。

第一篇 把工作问题定义清楚——任务、数据与证据

第1章 把模糊委托做成可验收的AI分流器

工作阶段: 定义工作并完成第一个可交付AI工程。
公共核心项目: 从“做一个企业运营服务助手”的含糊委托出发,与AI协同开发一个本地运行的“企业运营服务请求智能分流器”。
核心技术: 监督学习、中文文本分类、字符向量化、Embedding、Softmax四类分数、拒绝阈值与混淆矩阵。
输入输出链: 模拟中文请求 → 高风险规则门 → Keras文本分类模型 → 四类分数与候选去向 → 人工确认或接管。
应用中的AI: 在本地把普通请求分到“业务设备、网络与账号、公共设施、环境服务”四个候选去向的小型文本分类模型。
协助开发的AI: 帮助追问委托、审查标签、生成并解释代码、分析运行日志和提出限定修改的大语言模型。
人的责任: 确认任务和标签,核对数据,制定高风险门,运行并观察工程,审查AI修改,用固定测试决定采用、限用、退回或停止。
主要交付物: 任务与标签合同、数据卡、完整工程、Keras模型、本地网页、测试报告、模型卡和复现说明。
明确边界: 系统只给候选去向,不诊断故障、不承诺时限、不自动派单;高风险、低信心、多意图和范围外请求交给人。
跨章关系: 本章先跑通“数据—模型—应用—测试”;第2章再系统学习数据底座,第10—12章处理真实工作流、试运行与交付维护。

学习目标

完成本章学习后,你将能够:

  1. 把含糊委托改写为输入、标签、输出、边界和验收明确的文本分类任务;
  2. 审查带标签文本,区分训练、验证和固定测试,发现重复与来源泄漏;
  3. 在大语言模型协助下运行并读懂一个完整的Keras字符级中文分类模型;
  4. 解释字符编号、嵌入、句子表示和Softmax四类分数在当前项目中的作用;
  5. 说明规则、模型、阈值和人工确认怎样共同组成一个本地网页应用;
  6. 使用关键词基线、固定测试和限定修改完成验收与交接。

项目导入

“做一个企业运营服务助手,最好能自动处理各种报修”不能直接交给开发人员或模型。它没有说明接收什么请求、输出给谁、企业有哪些真实服务去向,也没有说明哪些错误会造成严重后果。若一开始把任务理解错了,后面的界面和代码越完整,返工范围越大。

本章把委托缩成一个可以训练和测试的作品:使用者在本地网页输入一条模拟企业运营服务请求,系统先检查高风险线索;普通请求再交给Keras小模型,得到四个候选去向的分数。系统只有在最高分和前两名分差同时达到门槛时才显示模型建议,其他情况转人工。页面始终保留原文和人工决定,不连接真实工单系统。

例如,输入:

门店收银台的扫码枪无法读取商品条码,请安排检查。

这条首次体验用的句子来自教学训练样例,不计入后面的固定测试。系统可以显示“业务设备”为最高分候选,同时列出另外三类分数,最后由值班人员接受、改判或转人工。若输入“墙上插座正在冒烟”,确定性规则必须先拦截,分类模型不运行,页面直接提示进入人工紧急渠道。

模拟中文请求
   │
   ├─ 命中高风险规则 ─→ 不运行模型 ─→ 人工紧急渠道
   │
   └─ 未命中
        └─ 字符向量化 → Embedding → 句子表示 → Softmax四类分数
                                                    │
                      ┌─────────────────────────────┴────────────────────────┐
                      │最高分和前两名分差达到门槛                            │未达到门槛或多意图
                      ↓                                                       ↓
                 显示候选去向                                             人工复核
                      └─────────────────────────────┬────────────────────────┘
                                                    ↓
                                                人工确认

本项目有两种AI。“应用中的AI”是训练后在本地运行的小模型;“协助开发的AI”是帮助学生理解任务和工程的大语言模型。学生不从空白手写全部Python,却必须亲自运行、查看中间结果、解释关键链路、限定一次修改并重跑测试。

课堂采用“先使用、再拆解、后重建”的顺序。第一次课先加载随资源提供的模型并体验网页,让学生知道要做出的作品是什么;随后打开数据、训练脚本和推理代码,沿同一条输入输出链理解技术;最后再建立环境、重新训练并比较自己的报告。这样既避免把安装和语法变成起点,又不会把完整实现藏在按钮后面。

建议用6—8学时完成。电脑只需CPU,不要求独立显卡;首次建立环境需要下载依赖,训练、评估和网页运行都可在本机完成。具体Python、TensorFlow和Keras版本以配套工程的requirements.txt为准,不把易变版本写成稳定知识。

本章成果

AI协同开发路线

本章按“委托—合同—数据—基线—训练—应用—测试—修改—交付”推进。学生先把原始委托和真实限制交给开发AI,要求它只提出会改变输入、标签、输出、安全或验收的问题;学生根据企业责任人确认的材料回答,不能让AI代替业务部门补制度。随后,AI可以协助审查数据和生成完整代码,学生负责运行、提交日志、阅读差异和决定是否采用修改。

生成工程前可这样说明任务:“请先列出数据、训练、推理、网页和测试文件,不要先写代码。应用模型统一使用Keras/TensorFlow,网页服务使用Python标准库,不增加其他机器学习或Web框架。高风险规则必须在模型之前,任何输出都保留人工确认。得到我的确认后再逐个生成完整文件,并为每个文件说明输入、输出和测试方法。”

学生还要保存六类协同证据:最初提供的任务与限制;AI提出的必要问题;首版文件清单和解释;实际运行日志;限定修改及文件差异;固定回归和最终结论。聊天窗口中的最后一句回答不是交付物,能够复现的项目目录、版本和报告才是。

运行失败时,不要只发一句报错。应提供实际命令、环境版本、完整错误、相关文件、预期结果和已经尝试的动作。修改时限定文件和目标,例如“只检查inference.py为什么没有把该样例转人工,不修改模型、标签和页面;给出差异并运行全部回归”。

第一节 定义可训练、可验收的任务

一、从“万能助手”缩成四分类

一个可训练任务至少要说明:一条样本是什么,标签由谁定义,模型输出是什么,错误怎样处理。经确认,本章输入是一条不超过500个字符的模拟中文请求;输出是四个接收去向的相对分数和一个候选标签。程序没有正式派工权限。

四个标签不是模型自己发现的天然类别,而是人根据工作流确定的约定:

标签 本章纳入的普通请求 边界与人工责任
业务设备 扫码枪、业务电脑、会议音视频设备、订单打印机、叫号屏等 只分流,不判断内部故障原因
网络与账号 办公网、认证、账号、密码、平台登录等 不读取密码,不替用户修改账号
公共设施 作业照明、桌椅、门窗、饮水机、水龙头、扶手等 冒烟、漏电、人员受伤先过高风险门
环境服务 垃圾、污渍、纸屑、灰尘、一般积水和异味等 涉及用电、伤害或制度未知时转人工

一条请求同时出现“前台叫号屏无画面”和“工单平台账号无法登录”时,单标签模型会丢失一个意图,因此不能强行选最高分。程序先检查各类明确线索,发现多意图就转人工。请求过于含糊、完全范围外或模型前两类分数接近时,也交给人处理。

二、把高代价错误放到模型外

本工程用明确词表拦截冒烟、明火、起火、漏电、触电、电火花、人员受伤、流血、被困和坠落等线索。顺序必须是“先规则、后模型”。如果先让模型分类,再根据分类决定是否紧急,一个普通准确率很高的模型仍可能漏掉最重要的样例。

关键词规则透明、容易检查,却不能理解全部语言变化。它只是教学原型的第一道门,不是单位安全制度。使用者和值班人员仍须阅读原文;真实渠道和责任人必须来自本单位确认材料,不能由语言模型或训练数据推测。

三、建立简单基线

在训练神经网络前,先用baseline.py中的四组透明词表建立关键词基线:只命中一个标签时给出该标签;一个都未命中或同时命中多个标签时转人工。它不用训练,能解释每次判断,适合回答“复杂模型是否真的有必要”。模型运行链不把“必须命中一个关键词”作为许可条件,只把同时命中多个领域作为多意图证据;这样模型才有机会处理词表之外的普通表达,基线比较也不会预先决定模型答案。

关键词基线容易处理“扫码枪坏了”“垃圾桶满了”,却可能不认识“业务终端停在启动界面”“靠背总让人坐不稳”等没有典型关键词的表达。模型只有在相同的封存样例上改善普通分流,同时不破坏高风险门和人工接管,才值得保留。若简单方法已经满足任务,停止增加模型也是合格结论。

四、冻结任务合同和验收门

合同项目 冻结内容
使用者 提交模拟请求的学生;审查候选的值班人员角色
输入 脱敏中文文本,不收集姓名、电话、健康信息和密码
模型输出 四类Softmax分数、最高分候选与前两类分差
规则输出 高风险接管、空值与长度拒绝、多意图与未知线索
人工动作 接受、改判、转人工或进入紧急渠道
禁止动作 不自动派单,不承诺时限,不控制设备,不替代正式渠道
版本对象 标签、数据、模型、阈值、规则、网页和固定测试
验收 分类、高风险接管、人工复核、故障降级与另一组复现

配套工程给出首版运行门:普通分类固定样例通过率不低于75%,高风险样例必须全部在模型前拦截,人工复核样例通过率不低于75%。另有一条采用门:神经网络若不能在同一独立测试中相对透明基线带来可说明的改善,就不能仅因“用了AI模型”而替换简单方法。这些门槛在运行前冻结,不是把测试结果预先写成答案;实际数值必须由当前版本报告生成。任何高风险漏拦截都不能被普通分类的平均成绩抵消。

阶段检查: 另一位同学应能只看合同判断“新增员工休息区门禁处理并自动安排维修人员”已经改变数据、权限和错误后果,不能作为一句提示词直接加入首版。

第二节 准备数据并训练文本分类模型

一、审查480条生成式教学数据

配套工程包含480条模拟教学数据,其中384条用于训练、96条用于验证。四类保持均衡:每类96条训练、24条验证。字段包括sample_id、text、label、source_group和split。

sample_id,text,label,source_group,split
train-业务设备-001,客户服务前台的业务电脑停在启动界面,请安排检查。,业务设备,synthetic_workplace_train_v2,train
train-业务设备-005,门店收银台的扫码枪无法读取商品条码,请安排检查。,业务设备,synthetic_workplace_train_v2,train
validation-业务设备-001,刚才发现订单打印机发出异响后停止出纸,应该联系哪个服务组?,业务设备,synthetic_workplace_validation_v2,validation
validation-环境服务-001,刚才发现仓库入口散落大量塑料包装,应该联系哪个服务组?,环境服务,synthetic_workplace_validation_v2,validation

这些数据由固定信号、地点和句式模板可重复生成,适合第一次观察训练链,却不能代表真实工作现场语言。训练与验证使用不同地点和句式模板,但部分现象短语相同,因此验证结果主要检查模板变化,不足以证明真实泛化。另有29条由人工编写、训练期间不读取的固定系统样例,用来补充检查口语表达、多意图、信息不足和高风险边界。

source_group记录样例来自哪套生成或编写过程,split记录它只能用于训练还是验证。生成脚本只写train.csv,不读取或改写固定测试。学生可以检查脚本怎样组合信号、地点和句式,但不能为了提高结果反复生成到某条测试正好通过。数据版本发生变化时,要同时记录生成脚本、随机种子和文件摘要。

学生应检查:编号和文本是否重复;标签是否属于四类;每类数量是否均衡;split是否合法;固定测试文本是否混入训练。大语言模型可以生成候选表达,却不能自行批准标签或把固定测试答案写回训练文件。

二、理解字符怎样进入模型

中文句子通常没有空格。本章使用TextVectorization(split="character")把文本按Unicode字符切开,再把字符映射为整数。例如“扫码枪”会变成三个字符编号;词表之外的字符进入未知项,较长文本被截断或补齐到固定长度。

Embedding为每个字符编号学习一个32维向量。训练开始时这些数值没有专业含义;经过许多带标签样本后,在相似请求中出现的字符会形成对分类有用的表示。全局平均池化把一串字符向量汇总为一句话的表示,隐藏层再组合特征,最后四个Softmax分数总和为1。

Softmax分数表示模型在当前四个标签之间怎样分配相对支持,不是现场事实正确率,也不是经过校准的安全概率。平均池化实现简单、运行快,但会弱化字符顺序;生成数据规模小,模型还可能学到模板措辞而非真实工作含义。这些局限必须写入模型卡。

三、运行完整Keras主链

学生先运行教师提供的预训练版本,观察输入和输出;随后再让协助开发的AI解释并重建训练工程。纸书保留从训练文本建立词表、构建模型、训练、验证到保存的主要链路。课堂可逐格运行resources/ch01/project/notebooks/ch01_service_router_lab.ipynb,权威训练脚本、CSV校验、元数据摘要和完整命令行参数见resources/ch01/project/train.py。

import keras
import tensorflow as tf

LABELS = ("业务设备", "网络与账号", "公共设施", "环境服务")

# 词表只能根据训练部分建立,不能读取验证或固定测试。
vectorizer = keras.layers.TextVectorization(
    max_tokens=2000,
    standardize="lower_and_strip_punctuation",
    split="character",
    output_mode="int",
    output_sequence_length=96,
    name="character_vectorization",
)
adapt_dataset = tf.data.Dataset.from_tensor_slices(train_texts).batch(32)
vectorizer.adapt(adapt_dataset)

inputs = keras.Input(shape=(), dtype=tf.string, name="request_text")
x = vectorizer(inputs)
x = keras.layers.Embedding(
    input_dim=len(vectorizer.get_vocabulary()),
    output_dim=32,
    mask_zero=True,
    name="character_embedding",
)(x)
x = keras.layers.GlobalAveragePooling1D(name="average_pooling")(x)
x = keras.layers.Dense(32, activation="relu", name="hidden")(x)
x = keras.layers.Dropout(0.20, name="dropout")(x)
outputs = keras.layers.Dense(4, activation="softmax", name="category")(x)

model = keras.Model(inputs, outputs, name="enterprise_service_router")
model.compile(
    optimizer=keras.optimizers.Adam(learning_rate=0.003),
    loss="sparse_categorical_crossentropy",
    metrics=[keras.metrics.SparseCategoricalAccuracy(name="accuracy")],
)
history = model.fit(
    train_dataset,
    validation_data=validation_dataset,
    epochs=35,
    callbacks=[keras.callbacks.EarlyStopping(
        monitor="val_accuracy", patience=6, restore_best_weights=True
    )],
    verbose=2,
)
model.save("models/service_router.keras")

大语言模型生成代码后,学生至少要回答:原始字符串在哪一行进入;为什么adapt只能看训练文本;Embedding学习的是什么;四个输出与标签顺序怎样对应;模型文件是否已经包含字符向量化。答不清这些问题,程序即使能运行也不算完成学习。

四、运行训练并读实际结果

训练时终端逐轮显示训练损失、训练准确率、验证损失和验证准确率。EarlyStopping连续若干轮看不到验证改善时停止并恢复较好权重,防止只追求更多轮数。程序保存模型、metadata.json和training_history.json,其中记录数据摘要、随机种子、依赖版本、训练轮数和验证结果。

配套参考模型已经在CPU环境真实运行:TensorFlow 2.21.0、Keras 3.15.1、随机种子20260807,训练14轮后停止并恢复第8轮权重,96条验证样例准确率为98.96%。这个数字并不证明模型已经“学会企业服务语言”,因为训练与验证虽然句式和地点不同,却共享合成机制与一批现象短语,结果容易过于乐观。

29条独立固定样例同时检验普通分流、安全门和拒绝能力。当前Keras模型通过16/16普通请求、5/5高风险拦截和8/8多意图或信息不足转人工;透明关键词基线也得到相同的16/16、5/5和8/8。两套系统在这批小型作者编写样例上打平,因此结果证明的是工程按合同运行,而不是神经网络优于简单规则,更不能据此宣布真实企业上线。

固定测试另取仓库、门店、客户服务和办公场景,并保留多意图、信息不足及高风险输入。M03同时涉及会议摄像头和业务账号,虽然模型给出“网络与账号”候选,但多意图规则、51.2%的低置信和2.7%的小分差共同触发人工复核。学生应打开元数据、训练历史、基线报告和模型报告,核对样本来源、阈值、逐题路由和混淆矩阵,而不是照抄总分。

可向开发AI提出:“读取训练历史、元数据、基线报告和模型报告,只描述文件中真实存在的现象;解释为什么验证集98.96%且两套系统在固定测试上打平,并列出最多三个进入真实企业前需要补充的证据。先不要改模型,不得把固定测试写进训练数据。”AI的解释仍是候选,学生要回到日志和代码核实。

第三节 把模型接入本地网页应用

一、先执行规则,再调用模型

inference.py是网页和固定测试共同使用的核心。它先验证文本,再找高风险词;只有通过规则门后才调用模型。模型故障、最高分不足、前两类过近或出现多个领域的明确线索时都转人工。没有命中关键词不等于模型一定不能理解;本版4条范围外样例恰好因最高分或分差不足被拒绝,但Softmax也可能对陌生输入过度自信,因此这些阈值不是可靠的“未知检测器”,只能与持续新增的边界测试和人工接管一起使用。

import numpy as np

def classify_request(text, model, metadata):
    normalized = validate_text(text)
    matched = find_high_risk_terms(normalized)
    if matched:
        return high_risk_result(normalized, matched)  # 模型没有运行

    if model is None:
        return model_fault_result(normalized)

    try:
        # 使用 object 数组交给端到端字符串模型,避免 NumPy 固定宽度
        # Unicode 类型在 Keras 3 中被误判为不支持的数据类型。
        batch = np.asarray([normalized], dtype=object)
        raw_scores = model.predict(batch, verbose=0)[0]
        labels = metadata["labels"]
        order = sorted(
            range(len(labels)), key=raw_scores.__getitem__, reverse=True
        )
        top1, top2 = order[0], order[1]
        confidence = float(raw_scores[top1])
        margin = confidence - float(raw_scores[top2])
        cue_groups = find_domain_cues(normalized)

        review_reasons = []
        if len(cue_groups) > 1:
            review_reasons.append("请求包含多个服务去向的明确线索")
        if confidence < metadata["thresholds"]["top1"]:
            review_reasons.append("最高分低于门槛")
        if margin < metadata["thresholds"]["top1_top2_margin"]:
            review_reasons.append("前两类分差低于门槛")

        return {
            "route": "manual_review" if review_reasons else "model_suggestion",
            "probabilities": dict(zip(labels, map(float, raw_scores))),
            "model_suggestion": {
                "label": labels[top1],
                "confidence": confidence,
                "margin": margin,
            },
            "review_reasons": review_reasons,
            "human_decision_required": True,
            "automation_permitted": False,
        }
    except Exception:
        return model_fault_result(normalized, "模型推理失败,已转人工")

工程默认最高分门槛为0.60,前两名分差门槛为0.12。它们只是首版配置,不是自然规律。提高门槛通常会增加人工复核,降低门槛可能扩大模型建议,也可能放行更多错误。选择阈值要同时看验证样例、错误后果和人工工作量,不能为了通过测试不断降低要求。

二、把完整模型封装为稳定输入输出

训练保存的.keras文件包含字符向量化和神经网络,因此网页可以直接提交原始中文字符串,不需要在网页里复制另一套分词代码。metadata.json保存标签顺序和阈值;加载时若模型标签顺序与应用不同,网页服务可以继续打开,但模型进入安全降级,所有请求转人工,避免把第一列分数误解释成错误类别。

系统输出包含:原始请求、高风险门状态、四类分数、最高分候选、前两类分差、人工复核原因以及“禁止自动执行”标记。页面不只显示一个答案,是为了让使用者能够看见模型犹豫和规则接管位置。

三、运行本地网页并观察完整链路

完整服务器和页面分别位于app.py、static/index.html、static/styles.css和static/app.js。服务器只使用Python标准库,默认监听127.0.0.1;页面采用“输入请求—观察系统—人工决定”三步结构。代码全部可见,但纸书不重复几十行HTTP和样式样板。

页面应同时显示原文、高风险门是否运行、四类分数或“模型未运行”、模型建议、复核原因和人工动作。隐藏其他类别、只显示一个醒目答案会放大自动化错觉。服务只监听本机并不等于可以输入隐私;课堂仍只使用模拟或脱敏文本,下载的处理记录也要在交接前检查是否包含不必要信息。

cd resources\ch01\project
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
python acceptance.py
python train.py
python evaluate.py
python app.py
# 浏览器打开 http://127.0.0.1:8000

运行后依次观察四种输入:普通业务设备请求应显示四类分数;含糊请求应转人工;同时包含两个去向的请求应说明多意图;高风险请求应显示“模型未运行”。要验证模型缺失时的安全降级,应先停止网页服务,临时移走模型文件,再重新启动服务;确认所有请求转人工而不是报出一个假答案后,将模型文件放回原位。

四、让学生参与而不是只点按钮

网页运行不是学习终点。学生要从页面结果回到inference.py,指出一次请求经过了哪些判断;从元数据找到标签顺序和阈值;从模型代码找到字符表示和Softmax;最后保存一次人工接受、改判或转人工的证据。

协助开发的AI可以解释工程,但学生要限定其工作范围。例如:“只解释一条请求从HTTP接口到classify_request再到页面结果的调用链,按文件列出输入和输出,不修改代码。”如果AI说规则在模型之后,学生应以实际文件和固定测试纠正它。

本章不要求学生记住服务器语法,也不把按钮颜色当作项目能力。需要掌握的是:同一个模型怎样被训练和加载,规则怎样挡在模型之前,网页怎样展示而不隐藏不确定性,人怎样保留最后决定。

第四节 用固定测试改进并交付项目

一、用29条封存样例测试系统

data/fixed_test.csv不被训练脚本读取,共29条:16条普通分类样例,每类4条;5条高风险样例;4条多意图和4条信息不足样例,共8条人工复核样例。它们使用人工编写的表达和独立source_group,用于检查训练模板之外的行为。

测试类型 数量 检查重点
普通分类 16 候选去向正确,分数和分差达到当前门槛
高风险 5 规则先拦截,model_suggestion为空
多意图 4 不强行压成一个标签,转人工
信息不足 4 没有充分线索时转人工,不编造请求内容

这29条CSV固定样例检查正常分类、高风险、低信心、多意图和信息不足等数据行为,但不包含模块故障或HTTP故障,因为这类状态不能仅靠一行输入数据表达。tests/中的31项单元、HTTP与网页策略测试另行覆盖数据隔离、关键词基线、模型推理异常时的安全降级、空输入、HTTP端点和页面决策策略。两部分合起来才是完整系统测试;页面能打开、某一条演示成功或验证准确率较高,都不能代替它们。

二、让验收程序自动留下证据

evaluate.py逐条调用网页使用的同一个推理函数,并根据期望行为判断是否通过。核心逻辑如下,完整报告可以另存为JSON:

def case_passed(row, result):
    if row["expected_behavior"] == "high_risk":
        return result["route"] == "high_risk" and result["model_suggestion"] is None
    if row["expected_behavior"] == "manual_review":
        return result["route"] == "manual_review"
    if row["expected_behavior"] == "classify":
        suggestion = result.get("model_suggestion") or {}
        return (
            result["route"] == "model_suggestion"
            and suggestion.get("label") == row["expected_label"]
        )
    raise ValueError("未知测试行为")

required_rates = {
    "classify": 0.75,
    "high_risk": 1.00,
    "manual_review": 0.75,
}

def check_required_rates(actual_rates):
    for behavior, minimum in required_rates.items():
        if actual_rates.get(behavior, 0.0) < minimum:
            raise SystemExit(f"{behavior}未达到验收门:{minimum:.0%}")

最低门只用于判断当前版本是否达到基本运行条件,不能证明它仍是教材记录的正式版本。默认acceptance.py会现场生成关键词基线报告,并与reports/baseline_evaluation.json逐字段比较;加上--require-model后,还会现场加载当前Keras模型、生成完整模型报告并与reports/model_evaluation.json逐字段比较。验收同时重算data/train.csv的SHA-256并核对模型元数据,防止训练数据、模型或逐题结果变化后仍沿用旧报告。

运行后不能只看“通过/失败”。应打开失败明细,区分四种原因:标签合同不清,生成数据覆盖不足,字符平均表示能力有限,或规则与阈值设计不当。不同原因需要不同修改,不能一律增加训练轮数。

还要把模型测试与系统测试分开理解。模型测试关心普通请求的候选类别;系统测试还关心规则先后、模型不可用时的降级、低信心拒绝和人工决定。一个分类错误可能只增加人工改判,一次高风险漏拦截却可能直接否决版本。验收必须按错误后果设置门槛,不能用所有样例的一个平均数掩盖关键失败。

三、完成一次限定修改与固定回归

先用验证样例观察阈值,而不是根据29条封存测试逐题调答案。学生可只修改最高分门槛,例如从0.60调整为另一个候选值,前两名分差、数据、模型结构和固定测试保持不变。修改前预测:门槛降低可能减少人工复核,也可能增加错误建议;门槛提高则相反。

让开发AI只修改元数据或命令参数中的一个阈值,禁止改训练数据、测试文件和其他规则。学生审查差异后重新运行acceptance.py --require-model,记录普通分类、人工复核和高风险三类变化。如果固定测试已经反复参与调参,它就不再是完全独立的最终证据;新版本还需要补充从未见过的新封存样例。

另一条改进路线是增加一个经过人工确认的边界样例。新样例只能进入新的训练或验证版本,原固定失败样例不得直接复制成训练答案。修改数据后要重新生成模型、元数据和测试报告,并说明为什么这项新数据能代表一类真实表达,而不是只修一道题。

四、交付工程并迁移到专业场景

交付包至少包含:README与锁定依赖;任务和标签合同;生成脚本、训练/验证数据与数据卡;完整训练、推理、网页和测试代码;模型及元数据;固定测试报告;模型卡;AI协同记录、文件差异和人工决定;复现与回滚说明。另一组应能从干净目录建立环境、训练或加载模型、启动网页、运行29条测试并说明已知失败。

验收结论有四种:采用表示在冻结课堂范围内达到全部门槛;限用表示只给候选、必须人工确认;退回表示数据、分类、规则或复现仍需限定修改;停止表示授权、安全或维护条件不具备。对于生成式小数据和关键词安全门构成的首版,即使测试通过,合理结论通常仍是“课堂模拟范围限用”,不能直接接入企业真实系统。

专业迁移卡A:商贸咨询分流。 标签改为商品、订单、售后和账号;数据来自脱敏咨询,虚假价格和退款承诺属于高代价错误,最终去向由客服责任人确认。
专业迁移卡B:设备报障路由。 标签按机械、电气、网络和环境支持设计;停机、漏电和人员伤害必须先接管,设备技术人员批准规则。
专业迁移卡C:数字媒体技术支持。 标签改为拍摄、录音、剪辑和发布;素材授权与账号隐私不能交给分类模型,内容和技术负责人共同验收。

迁移不能只替换网页标题。必须重新建立标签合同、数据来源、高代价错误、规则门、固定测试、接收人员和维护责任。

交接完成后仍要保留停止条件:依赖无法安装、模型或元数据缺失、标签顺序不一致、输入超出范围、固定回归失败时,系统默认不提供普通建议。维护者只能在版本化副本上修改,验收通过后再替换当前版本;上一已验收模型、阈值和报告应能恢复。

本章小结

本章把含糊委托做成了第一个“数据—模型—应用—测试—交付”闭环。任务合同确定四个真实去向和人工责任;480条生成式教学数据用于训练与验证,29条人工固定样例保持在训练之外;字符向量化、Embedding、句子表示和Softmax组成Keras文本分类模型;高风险规则在模型之前,低信心、多意图和故障结果转人工;本地网页让四类分数、规则状态和人的决定可见。

大语言模型贯穿开发过程,却不替学生决定标签、修改验收门或承担正式处置。学生通过自然语言提供上下文、要求完整实现、提交运行日志和限定修改,再用文件差异与固定测试判断是否采用。真正的成果不是“模型给对了一次”,而是能够说明它学自什么数据、为何这样输出、什么时候不应使用,以及另一组怎样复现和接管。

关键术语

目标测试

  1. 为什么“做一个万能企业助手”不能直接作为训练任务?
    A. 名称不够新颖 B. 没有明确输入、标签、输出、边界和验收 C. 没有使用最大模型 D. 网页颜色没有确定
  2. 下列哪一项必须在分类模型运行前处理?
    A. 扫码枪无法识别条码 B. 工单平台账号无法登录 C. 墙上插座正在冒烟 D. 垃圾桶已经装满
  3. TextVectorization为什么只能用训练部分执行adapt?
    A. 验证文件太小 B. 防止验证或测试信息进入词表形成泄漏 C. Keras不能读取CSV D. 为了增加训练轮数
  4. 模型最高Softmax分数为0.90,最合理的解释是什么?
    A. 现场事实有90%概率正确 B. 可以自动派单 C. 模型在当前四类中给该类较高相对支持,仍需规则和人工确认 D. 数据一定没有偏差
  5. 判断并改错:“只要普通分类通过率很高,五个高风险样例漏掉一个也可以接受。”
  6. 判断并改错:“学生没有从空白手写全部Python,因此不需要理解数据、字符表示、模型和输出。”
  7. 为“业务设备”和“公共设施”各补充一条标签边界,并说明由谁确认。
  8. 说明生成式教学数据的一个优点和两个局限,解释为什么还需要人工固定测试。
  9. 设计一次只修改最高分阈值的控制变量实验,列出保持不变的条件和必须记录的结果。
  10. 某版本能打开网页,但多意图请求被强行分为一类,高风险测试有一条未拦截,另一组也无法复现环境。请作出采用、限用、退回或停止结论,并说明最小修改、责任人和重新验收范围。

第2章 把多模态原件做成可追溯数据包

工作阶段: 定义工作。
公共核心项目: 完成“工作场所设备巡检记录数据包”,把授权原件、候选提取、契约校验、问题分流、来源级划分和数据卡连成完整工程。
核心技术: 多模态信息提取、样本与标签、数据类型与模式、数据契约、质量检查、数据划分和来源追踪。
输入输出链: 授权材料与原件 → 来源索引 → AI候选提取 → 数据契约校验 → 人工复核 → 清洗数据与数据卡。
应用中的AI: 从不同形式材料中提取候选字段的多模态或语言模型;参考工程使用明确标记的离线候选回放。
协助开发的AI: 帮助设计字段、生成校验程序、解释错误日志和限定修改的项目型AI助手。
人的责任: 确认授权与标签含义,保存原件,处理冲突和缺失,批准数据版本。
主要交付物: 原始材料索引、数据契约、候选与清洗数据、问题记录、数据字典、数据卡和版本说明。
明确边界: 不收集无关身份信息;模型提取结果只是候选;无法确认的内容保留缺失,不用猜测填充。
跨章关系: 承接第1章的任务合同,为第3章检索、第5—9章模型训练和第10—12章系统交付提供可靠输入。

学习目标

完成本章学习后,你将能够:

  1. 为原始材料建立授权、来源、版本和保存位置记录;
  2. 根据工作输出设计字段、类型、单位、标签和缺失表示;
  3. 运行AI生成的完整校验程序,发现缺失、重复、越界和来源错误;
  4. 解释样本、特征、标签以及训练、验证、测试划分在当前数据包中的含义;
  5. 区分真实模型输出、离线候选回放和人工录入基线,不虚构效率或准确率;
  6. 将原件、数据、程序和说明组成另一组可以复现的数据包。

项目导入

人工智能项目常从“手头有不少材料”开始。图片存在聊天记录中,巡检表使用不同版本,录音没有时间和地点,环境数值缺少单位。多模态模型能够阅读图片、听取录音并概括文档,但它不能自动知道材料是否获准使用、某个编号指向哪台设备、18表示摄氏度还是湿度,也不能替专业人员确认标签。

本章完成一个可运行的工作场所设备巡检记录数据包。为避免使用真实个人与企业资料,样例包含模拟值班文字、虚拟传感器CSV、铭牌图片的观察文字替身、录音转写,以及一个专门用于隐私和授权阻断的测试原件。真实项目可把文字替身换成获准的图片和音频,但数据契约与验收门不变。

candidate_adapter.py把候选提取与具体模型隔离。课堂默认读取is_model_output=false的离线回放,断网也能运行;接入真实模型时必须登记模型与日期,不得上传未授权原件。普通程序依据数据契约检查字段,学生再回到原件复核。项目目标不是“全部识别”,而是让每条可用数据能回到来源、每个未知项没有被偷偷猜出。

本章成果

AI协同开发路线

学生先阅读TASK_CONTRACT.md并核对索引哈希,再观察离线候选怎样进入契约校验。学生亲手只改变一个单位规则,预测clean与issues数量变化;随后让协助开发的AI只增加“原件哈希变化”测试,审查差异并运行全部回归。接入真实多模态模型是可选扩展:模型候选先导出为带来源声明的JSON包,再通过--candidates进入与离线回放完全相同的校验主链;它不能改变原件只读、候选不等于事实和未授权来源必须阻断这三条规则。最终由另一组按README复现。

第一节 保留原件、授权和来源,再提取候选信息

一、原件先于提取结果

模型处理的是原件的某种表示,提取结果不是原件本身。项目目录先建立raw/,只读保存收到的文件;再建立index.csv,为每个原件分配source_id。索引至少记录文件名、材料类型、提供者、获取日期、授权范围、是否含个人信息、文件摘要和备注。文件摘要是由普通程序根据文件内容计算的短标识,可帮助发现原件是否被替换,不代表授权或真实性。

未经授权的人脸、姓名、联系方式和对话不得为了“训练AI”进入共享数据。若材料含完成任务所必需的个人信息,应按单位制度缩小访问范围,课堂样例优先使用模拟或脱敏数据。删除原件也要保留删除原因和责任人,不能让清洗后的表格变成没有来历的孤立数据。

配套工程位于resources/ch02/project/,关键目录如下:

project/
├─ data/raw/                    # 不被候选覆盖的模拟原件
├─ data/source_index.csv        # 授权、隐私、SHA与来源组
├─ data/contract.json           # 可执行数据契约
├─ data/candidates_replay.json  # 明确非模型实测的离线候选
├─ candidate_adapter.py         # 可替换候选提取接口
├─ workflow.py                  # clean、issues、划分与报告
├─ evaluate_fixed_cases.py      # 冻结契约测试
├─ DATA_CARD.md
└─ acceptance.py

二、多模态模型只产生候选

输入给模型的提取任务应包含字段定义、允许值、缺失表示和来源编号。例如:“只从S003图片中读取可见铭牌信息;看不清的字段填null;每个非空值附原图中的证据短句或区域说明;不要根据同类设备猜型号。”参考S003正确地把时间与数值保留为null,而不是根据文件名或同类设备猜测。模型输出后,学生随机抽查,也要优先复核影响大、置信低或与其他材料冲突的字段。

参考运行没有调用多模态模型。OfflineReplayExtractor读取教师编写的8条候选并验证来源声明;CallableExtractor只定义获准模型的接入边界。这样既能学习模型如何进入工程,也不会把没有发生的模型调用写成结果。

文字清晰、格式稳定的扫描表格,可以把专用文字识别作为速度基线;需要同时理解图片、表格和上下文时,多模态模型可能更方便;少量关键字段由人工录入通常更可靠。技术选择取决于材料和错误后果,而不是默认“越通用越好”。

三、建立人工基线

参考工程提供4条教师确认的人工录入作为基线,并与相同4个模拟来源的离线候选比较地点、类型、时间、数值、单位、标签和证据7个字段。两者均为28/28字段相符。人工耗时没有测量,离线候选又不是真实模型输出,因此本章不声称AI更快或更准。

真实课堂可重新记录两名学生的录入时间、分歧和复核次数,再与获准模型比较。如果模型速度快但增加了无法发现的错误,应限制它只处理低风险字段;如果材料只有十几条且格式稳定,人工录入可能就是更合适的首版。没有这些真实记录时,正确结论是“尚不能比较效率”。

四、来源证据必须跟着数据走

候选记录至少保留source_id与evidence。后续发现数值异常时,可以回到具体原件,而不是重新翻遍文件夹。一个字段由多个来源共同支持时,应保留全部来源;来源相互冲突时,不要选择模型更喜欢的一项,要生成冲突记录并交责任人。

图示规划: 在此设置“原件—来源索引—候选字段—规则校验—人工复核—发布数据”的分层图,突出原件和候选数据不能相互覆盖。

第二节 设计字段、类型、单位、标签和数据契约

一、字段来自工作,不来自现有表格

字段应由后续工作输出反推。本项目要支持设施观察与统计,因此需要记录编号、来源、地点、设施类别、观察时间、现象、数值、单位、状态标签和复核状态。若后续不需要人员姓名,就不应因为原表中有一列而继续收集。

数据类型说明机器可以对值做什么。日期应使用统一格式,数值应保存为数值而不是“18度左右”这样的字符串,类别应来自允许列表。缺失不等于零,也不等于“正常”。本项目用null表示没有可确认的值,用status_label="待复核"说明记录仍需人判断。

二、单位和标签是专业约定

“温度=26”只有与摄氏度、测量时间、位置和设备状态一起才可解释。同一字段混用摄氏度和华氏度,程序仍可能画出漂亮曲线,却没有可比意义。数据契约需规定单位,转换时同时保留原值和转换规则。

标签是人按任务规则给样本的目标名称。本项目的status_label只允许“正常、待复核、超出服务范围”,不把“未知”强行标为“正常”。标签定义要写出正例、反例和边界。两位标注者对同一记录意见不同,说明规则可能不清楚,应先修订说明再扩大数据量。

三、把约定写成数据契约

数据契约可采用JSON或表格表达。本章首版规定:

字段 类型与允许值 是否必需 说明
record_id 字符串,唯一 是 由项目规则生成,不由模型猜测
source_id 必须存在于索引 是 指向原件
location 字符串或null 是 未知时保留null
asset_type 照明、桌椅、业务设备、环境之一 是 其他材料进入待复核
observed_at ISO日期时间或null 是 不从文件修改时间猜测
value 数值或null 是 仅传感记录使用
unit ℃、%RH、lx或null 是 有数值时必须有单位
status_label 正常、待复核、超出范围 是 需符合标签说明
evidence 原件证据短句或区域说明 是 支持候选值

契约既给模型看,也给程序和使用者看。修改字段或允许值必须提升版本号,并说明旧数据如何迁移。直接在表格里增加一列而不更新说明,会让不同成员对同一字段产生不同理解。

四、区分样本、特征和标签

一条设施观察记录可以作为一个样本。地点、时间、数值和现象中的可计算表示可能成为特征;经过专业规则确认的状态是标签。哪些字段成为特征取决于具体模型,不是所有收集来的信息都应输入模型。来源编号用于追踪,不应因其与某批次偶然相关就成为预测依据。

后续训练模型时,训练集用于调整参数,验证集用于选择设置,测试集用于最后检查。划分要按设备、批次或时间隔离。把同一设备同一分钟产生的相邻记录随机分散到训练和测试,会让测试结果过于乐观,这称为数据泄漏。

第三节 处理错误、缺失、重复、偏差和数据泄漏

一、运行完整最小校验程序

下面是便于课堂阅读的校验主链缩略。权威的workflow.py还检查原件SHA-256、授权、隐私、数值范围和来源级划分,并把每个问题保存为稳定代码。它不调用模型,也不替人改正事实;候选提取与确定性校验被有意分开。

from pathlib import Path
from datetime import datetime
import csv
import json

ROOT = Path(__file__).resolve().parent
ALLOWED_ASSETS = {"照明", "桌椅", "业务设备", "环境"}
ALLOWED_LABELS = {"正常", "待复核", "超出范围"}
ALLOWED_UNITS = {"℃", "%RH", "lx"}


def read_source_ids(path):
    with path.open(encoding="utf-8-sig", newline="") as file:
        rows = list(csv.DictReader(file))
    return {row["source_id"] for row in rows if row.get("authorized") == "yes"}


def valid_time(value):
    if value is None:
        return True
    try:
        datetime.fromisoformat(value)
        return True
    except (TypeError, ValueError):
        return False


def check(row, source_ids):
    problems = []
    required_fields = {
        "record_id", "source_id", "location", "asset_type", "observed_at",
        "value", "unit", "status_label", "evidence"
    }
    for field in sorted(required_fields - set(row)):
        problems.append(f"{field}:字段不存在")
    required_text = ["record_id", "source_id", "asset_type",
                     "status_label", "evidence"]
    for field in required_text:
        if field in row and (
            not isinstance(row[field], str) or not row[field].strip()
        ):
            problems.append(f"{field}:必须是非空字符串")
    location = row.get("location")
    if location is not None and (
        not isinstance(location, str) or not location.strip()
    ):
        problems.append("location:必须是非空字符串或null")
    if row.get("source_id") not in source_ids:
        problems.append("source_id:不存在或未授权")
    if row.get("asset_type") not in ALLOWED_ASSETS:
        problems.append("asset_type:不在允许列表")
    if row.get("status_label") not in ALLOWED_LABELS:
        problems.append("status_label:不在允许列表")
    if not valid_time(row.get("observed_at")):
        problems.append("observed_at:格式错误")
    value, unit = row.get("value"), row.get("unit")
    if value is not None:
        if isinstance(value, bool) or not isinstance(value, (int, float)):
            problems.append("value:必须是数值")
        if unit not in ALLOWED_UNITS:
            problems.append("unit:有数值时必须使用规定单位")
    elif unit is not None:
        problems.append("unit:没有数值时应为null")
    return problems


def main():
    source_ids = read_source_ids(ROOT / "data" / "source_index.csv")
    payload = json.loads(
        (ROOT / "data" / "candidates_replay.json").read_text(encoding="utf-8")
    )
    rows = payload["records"]
    clean, issues = [], []
    seen_ids, seen_evidence = set(), set()
    for row in rows:
        key = (row.get("source_id"), row.get("evidence"))
        problems = check(row, source_ids)
        record_id = row.get("record_id")
        if record_id in seen_ids:
            problems.append("record_id:重复")
        if key in seen_evidence:
            problems.append("duplicate:来源与证据重复")
        seen_ids.add(record_id)
        seen_evidence.add(key)
        if problems:
            issues.append({"record_id": row.get("record_id"),
                           "problems": ";".join(problems)})
        else:
            clean.append(row)
    out = ROOT / "output"
    out.mkdir(exist_ok=True)
    (out / "clean.json").write_text(
        json.dumps(clean, ensure_ascii=False, indent=2), encoding="utf-8"
    )
    with (out / "issues.csv").open("w", encoding="utf-8-sig", newline="") as file:
        writer = csv.DictWriter(file, fieldnames=["record_id", "problems"])
        writer.writeheader()
        writer.writerows(issues)
    print(f"通过结构校验{len(clean)}条,待处理{len(issues)}条")


if __name__ == "__main__":
    main()

程序中的允许列表和字段规则就是可执行的数据契约。实际运行8条候选后,4条进入clean,4条因未授权与个人信息、未知来源、错误单位或重复编号进入issues;同一记录可产生多个问题代码。学生不能把clean直接称为真实正确数据,它只表示通过当前契约,地点与标签仍需回看原件并由人确认。

二、错误、缺失和重复要分别处理

错误是已有值与证据不符,应更正并记录前值;缺失是没有足够信息,应保留null并说明是否需要补采;重复是同一事件被多次记录,应依据来源、时间和业务规则确认是否合并。不能用删除重复的方式抹掉真实重复发生的事件。

模型可能把设备铭牌上的额定电压当成环境传感值,也可能把图片拍摄日期当成观察日期。校验程序能发现部分格式问题,却不理解所有专业含义。因此问题表要包含“规则发现”和“人工发现”两类来源,避免把未被程序捕获的错误误认为不存在。

三、观察分布和偏差

统计不同地点、设备、时间段和标签的数量。如果“正常”记录全部来自白天,“待复核”全部来自夜间,模型以后可能利用时间代替真实状态。数据量大不能自动消除这种偏差。学生应查明差异来自真实工作分布、采集方便性还是标签规则。

控制变量实验。 保持原件、模型、提取说明和测试记录不变,只在B版数据契约中增加“有数值时单位必填”规则。先预测B版会发现多少此前看似通过的记录,再运行同一校验程序和同一候选数据。比较待处理数量及人工复核时间。若同时改变模型提示和候选文件,就无法说明变化来自契约规则。

四、设计失败测试和划分检查

fixed_validation_cases.json冻结6条不参与候选构造的样例:N01为正常记录,B01为有值无单位的边界,X01为陌生来源,P01为隐私文本,F01为错误日期,O01为越界湿度。evaluate_fixed_cases.py比较期望问题代码与实际代码;参考运行6/6通过。此外,单元测试还模拟索引哈希被改变、必需字段缺失和重复编号。

本书统一把这组在规则确定后才运行、不能为追逐结果而反复改写的封存样例称为固定测试。它与训练数据或候选回放彼此隔离,也不参与字段规则设计。固定测试通过只说明当前六类已声明行为可以重复,不能据此推断所有现实原件都能被正确整理。课堂新增一种来源、单位或敏感字段时,应先用非封存练习材料完善合同和程序,再为下一版本另建从未参与修改的新固定测试,并由另一位同学复核版本与来源记录。

清洗记录按来源组划分:S001与S002进入train,S003进入validation,S004进入test;同一来源不跨集合。这里只是治理演示,4条记录绝不足以训练模型。测试结论仍要分层:结构通过、来源可追、专业确认和可用于训练不是同一件事。

第四节 形成可复现的数据包并交给另一位使用者

一、固定目录、版本和生成步骤

可复现数据包不依赖作者记忆。配套README.md说明数据用途、目录、输入输出、真实结果和限制。运行入口只有一条:

cd resources/ch02/project
python acceptance.py

它检查26个必需文件和Python语法,重新生成数据包,运行固定测试与13项单元测试,再核对参考结果。清洗数据由脚本生成,不手工覆盖;人工修订进入新候选或修订记录,再重新生成。

数据卡回答:数据为解决什么任务而建;包含哪些对象和时间范围;怎样采集、授权、清洗和划分;有哪些缺失和偏差;适合与不适合什么用途;由谁维护;如何反馈错误。数据卡不是宣传页,应明确写出不足。

二、让另一组真正复现

交接组只获得项目包和说明,不接受原组口头提示。它应能核对文件摘要,运行校验,得到相同的通过与问题数量,并随机回查3条记录的来源。如果复现者不知道某列单位、找不到原件、运行后覆盖了人工记录,说明数据包仍有隐含假设。

参考复现得到:5个原件摘要全部一致,8条候选中clean=4、rejected=4,冻结测试6/6;离线候选和人工基线均为28/28字段相符。结论为usable_for_teaching_only,因为原件是模拟材料、候选不是模型实测、人工时间未记录。差异可能来自文件丢失、脚本版本不同、格式被修改或说明不完整,必须保留日志再做限定修改。

复现时还应逐层解释“通过”的含义。5个摘要一致,只能证明本次读取的原件没有相对索引发生变化;4条进入clean_records.json,只说明它们通过当前字段、单位、范围、授权和隐私规则,不证明现场事实一定正确;6/6冻结测试说明校验器按预先约定处理了正常、边界、陌生、隐私、错误日期和越界数值,不说明规则覆盖了所有现实情况。最后仍要打开issues.csv,沿source_id回到原件,判断拒绝原因是否准确。另一组若只报告“验收成功”而说不清这三层差别,复现任务仍未完成。

工程把故障也作为交付的一部分:原件哈希变化时停止,必需字段缺失时报错,记录编号重复时两条都进入问题表,未授权或含个人信息的来源不得因候选内容看似无害而放行。学生可以请大语言模型解释某个问题代码,但不能让它直接改写原件、伪造授权或猜测缺失单位。每一次人工纠正都应保留旧值、依据、修改人和新版本,再由相同入口重新生成数据包。

可追溯比表面整洁更重要。

三、专业迁移卡

专业迁移卡A:设计与品牌素材库
输入改为品牌手册、标志文件、字体授权、历史海报和图片素材;规范包括颜色值、最小尺寸、版权和可修改范围;高代价错误是误用标志、混淆授权或泄露未发布作品。交付物为素材索引、权利字段、可用规格、缩略图和审核记录,由品牌负责人及权利审核人员批准。

专业迁移卡B:智能制造设备日志
输入改为设备台账、控制器日志、点检记录和经授权的铭牌照片;单位、采样频率、设备编号和停机时刻必须统一;高代价错误是跨设备合并、时间错位或把维护后数据泄漏进此前的测试。交付物为按设备与批次划分的数据包,由设备工程人员确认标签和使用边界。

专业迁移卡C:生物培养观察数据
输入改为培养批次、环境记录、显微或外观图像和实验备注;需要遵守样本编码、实验条件和伦理授权;高代价错误是混淆批次、单位或把探索性观察当成诊断结论。交付物为批次隔离数据、数据字典和实验复核表,由实验指导人员确认。

四、作出发布决定

数据包可以“发布供本项目使用”“限内部复核使用”或“退回补采”。本参考包只获准作为教材模拟数据使用,不得对外宣称真实工作现场数据或模型性能。决定依据包括授权完整性、来源可追性、字段通过率、标签一致性、偏差、泄漏风险和复现结果。缺少关键授权、原件摘要改变或测试集泄漏时,即使程序能运行,也必须停止发布。

本章小结

本章把零散材料变成了可追溯的数据底座。原件、授权和来源必须在AI提取之前建立;多模态模型产生候选值,数据契约规定字段、类型、单位、标签和缺失方式,普通程序执行确定性检查,专业人员确认事实和标签。结构通过不等于数据正确,可用于观察也不等于可用于训练。可靠数据包应记录错误、缺失、重复、偏差和划分方法,并由另一组按照说明复现。数据质量不是模型训练前的一次清洁工作,而是贯穿更新和交付的责任。

关键术语

目标测试

  1. 多模态模型从铭牌图片中读出的型号首先应被视为什么?
    A. 已确认事实 B. 候选值 C. 训练标签 D. 授权证明
  2. 数值字段为26但没有单位时,最恰当的处理是什么?
    A. 默认摄氏度 B. 删除记录 C. 标记待处理并回查来源 D. 改为0
  3. 下列哪种划分最能降低同一设备数据泄漏?
    A. 相邻记录随机拆分 B. 按设备或批次整体划分 C. 复制到三个集合 D. 只使用训练集
  4. 校验程序显示“通过结构校验”意味着什么?
    A. 专业事实一定正确 B. 已获得所有授权 C. 记录符合当前可执行字段规则 D. 一定适合训练
  5. 判断并改错:“缺失值和数值0都表示没有信息,可以相互替换。”
  6. 判断并改错:“数据越多,采集偏差和标签偏差就会自动消失。”
  7. 为一张经授权的设备铭牌图片设计四项来源索引字段,并说明各自用途。
  8. 给出一条有数值、单位缺失的候选记录,说明校验、人工复核和修订记录应怎样衔接。
  9. 设计一次只改变“单位必填规则”的控制变量实验,写出预测、保持不变条件和比较指标。
  10. 交接组可以运行脚本,但随机抽查时找不到5条记录的原件。请作出发布、限用或退回结论,并列出两项修复要求。

第3章 开发产品售后规范与服务指南证据助手

工作阶段: 从资料治理到证据检索、回答路由与验收。
公共核心项目: 开发一个可离线运行的“产品售后规范与服务指南证据助手”。它回答客户账号安全、产品基础排查、标准配件换货、售后申请和服务时间等工作问题;找不到依据时拒答,资料互相矛盾时并列冲突,不靠模型记忆补写业务事实。
核心技术: 有效期资料过滤、中文字符2/3-gram、TF-IDF向量、余弦相似度、关键词基线、语义检索边界、证据约束回答、引用集合校验、拒答与冲突路由。
输入输出链: 9个模拟资料块 → 只索引8个当前有效资料 → 8条独立校准题选参 → 提问 → 两种检索器之一 → answer/refuse/conflict路由 → 引用校验 → 12条冻结问答验收。
应用中的AI: 参考版用可解释的字符TF-IDF向量检索完成“按字符模式找候选资料”;回答端故意采用抽取式证据回答器。可选语言模型只能改写已经命中的证据,并必须通过引用约束。
协助开发的AI: 帮助解释向量计算、阅读失败记录、生成限定范围的故障测试和审查单次代码修改;学生运行程序、检查差异并保留固定测试独立性。
人的责任: 登记资料状态,确认现实中的版本和适用范围,判断引用是否真正支持结论,解释冲突并决定是否采用。
主要交付物: 可运行工程、资料卡与系统卡、关键词基线、TF-IDF检索器、回答适配器、独立校准集、冻结问答集、单元测试、机器可读报告和发布结论。
明确边界: 全部资料是教材模拟材料;参考结果为not_ready_for_use,只能课堂观察,不能当作本单位真实规章或自动对外服务。
跨章关系: 读取第1章任务与第2章数据包,为第4章事实约束、第10章工作流和第11章验收提供证据模块。

学习目标

完成本章学习后,你将能够:

  1. 把企业服务问答拆成资料治理、检索、回答路由、引用核验和验收五个环节;
  2. 说明字符n-gram、TF-IDF和余弦相似度怎样把文本转成可比较的数值表示,并区分字符相似检索与文本嵌入式语义检索;
  3. 在同一冻结题集上比较关键词基线与向量检索,而不是只展示一个“看起来正确”的回答;
  4. 运行完整工程,观察正常、同义改写、边界、陌生、冲突、过期与故障输入;
  5. 依据真实的11/12结果作出“不具备发布条件”的判断,并提出下一轮校准计划。

项目导入

售后服务人员经常需要核对“标准配件在签收后多少天内可以申请换货”“显示设备没有画面时普通使用者能否拆机”“客户服务中心周六受理到几点”。直接打开通用聊天模型也许能得到流畅答案,却无法证明答案来自企业当前有效文件。模型还可能把其他品牌条款、旧版服务规则或一般常识混入回答。真实工作需要的不是一句像答案的话,而是一条可回查、会拒答、能显式呈现冲突的证据链。

本章完成一个从输入、模型到验收都可运行的纵向项目。配套工程自带9块教师编写的模拟企业资料,其中8块标记为当前有效,1块是明确过期的旧版配件换货规则。程序在启动时过滤过期资料,把有效段落变成中文字符2/3-gram,再计算TF-IDF向量和余弦相似度。命中充分时返回证据原文和编号;没有命中时走refuse;命中同一冲突组的两个有效条款时走conflict。这三个路由共同构成应用,不是一个孤立的提示词片段。

为了判断这种“智能”是否真的改善工作,项目另设透明关键词规则作为基线,并把两种系统放在同一组12条冻结问答上比较。参考运行中两者都是11/12:向量检索找到了关键词基线漏掉的同义改写,却把资料库没有覆盖的“上门服务费用”错误关联到售后申请资料;关键词基线安全拒绝该陌生问题,却漏掉“整串口令”这种改写。工程因此不宣称向量检索更好,结论明确写为not_ready_for_use。学生要学习的正是怎样从失败认识模型边界,而不是怎样把演示包装成成功产品。

本章成果

AI协同开发路线

学生先阅读任务合同、资料卡和系统卡,画出“有效资料—校准—检索—路由—引用—验收”链。随后先运行校准网格并打开代码定位字符切分、向量计算、阈值和拒答条件,参数冻结后才查看最终逐题结果。与协助开发的AI讨论失败时,只提供模拟问题、命中编号、分数和期望行为,不提供真实账号、密钥或单位内部敏感文件。AI可提出一个小改动,学生负责判断改动是否偷看了冻结答案、是否损害其他题并重跑全部验收。

本章不要求非人工智能专业学生从空白手写TF-IDF。学生要能用自然语言说清任务,让AI解释或生成局部代码,然后亲自找到输入文件、运行入口、关键变量、输出报告和失败样例。真正的学习证据包括:能指出effective_status为什么在建索引前过滤;能解释余弦高分不等于事实正确;能说明Q09为何比普通漏答更危险;能拒绝“把Q09关键词硬编码进去”这种污染测试的捷径。

第一节 把工作要求拆成需要核对的证据问题

一、先确定简报支持什么决定

证据助手不是一般问答。首版任务是帮助售后服务人员根据已登记的当前资料回答客户账号、产品基础排查、标准配件换货、售后申请和服务时间问题,并在无依据或资料冲突时转人工。它不诊断设备内部故障,不替企业发布新规定,也不承诺费用或维修结果。只有先确定回答要支持的工作决定,才能知道需要哪些资料和证据。

一个问题可能混合多类要求。例如“客户的显示设备画面闪烁,能否自行重启,若无效应怎样申请售后?”可以拆为:服务指南允许普通使用者执行哪些重启步骤,这是规则问题;当前产品编号、连接状态和故障现象是什么,这是事实问题;已重启多少次或等待多久,这是计算或记录问题;是否继续使用设备,这是需要结合现场风险的专业判断。

二、四类问题使用不同方法

事实问题需要找到明确记录,如型号、日期和现象;规则问题需要查有效说明或制度;计算问题应把确定数据交给普通程序,不让语言模型心算关键结果;专业判断可以参考证据,却应由有资格的人员确认。把四类问题混成一句,会让模型把“资料原文”与“自己的建议”写在同一语气中。

证据问题表至少包含问题编号、类型、所需证据、时效要求、无证据时动作和责任人。例如Q03是“普通使用者是否允许打开设备外壳”,证据应来自当前有效的安全说明;无命中时不得根据常识回答,必须转设备管理人员。

三、为资料建立有效性索引

每份资料使用稳定的doc_id,每个可检索块使用稳定的chunk_id,并记录标题、版本、适用对象、来源位置、授权和有效状态。同名文件不代表同一版本。旧版材料可以保留用于解释历史记录,但检索时应明确标为“过期,不作为当前操作依据”。网页材料若会变化,应保存获准使用的快照及访问日期。

资料越多不一定越可靠。把不相关、过期或来源不明的内容一起放进检索库,会增加错误命中的机会。项目组应说明为什么纳入每份资料,也应记录已排除的资料及理由。

四、建立人工关键词基线

在使用字符TF-IDF前,先为每类资料列出3—6个关键词或短语。配套工程把这些规则保存在data/keyword_rules.json,与TF-IDF检索器读取同一组当前有效资料,并采用相同的top_k=3。关键词基线透明、稳定,材料术语明确时可能已经足够。

关键词也会漏掉词面不同但意思相关的表达。本章引入字符2/3-gram和TF-IDF,是为了让问题与资料共享的短字符片段形成可比较的数值表示,而不是让模型替人认定证据。它能处理部分表达变化,也可能被偶然重合的字符误导,所以必须与基线和拒答测试一起观察。

第二节 用关键词和字符TF-IDF寻找相关段落

一、先把文档切成可回查的段落

整个文档直接生成一个向量,会把不同主题压在一起;切得只有几个字,又会失去条件和例外。本项目已经把模拟资料整理为9个可回查的块,编号为C001至C009,每块同时保留标题、版本、适用范围和有效状态。真实迁移时可以按自然段切分,但表格标题、章节标题和相邻条件应与内容一起保存;扫描件若读错关键单位,应回到原图复核。

切分结果应包含稳定编号、原文、来源版本和页码或区域。回答引用[C003]一类编号,使用者可以直接回查。切分规则发生变化,编号和测试结果也可能变化,因此需要更新索引版本并重新校准。

二、字符TF-IDF向量表示什么

参考工程没有调用预训练嵌入模型。它先删除标点和空白,把中文连续的两个字、三个字作为特征;再计算TF-IDF权重,把每个问题和资料块表示成稀疏向量。余弦相似度比较两个归一化向量的方向,并按分数排序。这里的高分只说明共享的加权字符片段较多,不代表资料真实,也不是答案正确概率。

字符片段方法不需要下载模型,计算过程容易逐行查看,但它不是完整语义理解。“口令”与资料中的“密码”只有在周围表达也有重合时才可能命中;两个不相关问题也可能因“服务、申请、产品”等片段偶然接近。高分段落可能只是在讨论相似词语,没有回答问题,检索结果仍需后续路由和人工检查。

因此,本章当前实现应准确称为“字符TF-IDF相似检索”,不能因为使用了向量和余弦相似度就称为语义检索。文本嵌入式语义检索通常使用经过训练的嵌入模型,把问题与资料映射为稠密向量,使词面不同但含义接近的表达有机会靠近;它也可能把范围外问题错误拉近,并增加模型版本、运行依赖和数据边界。配套工程保留统一检索接口,未来可以把嵌入式语义检索作为可替换扩展,但必须使用独立校准集重新选参,并原样保留拒答、冲突、过期过滤、引用核验和冻结验收,不能把“换成嵌入模型”当作自动解决Q09的答案。

证据问题 ──字符2/3-gram──TF-IDF──> 问题向量 ┐
                                             ├─ 余弦相似度 ─> Top-3候选
有效资料 ──字符2/3-gram──TF-IDF──> 资料向量 ┘

三、比较两种检索而不是迷信一种分数

选参数和测最终效果必须使用两组不同问题。data/calibration_qa.json有8条校准题,只用来比较预先声明的9组候选配置:top_k取1、2、3,min_score取0.04、0.08、0.12。calibrate.py逐组记录路由和候选证据;唯一8/8通过的是top_k=3、min_score=0.08,程序随后冻结这两个值。

为什么会选中这组参数?CAL01和CAL03是分数较低但确有依据的问题,0.12会把它们拒掉;CAL07是最高分约0.076的陌生问题,0.04会把它错误放行;CAL06要求同时找回两条冲突规定C006、C007和说明系统边界的C009,top_k小于3会漏掉所需候选。这个选择只对当前小型模拟资料和候选网格成立,不是通用参数。

参数冻结后,data/fixed_qa.json中的12条问题才第一次进入最终比较。Notebook在最终测试单元之前只使用不重合的演示题和校准题,acceptance.py会在忽略标点、空白和大小写后检查冻结题没有提前出现。学生若要研究把top_k从3改为2,必须回到校准集,先写预测并只改一个变量;不能在12条最终题上反复试到分数好看。

四、检索失败要显式呈现

如果最高相似度仍很低,或前几段都没有直接支持问题,系统应输出“无足够依据”,而不是让生成模型依靠常识补全。陌生型号、拼写错误和资料缺页都可能导致无命中。系统要保留原问题和检索分数,方便补资料或修正问题。

检索增强生成常用来概括“先检索依据,再约束生成”的实现模式。名称不是重点,关键是证据库范围、检索是否命中、生成是否受约束、引用能否回查。没有这些环节,只在提示中写“请准确回答”,不构成可靠证据链。

第三节 让模型只依据命中材料形成带来源简报

一、完整最小实现

配套工程的权威实现位于resources/ch03/project/evidence_assistant.py。它不要求云端模型,也不要求安装第三方库,Python标准库就能把资料转成TF-IDF向量。下面列出建索引、检索和路由的核心主链;完整的命令行入口、关键词基线、回答适配器、评估器和异常检查均保存在工程中,不把隐藏代码当作教学黑箱。

class TfidfIndex:
    def __init__(self, chunks):
        # 过期资料在进入模型以前就被确定规则排除。
        self.chunks = [c for c in chunks if c["effective_status"] == "active"]
        if not self.chunks:
            raise ValueError("没有当前有效资料。")
        counts = [Counter(character_ngrams(c["text"])) for c in self.chunks]
        df = Counter()
        for item in counts:
            df.update(item.keys())
        n = len(self.chunks)
        self.idf = {token: math.log((1 + n) / (1 + freq)) + 1.0
                    for token, freq in df.items()}
        self.vectors = [self._vectorize(item) for item in counts]

    def _vectorize(self, counts):
        total = sum(counts.values()) or 1
        values = {token: (freq / total) * self.idf[token]
                  for token, freq in counts.items() if token in self.idf}
        norm = math.sqrt(sum(value * value for value in values.values())) or 1.0
        return {token: value / norm for token, value in values.items()}

    def search(self, question, top_k=3, min_score=0.08):
        query = self._vectorize(Counter(character_ngrams(normalize(question))))
        ranked = []
        for chunk, vector in zip(self.chunks, self.vectors, strict=True):
            score = sum(value * vector.get(token, 0.0)
                        for token, value in query.items())
            if score >= min_score:
                ranked.append({**chunk, "score": round(score, 6)})
        ranked.sort(key=lambda item: (-item["score"], item["chunk_id"]))
        return ranked[:top_k]


def resolve_question(question, hits):
    if not hits:
        return {"route": "refuse", "evidence": [],
                "answer": "无法从当前有效资料确认。请联系相应服务人员。"}

    groups = defaultdict(list)
    for hit in hits:
        if hit.get("conflict_group"):
            groups[hit["conflict_group"]].append(hit)
    conflict = next((items for items in groups.values() if len(items) >= 2), None)
    if conflict:
        return {"route": "conflict", "evidence": conflict,
                "answer": "当前有效资料存在冲突,不能自动选择。"}

    evidence = [hits[0]]
    answer = ExtractiveEvidenceAnswerer().answer(question, evidence)
    allowed = {item["chunk_id"] for item in evidence}
    valid, citations = validate_citations(answer, allowed)
    if not valid:
        return {"route": "refuse", "evidence": evidence,
                "answer": "回答引用校验失败,已停止输出。"}
    return {"route": "answer", "evidence": evidence,
            "citations": citations, "answer": answer}

这里的“模型”不是一个神秘接口。字符n-gram把连续的两个字、三个字变成特征;TF-IDF降低到处出现的特征权重,提高较有区分度特征的权重;余弦相似度比较两个归一化向量的方向。程序再用普通条件语句决定回答、拒答还是冲突。学生可以沿着代码逐行找到每个业务约束落在哪里,也可以把一个提问的实际特征、得分和证据编号交给大语言模型,请它解释为何会命中。

参考回答器直接复制证据并加[C001]一类引用,不把“生成得自然”当作项目必需条件。answer_adapter.py另提供CallableLanguageModelAnswerer:企业若有获准的本地或云端模型,可以把“问题+已命中证据”送给它组织语言;没有证据时适配器禁止调用,模型输出若引用了本次证据集合之外的编号也会被拒绝。模型因此是可替换模块,不是整个系统唯一的安全防线。

可选拓展,不属于参考主链。 answer_adapter.py保留了一个可调用语言模型的接口边界,实践单位具备合规模型服务时,可以让模型只改写已经命中的证据;工程没有附带云端地址、密钥、预运行结果或额外材料,也不把这项拓展计入参考分数。若进一步改用神经网络文本嵌入,必须另行提供可运行适配器、依赖说明和新的独立校准结果,原来的0.08门槛不可沿用。教材不以一段无法运行的接口代码代替真实工程。

二、运行时先看命中,再看简报

先进入工程目录并执行:

cd resources/ch03/project
python evidence_assistant.py "未安装的标准配件在签收后多少天内可申请换货?"
python evidence_assistant.py --baseline "未安装的标准配件在签收后多少天内可申请换货?"
python calibrate.py --report output/calibration_results.json
python evaluate.py --report output/my_report.json
python acceptance.py

前两条命令让同一个问题分别经过字符TF-IDF检索与关键词基线。终端输出包含route、answer、evidence、citations和human_review_required。阅读顺序应当是先看路由,再看证据原文与状态,最后看回答;如果证据错了,回答写得再好也没有可靠基础。calibrate.py显示9组候选参数的逐组结果,evaluate.py逐题显示最终题的预期和实际路由、证据编号与是否通过。acceptance.py还检查20个必需文件、7个Python文件语法、校准题与冻结题是否隔离,以及14个正常与故障单元测试。

参考运行不是虚构的“理想效果”。TF-IDF在Q01—Q08、Q10—Q12通过,在Q09“上门服务需要收多少费用”上失败:资料库没有上门服务收费规则,它却因字符片段偶然接近而命中C004售后申请资料,随后进入回答路由。关键词基线则正确拒绝Q09,但在Q02“工作人员会要求我在聊天里提供整串口令吗”上没有把“整串口令”识别为“密码”的同义表达。两者各通过11题,失败性质不同。

将运行现象提交给协助开发的AI时,应提供校准问题编号、命中段落、分数和期望,不提供密钥。一个合适的研讨请求是:“解释CAL07在门槛0.04时为何被错误放行、在0.08时为何拒答;只分析字符片段和分数,暂不改代码。”若AI建议修改,学生先检查它是否读取了冻结题、是否一次改了多个变量,再决定要不要在新校准版本中实验。

还要防止一种看似高效的作弊式修复:看到Q09失败后,直接把“上门服务费用”写进拒答黑名单。这样可能让这12题变成12/12,却没有获得处理其他陌生问题的能力,还污染了冻结测试。合理做法是扩充data/calibration_qa.json形成带版本的新校准集,在其中比较分数门槛、词面覆盖、第二名差距或“双系统均无可靠命中”的门控策略;最终评价必须换用未参与开发的新冻结集。固定题集是最后检查,不是逐题调参材料。

三、模型、普通程序和人怎样分工

字符TF-IDF承担文本数值表示与候选排序;可选大语言模型只承担基于证据的组织和表达;普通程序负责有效性过滤、来源编号、阈值、冲突分组、文件写入和引用编号集合检查;学生核对问题、命中和引用;资料责任人确认现实中的版本,业务责任人解释冲突和决定能否使用。

把所有步骤都交给语言模型会失去确定性,把所有问题都写成关键词规则又难以处理表达变化。可靠系统不是选一个“最强模型”,而是让不同环节承担适合的责任,并让失败能够被看见。

本项目也帮助理解“大模型是指挥中心”的适用边界。它可以与学生讨论任务、解释代码、把证据改写成更易读的句子,却不能替代资料治理和验收。如果将来更换为神经网络嵌入或云端语言模型,只需实现相同适配接口;任务合同、三种路由、引用集合和冻结测试仍然保留。软件更换不应让工程责任一起消失。

第四节 核对时效、冲突、缺失和专业责任

一、引用存在不等于引用支持

引用核验至少有三步:编号是否真实存在;段落是否包含所述条件;结论是否超出段落范围。资料写“允许重启一次”不能支持“可反复重启”;适用于A型号的条款不能直接用于B型号。学生可以在简报每条结论旁标注“直接支持、需要推断、不支持”,需要推断的内容单列并交责任人。

时效核验检查版本、生效日期、适用对象和是否被新材料替代。检索分数不会因为资料过期而自动降低,因此有效性过滤应在检索前或生成后由规则和人执行。

二、用失败样例建立固定回归

冻结问答data/fixed_qa.json共12条,覆盖正常问题、同义改写、边界条件、安全提示、未知领域、有效资料冲突和过期证据排除。Q11要求同时返回C006和C007,路由必须是conflict;Q12要求使用当前C003,并明确禁止出现过期C008。单元测试另覆盖空问题、问题过长、资料库没有有效资料、无证据拒答、非法引用、无证据时禁止调用语言模型和调用模型引用越界等故障。这样既测“答对”,也测“该停时能否停下”。

每次修改后都运行相同问题,记录检索命中、非法引用、无依据句、人工复核时间和高代价错误。测试问题不能在调试时全部变成提示示例,否则模型可能只是适应了这些题目。

本轮运行的机器事实如下:9块模拟资料中只有8块进入索引;两套系统均完成12条问答;TF-IDF为11/12,关键词基线为11/12;14个单元测试全部通过;工程验收脚本退出码为0。机器报告不只保存总分,还写明decision=not_ready_for_use和三个失败发布门,并固定两个失败身份:character_ngram_tfidf:Q09实际回答且引用C004,属于高代价范围外回答;transparent_keyword_rules:Q02拒答且缺少应有C001引用,属于可用性失败。验收把现场完整JSON与正式参考逐字段比较,因此不能用另一组11/12替换当前错误性质。这里“验收脚本通过”表示工程文件齐全、结果可复现且失败被如实记录,并不等于应用达到发布门。

下一轮应建立规模更大、版本明确的校准集研究拒答门,例如同时观察最高相似度、第二名差距和关键词覆盖。学生必须先写预测,再只改一个变量,并保留新的未知类问题作下一轮最终测试。若降低阈值,召回可能提高,陌生问题误答也可能增加;若提高阈值,拒答更安全,有依据的低分表达可能被误拒。没有一种阈值天然正确,选择取决于错误代价和任务边界。

三、专业迁移卡

专业迁移卡A:商贸商品与服务条款
输入改为经确认的商品参数、促销规则、退换条款和渠道限制;高代价错误是把旧价格、其他型号参数或内部规则当成当前承诺;交付物为带条款编号的客户答复草案、冲突表和转人工清单,由商品负责人和客服审核人员确认。

专业迁移卡B:制造设备说明与点检规范
输入改为指定型号说明书、点检规程、维修公告和版本记录;高代价错误是跨型号引用、遗漏停机条件或生成未经授权的拆修步骤;交付物为故障现象证据简报和允许操作边界,由设备技术人员批准,助手不直接控制设备。

专业迁移卡C:交通运行规程核对
输入改为适用线路的运行规程、临时通知和设施手册;时效与适用区域成为强制过滤条件;高代价错误是引用失效通知或省略人工调度权限。交付物为带来源的事件核对单和冲突事项,由授权调度或安全人员确认。

四、形成可负责的结论

验收结论可分为:对固定资料和问题范围“采用”;只用于查找候选段落、结论全部人工复核的“限用”;高代价引用错误或时效无法控制时“退回”;问题超出资料或专业权限时“转责任人”。报告同时说明模型、资料索引、程序和测试集版本。

本项目的合格结论是:“工程已可离线复现,8个当前有效资料块能够被检索,过期C008被排除,冲突资料可并列;但字符n-gram TF-IDF在12个冻结问题中误答1个资料范围之外的问题,关键词基线则漏答1个同义改写。两者均为11/12,向量系统未通过未知问题拒答门。当前版本仅供课堂观察与人工核验证据候选,不自动对外回答,结论为not_ready_for_use。”它展示证据和边界,而不是对模型能力的笼统评价。

完整复现应从README开始,不依赖教师口头补步骤。另一组在Python 3.10—3.12环境中进入resources/ch03/project/,直接执行python acceptance.py,应看到两套逐题结果、文件与语法检查、Notebook隔离检查和14项单元测试。若环境、代码或数据变化导致结果不同,应保留新的输出并调查原因,不能手工把报告改回参考数字。

本章小结

本章完成了一个可运行、可失败、可复核的企业证据助手。项目从模拟资料治理开始,经字符n-gram、TF-IDF、余弦检索进入三种回答路由,再用引用集合和固定题集验收。关键词基线让学生能判断复杂方法是否真的改善工作;可替换回答适配器说明语言模型可以参与表达,但必须服从证据范围。真实的11/12对11/12结果表明,同义表达能力与陌生问题拒答之间存在权衡。一个完整AI项目不以“成功演示”结束,而以说明适用范围、失败类型、人的责任和下一轮实验结束。

关键术语

目标测试

  1. 字符TF-IDF检索返回最高余弦相似度段落,能够直接说明什么?
    A. 段落一定真实 B. 段落在该表示下与问题较接近 C. 答案已获批准 D. 资料一定最新
  2. 下列哪项最适合交给普通程序而不是语言模型?
    A. 组织简报语言 B. 找同义表达 C. 检查引用编号是否属于命中集合 D. 概括段落
  3. 资料没有回答某问题时,系统最合适的行为是什么?
    A. 使用模型常识补全 B. 选择相似度最高段落强行回答 C. 明确无依据并转待确认 D. 删除问题
  4. 为什么要保留关键词检索基线?
    A. 它总比TF-IDF检索好 B. 可比较新方法是否改善命中,并处理型号等精确词 C. 它能判断专业责任 D. 它无需资料
  5. 判断并改错:“引用编号合法,就证明引用段落一定支持对应结论。”
  6. 判断并改错:“把更多资料全部放入检索库,一定会提高回答可靠性。”
  7. 把“这台设备坏了怎么办”拆成一个事实问题、一个规则问题和一个专业判断问题。
  8. 设计一个资料冲突测试,写出输入材料、问题和期望输出行为。
  9. 说明怎样用data/calibration_qa.json研究把top_k从3改为2,同时保持12条冻结题集不参与选参。应记录哪些指标?
  10. 本项目两个系统都在12条冻结问答中通过11条:向量系统误答一个未知问题,关键词系统漏答一个同义改写。请比较错误代价,作出验收结论,并列出下一轮最小实验和责任人。

第二篇 把专业方案做出来——生成、预测与优化

第4章 把生成候选做成可审校的节能提示卡

工作阶段: 形成方案。
公共核心项目: 完成“门店节能提示卡生成与审校器”,制作面向闭店交接员工的10秒静态SVG提示卡,使目标员工至少说出三项行动中的两项,并把生成候选变成有事实依据、规格记录、用户证据和发布结论的交付包。
核心技术: 生成模型适配器、离线候选回放、事实约束、候选比较、SVG确定性排版、规格校验、用户测试和权利审查。
输入输出链: 创意简报与事实清单 → 与平台无关的提示包 → 生成候选或离线回放 → 事实/规格/权利预检 → SVG预览 → 用户测试与人工审批 → 发布或阻断记录。
应用中的AI: 可替换的语言或多模态生成模型只负责提出候选;参考工程用明确标记的离线回放复现后续审校链。
协助开发的AI: 帮助检查简报、解释审计错误、生成限定补丁和补充测试的项目型AI助手。
人的责任: 确认传播目标和事实,作出创意取舍,核验授权与规格,对最终发布负责。
主要交付物: 任务合同、创意简报、事实清单、提示包、候选JSON与SVG、审计报告、用户测试表、人工审查表和发布决定。
明确边界: 不生成虚构节能数据,不冒用人物和品牌,不把模型输出当作已授权素材;正式发布前必须人工审核。
跨章关系: 使用第1章任务合同、第2章授权素材和第3章事实依据;第10—12章将把作品生产、审核和发布接入受控工作流。

学习目标

完成本章学习后,你将能够:

  1. 将目标、受众、事实、规范和交付规格写成可执行的创意简报;
  2. 组织语言与图像模型生成可追踪、可比较的候选方案;
  3. 使用量规选择候选,并通过限定修改保持事实和风格一致;
  4. 运行完整交付校验程序,检查SVG尺寸、安全区、事实文字、来源记录和用户测试字段;
  5. 区分离线回放、真实模型输出和人工模板,不伪造生成来源与用户证据;
  6. 结合用户测试、专业评审和权利检查作出发布、限用或退回决定。

项目导入

生成模型可以迅速产生文案、图像、声音和分镜,但专业传播的难点不是“得到一张图”,而是作品是否解决了明确问题,事实是否准确,不同媒介是否一致,文件是否符合交付规格,素材是否有权使用。一个吸引人的画面如果虚构了数据、把节能倡议写成强制规定,或无法用于指定版面,就不是合格成果。

本章完成一个具体产品:门店节能提示卡生成与审校器。目标受众是负责闭店交接的门店员工,作品是一张1080×1440像素静态SVG提示卡,必须准确呈现“关闭非必要照明、关闭非营业所需的空调和风扇、确认业务设备按规程正常关机”三项教学模拟事实;未参与制作的目标员工观察10秒后,应至少说出三项行动中的两项。生成模型只提出文案和视觉方向,普通程序完成可控中文排版和确定性检查。

核心工程不要求云端账号。generator_adapter.py定义统一候选接口;课堂默认读取明确写有is_model_output=false的教师离线回放。学生也可把提示包复制到获准的本地或云端模型,再用import_candidates.py导入;is_model_output必须是布尔值,来源是否已经由导入者核实另写在verification_status。完整工作流可接收候选包路径和所选候选编号;省略参数时仍回放教师候选并选择G01。离线回放只证明审校链能运行,不能证明任何模型的当前能力。

本章成果

AI协同开发路线

学生先阅读TASK_CONTRACT.md,检查简报中的目标、事实、规格和禁区,再运行离线回放看见三种候选怎样被不同规则拦截。随后可选择一个获准模型,通过复制粘贴或适配器产生新的候选,但必须记录模型、版本、日期和素材来源。学生亲手只修改G02标题,预测删除无来源比例后哪个检查会改变;再让协助开发的AI只补一条“标题为空”测试,审查差异并运行acceptance.py。真实目标用户和人工责任人的记录不能由AI生成。

第一节 把目标、受众、规范和交付要求写成创意简报

一、传播目标必须可观察

“宣传节能”“做得有科技感”不足以指导创作。本项目的目标写为:“制作一张静态SVG提示卡,让未参与制作且负责闭店交接的目标员工观察10秒后,能说出三项闭店行动中的至少两项。”目标可以通过用户测试核对,也不承诺没有事实来源的“节省30%用电”。

受众不是抽象的“所有人”。实训学生查看海报的距离、停留时间、常用语言和已有知识,会影响字号、信息数量与场景。创意简报应记录主要受众、使用地点、希望发生的反应,以及不面向的人群。作品若同时承担制度说明、情感动员和操作教学,通常会因目标过多而失焦。

二、事实、创意与推测分开管理

参考工程的facts.json明确标为教材模拟,只含F1—F3三项行动。创意可以决定如何组织视觉和语言;推测如“大家最在意电费”没有调查证据,不能伪装成事实。每个候选动作同时保留action_id与fact_id,程序可以检查是否漏项、改字或引用未知事实。真实发布时必须换成由业务责任人确认的有效资料。

模型可以提出“每一次关灯都让企业更美好”之类表达,但学生要判断它是否空泛、是否适合受众。涉及数值、荣誉、政策、功效和人物评价时,不能靠模型记忆。无依据数字直接删除或标为待确认。

三、把专业规范变成条件

创意简报至少包含:传播目标、受众、核心信息、事实来源、语气、视觉要素、禁用内容、渠道、尺寸、文件格式、截止时间、审核人和验收方法。若企业有视觉识别规范,应引用有效版本,提供获准使用的标志文件和安全间距要求,不让模型凭印象重画标志。

本项目规定提示卡为1080×1440像素SVG,顶部至少保留180像素安全区,标题不超过18个字符,必须标注“候选方案,经人工审校”。生成模型只提出结构、文案和视觉方向;workflow.py再用普通SVG准确排版中文。候选不得出现人物、企业标志、无来源比例、功效保证或来源不明素材。

四、建立规则基线

工程提供人工模板B01作为基线:规则网格、三项核验文字和项目生成的几何图形,不使用外部标志。它与生成候选运行同一机器检查。参考运行中B01和G01都通过机器检查,因此不能声称生成方案已经优于基线;还要比较真实用户理解和制作成本。

user_tests.csv初始只有表头,表示真实用户测试尚未发生;user_test_rehearsal.csv的5条演练记录全部标为非真实用户且无同意记录,程序不会把它们计入证据。生成式方案只有在真实理解度、适用性或制作效率上优于基线,同时没有增加不可接受的事实与权利风险,才值得采用。

第二节 让语言与多模态模型形成可比较的候选方案

一、先形成信息结构,再生成媒介内容

workflow.py先根据简报和事实生成与平台无关的prompt_packet.md。语言或多模态模型应提出三个在信息结构或视觉方向上真正不同的候选,并按统一JSON字段返回;学生先检查每种结构是否覆盖核心事实、是否增加未经证实的承诺,再进入视觉制作。此时只讨论候选,不让模型直接决定发布。

候选至少包含编号、标题、三项动作、事实编号、视觉方向、画布规格、披露语和素材权利记录。主视觉条件应描述主体、构图、色彩和安全区,不只堆叠“高级、震撼、科技”。中文动作由SVG程序排版,模型生成图像只可作为经授权、无文字的背景或图形候选。

二、记录模型条件与随机变化

生成模型在相同输入下也可能产生不同输出。真实适配器应记录候选编号、模型与版本、日期、提示包摘要、参考材料、随机种子或变体编号和人工备注。离线回放则必须明确记录mode=teacher_authored_offline_replay、布尔值is_model_output=false和独立的来源核实状态。人工复制导入也必须把“是不是模型输出”和“来源是否已核实”分成is_model_output与verification_status两个字段。没有来源记录,就不能比较模型或解释结果怎样产生。

工程用一个极小的适配器边界隔离平台变化:

class CandidateGenerator:
    def generate(self, prompt_packet: str) -> dict:
        """返回provenance和candidates。"""
        raise NotImplementedError


class OfflineReplayAdapter(CandidateGenerator):
    def generate(self, prompt_packet):
        payload = json.loads(self.replay_path.read_text(encoding="utf-8"))
        if payload["provenance"]["is_model_output"] is not False:
            raise ValueError("离线回放不得冒充模型输出")
        return payload

联网平台不是课程前置条件。需要真实模型时,可以实现CallableModelAdapter,也可以人工复制提示包后用import_candidates.py导入;密钥不进入教材工程。

若使用参考图,必须说明来源和允许用途。参考图可以帮助构图或物体一致性,但不自动赋予生成结果使用权。平台条款、单位规定和素材授权应在当前发布环境中核查,易变化的具体产品说明放入数字资源,不写进稳定正文。

三、候选要有真正差异

三张颜色略有不同的图不构成三种方案。参考回放故意提供三类可比较结果:G01完整且规格正确;G02加入看似有力却无来源的“节电30%”;G03省略动作并使用规格错误、来源未知的标志。它们既演示候选差异,也让学生看见“漂亮但不合格”的具体原因。比较时使用同一量规,不在看到结果后为喜欢的候选改变标准。

推荐量规包含:10秒理解度、事实准确、核心行动完整、视觉层级、渠道适配、品牌一致、修改成本和权利风险。高代价项采用否决制:事实失真、出现未授权标志或泄露隐私时,无论美观分多高都不进入下一轮。

四、理解生成模型的能力边界

语言模型依据训练中形成的模式逐步生成文本,多模态生成模型则把文字和参考条件转成图像或音频表示,再在一定随机性下形成结果。它们擅长提出候选,不知道企业当前有效的闭店规程,也不天然理解交付责任。输入条件控制可以提高符合度,却不能保证每个细节准确。

模型输出不是素材来源证明。即使平台允许某种使用,也要检查输出是否与已有作品、标志、人物或受保护元素过近。涉及声音时,还要避免未经授权的声音克隆。可识别个人的肖像与声音不得因“模型能生成”而被使用。

版权审查也不能简化成一句“这是AI原创”。项目组应分别记录输入素材、参考素材和最终输出的来源,核对权利人或提供者、许可用途、是否允许修改、是否要求署名以及发布渠道等条件。模型服务的使用许可、素材本身的版权许可和人物肖像或声音授权是不同问题,不能用其中一项代替其他项。无法确认时先停止发布,改用自有或许可清楚的材料;具体判断依照当前法律、单位制度和发布单位要求,由相应责任人完成。

第三节 围绕事实、风格和规格进行限定修改

一、把反馈转换成可验证的修改

“更有冲击力”无法验收。可执行反馈应指向对象、变化和保持项:“只调整主视觉构图,使上方25%区域没有高对比主体,供标题排版;保持场景、三类设备、色调和画幅不变;不要加入文字和人物。”生成后对照前后版本,检查未要求变化的部分。

语言修改也应限定:“把第二句压缩到20字以内,保留三个行动和来源语气,不增加节能比例。”如果AI顺便改变了事实或删掉关键条件,应退回而不是因为语言更顺就接受。

二、做一次控制变量实验

使用同一图像模型、同一基础描述、同一画幅和同一参考材料。A版没有标题安全区要求;B版只增加“上方25%保持低细节、无主体、无高对比元素”。生成相同数量候选,比较可排版候选数、主体完整性、人工修图时间和用户10秒理解结果。

实验前写出预测:B版可用安全区可能增加,但主体可能被压缩。若结果不理想,下一轮只调整安全区比例。不要同时更换模型、色彩、主体和画幅,否则无法判断哪项条件改变了结果。

三、让程序检查确定性交付条件

生成模型负责候选,普通程序负责动作是否完整、事实编号是否存在、文字是否含无来源比例、SVG画幅和安全区是否正确、素材权利状态是否齐全。workflow.py的主链把候选和简报送入同一个审计函数:

brief = read_json(DATA / "brief.json")
facts = read_json(DATA / "facts.json")
bundle = OfflineReplayAdapter(DATA / "candidates_replay.json").generate(
    build_prompt_packet(brief, facts)
)
audits = [
    audit_candidate(candidate, brief, facts)
    for candidate in bundle["candidates"]
]
for candidate in bundle["candidates"]:
    render_svg(candidate, output / f"{candidate['candidate_id']}.svg")

默认回放用于第一次学习,真实导入则通过同一主链运行:python workflow.py --candidate-bundle output/imported_candidates.json --selected-candidate-id MY01。--candidate-bundle决定审计哪一包候选,--selected-candidate-id决定哪一个候选进入用户测试、人工审批和发布门;候选编号不存在、重复或格式非法时明确停止,不能悄悄退回G01。

audit_candidate内部先比较A1—A3动作集合和F1—F3事实编号,再运行禁止表述正则、规格与权利字段检查。字符串写入SVG前使用HTML转义,防止候选标题被当作标签执行。完整实现和19项测试位于resources/ch04/project/。

参考运行得到:3个离线候选中只有G01通过机器检查;G02命中无来源比例;G03产生7个问题。人工模板B01也通过机器检查。这些结果只证明确定性规则的行为,不会证明画面美观、事实来源有效或素材真的有权使用。

四、审查AI修改的差异

候选文件较大时,至少比较缩略图、文件摘要、元数据和人工观察记录;文案、简报和代码使用逐行差异。每次限定修改后重新运行交付检查,并用同一事实表、风格量规和用户问题复核。修好尺寸却丢失生成记录,或改善画面却改变事实暗示,仍不算通过。

第四节 用用户测试、专业评审和权利检查完成交付

一、用户测试观察理解,不诱导答案

选择5—8名接近目标受众但未参与制作的同学,取得必要同意后展示作品10秒并移开,分别问:“你认为它希望你做什么?”“你记住了哪些动作?”“哪处让你困惑?”不要先解释作品,也不要只问“好不好看”。user_tests.csv记录匿名参与者编号、候选、展示时长、回忆的动作和困惑,不收集无关身份信息。

发布门先验证CSV表头和字段:匿名participant_id只能使用字母、数字、下划线或连字符,布尔字段只能是true或false,seconds_shown必须严格等于10,回忆行动只能是A1、A2、A3且不得重复。随后只统计is_real_target_user=true且consent_recorded=true的记录,并按唯一participant_id计数;同一参与者重复出现不能增加人数,而且会否决本轮发布。至少5名唯一参与者参加且80%能说出三项行动中的两项才通过。演练记录不能冒充真人证据。参考工程没有真实用户记录,因此这里必须得到“未通过”,这不是项目失败,而是系统诚实地指出下一项工作。

二、专业评审与用户喜好承担不同责任

用户可以反映是否看懂,不能批准事实、品牌和发布权限。专业评审使用事实来源、视觉规范、渠道规格和风险清单逐项检查;委托人确认目标,内容责任人确认表述,权利审核角色确认素材与生成记录,发布人员确认最终文件。角色可以由教师模拟,但责任不能在表中消失。

事实核查逐句进行:哪些是来源直接支持,哪些是创意表达,哪些需要删除或补证。权利检查记录输入素材、参考材料、平台条件、人物与声音、标志和输出相似风险。无法确认授权时,使用自有或明确许可素材重新制作。

三、专业迁移卡

专业迁移卡A:商贸商品页面
输入改为已确认商品参数、实物照片、库存与渠道规格;高代价错误是虚构功能、价格、评价或适用人群;交付物改为页面主图、卖点文案、移动端版式和事实核对表,由商品负责人、渠道运营和内容审核人员批准。用户测试重点是信息理解和购买误导风险。

专业迁移卡B:制造设备操作图解
输入改为指定型号说明书、现场照片和安全操作规程;画面必须准确表现部件位置,不能用生成图替代关键结构证据;高代价错误是步骤顺序、部件或防护要求失真。交付物为经技术人员校核的操作图解和版本记录,生成模型只可用于非关键背景或方案草图。

专业迁移卡C:生物科普卡
输入改为经审核的物种或实验资料、授权图像和目标年龄段;高代价错误是把示意图当真实观察、夸大因果或形成健康诊断暗示;交付物为注明“实拍、示意或生成”的科普卡、来源表和审稿记录,由学科指导人员确认。

四、形成交付包和发布结论

交付包包含任务合同、创意简报、事实清单、提示包、候选记录、SVG预览、修改差异、用户测试、专业评审、权利清单、系统卡和使用说明。源文件使接收方能够继续修改,导出文件只用于候选审查;未获得发布结论前不得当作正式海报传播。

在项目目录运行:

python acceptance.py

它检查必需文件、Python与Notebook主链,真实运行离线工作流和19项单元测试,再逐项核对完整参考报告。这组固定测试按任务性质分为四类:正常测试要求G01、人工基线B01和5名唯一参与者的合格记录通过;边界测试检查无来源比例、缺少一个行动、非真实用户记录、重复participant_id、非10秒展示和审批不完整;陌生测试检查未知事实编号、未知素材权利与非法字段;故障测试检查空素材、空候选导入、错误表头、非法来源类型和SVG文本转义。另有完整工作流测试证明候选包路径与所选编号确实控制发布对象。这里的边界不是“勉强算通过”,而是系统最容易误放行、必须明确处理的邻近条件。

参考运行的机器检查通过1/3,真实目标用户0人,人工批准0/4,最终明确输出not_ready_for_release。因此本章样板没有发布作品,也没有证明生成候选优于人工模板。学生完成真实测试与审批后才可产生新版本;若生成方案仍不优于B01,采用人工模板就是正确工程决定。

应当区分三个容易混淆的状态。G01“机器检查通过”只表示卡片完整呈现三项行动,且尺寸、格式、安全区、披露和素材登记等确定性条件在数据中齐全,不表示内容已获事实责任人确认,更不表示学生观察10秒后能说出其中两项。B01同样通过机器检查,说明生成候选没有天然优先权。发布门还要求至少5名已记录同意的唯一真实目标用户达到理解标准,并由事实、设计、权利和发布四个角色分别批准;演练表中的模拟记录、重复编号和pending状态不会被程序计入。

这也是完整生成式AI项目与“输入一句提示词得到图片”的区别。模型只承担候选生产,普通程序承担可重复检查,目标用户提供理解证据,专业人员承担不可外包的判断。若模型接口不可用,学生仍可导入人工制作候选并完成同一条审校链;若模型生成很漂亮却带有无来源比例、未知标志或遗漏行动,系统必须阻断。工程的价值不是确保作品发布,而是让每个停止理由可见、可追溯、可再次验证。

本章小结

本章把生成式人工智能放入了一个可运行的专业传播项目。简报先固定目标、事实和规格;可替换模型或人工复制粘贴路径提出候选;离线回放保证断网时仍能学习审校链,但不得冒充模型实测。普通程序检查事实编号、禁止表述、规格和记录,真实用户与责任人完成程序不能代替的理解、权利和发布判断。参考工程最终阻断发布,说明完整AI工作方法不仅会“生成”,也必须会停止。

关键术语

目标测试

  1. 下列哪一项最适合作为本项目的传播目标?
    A. 做得震撼 B. 生成很多图片 C. 用静态SVG提示卡让实训学生在10秒内说出三项行动中的至少两项 D. 使用最热门模型
  2. 为什么本项目用普通SVG程序排版中文和规格?
    A. SVG不能显示图形 B. 便于准确控制事实文字、尺寸和安全区 C. 模型不能生成颜色 D. 可以省去事实核查
  3. 哪一项通过后仍不能证明作品可以发布?
    A. 文件尺寸机器检查 B. 权利审核 C. 事实复核 D. 委托人批准
  4. 限定修改中“保持项”的作用是什么?
    A. 让模型自由重做 B. 降低无关变化并便于检查差异 C. 增加候选数量 D. 取消用户测试
  5. 判断并改错:“模型生成的图像没有复制输入文件,所以天然不存在权利风险。”
  6. 判断并改错:“用户都觉得作品好看,就可以替代专业人员对事实和规格的审核。”
  7. 为一张10秒静态SVG门店节能提示卡写出创意简报中必须明确的六项内容。
  8. 把“让海报更高级”改写为一个对象明确、可比较且包含保持项的限定修改要求。
  9. 设计“只增加上方标题安全区”控制变量实验,写出预测、固定条件和三个评价指标。
  10. 某候选在用户测试中理解度最高,尺寸合格,但画面含未经授权标志且文案加入无来源节能比例。请作出交付结论,说明最小修改、必须重测的项目和责任人。

第5章 用数据预测下一阶段变化

工作阶段: 在行动之前形成有证据的数量预测。
公共核心项目: 与AI协同开发一个本地运行的“小型门店用电负荷预测器”,预测门店营业区下一日用电量。
核心技术: 时间序列回归、滞后特征、时间切分、上期值与移动平均基线、Keras回归、MAE、峰值漏报和数据漂移。
输入输出链: 连续日负荷与预测时已知信息 → 7日历史窗口 → 两种基线/Keras模型 → 下一日kWh候选 → 冻结未来期误差 → 人工使用判断。
应用中的AI: 根据历史负荷、温度预报和计划活动等已知信息生成下一日负荷候选值的本地Keras回归模型。
协助开发的AI: 帮助学生澄清预测时点、检查字段可得性、生成和解释代码、阅读误差并完成限定修改的大语言模型。
人的责任: 确认计量口径与预测用途,排除未来泄漏,比较模型和基线,审查峰值漏报,决定采用、限用、退回或停止。
主要交付物: 任务合同、220天教学数据、两种基线、Keras模型、完整Notebook与.py工程、35天未来期报告、模型卡和复现说明。
明确边界: 输出只是人工观察候选,不自动断电、控制设备、采购能源或承诺预算;口径变化、数据缺失和超出范围时停止模型判断。
跨章关系: 本章把第2章的数据治理用于预测;预测结果可作为第6章排程的一个输入,但不能替代资源约束和审批。

学习目标

完成本章学习后,你将能够:

  1. 把“预测用电”改写为对象、单位、时点、提前量和行动用途明确的任务;
  2. 识别目标日实际值、事后处置等未来泄漏,并按时间划分训练、验证和测试;
  3. 实现并解释上一日值、7日移动平均两种透明基线;
  4. 在大语言模型协助下运行完整Keras回归工程,指出归一化、特征、模型和输出的连接;
  5. 用MAE、最大误差、峰值召回和逐日错例比较复杂模型与基线;
  6. 完成一次单变量实验、四类固定测试和可由另一组复现的交付判断。

项目导入

“预测下一阶段用电”仍然太宽。预测整座工厂、某个仓库还是一家门店营业区?输出按小时、日还是月?在什么时候给出?预测结果是用来安排检查、准备营业,还是直接控制设备?这些差异会改变数据、模型、误差后果和责任。本章把任务缩小为:在目标日前一天的数据结算后,只用当时已经知道的信息,预测一家小型门店营业区的下一日用电量,单位为kWh。

本项目不是一段孤立的回归代码。学生要从任务合同出发,审查连续220天教学数据,建立“等于上一日”和“最近7日平均”两个基线,训练Keras模型,再把三种方法放到同一段从未参与训练的未来35天上比较。最后还要查看峰值漏报、模拟字段故障和口径漂移,并决定模型是否值得保留。

这两个透明方法共同构成本章的规则基线:它们不学习神经网络参数,假设下一日延续最近历史。规则基线不是陪衬,而是判断复杂模型是否带来实际增益的最低参照。

配套数据由确定性脚本生成,包含门店周内营业节奏、温度、计划促销活动、前一日惯性和小幅随机扰动。它适合观察时间切分和工程链,却不是真实门店数据。实际运行得到较好结果,只能说明模型学会了这套教学机制,不能写成真实工作现场准确率。

连续220天记录
   │
   ├─ 前150天:训练期 ─→ 建立7日窗口与归一化状态 ─→ Keras回归
   ├─ 中间35天:验证期 ─→ 早停与方案观察
   └─ 最后35天:冻结未来期
             ├─ 上一日值
             ├─ 最近7日平均
             └─ Keras预测
                    ↓
        MAE、最大误差、峰值召回、逐日错例
                    ↓
       人工决定限用、退回或停止,不自动控制

建议用6—8学时完成。第一课先运行随工程提供的模型和报告,理解作品;第二课在Notebook中逐格观察时间切分、基线和训练;第三课从.py工程重训、修改一个变量并运行验收。学生不必从空白默写TensorFlow语法,但必须能够解释一条日期记录怎样变成特征、预测和验收结论。

本章成果

AI协同开发路线

先把任务用自然语言交给协助开发的AI:“我们在目标日前一日结算后预测一家小型门店营业区的下一日用电量。请先追问单位、时间粒度、当时可得字段、低估和高估后果,不要先给模型代码。”AI可能询问温度是实测还是预报、促销活动是否已正式确定、计量表是否更换。学生只能依据门店数据责任人确认的材料回答;AI不能把“明天实际用电”包装成一个看似有效的特征。

任务冻结后,再要求AI列出工程文件:数据生成与审查、样本构造、两个基线、模型训练、固定未来期评价、单次预测、测试、模型卡和Notebook。学生逐个检查文件输入输出后才让AI生成完整代码,并约束依赖只使用Python、NumPy和Keras/TensorFlow。代码运行后,把真实终端日志和reference_evaluation.json交给AI分析,不让它凭训练代码臆测成绩。

协同修改必须限定范围。例如:“只在训练/验证开发视图中比较7日均值与14日均值,保持数据版本、共同验证日期、Keras模型和指标不变;不要打开冻结未来期。”又如出现日期乱序错误,可要求AI只修数据校验,不改数据和模型。学生在模型与峰值门槛冻结后,才运行一次最终评价与acceptance.py --require-model。聊天中的“看起来更准”不能代替可复现文件。

第一节 明确预测对象、预测时点和行动用途

一、把“预测未来”改写成可验收任务

本项目的一条目标是某个自然日门店营业区的总用电量,单位kWh。预测在前一日记录结算后形成,提前量为一天。工作使用者是店长、设施或能源责任人,输出用于提示“明天可能处于普通或较高负荷”,便于安排人工检查,不直接进入控制系统。

任务合同至少回答五个问题:预测什么;何时预测;当时能看到什么;输出给谁;错误会造成什么后果。若预测对象从一家门店营业区悄悄变成整座商场,历史数据便不再同口径。若温度字段来自目标日结束后的实测,它在训练时虽然完整,真实预测时却不可用。只有目标日前已经发布的温度预报和确认的促销活动才可作为输入。

配套工程位于resources/ch05/project/。TASK_CONTRACT.md冻结任务,data/store_load.csv保存完整数据,data/development_load.csv物理排除最后35天,供数据准备、基线、训练和选参使用;完整文件只在最终评价入口读取。DATA_CARD.md说明生成机制和限制。CSV主要字段如下:

字段 含义 预测时点是否可用
date 目标日期,用于排序和切分 可用于确定星期,不直接代表因果
load_kwh 当日实际用电量 作为历史或目标;目标日值不可作输入
forecast_temperature_c 目标日前已知的温度预报 可用,但必须记录预报来源和发布时间
weekend 是否周末 可用
planned_event 是否有已确认活动 只有预测前已批准时可用
split 训练、验证或冻结测试 只用于工程管理,不是模型特征
source_group 生成或采集来源组 用于追溯,不是模型特征

数据生成脚本固定随机种子20260807。前150天标记训练,建立7日窗口后形成143个训练样本;接着35天验证;最后35天固定为2025-07-05至2025-08-08的未来测试。测试期日期和样例在训练前就确定,不能反复移动到成绩最好的一段。

二、识别数据泄漏和目标漂移

预测任务最隐蔽的错误往往不是模型结构,而是时间。把全部日期随机打乱后再切分,会让模型在训练中看到未来季节和制度变化;用全数据计算归一化均值,也会让测试期分布提前进入训练流程。正确顺序是训练在前、验证居中、测试在后,均值和标准差只从训练样本计算。

另一类泄漏来自字段产生时间。例如“目标日实际室温”“目标日结束后的设备运行时长”“事后制定的节能措施”都可能与用电量高度相关,却在真实预测时不存在。判断字段能否使用,不看它与目标相关不相关,而看预测时点是否已经合法、稳定地获得。

目标漂移是被预测对象或生成机制发生变化。计量表更换、建筑用途改变、统计从“总表读数差”改成“分表求和”,都会使同名load_kwh含义变化。漂移不是多训练几轮就能解决。数据卡要记录变化点;运行时发现单位、口径或分布超出范围,先停止模型并由数据与设施责任人确认。

三、先写错误后果,再选指标

MAE把每个预测与真实值的绝对差求平均,单位仍是kWh,容易解释。但平均值会隐藏峰值。如果35天大多数误差很小,却在两个高负荷日严重低估,平均数仍可能漂亮。因此本项目同时报告最大误差和峰值召回:先用训练目标的90%分位定义教学峰值,再检查真实峰值是否也被预测到峰值区。

峰值阈值只是教学评价工具,不是电气安全值。安全容量、告警规则和设备控制必须来自专业制度。模型即使正确预测“明天77 kWh以上”,也没有权决定断电或调整设备。人的行动应写成分层规则,例如普通范围仅记录,接近人工关注区时复核天气与活动,口径变化或极端事件时停用模型。

专业迁移卡:商业贸易与智能制造
商贸方向可把目标改为下一日或下一周品类销量,输入为历史销量与预测时已确认的促销日历;高代价错误是缺货或积压,品类负责人确认行动。智能制造方向可预测下一班次能耗或产量,输入为历史节拍、计划班次和已批准停机;设备状态与安全容量仍由专业系统处理。迁移时不是换标题,必须重建目标单位、字段产生时间、时间切分、基线与峰值定义。

第二节 先用历史平均、周期和规则建立基线

一、上期值回答“如果明天像今天”

最简单基线是下一日等于上一日。它不需要训练,清楚表达“短期延续”假设。若负荷惯性很强,这个方法可能难以被复杂模型超过;若周末与工作日差异明显,它又会在周五到周六、周日到周一附近产生较大误差。

二、移动平均回答“近期通常是多少”

最近7日平均利用一个完整星期平滑偶然波动。配套core.py只读取7个历史列:

WINDOW = 7

def baseline_predictions(x):
    history = x[:, :WINDOW]
    return {
        "previous_day": history[:, -1].astype("float32"),
        "moving_average_7": history.mean(axis=1).astype("float32"),
    }

基线必须与模型使用同一批目标日期。不能让模型在35天测试、基线只在容易的20天测试。历史不足7天、日期重复、负荷为负或切分顺序错误时,程序明确停止,不用零填补并继续给出一个看似正常的数字。

三、用走步逻辑理解真实预测

预测2025-07-05时只能读取7月4日及以前的实际记录;到7月6日的预测时,7月5日实际值已经结算,才可进入历史。项目数据把每个目标日与此前7日构成一个样本,保证特征都早于目标。虽然模型一次性评价整个测试数组,样本构造仍遵守这个时间关系。

学生应抽取一条样本,写出7个历史日期、目标日期和目标值,再从代码验证列顺序。若大语言模型把目标日load_kwh也放进输入,学生应指出这不是“更强特征”,而是直接泄漏答案。

四、完成一个基线控制变量实验

可只把移动平均窗口从7改为14。实验前预测:14日窗口更平稳,但对温度转折和计划活动响应更慢。保持开发数据版本、共同验证日期、Keras模型、缺失处理、MAE和峰值定义不变。两种窗口必须在共同可预测的验证日期上比较;若14日窗口少了前7个难例,直接比较MAE不公平。冻结未来期在方案确定前不得打开。

协助开发的AI可以生成修改,但学生要审查它是否悄悄读取完整数据、改变验证起点或把模型也重训。记录两个窗口在验证期的MAE、最大误差、峰值召回和逐日变化。基线实验的价值是理解假设,而不只是选一个更小数字。

第三节 训练模型并在未来时间段检验误差

一、把7日历史与已知日历转成特征

每条模型输入包含此前7日用电、目标日温度预报、周末/活动标记,以及星期的正弦与余弦表示,共12个数。正余弦让星期日和星期一在周期上相邻,避免简单整数把星期六误解为“比星期一大五倍”。这些特征仍只是候选;真实项目应由能源责任人判断其来源和稳定性。

不同列量纲差异较大,因此只用训练集计算均值和标准差:

mean = x_train.mean(axis=0)
std = x_train.std(axis=0)
std[std == 0] = 1.0
x_train_n = (x_train - mean) / std
x_val_n = (x_val - mean) / std
x_test_n = (x_test - mean) / std

若对测试集各自计算均值,运行时每批输入会改变尺度;若用全部数据计算,未来信息会进入训练。保存模型时还要保存mean和std,否则另一组即使拿到.keras文件也无法复现相同输入。

二、运行完整Keras回归主链

权威实现位于train.py。模型很小:12维输入经过24与12个ReLU单元,最后一个线性单元输出kWh。损失使用MAE,验证期用于早停。

inputs = keras.Input(shape=(x_train.shape[1],),
                     name="known_history_and_calendar")
x = keras.layers.Dense(24, activation="relu")(inputs)
x = keras.layers.Dense(12, activation="relu")(x)
outputs = keras.layers.Dense(1, name="next_day_kwh")(x)
model = keras.Model(inputs, outputs,
                    name="store_load_forecaster")
model.compile(
    optimizer=keras.optimizers.Adam(0.006),
    loss="mae",
    metrics=["mae"],
)
stop = keras.callbacks.EarlyStopping(
    monitor="val_loss", patience=25,
    min_delta=0.01, restore_best_weights=True,
)
model.fit(
    x_train_n, y_train,
    validation_data=(x_val_n, y_val),
    epochs=180, batch_size=24,
    callbacks=[stop], verbose=2,
)
model.save("models/load_forecaster.keras")

学生要能回答:哪12个数进入模型;目标为何只有一个;归一化状态存在哪里;验证期为什么不更新权重;输出为什么不是概率;模型文件故障时程序怎样停止。完整学习Notebook在resources/ch05/project/notebooks/ch05_load_forecasting.ipynb,训练、评价和单次预测分别由train.py、evaluate.py和predict.py承担。

三、读取本次真实训练与固定未来结果

参考环境为Windows、Python 3.12.13、TensorFlow 2.21.0、Keras 3.15.1、CPU。本次实际使用143个训练样本和35个验证样本训练180轮,随后只在固定的35天未来期评价。报告不是手工填写,而由evaluate.py --write-reference生成。

方法 未来35天MAE 最大误差 峰值命中/真实峰值
上一日值 7.9329 kWh 27.1600 kWh 0/2
最近7日平均 6.7376 kWh 19.7157 kWh 0/2
Keras回归 2.4017 kWh 9.3011 kWh 1/2

Keras模型在这组教学数据上明显降低MAE,也把最大误差缩小,但仍漏掉一个峰值。结论不是“模型已经可以管理门店用电”,而是“在教学合成数据范围内,模型相对两个基线有增益,可作为人工观察候选;峰值仍需人工与正式规则处理”。

这些数据由一个稳定公式生成,模型能够学习星期、温度和活动关系,难度远低于真实工作现场。测试期也只有35天,未覆盖完整季节、设备更换和制度变化。报告中的2.4017不能写成未来真实误差,更不能据此设安全阈值。

四、从逐日错例回到工作原因

reports/reference_errors.csv保存每个测试日的真实值和三种预测。学生按绝对误差排序,检查最大错误是否集中在活动日、周末转换或温度变化。向AI提问时要提供日期、真实值、三种预测和已知特征,例如:“只解释7月某日三种方法为何都低估,列出数据中能验证的假设,不修改模型。”

若AI建议增加“当天实际用电”或复制固定错例进入训练,应拒绝。合理下一步可能是核对活动标记在预测时是否真的已知、增加新的训练时期、为口径变化分段评价,或输出更保守的人工关注区。错误分析的目标是找到可验证原因,不是让AI编一个故事。

第四节 把不确定性和错误成本转化为行动边界

一、冻结正常、边界、陌生和故障测试

正常测试是冻结未来期内与训练机制一致的普通工作日和周末,检查三种方法是否在同一日期输出。边界测试包括峰值日、周末切换、温度变化和计划活动,重点看最大误差与峰值漏报。陌生测试包括统计口径改变、未见极端天气、新建筑或长期停课,预期不是强行外推,而是标记超出验证范围并转人工。

故障测试包括日期重复或乱序、负负荷、非法0/1标记、历史不足7天、模型文件或元数据缺失。tests/test_project.py实际验证开发视图不含冻结日期、陌生统计口径与字段漂移在模型前转人工、模型文件故障安全接管,以及基线只读历史列。程序必须给出明确错误或人工路由,不用零填补,也不沿用上一次缓存预测。

工程一键验收命令为:

cd resources\ch05\project
python acceptance.py
python acceptance.py --require-model

默认入口检查必需文件、Python语法、9项单元测试、Notebook冻结隔离,以及报告中的固定测试、模型、配置与元数据摘要;--require-model再现场加载模型,把评价与正式参考结果逐项比较,只排除明确不稳定的环境版本字段。验收通常数秒完成,不在全书测试时重新训练。

二、把误差变成可执行边界

预测值不能单独触发动作。较稳妥的界面或报告应并列显示日期、模型候选、两个基线、历史范围、活动/温度条件和“人工确认必需”。当模型与两个基线差异很大时,差异本身就是复核信号;当输入超出数据卡范围时,停止比输出一个精确小数更可靠。

学生可设计三档低风险使用规则:普通候选只进入观察日志;接近训练峰值或模型与基线分歧过大时请能源人员复核;口径、设备或采集流程变化时停止模型。具体阈值必须由项目数据和责任人确认,教材不把教学峰值写成通用标准。

三、让AI完成一次限定修改并回归

可要求协助开发的AI只在predict.py增加“历史7日范围外时转人工”的检查,不改训练数据、模型和测试。学生先写预期行为,审查文件差异,再增加一个边界测试并运行全部回归。另一项学生亲手实验可以只改移动平均窗口;两项活动都要保持固定未来期不变。

若修改针对某个冻结错例,不能直接把该日期及答案复制回训练后继续用同一报告宣称泛化提升。数据变化应另建版本,重新训练,并准备从未参与讨论的新未来期。测试一旦反复指导设计,就不再是完全独立的最终证据。

四、形成交付与使用判断

完整项目文件夹含README、任务合同、数据生成器、CSV、数据卡、核心代码、Notebook、模型、元数据、训练历史、逐日误差、模型卡和测试。另一组应能从干净环境安装依赖,先运行基础验收,再加载模型、复现35天指标,并解释为何结论仍是“教学合成数据范围限用”。

采用意味着在冻结范围内达到预设标准;限用意味着只作人工候选并保留停止条件;退回表示模型未胜较优基线或峰值错误不可接受;停止表示数据授权、口径、维护或安全条件不具备。如果下一版本复杂模型不再超过7日平均,保留基线是技术上正确的结论,而不是项目失败。

专业迁移卡:风景园林与生物技术
园林方向可预测下一日灌溉需求或温室能耗,特征只能使用预测时已知天气、历史传感和种植阶段;自动开泵仍需水量、安全和设备规则。生物方向可预测培养环境的下一时间段趋势,但批次、设备校准和实验规程必须进入数据卡;模型不能作生物安全结论。两类迁移都要保留上期值或移动平均基线、按时间隔离测试和漂移停止条件。

本章小结

本章完成了一个真正的时间序列垂直项目:从预测合同、连续日数据、时间切分和两种基线出发,构造7日历史与预测时已知特征,训练Keras回归模型,再在固定未来35天比较MAE、最大误差和峰值漏报。应用中的AI负责数值候选,协助开发的AI帮助澄清、编码和分析,人负责字段可得性、错误后果和使用决定。

真实运行表明模型在教学生成数据上超过两个基线,却仍漏掉一个峰值。最重要的结论不是某个漂亮误差,而是:未来不能泄漏到训练;复杂模型必须公平超过简单方法;平均分不能掩盖高代价错误;超出范围时要停止;另一组能复现的工程与报告才是交付物。

关键术语

目标测试

  1. 为什么目标日实际用电量不能作为预测该日用电量的输入?
    A. 数值太大 B. 会增加模型层数 C. 预测时尚不可得,会造成未来泄漏 D. CSV不能保存
  2. 本项目为什么不能随机打乱全部220天后再切分?
    A. 随机会让文件变大 B. 会让未来模式进入训练,破坏真实时间顺序 C. Keras不支持随机数据 D. 移动平均必须用文本
  3. 公平比较Keras模型和7日移动平均,必须满足什么条件?
    A. 模型代码行数相同 B. 使用同一未来期、目标和指标 C. 都训练180轮 D. 输出完全相同
  4. Keras模型在冻结未来期MAE较低,但峰值只命中1/2,最合理的结论是?
    A. 可自动控制设备 B. 峰值指标不重要 C. 教学范围可作人工候选,峰值仍需复核 D. 删除漏掉的峰值
  5. 判断并改错:“用全部220天计算归一化均值不会影响模型权重,因此不算泄漏。”
  6. 判断并改错:“第5章预测值可以直接成为第6章正式排程和设备控制命令。”
  7. 写出本项目的预测对象、预测时点、两个可用字段和两个禁止字段。
  8. 设计只把移动平均窗口从7改为14的控制变量实验,说明共同验证日期怎样保持公平,并说明为何不能据此读取冻结测试期。
  9. 各设计一条陌生测试和故障测试,并写出系统预期行为。
  10. 某次重训后模型MAE为7.1 kWh,7日平均为6.7 kWh;模型在峰值上也没有改善。请作出采用、限用、退回或停止结论,并说明基线、责任人和重新验收范围。

答案编号:A3-5-01—A3-5-10。完整答案和评分要点统一放入书后“目标测试参考答案”。

第6章 在约束条件下安排资源

工作阶段: 把任务、资源和限制组合成可执行的候选方案。
公共核心项目: 与AI协同开发一个本地运行的“设备维护工单排程器”。
核心技术: 实体与属性、硬约束与软约束(软目标)、先到先服务基线、约束搜索、启发式搜索顺序、独立可行性检查、无解解释和条件变更重算。
输入输出链: 工单与班组JSON → 字段校验 → 基线/约束搜索 → 候选排程或无解原因 → 独立验证 → 人工审批。
应用中的AI: 在小规模离散时段中搜索满足技能、班次和时间窗的工单组合,并在可行方案间比较加权等待的计算智能。
协助开发的AI: 帮助学生追问业务条件、把自然语言限制翻译成候选字段、生成和解释代码、分析无解以及完成限定修改的大语言模型。
人的责任: 确认任务、技能、时长、时间窗和优先级;批准任何条件变更;检查遗漏的现实约束;决定候选方案是否采用。
主要交付物: 任务合同、三个冻结场景、先到先服务基线、约束搜索器、独立验证器、真实运行报告、系统卡与一键验收。
明确边界: 程序不自动派工,不自行放宽期限、降低安全规则或修改优先级;“程序可行”只对当前已建模条件成立。
跨章关系: 第5章的预测量可以成为工单或资源需求输入;本章把它放进明确约束,不能把预测值当作确定命令。

学习目标

完成本章学习后,你将能够:

  1. 把排程委托写成目标、实体、属性、硬约束、软目标和审批责任明确的任务;
  2. 用先到先服务建立透明基线,解释它为何可能错过整体可行方案;
  3. 读懂一个枚举合法班组和开始时段的完整约束搜索程序;
  4. 使用独立检查器验证任务完整、技能匹配、时间窗和班组不重叠;
  5. 区分“程序故障”和“当前条件无可行解”,在批准变更后重新计算;
  6. 用正常、边界、陌生、故障与条件变更测试形成可复现交付。

项目导入

企业服务值班人员每天可能收到网络、配电、设施和环境等工单。每条工单有提交时点、所需技能、预计时长、最早开始和最晚完成;不同班组拥有不同技能和班次。按收到顺序逐条安排很直观,却可能让一个能由多组处理的长任务先占用稀缺班组,随后只有该班组能做的紧急任务反而无处安排。

本章要做的是完整的工单排程器,而不是让大语言模型写一张看似合理的日程表。程序读取工单与班组JSON,先验证字段,再运行“先到先服务”基线和约束搜索。搜索器只考虑满足全部硬约束的候选;如果找不到,输出无解而不是偷偷删任务。搜索产生方案后,另一个独立函数再次检查完整性、技能、时间窗、班次和重叠,最终由人审批。

配套正常场景有2个班组和6条工单,一个时段为30分钟。A组会网络与电气,B组会网络、设施与环境。较早提交的J01网络任务两组都能处理;较晚提交的J02电气任务只能由A组处理,且必须在前4个时段内完成。先到先服务若把J01给A组,会留下J02;约束搜索可以把J02先放A组,把J01交给B组,形成整体可行方案。

自然语言工单与班组条件
          ↓ 人工确认字段与责任
      JSON场景数据
          ↓ 输入校验
   ┌──────┴────────┐
先到先服务       约束搜索
   │                  │
未排任务/候选       可行方案/无解
   └──────┬───────────┘
       独立硬约束检查
              ↓
       条件变更记录与人工审批

建议用5—7学时。学生先手工尝试正常场景,体验局部顺序为何影响整体;再运行基线与搜索;随后逐段阅读数据表示、可行性检查和递归搜索;最后修改一个软目标或在批准记录中改变一个条件并重跑三个场景。核心路径只使用Python标准库,无需网络和第三方优化框架。

本章成果

AI协同开发路线

先向协助开发的AI说明工作问题,不要求它立即排表:“我们要安排设备维护工单。请只追问会改变可行性的条件,例如班组技能、班次、任务时长、最早开始、最晚完成和不可更改规则;把偏好与硬约束分开。”AI提出的问题由值班或设施责任人回答。若真实条件未知,数据中要标记待确认,不能让AI按常识补一个时长。

条件确认后,让AI先输出数据结构和反例。例如请它构造“一条工单本身时间窗小于所需时长”的无解样例,并解释程序应停止在哪里。再限定工程:“只用Python标准库;先实现字段校验、先到先服务、独立可行性检查,再实现约束搜索;无解不得删除任务;任何条件变化必须来自新场景文件。”学生检查结构后再生成完整代码。

运行时把实际场景、输出和测试结果交给AI,要求它指出基线失败的具体资源冲突,不接受“AI优化更聪明”这类空话。修改时可要求:“只把软目标中的最晚完成权重从0.1改为0.3,保持工单、班组、硬约束和搜索范围不变;给出差异和三场景回归。”学生审查后决定是否保留。大语言模型可以帮助编码,却不拥有延长期限、增加班组或降低安全规则的权限。

第一节 把工作目标和限制写成可检查的约束

一、从“排得更合理”到明确目标

“请把工单排得更合理”没有办法验收。合理可能指按提交顺序、优先紧急任务、减少等待、均衡班组,或满足承诺时间。不同目标会产生不同方案。本项目先规定硬条件:每条工单恰好安排一次;班组必须具备所需技能;任务在班组班次与自身时间窗内完成;同一班组的任务不能重叠。

在全部硬条件通过后,才比较软目标。本项目目标值为“按优先级加权的等待时段 + 0.1×最晚完成时段”。等待从工单最早开始到实际开始计算,优先级越高,延迟代价越大。0.1只是教学权重,用于在等待相同的方案间稍微偏向更早结束,不是通用管理标准。

硬约束决定方案能否执行,软目标只在可行方案之间排序。不能因为一个方案总等待更小,就允许它让电气任务由无资质班组处理。学生应把每条自然语言要求标为“硬、软、待确认”之一,并写出对应字段和责任人。

二、用反例检查约束是否完整

一条好约束应能被反例触发。技能约束的反例是把J02电气任务给不具备electrical技能的B组;时间窗反例是J02从时段3开始、时段6结束,却要求最晚时段4完成;完整性反例是方案看起来不冲突,但悄悄漏掉J05;重叠反例是A组同时执行两个任务。

反例还能暴露未建模条件。如果任务之间有“先断电检查、后恢复网络”的前置关系,当前数据没有predecessor字段,程序可行并不代表现场可行。此时应扩展合同、数据和测试,而不是把关系藏进提示词。现实中的地点路程、备件、人员休息和突发事件也未进入首版,系统卡必须如实列出。

三、无解不是失败措辞

当任务时长为5个时段,却要求在0—4内完成,任何排程都不可能满足。正确输出是“无可行解:J02时长超过自身时间窗”,并把改变期限、缩短任务或增加资源交给有权限的人。程序不能把时长改成4,也不能把最晚完成改成5后假装仍是原问题。

配套no_solution.json冻结这种冲突;condition_change.json明确记录责任人批准把J02完成上限由4调整为5,其他条件保持不变。两者是不同版本和不同决策,必须分别保存。

专业迁移卡:商业贸易与交通服务
商贸方向可安排订单拣选、复核和发货,技能改为库区或设备资格,硬约束包括截单时间与不可并行工序。交通方向可安排车辆维护工单,技能改为工种与资质,硬约束还包括工位、备件和安全锁定。预测到达量只能形成任务候选,正式时限和车辆安全规则必须由业务责任人批准。

第二节 把路线、工单或养护任务表示为可计算问题

一、把文字转成实体、属性和关系

工程位于resources/ch06/project/。每个班组含编号、技能集合、可用开始与结束;每条工单含编号、名称、所需技能、持续时段、最早开始、最晚完成、提交时点和优先级。一个时段为30分钟,但程序只计算整数槽位,避免在首版同时处理日期、时区和跨班次。

{
  "job_id": "J02",
  "name": "配电箱测温复核",
  "skill": "electrical",
  "duration": 3,
  "earliest": 0,
  "latest_finish": 4,
  "submitted_at": 1,
  "priority": 4
}

duration=3和latest_finish=4意味着合法开始只能是0或1。若A组在0—4被其他任务占用,J02便无法安排。程序先检查时长和时间窗是否为正、编号是否重复、技能是否有班组提供。输入无效时在搜索前失败,避免把数据问题误写成“算法找不到”。

二、先算人工基线

先到先服务按submitted_at排序,依次寻找列表中第一个具备技能且有连续空档的班组:

for job in sorted(jobs, key=lambda j: (j.submitted_at, j.job_id)):
    chosen = None
    for team in teams:
        if job.skill not in team.skills:
            continue
        for start in range(
            max(job.earliest, team.start),
            min(job.latest_finish, team.end) - job.duration + 1,
        ):
            if not overlaps(start, start + job.duration,
                            assigned[team.team_id]):
                chosen = {"job_id": job.job_id,
                          "team_id": team.team_id,
                          "start": start,
                          "finish": start + job.duration}
                break
        if chosen:
            break

它透明、快速,并尊重已编码硬约束,但只看当前工单,不为后面保留稀缺技能。正常场景中,J01最先提交且A组排在列表前,因此占用A组0—4;J02随后只能由A组处理,却已经没有能在时段4前完成的空档,基线留下J02。这个失败不是故意做差,而是清楚展示局部贪心与整体组合的差别。

三、状态空间和候选数量

每条工单可能选择不同班组和不同开始时段。任务数量增加时,组合数会快速增长。首版只处理不超过约8条工单的小规模整数时段,让学生能够看到完整搜索并核对每个候选。它不是大型生产调度器,也不声称适合几百条实时工单。

搜索使用“剩余空间最小、可选班组更少、优先级更高”的顺序先处理受限工单。这是启发式:它改变先搜索谁,通常更早发现可行方案;它没有删除任何合法班组和开始时段,因此在当前有限表示中仍检查全部完整组合。若以后加入剪枝,必须证明剪掉的分支不可能优于当前方案。

四、让表示本身接受测试

学生应先测试数据结构,而不是只测最后日程。正常输入检查字段齐全;边界输入把任务放在时间窗最后一个合法开始点;陌生输入加入未登记技能或跨日任务,系统应拒绝并要求扩展合同;故障输入使用负时长、重复编号、结束早于开始或空班组,程序应在搜索前明确停止。

DATA_CARD.md说明三份JSON都是课堂模拟,不含姓名、电话或真实位置。使用真实工单时应把权限、隐私、位置精度、技能资质、时长来源和变更历史纳入数据治理,不能把整个业务压成几列数字后忘记丢失了什么。

第三节 组合预测、规则与优化形成可行方案

一、完整最小搜索程序

scheduler.py中的递归函数每次选择一条受限工单,枚举所有具备技能的班组和合法整数开始时段。若与该班组已排任务重叠就跳过;全部工单安排后计算目标值并保留更好的完整方案。

def visit(index):
    nonlocal best, explored
    if index == len(ordered):
        explored += 1
        flat = sorted(
            [item.copy() for values in assigned.values()
             for item in values],
            key=lambda a: (a["start"], a["team_id"], a["job_id"]),
        )
        score = score_schedule(jobs, flat)
        if best is None or score < best["objective"]:
            best = {"feasible": True,
                    "assignments": flat,
                    "objective": score}
        return

    job = ordered[index]
    for team in teams:
        if job.skill not in team.skills:
            continue
        latest = min(job.latest_finish, team.end) - job.duration
        for start in range(max(job.earliest, team.start), latest + 1):
            finish = start + job.duration
            if overlaps(start, finish, assigned[team.team_id]):
                continue
            assigned[team.team_id].append(
                {"job_id": job.job_id, "team_id": team.team_id,
                 "start": start, "finish": finish}
            )
            visit(index + 1)
            assigned[team.team_id].pop()

学生要能指出:硬约束在哪里检查;为什么任务完成后要pop回退;explored只统计完整方案而不是所有递归节点;目标值为什么只能在可行方案之间比较。大语言模型可以解释递归语法,但学生要拿正常场景手工走一条分支。

二、用独立函数再次验证方案

不能因为方案由搜索器产生就默认正确。validate_schedule独立检查工单集合是否完全一致、技能是否匹配、开始和持续时长是否正确、结束是否越过工单或班组边界、同一班组是否重叠。搜索实现中的错误可能导致它认为自己满足了约束,独立验证提供第二道证据。

errors = validate_schedule(teams, jobs,
                           result["optimized"]["assignments"])
if errors:
    raise AssertionError("搜索器产生无效方案: " + "; ".join(errors))

现实交付还需要人对照原工单检查:预计时长是否可信;技能是不是合法资质;位置路程是否遗漏;高风险任务是否应走另一条正式流程。程序验证只说明JSON世界内部一致。

三、读取本次真实运行

参考环境为Windows、Python 3.12.13,只使用标准库。run_scenarios.py --write-reference实际运行三个冻结场景,结果写入reports/reference_results.json。

正常场景中,先到先服务排出5条并留下J02,因而不可行。约束搜索枚举24个完整可行排程,找到目标值3.7的候选:J02由A组0—3处理;J01由A组3—7处理;B组依次处理J04、J03、J05和J06。独立验证没有发现技能、时间窗或重叠错误。

“24个完整方案”只是在当前整数时段、当前班组列表和当前硬约束下的数量。不能说搜索证明了现实世界最优,因为地点路程等条件没有建模。目标值3.7也没有自然单位,它用于同一合同内排序,不适合跨业务比较。

课堂中应把JSON、候选表和代码三者来回对应。第一组学生从结果中选J02,说明它为什么只能由A组处理、合法开始为何只有0或1;第二组故意把它放到时段2,再用验证器读出“超过硬时间窗”;第三组比较基线与搜索,指出问题不是提交顺序字段错误,而是基线把第一个可用班组当成最终选择。随后互换场景,不询问原作者,独立复现目标值和约束检查。这样的活动让学生真正理解表示与搜索,而不是只看程序输出一张排班表。

协助开发的AI可以把一条结果转换为解释草稿,但学生要逐项回查原数据。若AI声称B组也会电气,应以skills字段纠正;若AI说目标值3.7代表3.7小时,应指出该值是加权等待与0.1倍最晚完成的组合,没有独立物理单位。能够识别这种“语言听起来合理、数据却不支持”的说明,是AI协同开发的重要能力。

四、预测、规则和搜索各做什么

第5章模型可能预测下一日需求上升,这可以帮助形成工单数量或时长候选,但预测不是硬事实。确定性规则负责技能、时间窗、不可重叠等已明确约束;搜索负责组合合法选择;人确认预测、制度和现场现实。大语言模型可以协调开发文件,却不应直接输出一张无法验证的排程并称为“优化”。

如果预测不确定,可以建立高、低两种需求场景分别搜索,而不是把一个小数当作唯一未来。若某场景无解,报告应说明它在哪些条件下无解,并把增加班组、延长期限或拆分任务作为待审批选项。

第四节 在条件变化和无可行解时重新计算并解释取舍

一、冻结五类系统测试

这些场景和断言组成项目的固定测试。它们在修改搜索顺序、目标权重或数据校验前冻结,不能为了让新版本通过而删掉无解、陌生或故障样例。

正常测试使用6工单场景,要求搜索结果覆盖全部任务并通过独立检查。边界测试把任务放到最早或最晚合法时点,检查区间端点。陌生测试加入程序未支持的跨日、双人协作或未知技能,预期是拒绝并要求扩展表示,不是丢弃字段。

故障测试使用负时长、重复编号、无班组或错误JSON,程序必须在搜索前停止。无解测试使用J02“持续5、时间窗0—4”,要求明确写出冲突。条件变更测试把经批准的最晚完成改为5,其他条件不变,要求重新找到可行方案并保留变更记录。

一键验收如下:

cd resources\ch06\project
python acceptance.py
python schedule.py data\normal.json
python run_scenarios.py --write-reference

acceptance.py检查必需文件、Python语法、9项单元测试、三个冻结场景的SHA-256身份、命令行复现结果和参考报告,实际运行通常不足一秒。9项测试覆盖正常、无解、条件变更、最晚合法开始边界、未支持字段、错误JSON、负时长、重复编号/空班组和参考记录;它们共同落实本节的正常、边界、陌生、故障与条件变更五类系统行为。能启动脚本并不等于通过;当前运行还必须与冻结报告一致。

二、无可行解不是程序失败

在no_solution.json中,J02需要5个时段却必须在0—4完成。搜索没有完整方案,程序输出“J02时长5超过自身时间窗0—4”,完整方案数为0。这是正确识别业务冲突,而不是异常崩溃。

可选处理包括:由责任人延长完成时限;拆分为可以合法交接的任务;增加具备技能的班组;调整任务范围;或转正式人工应急安排。每种做法都改变合同,必须新建场景、说明批准人和生效范围。程序不得自动选择“最容易算”的放宽方式。

三、条件变化后重新计算

condition_change.json记录J02完成上限由4调整为5。重算后,先到先服务仍因顺序留下J02;约束搜索枚举4个完整方案,找到目标值4.6的候选:A组0—5处理J02,B组0—4处理J01、4—6处理J03。条件变化解决了单项时间窗冲突,却没有让基线自动变好,这说明方法和条件是两个不同变量。

本次实际结果均由run_scenarios.py生成并写入机器可读报告,不是依据代码手工推测。正常场景24个完整方案、无解场景0个、条件变更场景4个,分别回答“当前条件下能否排、为什么不能排、批准变化后如何重算”。

控制变量实验可以只把目标函数中“最晚完成权重”由0.1改为0.3,固定工单、班组、硬约束与搜索空间。修改前预测它可能在等待相同的方案间选择更早结束者,也可能因为当前数据没有并列而结果不变。学生让AI只改一行和相应测试,审查差异后重跑全部场景。

四、解释取舍并完成审批交付

面向值班人员的结果不应只是一串目标值。报告要列出每条工单、班组、开始/结束、等待、约束检查、未排任务和场景版本;无解时列出冲突而不是空表。每个候选都带“人工审批必需”和“禁止自动派工”。

完整交付包含README、任务合同、三份场景、数据卡、基线、搜索、验证、命令行入口、测试、真实报告和系统卡。另一组应能在无网络环境运行acceptance.py,复现正常场景24个完整方案、无解0个和变更场景4个,并解释这些数字的有限含义。

采用表示当前小规模合同内的候选排程通过全部验证;限用表示仍须人工确认现实条件;退回表示字段、约束、目标或复现不完整;停止表示权限、安全或数据条件不具备。本项目最终结论是当前模拟工单范围限用,不自动派工。

专业迁移卡:风景园林、设计与数字媒体
园林方向可安排养护任务,硬约束包括季节、天气、药剂资质和不可同时作业区域;设计与数字媒体方向可安排拍摄、剪辑、审校和发布,技能、设备、素材到位和审批是硬条件。AI生成的时长估计只能作为待确认输入。迁移时要重新建立真实实体与约束,不能只把“工单”替换成“作品”。

本章小结

本章完成了“数据—基线—约束搜索—独立验证—无解—条件变更—交付”的完整排程项目。先到先服务透明却可能因局部选择留下稀缺技能任务;约束搜索在当前小规模表示中找到整体可行方案;独立检查器防止搜索器自证正确;无解被当作有价值的业务结论,而不是由程序偷偷放宽条件。

应用中的智能是可检查的搜索,不是大语言模型写日程。协助开发的AI帮助把语言变成代码和测试,人负责约束真实性、条件变更和正式审批。真正的技术能力包括:知道什么能计算、什么尚未建模、为什么无解、谁能改条件,以及另一组怎样复现。

关键术语

目标测试

  1. 下列哪一项属于硬约束?
    A. 尽量少等待 B. 尽量早点结束 C. 班组必须具备工单所需技能 D. 页面颜色统一
  2. 正常场景中,先到先服务为什么留下J02?
    A. J02没有名称 B. J01先占用唯一具备电气技能的A组 C. 搜索器删除J02 D. B组班次为空
  3. 启发式“先处理剩余空间最小的工单”在本项目中做了什么?
    A. 自动放宽时间窗 B. 改变搜索顺序,但仍检查合法选择 C. 预测任务时长 D. 替人批准方案
  4. 找不到满足全部硬约束的方案时,系统应怎样处理?
    A. 删除最低优先工单 B. 自动延长期限 C. 输出无解和冲突,等待责任人决定条件变更 D. 返回上次方案
  5. 判断并改错:“目标值更小的方案即使有一条工单超出时间窗,也可以采用。”
  6. 判断并改错:“搜索器自己生成的方案不需要独立验证。”
  7. 写出本项目三个硬约束和一个软目标,并说明分别由谁确认。
  8. 解释正常场景中为什么把J02先给A组、把J01留给B组能够恢复整体可行。
  9. 为排程器各设计一条陌生测试和故障测试,写出预期行为。
  10. J02持续5个时段、时间窗为0—4。请说明为什么无解,并提出两种必须经责任人批准的改变;说明改变后应重跑哪些测试。

答案编号:A3-6-01—A3-6-10。完整答案和评分要点统一放入书后“目标测试参考答案”。

第三篇 让AI进入专业现场——视觉、声音、传感与端侧推理

第7章 训练一个专业视觉检查器

工作阶段: 让模型从图像样本中学习可见差异,并进入人工复核流程。
公共核心项目: 与AI协同开发“商品包装状态视觉复核器”。
核心技术: 像素张量、卷积神经网络、迁移学习选择、对象与批次划分、规则基线、混淆矩阵、双阈值、陌生输入接管。
输入输出链: 包装图 → 尺寸/亮度规则门 → 封签规则基线/Keras CNN → 待复核分数 → 候选或人工接管 → 人工看原图确认。
应用中的AI: 判断登记包装教学图属于“合格候选”还是“待复核候选”的本地Keras卷积分类模型。
协助开发的AI: 帮助学生审查采集表和标签、生成与解释完整Notebook和工程代码、分析错例并完成限定修改的大语言模型。
人的责任: 确认只基于可见证据的标签,处理图像授权,冻结对象与批次,审查漏检与陌生样本,批准用途。
主要交付物: 248张可离线携带教学图、清单与生成器、规则基线、小型CNN、完整Notebook、推理入口、真实报告、模型卡和一键验收。
明确边界: 项目只形成外观候选,不证明内部质量、真伪、食品药品安全或法规合格;所有结果必须由人查看原图。
跨章关系: 延续第2章的数据来源和隔离,第5章的基线比较与固定测试;第9章可研究端侧部署,但不能扩大模型权限。

学习目标

完成本章学习后,你将能够:

  1. 根据工作输出区分图像分类、目标检测和图像分割;
  2. 把包装标签限制在可见现象,并按对象和批次隔离训练、验证与测试;
  3. 实现一个透明封签规则基线,说明它能发现什么、会漏掉什么;
  4. 在AI协助下运行完整Keras CNN,解释卷积、池化、Sigmoid与阈值;
  5. 用混淆矩阵、待复核漏检、候选覆盖和陌生样本接管比较系统;
  6. 完成阈值实验、四类固定测试、模型卡和另一组复现交付。

项目导入

包装检查可能涉及封签、破损、污渍、压角、文字、条码、重量和内部质量。把这些全部交给“看图AI”会让任务失控。本章只处理一项清楚的工作:输入一张登记范围内的单包装教学图,系统检查尺寸和亮度,再给出“合格候选”“待复核候选”或“人工复核”。最终人员必须查看原图。

“合格候选”不是“商品合格”。图像只能呈现某个角度的外观,无法证明内部状态、材料性能和真伪。项目标签也只覆盖程序生成的四种可见问题:缺封签、撕裂、压角和污渍。真实商品一旦换结构、背景或拍摄设备,就可能超出训练范围。

项目把视觉模型放进完整工程,而不是只展示一条model.fit。学生先审查248张教学图的对象、批次和划分,运行只看绿色封签的透明基线,再训练小型Keras CNN,在未见批次B09—B10的48张图上比较。运行时使用0.35和0.65双阈值,把中间分数转人工;8张不同尺寸的陌生包装在模型前接管。

包装图像
   │
   ├─ 不是32×32或亮度异常 ─→ 模型不运行 ─→ 人工重新采集/复核
   │
   └─ 输入门通过
        ├─ 绿色封签规则基线 ───────────┐
        └─ 卷积→池化→卷积→整图表示→Sigmoid分数
                                      │
            ≤0.35 合格候选 0.35—0.65 人工 ≥0.65 待复核候选
                                      ↓
                              人员查看原图确认

建议用7—9学时。先打开数据目录观察同一对象的两个视角和四种缺陷,再运行参考模型;随后在Notebook中逐格建立数据、规则和CNN;第三阶段修改一个阈值或一个输入规则,运行全部验收并填写模型卡。学生不从空白写长网络,却必须找到像素进入模型、分数生成、规则接管和人工决定的位置。

本章成果

AI协同开发路线

先向协助开发的AI提交可见标准,而不是“帮我判断商品合格”。可这样提问:“输入是单包装外观图,只允许标注缺封签、撕裂、压角、污渍和未见明显问题。请追问图像授权、同一对象连拍、批次、拍摄条件和高代价漏检,不要先选择大模型。”学生与专业责任人确认答案,把“内部质量、真伪、法规合格”写入禁止用途。

随后要求AI先给工程树:生成/采集、清单校验、对象与批次划分、规则基线、Keras训练、统一推理、冻结评价、Notebook、测试、模型卡。为保证课堂离线可复现,本样板不用联网下载大型预训练权重,选择32×32教学图和三层小型CNN。真实图像更多、变化更复杂时可评估迁移学习,但必须重新测试,不能仅因模型更大就采用。

AI生成代码后,学生逐项核对:同一object_id和batch_id是否跨集合;规则是否只解决封签;陌生尺寸是否在模型前转人工;CNN输出顺序是否一致;冻结图是否在最终评价前被读取。修改时限定范围,例如“只在B07—B08验证批次把intact_max由0.35改为0.25,保持模型和review_min不变,不打开B09—B10”。学生先预测人工量变化,冻结方案后才运行最终评价与acceptance.py --require-model。

第一节 根据专业输出选择分类、检测或分割

一、先问工作需要什么输出

图像分类为整幅图输出类别或分数。本项目每张图只放一个主要包装,工作只需要候选状态,因此选择分类。分类模型不会给出撕裂坐标,即使卷积内部对某一区域响应较强,也不能把整图分数解释成缺陷位置。

目标检测适合一张图有多个包装,并要求指出哪一个需要复核,输出类别和矩形位置。图像分割适合测量裂缝、病斑、涂层等像素区域。三者需要不同标注和指标,不是“模型越高级越好”。如果业务只需要整图候选,检测框和像素掩膜会增加不必要的标注成本。

多模态大模型可以描述包装图,适合帮助人员发现可能遗漏的现象,却也可能生成不在图中的解释。稳定执行固定分类标准时,需要明确数据、标签和冻结测试。本项目把大语言模型放在协助开发位置,运行时AI是本地CNN。

二、把标签限制在可见证据

intact表示当前教学图中没有看到四类已定义问题;review表示出现缺封签、撕裂、压角或污渍候选。使用“候选”是为了提醒:摄像头只看到一个视角,图片无异常不等于真实商品合格。

真实项目需要两名标注者先独立判断一小批图,记录分歧。若一个人把轻微压角标为合格,另一人标为待复核,先修订标准和示例,不要让模型在矛盾标签上学习。标签由质量或业务责任人批准,不能让AI从文件夹名称推断企业标准。

图像质量问题与包装状态也要区分。过暗、过亮、损坏文件和陌生尺寸不是包装缺陷类别,应由输入门转人工重新采集。把“照片模糊”标成review会让模型混淆物体状态与拍摄质量。

三、建立人工与规则基线

人工基线是按清单查看原图并记录判断与用时。工程中的计算基线更简单:只检查顶部区域是否存在足够比例的绿色封签。如果存在就给出intact候选,不存在给出review候选;尺寸和亮度不合格先转人工。

def rule_baseline(path):
    gate = scope_gate(path)
    if not gate["accepted"]:
        return {"route": "manual_review", "label": None}
    image = read_rgb(path)
    region = image[2:13, 9:23]
    green = ((region[:, :, 1] > region[:, :, 0] * 1.25) &
             (region[:, :, 1] > region[:, :, 2] * 1.25))
    ratio = float(green.mean())
    return {"route": "rule_candidate",
            "label": "intact" if ratio >= 0.08 else "review"}

规则能够稳定发现缺封签,却会把仍有封签的撕裂、压角和污渍当作合格。这一限制在运行前就写入系统,而不是等模型赢了再贬低基线。复杂模型只有在相同测试批次减少漏检,并且陌生与故障安全接管时才值得保留。

专业迁移卡:数字媒体与设计
数字媒体方向可把输入改为授权镜头截图,分类为“可进入初剪候选/需复核”,规则先检查分辨率、方向和黑帧;设计方向可检查作品是否属于已登记版式类别。素材授权、事实和发布仍由人确认,不能用分类分数自动发布。

第二节 采集、标注并按对象或批次划分图像数据

一、让样本覆盖真实变化

配套data/generate_images.py以固定种子20260807生成图像。每张32×32 RGB图有背景、包装矩形和轻微噪声;合格图有完整封签,待复核图从缺封签、撕裂、压角和污渍中选择。生成数据让学生不依赖外部下载即可跑通,但视觉模式远比真实商品简单。

每个包装对象生成两个轻微视角,字段包括image_id、相对路径、标签、object_id、batch_id、split、范围和缺陷类型。B01—B06共144图训练,B07—B08共48图验证,B09—B10共48图冻结测试。8张圆形、48×32图片作为未登记结构,不进入训练。

真实采集要覆盖光照、背景、距离、设备和生产批次,同时避免类别与背景绑定。如果合格图都在白桌面、问题图都在深色输送带,模型可能只学背景。图像可能含姓名、地址、订单或人物,采集前要确定授权,裁去无关个人信息,并保存原图与脱敏记录的对应关系。

课堂数据审查不能只数图片。每组先随机打开12张图,对照清单核查路径、对象、批次、标签和缺陷是否一致;再按标签和缺陷类型统计数量,确认“待复核”不是只有一种明显黑线。最后选择同一对象的两个视角,讨论哪些变化来自拍摄、哪些现象决定标签。若清单写“污渍”而图中没有可见依据,应先退回数据,不让模型替标注人员消化矛盾。

使用真实商品图片时还要形成权利清单:拍摄者是否同意教学和训练使用,包装上的品牌、人物和订单信息能否保存,数字资源能否公开下载,何时删除原图。获得查看权限不自动等于获得训练或发布权限。协助开发的AI可帮助列检查项,却不能判断一份授权是否覆盖当前用途。

二、按对象或批次隔离集合

同一对象两个视角高度相似。如果一个进入训练、另一个进入测试,模型可能记住纹理,测试分数会过高。同一批次还可能共享材料和背景,因此本项目同时要求对象与批次都不跨集合。load_manifest建立每个object_id和batch_id对应的切分集合,只要出现多个训练/验证/测试值就停止。

groups = {}
for row in rows:
    for kind in ("object_id", "batch_id"):
        groups.setdefault((kind, row[kind]), set()).add(row["split"])
leaked = [key for key, splits in groups.items()
          if len(splits - {"unknown"}) > 1]
if leaked:
    raise ValueError(f"对象或批次跨集合泄漏: {leaked[:3]}")

测试批次在建模前由教师或数据责任人封存。开发阶段使用不含B09—B10路径和标签的development_manifest.csv;学生不能查看冻结类别分布、运行基线或逐张调模型。模型与双阈值冻结后,最终评价单元才一次性打开完整清单。若结果反过来指导修改,新版本必须建立新的未见批次。

三、增强不能改变标签事实

真实项目常用轻微旋转、平移、缩放和亮度变化扩展训练,但每项变化都必须不改变标签。例如条码方向若是标准,水平翻转就可能制造不存在的包装;过强颜色变换会掩盖污渍或封签颜色。

本样板生成器已经提供少量位置与像素扰动,训练代码不再叠加随机增强,以便复现。学生若增加RandomRotation,应在训练/验证批次先可视化增强图、确认标签并比较验证结果;方案冻结后才进行一次新批次评价。增强不是“免费数据”,也不能补足真实产品缺失。

第三节 从零训练小型CNN并比较迁移学习选择

一、从像素到卷积与迁移选择

一张32×32彩色图进入程序后成为32×32×3张量。卷积核在局部区域共享参数,逐层组合边缘、颜色和纹理;池化缩小空间尺寸;全局平均把整幅特征图汇总;Sigmoid输出待复核相对分数。

迁移学习是复用大型预训练视觉网络,适合真实数据有限、图像更复杂的场景,但需要权重来源、较大计算和离线分发。本章为了让完整工程小、快、无网络,实际选择从零训练三层小型CNN。课堂比较两条路线的条件:先用样板学透CNN机制;真实迁移项目再引入经核验预训练权重,并重新完成基线、测试和模型卡。本章没有加载预训练权重,因此不能把本次结果称为迁移学习实验。

二、完整训练与推理链

train.py读取清单并把像素缩放到0—1。完整模型主链如下:

inputs = keras.Input(shape=(32, 32, 3), name="package_rgb")
x = keras.layers.Conv2D(8, 3, activation="relu",
                        padding="same")(inputs)
x = keras.layers.MaxPooling2D()(x)
x = keras.layers.Conv2D(16, 3, activation="relu",
                        padding="same")(x)
x = keras.layers.MaxPooling2D()(x)
x = keras.layers.Conv2D(24, 3, activation="relu",
                        padding="same")(x)
x = keras.layers.GlobalAveragePooling2D()(x)
x = keras.layers.Dense(16, activation="relu")(x)
outputs = keras.layers.Dense(
    1, activation="sigmoid", name="review_score"
)(x)
model = keras.Model(inputs, outputs,
                    name="package_visual_reviewer")
model.compile(
    optimizer=keras.optimizers.Adam(0.003),
    loss="binary_crossentropy", metrics=["accuracy"],
)
model.fit(
    x_train, y_train,
    validation_data=(x_val, y_val),
    epochs=45, batch_size=24,
    callbacks=[keras.callbacks.EarlyStopping(
        monitor="val_loss", patience=8,
        restore_best_weights=True,
    )],
)

训练模型使用0.5把分数变成二分类,只用于和规则公平比较。运行系统更保守:分数≤0.35才进入合格候选,≥0.65进入待复核候选,中间转人工。尺寸不是32×32、亮度异常或模型缺失时,模型不运行。

if score <= thresholds["intact_max"]:
    route, label = "intact_candidate", "intact"
elif score >= thresholds["review_min"]:
    route, label = "review_candidate", "review"
else:
    route, label = "manual_review", None

完整Notebook位于resources/ch07/project/notebooks/ch07_package_vision.ipynb,权威工程为vision.py、train.py、evaluate.py和review_image.py。Notebook让学生逐格观察,.py保证测试、命令行和其他应用共用同一推理逻辑。

三、读混淆矩阵和本次真实结果

参考环境为Windows、Python 3.12.13、TensorFlow 2.21.0、Keras 3.15.1、CPU。模型实际训练42轮后恢复验证损失较好的权重。冻结B09—B10共48张图,合格与待复核各24张。

方法 合格正确 合格误报复核 待复核漏检 待复核正确 准确率
绿色封签规则 24 0 16 8 66.67%
Keras CNN(0.5) 24 0 12 12 75.00%

CNN比规则多识别4张待复核图,准确率高8.33个百分点,但仍漏掉12/24个问题候选,不能自动放行。运行双阈值后,只有25/48张进入明确候选区,候选25/25正确,其余23张转人工。这里的100%不是全部测试准确率,而是较保守阈值筛出的候选正确率,代价是47.92%的人工接管。

报告如实同时保留模型能力与运行覆盖,不能只挑“25/25”宣传。图像由程序生成,结构简单,75%也不能外推到真实包装。最终判断是教学合成范围限用、始终人工确认。

课堂可以选择四张图完成“从原图到决定”的追踪:一张合格、一张缺封签、一张仍有封签但带污渍、一张48×32陌生结构。学生先不用模型按标签合同判断,再运行rule_baseline和review_image.py,把输入门、规则结果、CNN分数、路由和人工决定填入同一张观察表。缺封签图能说明规则的价值,污渍图能说明规则边界,陌生图能说明模型前接管,合格图则用于检查系统没有把所有对象都推给人工。

如果模型建议与学生判断不同,先回到原图和标签标准,不立刻改代码。检查图像是否损坏、清单是否错标、分数是否处于不确定区,再判断问题属于数据、模型还是运行阈值。协助开发的AI只能依据这些证据提出修改候选。每组还应把自己的解释交给另一组复核,确保别人能从文件和结果得出相同结论,而不是依赖口头补充。

四、读训练现象和错例

训练准确率上升不保证批次泛化。学生先列出12个漏检的defect_type和分数,检查它们是否集中在压角、污渍或不同位置。规则漏掉带封签的所有其他缺陷符合其设计;CNN错例可能来自小目标在全局平均中被弱化、训练样本不足或批次颜色变化。

开发阶段只向协助开发的AI提交验证错例编号、真实标签、分数、缺陷类型和图片,不只问“怎么提高准确率”。冻结测试结果只用于交付判断;若它暴露了新问题,可形成下一版假设,但必须用新批次验证。若建议删除错例、把冻结图加入训练或改阈值掩盖0.5分类错误,应拒绝。

图示规划: 绘制“像素—卷积局部特征—池化—整图表示—待复核分数—双阈值—人工确认”,旁边用小图对比分类、检测和分割的输出。

第四节 在光照、背景和陌生样本中测试泛化

一、只改变合格候选阈值

固定模型、B07—B08验证批次与review_min=0.65,只把intact_max从0.35改为0.25。修改前预测:合格候选减少,人工复核增加,误把问题图当合格的风险可能降低。用验证批次记录三种路由数量、候选正确率、待复核漏检和人工量,选定后冻结阈值;B09—B10只在最终评价运行一次。

阈值不会让模型学到新缺陷,也不能证明输入属于训练范围。若模型在0.5比较仍漏检,降低合格阈值只是更保守地转人工,不应写成模型能力提高。学生让AI只修改元数据或命令参数,审查差异并运行全部回归。

二、正常、边界、陌生和故障测试

正常测试是B09—B10中32×32、亮度正常、对象未见的图,检查规则、CNN分数和候选路由。边界测试使用分数接近0.35或0.65、允许范围内的轻微位置与亮度变化,预期进入人工或按阈值稳定分流。

陌生测试使用8张48×32圆形包装。它们格式正确却结构和尺寸未登记,系统在模型前全部转人工,不能让CNN在两个已知标签中强选。真实陌生样本还包括新包装结构、无关图片、训练未见缺陷和新设备背景。

故障测试包括损坏PNG、模型缺失、清单图像路径不存在、对象/批次跨集合、空清单和极暗图。损坏文件必须给出明确错误;模型故障默认人工;数据泄漏在训练前停止。tests/test_project.py实际包含8项检查,其中独立验证0.35、0.65及两侧人工区的边界路由。

cd resources\ch07\project
python acceptance.py
python acceptance.py --require-model
python review_image.py data\images\B09-O01-V1.png
python review_image.py data\images\U01.png

默认验收检查必需文件、Python语法、测试、Notebook冻结隔离,以及报告中的固定测试、模型、配置与元数据摘要;--require-model加载小模型,将48张冻结图的现场评价与正式参考结果逐项比较,只排除明确不稳定的环境版本字段。训练另用python train.py。

三、填写模型卡并决定用途

模型卡记录任务与类别、数据生成与批次、模型结构、基线、阈值、混淆矩阵、候选覆盖、陌生接管、允许输入、禁止用途和维护责任。本项目的允许用途只能写“教学图上的低风险外观候选”,不能省略合成数据和人工确认。

完整交付位于resources/ch07/project/,含README、任务合同、数据卡、248张图片、生成器、清单、完整Notebook、.py工程、模型、元数据、训练历史、真实报告、模型卡和验收。另一组应能先运行参考模型,再从源数据重训,并解释规则66.67%、CNN75%、双阈值覆盖52.08%三者为何不矛盾。

复现时先运行默认验收,确认数据和文件未损坏;再运行带模型验收,核对参考分数;最后才重新训练。重新训练可能因底层数值实现产生小幅差异,不能要求最后小数完全一致,但批次、样本数、标签顺序和使用结论必须一致。若重新训练跌破规则基线,报告应记录退回,而不是复制旧模型成绩。

采用表示在冻结且与真实用途相符的数据上达到预设门槛;限用表示只形成候选并人工确认;退回表示复杂模型未超过规则、漏检超门或复现失败;停止表示授权或质量责任不具备。本样板即使模型超过基线,也只限用于教学,绝不进入真实自动放行。

专业迁移卡:智能制造、交通与生物
制造方向可把标签改为零件外观“通过候选/复核候选”,按生产批次隔离,漏检门由质量负责人定义。交通方向若要指出路面问题位置,应改为检测而非沿用整图分类。生物方向可筛选显微图像候选,但标签需专业人员确认,模型不得形成诊断或生物安全结论。

本章小结

本章完成了从图像数据、规则基线、小型CNN、双阈值、陌生接管到模型卡的完整项目。任务选择由工作输出决定;标签只描述可见证据;对象和批次不跨集合;复杂模型必须与透明规则在同一冻结批次比较。

真实运行中,规则32/48正确,CNN36/48正确;双阈值只让25张进入候选区并把其余转人工;8张陌生图全部在模型前接管。这样的结果比一个孤立“准确率”更接近工程事实:模型有所增益,却仍有大量漏检和适用范围限制。大语言模型帮助学生开发,人和专业标准决定能否使用。

关键术语

目标测试

  1. 一幅图中有多个包装且要指出问题包装的位置,应优先选择( )。A.分类 B.目标检测 C.文本生成 D.回归
  2. 避免同一包装连拍造成泄漏的关键做法是( )。A.随机分每张图 B.按对象和批次整体划分 C.增加轮数 D.只看准确率
  3. 本项目规则基线最容易漏掉哪类样本?A.缺封签 B.尺寸陌生 C.仍有绿色封签但存在撕裂、压角或污渍 D.损坏文件
  4. 8张48×32陌生包装最合适的处理是( )。A.缩放后强制分类 B.默认合格 C.在模型前转人工 D.加入训练并覆盖测试
  5. 判断并改错:“双阈值候选25/25正确,说明全部48张测试图准确率是100%。”
  6. 判断并改错:“把测试错例加入训练后,继续用原测试集就能证明模型泛化改进。”
  7. 分别写出分类、检测和分割的一种专业输出,并说明本项目为何选择分类。
  8. 设计只把intact_max从0.35改为0.25的实验,写出保持项和要记录的四类结果。
  9. 各设计一条边界、陌生和故障测试,并说明模型是否应该运行。
  10. 某新版本CNN冻结准确率降到60%,低于规则66.67%,却有更漂亮的界面。请作出采用、限用、退回或停止结论,并说明责任人与重新验收范围。

答案编号:A3-7-01—A3-7-10。完整答案和评分要点统一放入书后“目标测试参考答案”。

第8章 用声音和传感数据发现异常

工作阶段: 把连续现场信号变成可观察、可比较的低风险提醒。
公共核心项目: 与AI协同开发“设备声音异常观察站”。
核心技术: 采样、时间窗口、会话级划分、波形、FFT频谱、时频统计特征、RMS基线、Keras二分类、漂移门与双阈值。
输入输出链: 1秒WAV → 采样/静音/削波检查 → 七维时频特征 → RMS基线/Keras模型 → 正常候选、低风险提醒或人工接管。
应用中的AI: 根据已登记正常与异常声音的时频特征输出异常候选分数的本地Keras分类模型。
协助开发的AI: 帮助学生审查采集情境、解释波形与频谱、生成和修改完整代码、分析误报漏报的大语言模型。
人的责任: 确认设备、负载、位置、会话与标签,处理声音授权,审查漂移和错例,决定是否检查设备以及任何现场动作。
主要交付物: 168个离线WAV、会话清单、RMS基线、时频Keras模型、完整Notebook与.py工程、漂移测试、真实报告和模型卡。
明确边界: 输出只表示声音接近已知异常候选,不诊断故障,不自动停机、断电、维修或调整生产。
跨章关系: 延续第7章的分组隔离、基线和模型卡;第9章可把特征和模型部署到离线终端,但安全动作仍由规则和人决定。

学习目标

完成本章学习后,你将能够:

  1. 说明采样率、1秒窗口、录制会话和工况记录怎样定义一条声音样本;
  2. 从波形提取RMS、峰值、过零率、频谱中心和频带能量比例;
  3. 按会话隔离训练、验证和测试,避免相邻窗口泄漏;
  4. 比较RMS阈值、Keras有标签分类和异常检测三种思路的适用条件;
  5. 用误报、漏报、双阈值、漂移和故障测试评价低风险提醒;
  6. 与AI协同完成一项限定修改、固定回归、模型卡和复现交付。

项目导入

设备声音包含转动、摩擦、冲击、环境噪声和人的活动。人有时能听出变化,但“听起来不对”很难批量记录和比较。人工智能可以把声音窗口变成数值特征,学习已确认的正常与异常模式,再给人员一个候选提醒。

这个任务不能写成“AI听声音判断设备故障”。一个异常分数只说明声音与训练中的已知模式相似,不能指出轴承、皮带或电机具体故障。麦克风位置、增益、转速和负载变化都可能改变声音。系统只能提示人员查看原始声音与工况,停机和维修必须走正式规程。

本章用可离线生成的教学声音跑通完整项目。每个文件为1秒、8 kHz、16位单声道WAV。登记数据有10个录制会话,每个会话16个窗口;S01—S06训练,S07—S08验证,S09—S10冻结测试。另有D01的8个不同基础频率窗口模拟未登记设备或工况漂移。

声音生成器刻意让正常和异常整体RMS接近:异常主要多出1250 Hz成分和7 Hz幅度调制。这样透明RMS规则会暴露“只看响度”的局限,时频模型才有机会通过频谱结构带来增益。数据设计与真实运行均公开,100%测试分也不会被包装成现实准确率。

连续设备声音
     ↓ 切成1秒窗口并记录会话/设备/负载
WAV格式、采样率、长度、静音、削波检查
     ↓
RMS、峰值、过零率、频谱中心、低/中/高频比例
     ├─ RMS阈值基线 ─────────────┐
     └─ 归一化→Keras二分类分数 ──┼→ 未见会话比较
                     漂移门 ──────┘
            ↓
正常候选 / 低风险提醒 / 人工复核
            ↓
人员结合原声、工况和正式规程决定

建议用7—9学时。学生先试听或查看几个合成WAV及其特征,再运行参考模型;随后在Notebook中逐格执行会话检查、FFT特征、RMS基线和Keras训练;最后改变一个提醒阈值、检查漂移与故障,形成模型卡。Python和Keras是实现材料,学习重点是信号如何变成样本、证据如何受情境限制。

本章成果

AI协同开发路线

先向协助开发的AI提交采集条件:“我们只在登记设备、固定麦克风位置和稳态负载下观察1秒声音。请先追问采样率、会话编号、标签来源、声音隐私、异常提醒后谁处理;不要先写分类代码。”学生依据设备人员和数据授权回答,把未知条件写入合同,不让AI假设“声音更响就是故障”。

条件冻结后,要求AI先列出生成/采集、WAV校验、特征、会话划分、RMS基线、Keras训练、漂移门、统一推理、评价、Notebook和测试文件。约束依赖只用Python标准库、NumPy与Keras/TensorFlow,不引用多个音频框架。学生确认文件关系后再生成完整代码。

开发阶段提交S07—S08验证混淆矩阵与具体窗口,而不是问“模型好不好”。修改时限定:“只在验证会话把提醒阈值从0.50改为0.70,保持模型分数、特征和漂移门不变,不读取S09—S10。”学生冻结模型、RMS门槛和运行阈值后,最终评价才一次性打开S09—S10;最终结果用于交付判断,不再反向选参。

第一节 把连续信号切分成带情境的学习样本

一、采样率决定每秒记录多少点

声音是连续变化的空气振动,数字设备按固定时间间隔记录幅度。8 kHz表示每秒8000个采样点;本项目每个文件恰好1秒,因此数组长度为8000。16位PCM把幅度保存为整数,程序再缩放到约-1到1。

采样率决定能表示的最高频率和文件大小。若训练都用8 kHz、运行却收到16 kHz文件,直接提取同样索引的频带会改变含义。本项目不静默重采样,采样率不符直接报错并转人工准备数据。真实工程可增加明确重采样模块,但必须固定参数并测试。

read_wav还检查单声道、16位、长度。损坏文件、立体声或窗口不足不是正常类别,不能用零填补后交给模型。输入检查属于确定性程序,模型不需要学习文件头规则。

二、时间窗口把长记录变成样本

连续录音不能直接对应一个标签。本项目把它切成1秒窗口,每个窗口计算特征并赋予经确认的正常或异常标签。窗口越短,响应可能更快,却可能看不到完整周期;窗口越长,特征更稳定,但提醒延迟和数据量增加。

窗口标签必须与设备状态和时间对应。如果一段会话前半正常、后半发生变化,不能只按整个文件名批量贴标签。真实采集要记录设备编号、负载、转速、麦克风位置、维护状态、开始时间和操作人员确认。没有情境的声音很难解释,模型也可能把环境声当设备特征。

配套生成器每个会话含8个正常与8个异常窗口,共10个登记会话160个窗口。D01的8个窗口使用另一基础频率并标记unknown,只测试漂移接管。清单不含真实谈话和个人信息。

三、按录制会话隔离数据

同一会话相邻窗口共享设备、房间、增益和背景,彼此高度相似。把窗口随机分到训练与测试,会让模型在测试中看到训练会话的近邻,得到虚高分。正确做法是先按session_id分组,再把整个会话放进一个集合。

sessions = {}
for row in rows:
    sessions.setdefault(row["session_id"], set()).add(row["split"])
leaked = [session for session, splits in sessions.items()
          if len(splits) > 1]
if leaked:
    raise ValueError(f"录制会话跨集合泄漏: {leaked}")

训练会话S01—S06有96个窗口,验证S07—S08有32个,冻结测试S09—S10有32个。测试基础频率与训练略有变化但仍属于登记设备范围。真实部署还应把不同日期、设备和位置作为更严格的现场测试,不因本章按会话隔离就声称解决全部泛化问题。

专业迁移卡:智能制造与交通
制造方向可采集电机、泵或风机声,必须记录负载、转速、传感器和维护状态;交通方向可观察车辆部件或轨旁声音,但位置、天气和速度是关键情境。声音模型只作低风险候选,设备或交通安全动作由正式制度和专业人员决定。

第二节 从波形、频谱和时间变化建立正常基线

一、波形描述幅度随时间变化

波形是8000个幅度随时间排列的数组。RMS等于平方平均后开方,用一个数概括整体能量;峰值是最大绝对幅度,可发现削波。持续近似零可能表示传感器断开或录制失败,不能当作“特别安静的正常设备”。

rms = float(np.sqrt(np.mean(samples ** 2)))
peak = float(np.max(np.abs(samples)))
if rms < 0.005:
    return {"accepted": False,
            "reason": "近似静音,传感器或录制疑似失效"}
if peak >= 0.98:
    return {"accepted": False,
            "reason": "波形削波,需重新采集"}

RMS规则基线只使用正常训练窗口:阈值=正常RMS平均值+1.5倍标准差。超过阈值给异常候选,否则正常候选。它透明、计算快,却只看到能量。异常如果音量相近而频率结构不同,RMS会漏掉。

二、频谱描述能量分布在哪些频率

快速傅里叶变换把加窗波形转换为各频率的能量。频谱中心是频率按能量加权的平均位置;低频、中频和高频比例分别统计400 Hz以下、400—1000 Hz和1000 Hz以上的能量。异常合成信号增加1250 Hz成分,因此高频比例和频谱中心会变化,即使RMS相近。

过零率统计相邻采样正负号变化比例,对高频和噪声较敏感。本项目最终七个特征为RMS、峰值、过零率、频谱中心、低频比例、中频比例和高频比例。特征压缩使模型容易观察和运行,却也丢掉瞬态顺序,不能捕捉所有真实异常。

课堂观察时,每组各取一个正常和异常窗口,先只看RMS,再看七维特征。两类RMS都接近0.225,学生应预测RMS规则难以区分;异常窗口的频谱中心和高频比例则更明显。随后换到另一个会话,检查结论是否仍成立。这个过程让学生看到“特征是为任务选取的表示”,模型并没有直接听懂声音含义。

特征名称、单位和计算参数必须随模型保存。频谱中心单位为Hz,三个比例无单位,过零率是0到1之间的比例。若后续把采样率或频带边界改变,七个数字即使列名相同,含义也已经变化,应建立新版本并重新训练,不能继续加载旧模型。

windowed = samples * np.hanning(len(samples))
spectrum = np.abs(np.fft.rfft(windowed)) ** 2
freqs = np.fft.rfftfreq(len(samples), 1 / 8000)
total = float(spectrum.sum()) + 1e-12
centroid = float((freqs * spectrum).sum() / total)
low = float(spectrum[freqs < 400].sum() / total)
mid = float(spectrum[(freqs >= 400) & (freqs < 1000)].sum() / total)
high = float(spectrum[freqs >= 1000].sum() / total)

三、控制变量:只调整窗口长度作观察

可把1秒窗口改为0.5秒,保持同一录音、特征定义、模型暂不训练,只观察RMS和频谱中心的稳定性。预测:窗口缩短会增加样本数和响应速度,但统计波动可能更大;若异常是短冲击,短窗口也可能更容易定位。

改变窗口会同时改变样本数和相邻性,必须重新按原始会话分组,不能把新的半秒窗口随机切分。学生记录每个会话的特征均值、标准差和计算时间,再决定是否值得进入下一模型版本。控制变量活动不是为了选一个万能长度,而是看清时间尺度如何改变证据。

第三节 比较规则、分类模型和异常检测

一、三条路径的条件不同

规则适合专业阈值能清楚表达的情况,例如输入静音或整体能量超过已确认边界。有标签分类要求正常和已知异常都有可靠样本,本章采用这条路径。异常检测通常只用正常数据建立正常范围,适合异常稀少且类型不断变化的场景,但“偏离正常”仍不等于故障。

三条路径不能只比名称。应看可用数据、标签可信度、错误后果和维护能力。本章既有正常也有明确生成的已知异常,因此训练二分类;RMS保留为基线;异常检测作为机制比较,不在同一章再引入第二套模型,以免学生把不同任务混成“异常AI”。

二、完整最小二分类链

七个特征量纲不同,归一化均值和标准差只从训练会话计算并随模型保存。Keras模型使用16和8个ReLU单元,Sigmoid输出异常相对分数:

mean = x_train.mean(axis=0)
std = x_train.std(axis=0)
std[std == 0] = 1.0

inputs = keras.Input(
    shape=(7,), name="time_frequency_features"
)
x = keras.layers.Dense(16, activation="relu")(inputs)
x = keras.layers.Dense(8, activation="relu")(x)
outputs = keras.layers.Dense(
    1, activation="sigmoid", name="abnormal_score"
)(x)
model = keras.Model(inputs, outputs,
                    name="sound_anomaly_observer")
model.compile(
    optimizer=keras.optimizers.Adam(0.01),
    loss="binary_crossentropy", metrics=["accuracy"],
)
model.fit(
    (x_train - mean) / std, y_train,
    validation_data=((x_val - mean) / std, y_val),
    epochs=100, batch_size=16,
    callbacks=[keras.callbacks.EarlyStopping(
        monitor="val_loss", patience=14,
        restore_best_weights=True,
    )],
)

完整Notebook在resources/ch08/project/notebooks/ch08_sound_observer.ipynb,权威工程为sound.py、train.py、evaluate.py与observe_sound.py。学生要能指出WAV在哪里验证、特征在哪里计算、归一化状态怎样保存、分数在哪里转路由。

三、读取本次真实比较

参考环境为Windows、Python 3.12.13、TensorFlow 2.21.0、Keras 3.15.1、CPU。实际训练使用96个窗口、32个验证窗口,26轮后恢复验证损失较好的权重;固定测试为未见会话S09—S10的32个窗口。

下面是evaluate.py --write-reference生成的本次实际结果。数据数量、环境、训练轮数与混淆矩阵同时写入reports/reference_evaluation.json,不是根据模型结构推测,也没有用训练集成绩替代未见会话测试。

方法 正常正确 误报 漏报异常 异常正确 准确率
RMS阈值0.232268 16 0 16 0 50.00%
Keras时频分类(0.5) 16 0 0 16 100.00%

RMS漏掉全部异常,说明这批异常不是简单变响;时频模型识别了生成器中明确的高频和调制模式。100%不代表现实设备性能。测试只有两个会话,信号由同一公式生成,异常类型单一,真实噪声与设备差异远复杂。正确结论是“模型在合成已知模式上证明了时频特征相对RMS的价值”,不是“AI能够准确诊断设备”。

学生要特别练习拆解这个100%。它不是160个登记窗口的总体成绩,不包含D01漂移,也没有覆盖新故障;它只是冻结S09—S10的32个合成窗口在0.5阈值下的分类结果。模型能够识别生成器写入的1250 Hz成分,与它能否识别真实轴承磨损是两个不同命题。报告同时写样本来源、会话数量、信号机制和禁止用途,才能防止指标脱离条件传播。

运行时采用≤0.35正常候选、≥0.65低风险提醒、中间人工的双阈值。本次32个冻结窗口都进入明确候选且正确;仍要保留人工确认和漂移门,因为高分模型对陌生输入也可能自信。

四、从特征回到声音情境

错例分析不能只看七个数字。RMS受距离和增益影响,频谱中心随转速变化,高频比例可能来自环境蜂鸣或谈话。学生要把分数、波形、频谱、原WAV、设备与负载记录放在一起。如果模型只在固定增益下正确,移动麦克风就可能导致漂移。

向协助开发的AI提交具体窗口、真实标签、特征、分数和会话,不只问“如何优化模型”。要求它区分输入质量、会话分布、特征表示和模型四类原因,并一次只建议一项实验。若AI建议把S09—S10测试窗口加入训练后继续报告原成绩,应拒绝。

图示规划: 绘制“1秒波形—加窗FFT—七维特征—RMS规则/Keras分类—漂移门—低风险提醒—人工复核”,并在会话划分处标出相邻窗口不可跨集合。

第四节 测量误报、漏报、漂移和响应时间

一、只改变提醒阈值

固定模型分数和S07—S08验证会话,分别用0.50与0.70作为异常提醒阈值。提高阈值通常减少误报,却可能增加漏报;降低阈值相反。两个版本都在验证集统计真正正常、误报、漏报和真正异常,并记录进入人工区的数量。

阈值改变不等于重新训练,也不会让陌生异常变成已知。学生先预测哪些验证窗口会变化,再让AI只修改开发配置,审查差异并冻结阈值;S09—S10只在最终评价运行一次。如果验证分数都远离0.5和0.7,结果可能不变,这也是有效观察。

二、四类测试和响应时间

正常测试使用未见会话S09—S10中已登记正常与异常窗口。边界测试包含分数接近双阈值、轻微增益变化和允许范围内的基础频率变化,预期低信心时转人工。陌生测试使用D01不同设备频率,系统计算特征与训练标准化距离;任一绝对标准化值超过6就不运行模型。本次8/8漂移窗口全部在模型前转人工。

故障测试包含静音、削波、16 kHz错误采样、长度不是1秒、损坏WAV、模型或元数据缺失。静音明确提示传感器疑似失效,不能判正常;错误采样率不静默变换;模型故障默认人工。tests/test_project.py实际运行8项检查。

cd resources\ch08\project
python acceptance.py
python acceptance.py --require-model
python observe_sound.py data\wav\S09-01.wav
python observe_sound.py data\wav\D01-01.wav

默认验收检查必需文件、Python语法、8项测试、Notebook冻结隔离,以及报告中的固定测试、模型、配置与元数据摘要;--require-model加载模型,将32个冻结窗口的现场评价与正式参考结果逐项比较,只排除明确不稳定的环境版本字段。模型训练另用python train.py。

响应时间从声音窗口开始形成就应计算。1秒窗口至少需要接近1秒观察,特征和推理再增加处理时间;如果连续三个窗口达到阈值才提醒,稳定性可能提高,延迟也至少增加到约3秒。报告要写清窗口时长、计算时延和连续策略,不能只报模型推理几毫秒。

三、发现漂移并规定低风险响应

工程用训练特征均值和标准差计算最大标准化距离,作为教学漂移门。它只能发现明显数值偏离,不能保证分布内输入就是已知。真实运行还应按设备、负载和位置登记,定期比较近期特征、模型分数、误报和漏报。

漂移提示原证据变弱,不等于设备故障,也不应让新数据自动进入训练。运行日志保存时间、会话/设备、工况、模型与阈值版本、特征、分数、路由、人员确认和响应时间;声音隐私要求只保留必要片段,明确访问和删除。

声音采集还有容易被忽略的隐私问题。设备旁可能有人谈话,原始WAV可能包含与任务无关的语音。真实项目应选择合适位置和时段,明确告知与授权,尽量在设备端提取必要特征,并设置原声保存期限与访问权限。不能因为模型只输出七个特征,就假设采集过程天然匿名;学生与责任人要审查原始数据链。

一次完整课堂演练应由四个角色完成:采集角色确认会话与工况,开发角色运行特征和模型,复核角色听原声并查看频谱,责任角色决定是否发出低风险检查请求。角色互换后再运行一遍,可以暴露哪些结论依赖某个人的口头经验。AI可以整理日志和提出问题,却不能签署设备安全决定。

课堂结束前,每组还要完成一次“证据反向核对”:从一条低风险提醒出发,依次找到异常分数、七维特征、原始WAV、会话与工况、模型和阈值版本,再找到人员的最终确认。任何一环缺失,都不能把提醒作为可追溯成果。另一组应只依据交付目录复现这一条链,并故意移走模型文件,确认系统会转人工而不是继续显示旧结果。这个练习把声音模型从演示程序变成可交接的小工程,也让学生理解运行记录、版本和人工责任为何属于人工智能系统的一部分。

低风险响应只能是页面提示、日志或请值班人员查看。停机、断电、维修和生产调整必须由设备安全规则与有权限人员决定。连续误报、传感器故障、模型文件不一致或输入范围变化时,系统退回人工巡检。

交付包含README、任务合同、数据生成器、168个WAV、清单、数据卡、完整Notebook、.py工程、模型与元数据、训练历史、真实报告、模型卡和验收。另一组应能复现RMS 50%、Keras 100%和漂移8/8接管,同时解释为何最终仍只是登记业务设备范围的低风险提醒。

专业迁移卡:生物与风景园林
生物方向可把声音换成培养箱温湿度序列,按实验批次隔离,异常标签由实验人员依据规程确认;园林方向可输入土壤水分或光照,窗口改为小时或天,传感器校准和季节是关键情境。提醒只触发人工检查,不直接启动水泵、药剂或生物安全动作。

本章小结

本章完成了“声音—窗口—情境—特征—基线—模型—漂移—提醒—交付”的完整项目。连续信号必须按会话切分,WAV质量和静音由规则检查,RMS是透明能量基线,时频特征让Keras模型学习已知频率结构。

真实运行中,RMS在冻结会话仅16/32并漏掉全部异常,时频模型32/32;8个漂移窗口均在模型前接管。这些数字如实说明生成数据上的机制,同时也暴露其简单性。应用中的AI只给候选,协助开发的AI帮助学生理解与修改,专业人员承担设备判断和现场动作。

关键术语

目标测试

  1. 把同一长录音的相邻窗口随机分到训练和测试,主要风险是( )。A.会话泄漏 B.容量超限 C.文本幻觉 D.排程无解
  2. RMS规则最直接反映的是( )。A.故障部件 B.整体声音能量 C.全部设备状态 D.维修方案
  3. 本次RMS准确率50%且漏掉16个异常,主要说明( )。A.异常不存在 B.只看响度无法识别这批频率结构变化 C.测试应删除 D.Keras自动诊断故障
  4. D01漂移窗口最合适的处理是( )。A.相信最高分 B.模型前转人工并核对设备工况 C.自动停机 D.加入训练覆盖测试
  5. 判断并改错:“Keras在32个合成测试窗口上100%,因此可以诊断真实设备故障。”
  6. 判断并改错:“为了适应现场,应把每次运行声音未经审核自动加入训练。”
  7. 说明为什么声音必须按录制会话而不是按窗口随机划分。
  8. 设计0.50与0.70提醒阈值的控制变量实验,写出保持项和四类数量。
  9. 各设计一条边界、陌生和故障测试,说明模型是否运行以及预期动作。
  10. 比较RMS规则、有标签分类和只用正常数据的异常检测的适用条件,并说明本章为何只实现分类路径。

答案编号:A3-8-01—A3-8-10。完整答案和评分要点统一放入书后“目标测试参考答案”。

第9章 制作可离线运行的现场感知终端

工作阶段: 进入现场——把一个可追溯训练、可验证导出的环境小模型放进可重复运行的本地终端。
公共核心项目: 完成“离线现场感知终端”:用虚拟或预录环境窗口跑通设备接口、本地组合偏离模型、独立规则、提示状态和故障降级;有条件时再只替换适配层接入真实设备。
核心技术: 虚拟设备接口、传感器适配、模型导出与端侧推理、资源预算、超时、故障检测和安全降级。
输入输出链: 物理现象或回放数据 → 设备适配层 → 预处理 → 本地模型 → 概率或异常分数 → 独立规则 → 提示与日志 → 人工确认。
应用中的AI: 使用本章独立训练的温湿度与噪声组合偏离小模型;专业迁移只复用接口、导出验证和模型外规则方法,不假称已经直接复用前章模型。
协助开发的AI: 根据学生提供的任务合同、官方设备资料和真实日志,生成并解释适配代码、模型转换代码和故障测试。
人的责任: 核实型号、接口、电压、单位、采样频率和使用边界;审查代码差异;决定是否部署以及何时停止。
主要交付物: 可运行工程、任务合同、H0虚拟/预录两路实现、真实设备适配接口、本地模型、冻结测试、参考报告和系统卡。
明确边界: 终端只观察、记录和提示,不直接控制市电、燃气、压力、加热、高速运动、门锁、交通工具或医疗设备。
跨章关系: 沿用第1章任务合同、第2章数据约定以及第7、8章的模型训练与独立测试方法;本章环境模型另行训练,并未直接加载前章视觉或声音制品;输出可在第10章接入受控工作流。

学习目标

学完本章,你将能够:

  1. 画出从物理现象到人工确认的完整信号链,并指出模型、规则和设备各自承担什么;
  2. 区分H0预录或虚拟接口、H1电脑或USB设备、H2边缘设备三种实现路径;
  3. 根据经过核实的官方资料,与AI协同生成并限定修改设备适配代码;
  4. 比较模型在云端、本地电脑和端侧设备上的精度、延迟、内存、断网能力与维护负担;
  5. 用断网、设备断开、输入超范围和资源不足样例验证安全降级。

项目导入

前面章节已经学习模型训练和独立测试的方法,但“有一个模型文件”还不是现场应用。本章没有把不相干的视觉或声音模型硬接到环境任务,而是独立生成温度、湿度和噪声教学数据,训练一个环境组合小模型,再把它导出到本地终端。现场设备仍可能没有接好,输入单位可能变化,模型也可能因资源不足或陌生环境失效,因此终端必须把设备、模型、规则、日志和人的行动连成一条可以检查的链。

本章公共项目是一个低风险的异常观察终端。它每隔固定时间读取一段声音、振动或环境数据,调用本地模型输出概率或异常分数;确定性规则检查输入是否完整、分数是否达到提示阈值、模型是否超时;满足条件时只在屏幕上提示并写入日志,由巡检人员确认。它不自动停机、不切断电源,也不代替法定报警和专业检测。

硬件不是进入本章的门槛。H0使用预录数据或虚拟接口,在普通电脑上完成完整链路;H1使用电脑自带摄像头、麦克风或小组共享的USB传感器;H2把同一接口迁移到边缘设备。三条路径共享输入输出契约、测试集和安全规则,学生即使没有设备也能完成核心学习。

本章成果

AI协同开发路线

学生先向协助开发的AI提交任务合同、模型输入形状、标签、官方设备资料、运行系统和“不允许控制危险设备”等边界。AI需要追问接口类型、采样频率、单位、窗口长度、日志位置和超时条件,再提出“设备层—预处理层—模型层—规则层—输出层”的文件方案。AI生成H0完整首版,学生使用回放数据运行,逐层查看输入形状、模型分数和日志。确认H0稳定后,先要求AI只修改设备适配文件接入H1;迁移H2若需更换端侧模型格式或推理运行库,再把“模型运行适配”作为第二个独立变更。两次均保持输入输出契约、规则和测试不变,审查差异后用同一组正常、边界、陌生和故障样例回归。

第一节 设计传感器、模型、规则和输出的完整信号链

一、从物理现象画到人的行动

终端的起点不是模型,而是现场需要观察的物理现象。设备异响、振动幅度、环境温湿度或画面状态先被传感器转换为数字数据,再经过裁剪、缩放、切窗或归一化,才能满足模型输入要求。模型输出的是概率、类别或异常分数,不是“设备一定故障”的事实。规则检查数据有效性和阈值,界面显示证据,最后由责任人确认。

信号链至少标出九项:被观察现象、传感器、原始单位、采样频率、预处理、模型输入形状、模型输出、规则状态和人工动作。例如声音模型要求16 kHz、1秒窗口,设备却以48 kHz持续录音,适配层就必须重采样并切成模型需要的长度。若单位、频率或数组顺序错误,即使程序没有报错,模型结果也可能失去意义。

模型和规则承担不同责任。模型处理环境变化较大、难以用单一阈值描述的模式;规则负责“传感器读数是否存在”“分数是否为有效数值”“是否连续达到阈值”“模型是否超时”等确定性条件。安全规则独立保存,不能由语言模型在运行时改写。

二、为三种硬件路径建立同一接口

H0、H1和H2的采集差别应集中在设备适配层。上层程序统一调用read_window()取得带时间戳、单位和质量标记的数据。H0从CSV、WAV、JPEG或虚拟数据读取;H1从电脑自带设备或USB传感器读取;H2从边缘设备接口读取。若H2不能直接加载原模型格式,可以另换端侧模型运行适配器,但输入输出契约、预处理定义、规则、测试和日志语义不能随之改变。

路径 设备条件 核心任务 必须说明的限制
H0 普通电脑、预录数据或虚拟接口 跑通信号链、模型、规则和故障测试 不能证明真实采样稳定性
H1 摄像头、麦克风或USB传感器 比较位置、设备与采样差异 需要授权、端口和驱动检查
H2 边缘设备加传感器 断网推理、资源预算和持续运行 设备型号、功耗和维护具有现场差异

控制变量实验先固定模型、测试窗口和提示阈值,只把H0回放输入换成H1采集输入,比较形状、单位、分数和延迟。若同时更换模型、阈值和设备,就无法判断变化来自哪里。

三、把本章项目真正跑通

本章不要求学生先购买传感器,也不把“讲几个端侧概念”当作项目完成。配套工程位于resources/ch09/project/,默认完成的是一个可离线运行的“环境异常观察终端”:它接收温度、湿度和噪声三个数值,先检查字段、单位约定、有效范围和独立安全边界,再加载本地模型计算组合偏离分数,最后输出RECORD、REVIEW或明确的停止状态。输出只供巡检人员查看与复核,不连接任何控制设备。

这是一个从数据到交付的完整项目,而不是单独的模型演示。generate_training_data.py用固定算法和种子生成冻结CSV;train_export_model.py完成Keras训练、float JSON与INT8 JSON导出和一致性检查;models/同时保存.keras原模型和两种JSON;benchmark_runtime.py在独立冷启动进程中测量运行资源;config.json保存有效范围、安全范围、0.60模型门槛和推理时限;src/实现设备、标准库模型运行器、规则主链和命令行入口;data/还保存回放窗口与封存测试;tests/、evaluate.py和acceptance.py分别负责单元检查、逐例评估和整包验收;模型卡、系统卡与三类报告记录边界和真实结果。学生因此可以回答“数据怎样生成、模型怎样训练、参数怎样导出、失败时怎样停止、别人怎样复现”,而不只是看到一个界面。

设备层的核心不是某个品牌驱动,而是同一份输入契约。虚拟设备、JSONL预录设备和真实设备适配器都只公开read_window(),并交付SensorWindow:

@dataclass(frozen=True)
class SensorWindow:
    window_id: str
    timestamp: str
    temperature_c: float
    humidity_pct: float
    noise_db: float
    quality: str = "ok"

class Device(Protocol):
    def read_window(self) -> SensorWindow: ...

真实设备路径并没有虚构接线和驱动代码,而是用RealDeviceAdapter(reader)接收一个已经依据官方资料审核的只读函数。读取函数返回字段不全、类型错误或设备异常时,适配器统一抛出DeviceLostError。这样做把“设备怎么读”和“模型怎样处理”分开:接入新设备时只改适配层,模型、规则、日志状态和封存测试保持不变。默认H0路径安全可运行;H1、H2只有在教学实施单位具备具体设备、教师与现场责任人核对电气条件后才开展。

本地模型也不是人工在JSON里填写几项权重。生成脚本固定产生3000条教学样例:2400条训练、600条验证,正常和复核各1500条。标签规则公开为三个标准化绝对偏离的加权和达到2.30,但它只构造一个学生能够核查的学习任务,不代表真实工作现场分布。Keras模型直接接收三项原始读数,先按固定中心和尺度归一化;6个固定ReLU单元把每个特征拆成正、负偏离,最后一个Sigmoid层的权重和偏置由训练数据更新:

x_i = (value_i - center_i) / scale_i
h = [ReLU(x_1), ReLU(x_2), ReLU(x_3), ReLU(-x_1), ReLU(-x_2), ReLU(-x_3)]
score = sigmoid(bias + Σ(weight_j × h_j))

固定隐藏表示使偏离机制可检查,训练输出层则让学生看到真实的优化、验证和导出过程。600条合成验证数据在0.60门槛上的准确率为0.976667,仍只说明模型拟合这条教学规则。score不是设备故障概率,更不能直接推导停机决定。完整训练CSV、Keras制品、脚本、版本、哈希、误差和限制都保存在工程中,不能再用“模型导出”替代来源证据。

为什么不只写三个阈值?配套工程保留了raw_threshold_baseline()作为人工可解释基线。当温度、湿度和噪声分别都没有越过单项阈值时,基线会给出RECORD;但三项同时发生中等程度偏离时,组合模型可能给出REVIEW。这说明小模型可以表达多个弱信号的合成,并不说明它必然优于规则。若真实项目的固定测试表明规则更稳定、维护更简单,就应采用规则基线,不必为了“看起来像AI”而部署模型。

主链严格规定检查顺序:先读取新窗口;再检查有效范围;然后检查独立安全边界;质量未知时转人工;模型存在且结构有效时才计算分数;推理超过预算则停止;最后才用模型门槛决定记录或复核。这个顺序很重要。假如温度已经越过独立安全边界,程序不需要等待模型“同意”;假如设备没有新窗口,程序不能沿用上一次正常值;假如模型文件缺失,程序不能悄悄退回一个看似合理的固定分数。

result = terminal.run_once(device, network_available=False)
# 每条结果都显式带出:
# status、reason、score、baseline_status、inference_ms、
# model_bytes、network_required、human_confirmation_required

学生第一次运行时,在项目目录执行:

python acceptance.py
python -m src.main
python -m src.main --source replay --count 3

运行src.main可以看最小成功样例,--source replay逐条读取预录窗口;acceptance.py检查28项必需文件、全部Python语法、Notebook结构、冻结数据逐字节复现、三种模型制品哈希、12条导出一致性、8个单元测试和10条系统样例。默认H0只使用Python标准库,不访问网络,不要求TensorFlow、云账号或真实硬件。模型环境可用时运行python acceptance.py --require-model,程序会在output/model_rebuild/隔离重训、重导出、重新基准并加载Keras复核,不能用已有JSON冒充本次重建。Notebook用于逐格观察证据、输入、模型和状态,完整程序仍以脚本与src/为准。

四、按四类样例理解系统,而不是只看成功画面

正常类检查常见读数和断网输入,两者都应RECORD;边界类放在模型门槛附近,用来观察一个阈值变化怎样影响复核量;陌生类把quality设为未知,要求系统进入REVIEW而不是猜测;故障类覆盖设备无新数据、模型缺失、强制超时和输入越界,分别进入STOP_DEVICE_LOST、STOP_MODEL_MISSING、STOP_TIMEOUT和STOP_BAD_INPUT。此外还有独立安全样例,必须在模型之前进入STOP_SAFETY。

参考环境的实际报告显示10条固定系统样例10条通过,状态分布为3条RECORD、2条REVIEW以及5种停止状态各1条。正常样例的INT8 JSON模型分数约为0.000002;组合异常样例中,简单阈值基线仍给出RECORD,模型分数0.894227达到0.60复核门,转为REVIEW;边界样例分数0.554551,仍为RECORD。报告同时保存2416字节INT8 JSON、模型与模型构建报告的SHA-256以及本机观测延迟。延迟会随电脑和运行负荷变化,所以学生要重新运行并记录,不能照抄参考数值。

这四类测试不是为了凑数量。正常类说明最小闭环可用;边界类暴露决策对门槛的敏感性;陌生类验证系统是否知道“自己不知道”;故障类验证失败是否可见、可停止、可恢复。学生完成控制变量实验时只改变model_threshold,先预测哪些非封存练习窗口会改变状态,再运行比较复核量。与AI协同修改时,只委托它改一个设备适配器或新增一个故障测试,要求列出差异并重跑acceptance.py;不得把降低安全边界或删除失败样例当作“修复”。

第二节 根据官方资料协同生成设备适配代码

一、先建立设备事实包

让AI连接设备前,学生需要建立“设备事实包”,包括准确型号、官方资料版本、接口类型、供电要求、操作系统、驱动、采样格式、单位、最小示例和已经观察到的日志。网页讨论、相似型号代码和模型记忆只能帮助提出检索方向,不能替代官方资料和真机读数。

设备事实包还要写明禁止事项。例如不改变安全联锁、不写入固件、不接触市电、不自动执行控制动作、不把密钥或私人录音写进仓库。AI若建议使用未核实的端口、函数或接线,学生应要求它指出依据;无法定位依据就保持虚拟接口并停止真机连接。

二、限定AI只修改适配层

学生给AI的修改委托可以写为:“保持Sample数据契约、模型、阈值、日志字段和测试不变;只把ReplayDevice.read_window()替换为设备X的读取实现。所有接口必须依据随附官方资料;资料未说明的地方返回quality='unknown',不得猜测。”

修改后先看文件差异,再上设备。检查点包括:是否新建了不必要的网络连接;是否改变了单位、采样频率或数组顺序;是否捕获异常却假装成功;是否把设备密钥写入代码;是否绕过质量标记。然后在不加载模型的情况下打印十次原始读数,与设备自带工具或参考输入比较,确认适配层的事实正确。

三、用日志而不是猜测调试

“设备没有反应”不足以让AI定位问题。有效反馈应包含运行命令、操作系统、准确设备型号、端口列表、完整异常类型、关键日志和已经排除的条件。学生一次只解决一个层次:先确认设备被发现,再确认能读数据,再核对单位与频率,最后接模型。这样可以防止AI一次改动驱动、模型和阈值,造成新的不确定性。

故障基线采用虚拟设备。若真实适配出现问题,切回H0仍应通过全部模型与规则测试;这能判断故障位于设备层,而不是整个项目。H0不是“低配演示”,而是定位问题和保证可教学性的正式路径。

第三节 导出模型并比较本地运行的资源与性能

一、导出前先冻结输入输出契约

模型导出前记录输入形状、数据类型、归一化方式、标签顺序和输出含义。配套工程在environment_anomaly_model.keras之外同时导出float JSON和逐张量对称INT8 JSON;标准库运行器依据JSON中的中心、尺度、层形状、激活、整数参数和量化scale执行相同计算。转换后使用12条未参加训练的固定样例比较三种制品,不能只看文件是否生成。参考结果中float JSON相对Keras最大概率误差为8.4e-08,INT8最大误差为0.012003321,0.60门槛上的决策均为12/12一致。

比较表至少包含模型版本、文件大小、启动时间、单次推理延迟、峰值内存、固定测试指标、断网能力和所需运行环境。参考工程只实测同一台本地电脑上的Keras和标准库JSON,不虚构云端或边缘板性能;云端与H2数据必须在真正运行后另行补充。部署位置是工作选择,不是越靠近设备越先进。

二、先比较不压缩版本,再改变一个变量

公共核心把同一Keras稠密层先导出为float JSON,再把每个kernel和bias分别做对称INT8量化。结果纠正了一个常见预设:Keras制品为24,401字节,float JSON为2,265字节,INT8 JSON为2,416字节。INT8比float JSON多151字节,即增加6.667%,因为这个网络参数极少,每张量scale与JSON元数据抵消了整数表示节省。因此本项目不能得出“量化一定减小文件”的结论。INT8运行时还会解量化为Python浮点数,也不等同于硬件整数加速。

参考性能报告在Windows 11、Python 3.12.13中各运行3个独立冷启动进程。Keras的冷进程墙钟中位数为2650.6965毫秒、单次推理中位数0.9295毫秒、峰值常驻内存304,234,496字节;float JSON标准库运行时分别为72.7705毫秒、0.0022毫秒和19,992,576字节;INT8 JSON标准库运行时分别为68.6432毫秒、0.0022毫秒和19,927,040字节。float与INT8的推理中位数相同,INT8冷启动低5.672%、峰值内存低0.328%,不足以证明稳定收益。Keras与JSON的巨大差别主要说明这个极小模型中框架启动成本占主导,不代表更大的网络、另一台电脑或真实边缘设备仍有相同比例。

平均延迟不能掩盖最慢情况。现场终端还要记录首次启动、连续运行和高负载时的延迟。若模型偶尔超过规定时间,规则应标记超时并要求人工观察,而不是继续沿用旧结果。简单规则已经满足任务时,可以不部署小模型;模型增加的维护成本也是验收证据。

三、形成部署判断

采用本地或端侧的常见理由包括断网可用、隐私、低延迟和费用可控;不采用的理由可能是模型精度下降、设备资源不足、更新困难或现场维护能力不足。判断应与任务合同连接:企业展示可以接受短暂延迟,生产巡检的提示延迟和漏报后果则不同。任何路径都必须保留人工覆盖。

部署前还要完成一次持续运行观察。学生让终端连续处理一组有明确时间顺序的回放窗口,记录每轮延迟、内存变化、停止状态和日志文件增长,检查程序是否逐渐变慢、重复提示或丢失记录。短时间成功不能代表能够稳定工作;持续观察发现的问题也必须回到相同输入上复现,才能交给AI限定修改。

第四节 在断网、低资源和设备故障下安全降级

一、为失败规定可观察状态

安全降级不是显示一行“出错了”,而是让系统进入预先定义的状态。至少包含:RECORD正常记录、REVIEW需要人工复核、STOP_BAD_INPUT输入无效、STOP_TIMEOUT推理超时、STOP_DEVICE_LOST设备断开、STOP_MODEL_MISSING模型缺失和STOP_RUNTIME_ERROR运行异常。停止状态不继续产生业务建议,也不沿用上一次分数。

固定失败集包括:断开网络;删除或损坏模型文件;遮挡摄像头或输入全静音;拔出传感器;提供空数组、错误单位和超范围数值;压低可用内存;输入训练集合中没有的对象。每个样例写明期望状态、日志字段和人工动作。失败后恢复设备时,系统先做自检,再重新读取,不能自动补写缺失记录。

二、把安全保护放在模型之外

低置信度、资料冲突和传感器失效时默认不行动。即使模型输出高分,独立规则仍要检查数据质量、连续次数、超时和动作白名单。物理停止、人工开关和专业报警不能依赖同一个模型或同一段可被AI修改的代码。

本章终端只提示和记录。若专业迁移确需控制设备,必须另行完成风险评估、独立安全联锁和专业审批,且不属于本书公共项目。学生不能因“代码由AI生成”而降低接线、权限和安全审查标准。

三、专业迁移卡

专业迁移卡A:智能制造巡检。 输入改为经授权的设备声音与振动,H2采用隔离的边缘节点;高代价错误是把明显异常记为正常。交付物增加设备位置、负载和维护班次字段,终端只生成“待复核”记录,由设备责任人决定停机或检修。

专业迁移卡B:生物培养环境观察。 输入改为温湿度、光照或其他经专业教师审核的环境数据;高代价错误是单位错配、探头断线后继续给出正常结论。交付物增加校准记录、批次与实验负责人,终端不控制培养设备,只提示复核。

专业迁移卡C:数字媒体互动展示。 输入改为摄像头手势或授权声音,错误后果主要是互动失灵和采集隐私。交付物增加采集范围、删除方式和观众提示;输出仅改变低压界面效果,不控制门锁、照明市电或机械装置。

四、形成终端交付卡

终端交付卡写明H0/H1/H2路径、设备与模型版本、输入输出契约、模型性能、资源预算、日志位置、固定测试、已知失效、恢复步骤、禁止动作和责任人。接手者应能在无网络条件下运行H0,制造一次设备断开并看到正确停止状态。若只有原开发者知道怎样恢复,项目尚未达到可交接状态。

本章小结

模型进入现场后,真正的工作对象变成设备、数据、模型、规则、日志和人的完整链路。H0、H1和H2使用同一接口,使没有硬件的学生也能学习机制,并使真实设备故障可以被定位在适配层。

AI可以依据核实资料协助生成代码,但设备事实、代码差异、安全保护和部署决定必须由人检查。本地运行的价值要用断网能力、延迟、隐私、资源和维护证据说明。低置信度、设备故障和陌生输入时默认不行动,是终端进入专业现场的基本条件。

关键术语

目标测试

一、单项选择题

  1. H0路径的主要价值是( )。A.证明真机长期稳定 B.在无新增硬件时完成全链路并定位设备层问题 C.绕过模型测试 D.自动控制设备
  2. 设备适配代码最可靠的事实依据是( )。A.模型记忆 B.相似产品帖子 C.准确型号的官方资料和真实日志 D.代码越长越好
  3. 模型输出异常分数后,最适合由确定性规则完成的是( )。A.重新训练模型 B.检查单位、超时和提示阈值 C.推断设备故障原因 D.决定专业责任
  4. 比较量化前后模型时,正确的控制变量做法是( )。A.同时换测试集和设备 B.固定模型任务、设备和测试集,只改变量化 C.只比较文件名 D.把测试数据加入训练

二、判断并改错

  1. “真实设备无法连接时,H0路径没有教学价值。”请判断并改正。
  2. “模型输出高置信度后,可以绕过独立安全规则直接控制现场设备。”请判断并改正。

三、简答与操作题

  1. 选择一种声音、图像或环境感知任务,画出从物理现象到人工确认的完整信号链,并标明模型和规则的位置。
  2. 为一个H1设备拟定事实包,至少列出型号、接口、单位、采样频率、官方资料和两项禁止事项。
  3. 设计一个只改变部署位置的对照实验,列出至少四项性能或使用指标。
  4. 为设备断开、模型缺失和输入超范围分别写出期望状态、日志内容和人工恢复动作。

答案编号:A2-09-01—A2-09-10。完整答案与评分要点统一放入书后“目标测试参考答案”。

第四篇 把原型变成可靠交付——工作流、验收与持续改进

第10章 把模型结果接入专业工作流

工作阶段: 可靠交付——把分散的模型、资料、规则和工具连接为受控工作流。
公共核心项目: 完成“设备巡检闭环助手”,从18条模拟工作文字训练一个小型分类模型,把低风险现场事件经过模型分流、指定资料检索、证据约束候选、状态机和复核员确认,转成可持久重放的本地处理记录。
核心技术: 字符TF-IDF与质心分类、透明关键词基线、结构化接口、检索、证据约束生成、确定性规则、状态机、角色权限、内容感知幂等、审计日志和人在回路。
输入输出链: 冻结训练文字 → 模型制品 → 脱敏巡检事件 → 风险规则/模型分类 → 指定资料检索 → 候选说明 → 人工确认 → 本地事件写入 → 持久重放。
应用中的AI: 默认使用实际训练并导出的字符TF-IDF质心分类模型;语言模型只可替换证据约束候选模块,不掌管引用、状态、权限或写入。
协助开发的AI: 帮助学生设计模块接口、生成多文件工程、解释日志、补充异常路径和回归测试。
人的责任: 定义状态、权限、证据要求、人工确认点和停止条件;核对写入结果并承担专业决定。
主要交付物: 系统图、接口契约、状态表、权限矩阵、可运行工作流、事件重放包、审计日志和操作说明。
明确边界: 大语言模型不直接决定权限、金额、安全处置或最终工单状态;任何外部写入均先预览、确认且可追踪。
跨章关系: 组合第3章的证据模块与第7—9章至少一个感知模块;输出交给第11章验收和试运行。

学习目标

学完本章,你将能够:

  1. 画出事件从接收、识别、查证、建议、确认到关闭的状态变化和责任边界;
  2. 分别说明模型、检索、规则、普通程序、状态、权限和人的作用;
  3. 用结构化数据契约连接不同模块,检查字段、来源和失败状态;
  4. 实现人工确认、停止、重复提交与中途写入失败恢复,并说明生产系统还需怎样处理撤销和工具超时;
  5. 重放正常、失败、重试和换班交接事件,并利用审计日志定位问题。

项目导入

一个视觉模型能够把包装判为“待复核”,一个检索程序能够从规范中找到相关段落,一个语言模型能够整理说明,但这些能力并不会自动形成可靠工作。真实任务还需要回答:识别结果由谁接收?没有资料依据时怎样停下?谁有权确认?写入失败能否重试?同一事件重复提交会不会产生两张工单?换班人员能否看懂此前发生了什么?

本章公共项目处理低风险的工作现场设备或环境文字事件。学生先用18条模拟工作文字训练三类文本模型,再把模型接入检索、候选说明、状态、权限和审计链。系统也可以按接口接收第9章终端事件,但本章冻结测试直接使用文字事件,避免把两个项目的误差混成一个分数。系统不下达停机、断电或维修命令;高风险或证据不足事件只进入人工队列。

“大语言模型协调”不等于把全部流程交给模型。已训练小模型负责文字分类,检索模块寻找依据,propose()把结构化事实和证据组织为候选说明,规则检查支持性和边界,状态机记录工作走到哪一步,权限系统决定谁能执行什么,人员作最终确认。参考版propose()采用确定性模板;即使接入语言模型,验证器也只接受与事件、类别和证据所确定的模板逐字段一致的输出。自由改写属于新系统,必须另建支持性和风险验收。只有这些职责分开,系统才可能被测试和交接。

本章成果

AI协同开发路线

学生向协助开发的AI提供第1章任务合同、三类训练样例、第3章资料索引、角色清单和禁止动作。AI先帮助检查训练/测试分离,再生成字符特征、TF-IDF、质心训练、模型导出与关键词基线;随后追问事件唯一编号、证据不足状态、确认角色、写入目标和日志字段,提出模块边界。学生逐个运行train.py、evaluate.py和acceptance.py,查看模型分数、检索来源、候选引用与状态日志,不允许用一段大函数隐藏全部过程。故意制造无证据、多意图、同编号不同内容、越权和写入故障后,只修改对应模块;审查差异并重跑固定测试(公开回归包),最后由有权限的同学完成确认与交接重放。

第一节 画清信息流、状态变化、角色和接管点

一、先确定工作状态,再决定自动化

工作流不是一串按钮,而是事件在若干明确状态之间变化。本工程持久工作状态包括:RECEIVED已接收、ANALYZED已分析、EVIDENCE_FOUND找到依据、PROPOSAL_READY候选已形成、AWAITING_CONFIRMATION等待确认、COMMITTED已确认记录、CLOSED_NO_ACTION拒绝后关闭和MANUAL_REVIEW人工接管。中途写入恢复先追加RESUMED及原最后状态,再从RECEIVED重跑确定性主链;这是显式、可审计的恢复环,不是第二次业务提交。STOP_ID_CONFLICT与STOP_WRITE_FAILED是本次请求的故障结果,不覆盖事件原有持久状态;写入失败时系统可能根本无法记录新状态。区分“事件状态”和“请求结果”,才能正确解释重试与审计。

若先写自动化代码再补状态,常见结果是模型一返回文字就被当成完成,或者写入失败后无法知道是否已经执行。状态表应在开发前回答:低置信度去哪;检索无命中去哪;语言模型输出不符合结构去哪;确认人拒绝后能否修改再提交;写入超时是重试还是人工核对。状态越清楚,需要大语言模型自由发挥的部分越少。

二、把角色和责任放到图上

公共项目运行期包含巡检员inspector、复核员reviewer和审计员auditor。巡检员可以提交事件但不能确认;复核员查看模型、证据和候选后接受或拒绝;审计员只能重放。维护者可以更新程序,但运行期没有借维护身份取得确认权。一个人可能在课堂中扮演多个角色,系统仍需按角色记录权限,避免因为“同一台电脑”就取消边界。

应用中的AI没有人员身份。它能提出候选分类和说明,却不能拥有批准权。协助开发的AI只在授权项目目录内修改代码,也不能更改运行期权限表。专业人员负责规定哪些事件必须升级、哪些资料具有权威性、哪些错误不能接受。

三、完整信息流

系统图至少画出五种不同箭头:事件数据流、证据流、模型输出流、批准或拒绝指令、审计日志。资料检索返回的是命中段落和来源,不是最终处置;规则返回的是通过、拒绝或需复核,不是自然语言理由;工具写入返回记录编号或错误,不是模型的主观判断。

控制变量实验固定训练数据、练习事件、资料和人员,只改变minimum_score或maximum_secondary_score中的一个,观察事件进入MANUAL_REVIEW或继续查证的比例。修改前先预测哪几个非封存练习样例会改变;选定参数后再用没有参与调节的新测试批次验证。阈值变化不能顺便改变权限、检索资料或原冻结报告。

第二节 用结构化接口连接模型、资料、规则和工具

一、用接口契约避免模块互相猜测

接口契约规定字段名称、类型、单位、允许值、来源和缺失表示。感知模块输出事件编号、类别、分数、时间和设备;检索模块接收类别与问题,返回来源编号、段落和相似度;建议模块接收事件和证据,输出候选说明、引用和不确定项;规则模块检查格式、阈值和禁区;记录工具只接受已经批准的结构化内容。

JSON只是传递结构的一种方式,不是AI技术。结构化接口的价值在于每层都能单独替换和测试。语义检索可以从关键词基线升级为嵌入检索,语言模型可以更换,本地记录也可以换成经批准的业务系统,只要契约保持稳定,上下游不必全部重写。

二、把设备巡检事件做成完整闭环

配套工程位于resources/ch10/project/。它不是一段“如何写提示词”的示例,而是一个可以从巡检事件走到正式记录的完整设备巡检闭环助手。使用者分为巡检员、复核员和审计员;输入是一条带唯一编号、脱敏现象文字和位置的事件;输出包括候选类别、可定位的资料依据、当前状态、人工决定和只追加审计事件;完成状态是正常、边界、陌生、高风险、检索故障、重复提交和越权测试都通过,并能从事件日志重建最终状态。真实工单写入不在本教材参考工程范围内。

项目首先建立人工表单基线。人工基线可以安全接收全部七类事件,也可以让责任人逐条查资料,但不会自动找到证据,速度和一致性受人员经验影响。助手真正要改善的是“先分流、再找到指定依据、把候选送给正确的人”,不是替人做维修决定。若助手不能保持权限和停止条件,宁可退回人工表单。

完整工程把责任拆开:calibrate.py用开发验证集选择路由门限;train.py与small_model.py训练、导出和加载模型;baseline.py与manual_baseline.py现场运行关键词和人工基线;classifier.py把高风险规则置于模型之前;retrieval.py要求模型类别与资料类别一致;coordinator.py实现真实存在的propose()并拦截无依据动作;workflow.py规定状态、确认预览和人工确认;store.py把只追加事件刷新到JSONL;build_replay.py重建事件包;main.py把一条事件走完整条链。任务合同、接口合同、数据卡、模型卡和权限矩阵使代码之外的约束也能被接手者检查。

训练集包含“业务设备、环境服务、网络与账号”三类文字,每类6条。程序把每条文字切成连续2字和3字片段,计算TF-IDF:一条文字里反复出现的片段权重增加,在许多文字里都出现的片段权重降低。每类训练向量取平均并归一化为一个质心;新事件分别与三个质心计算余弦相似度,最高者是候选类。另有8条开发验证文字,只用于从18组候选中选择路由门限,不参与质心训练,也不包含7条最终流程回归样例。训练结果不是藏在代码里的手填答案,而是calibrate.py和train.py现场生成的JSON制品;制品绑定训练与验证数据、路由配置、样本数、词权重和三个质心。

模型最高分低于0.08时转unknown,前两名间隔低于0.015时转ambiguous,第二名仍达到0.10时转multi_intent。高风险词由模型外规则优先转人工。以下是模型接口,score是几何相似度而非正确概率:

{
    "route": "candidate" | "manual",
    "reason": None | "high_risk" | "multi_intent" | "ambiguous" | "unknown",
    "label": "业务设备" | "环境服务" | "网络与账号" | None,
    "score": 0.0,
    "margin": 0.0,
    "scores": {"业务设备": 0.0, "环境服务": 0.0, "网络与账号": 0.0}
}

关键词基线不训练模型,只检查少量明示术语;人工基线由manual_form_route()逐条接收合法表单,不自动补证据。它们必须现场运行,而不是在报告中填一个常数,因为复杂方法要证明额外价值。本次7条公开回归样例上,小模型与关键词基线都是7/7,不能宣称模型更好;模型保留在教材中,是为了让学生完整经历“数据—训练—制品—加载—工作流—验证”,真实采用仍需更大且独立的新表达测试。

检索模块只在本地knowledge.json中查找与模型类别一致且文字命中的条目,返回doc_id、类别、标题、摘录、匹配词和分数。“模型说业务设备、检索却给出积水资料”会返回无命中,不允许把两个看似成功的模块错误拼接。检索器不把自己的常识写成制度,也不把“找到一条资料”解释为“资料已经批准处置”。如果知识库不可用或没有证据,主链进入MANUAL_REVIEW。这就是检索增强的本质:用外部可定位资料约束候选内容,而不是用一个流行缩写掩盖证据责任。

状态机把工作过程固定为:

RECEIVED → ANALYZED → EVIDENCE_FOUND
→ PROPOSAL_READY → AWAITING_CONFIRMATION → COMMITTED / CLOSED_NO_ACTION

每一次变化都作为事件追加保存。巡检员可以提交,但不能接受候选;复核员可以接受或拒绝;审计员只能查看重放。下面是主链最关键的控制逻辑,完整实现保存在资源工程:

analysis = self.classifier(event["text"])
if analysis["route"] == "manual":
    return move_to("MANUAL_REVIEW", reason=analysis["reason"])

evidence = retriever.search(event["text"], analysis["label"])
if evidence is None:
    return move_to("MANUAL_REVIEW", reason="no_evidence")

move_to("EVIDENCE_FOUND", evidence=evidence)
proposal = coordinator.propose(event, analysis, evidence)
move_to("PROPOSAL_READY", proposal=proposal)
move_to("AWAITING_CONFIRMATION")
# reviewer先读取review_packet,再把preview_digest交给confirm()

这里的“模型协调”不是让一个大模型自由指挥所有模块。程序先按接口调用分类,再按规则决定是否检索,最后由状态机检查是否允许确认。权限、状态和幂等都由可检查的确定性代码执行,不能由语言模型在每次运行时临时发明。

三、让幂等、权限和重放进入主流程

事件编号与规范化载荷SHA-256共同承担幂等判断。同一编号、同一文字和位置再次提交时返回当前状态和duplicate=True,不再分类、检索或追加第二组记录;同一编号对应不同内容时进入STOP_ID_CONFLICT并追加冲突事件,不能把新内容误当旧请求。这样可以处理双击和客户端重试,同时识别编号复用。幂等不是“禁止用户再试”,而是让同一业务意图无论重试几次都只有一次提交副作用。

权限检查发生在动作之前。非reviewer调用confirm()会抛出PermissionDenied;事件不在AWAITING_CONFIRMATION时也不能确认。复核员必须先调用review_packet(),从持久日志恢复原事件、模型分析、完整证据和候选;confirm()要求提交这份预览的SHA-256,旧摘要或缺失预览不能确认。这样程序重开后的接手者不会在看不到依据时“盲确认”。若第一次写入就失败,内存不残留伪提交;若提交后的中间状态写入失败,同载荷重试识别为resumable,重新运行确定性主链且不产生第二条submitted。这只覆盖单进程、逐记录故障,不等于事务数据库。课堂工程的正式记录只是本地事件;若以后连接真实工单、消息或数据库工具,还必须预览目标、内容和权限,再由责任人确认。

事件重放不是重新询问模型。replay_states()按sequence读取state_changed事件,恢复每个事件的最后状态;完整轨迹仍保存在原始JSONL中供人或后续工具检查。当前函数不对任意外部日志执行独立的状态转移合法性验证,合法路径由WorkflowEngine控制。若新版本对同一冻结事件包产生不同最终状态或不同JSONL,验收会失败并要求调查。

学生在项目目录运行:

python acceptance.py
python calibrate.py
python train.py
python -m src.main
# 只有显式人工演示确认时才运行:
python -m src.main --actor reviewer --decision accept

main默认使用“客户洽谈室投影显示无信号”走到候选并停止,不会自动冒充复核员确认;只有显式传入--actor reviewer --decision accept/reject才执行人工演示确认。这里的角色参数是接口演示,不是真实身份认证。验收程序检查完整交付文件,现场重建并要求路由配置、模型制品和36条事件重放包逐字节一致,运行11项单元测试、7个公开流程回归样例和8项操作约束,再把当前报告与冻结报告全量比较。默认工程只使用Python标准库和本地资料,不访问网络,也不写入真实工作现场系统。

四、用回归与故障测试解释参考结果

正常类有三条:投影无信号、入口积水、办公网认证失败。它们分别命中K001、K002、K003,都只能走到AWAITING_CONFIRMATION,没有一条被自动提交。边界类是一条同时包含投影和网络问题的事件,分类器不能确定一个单一流程,因multi_intent转人工。陌生类“这里有个东西不太对”没有受支持术语,因unknown转人工。安全类包含“插座冒烟”,因high_risk立即转人工,不生成常规处置。故障类模拟检索模块不可用,因module_fault转人工。

参考环境实际运行7条公开流程回归样例,模型主链7/7:3条到达AWAITING_CONFIRMATION并形成与K001—K003绑定的候选,4条进入MANUAL_REVIEW。关键词基线也是7/7;可执行人工表单基线7/7都安全转给人,但自动找到证据为0条。8项操作约束进一步通过同载荷幂等、同编号不同载荷停止、权限、带预览摘要的人工确认、持久重开与重放、候选支持性、首次写入停止和中途写入恢复。结论是“工程闭环成立、模型优越性未证明”,而不是用7/7包装部署能力。

学生的控制变量实验只扩展一个门限候选或一条知识记录,用开发数据和非封存练习事件比较“自动给出证据的数量、误路线数量和转人工数量”。参考propose()只接受安全模板;若把它换成语言模型并允许自由改写,就已经改变系统边界,必须新增“正确引用却加入无依据动作、承诺或诊断”的支持性测试,不能只重跑旧包。若生成更流畅却引入虚构或无依据内容,应拒绝采用。

五、检索增强与工具连接只讲本质

“先检索依据,再把命中材料交给语言模型生成”常被称为检索增强生成。它不能保证资料正确,也不能保证模型引用准确,因此仍需无命中、冲突和错误引用测试。小资料集用关键词或数组相似度即可,不必为名词搭建复杂平台。

工具连接协议可以帮助不同AI客户端用统一格式发现工具和参数,但协议本身不是模型,也不提供权限和责任。公共项目直接使用清楚的Python函数和JSON契约;在拓展框中说明标准协议的价值即可,不能让接口名遮住“谁能调用、调用什么、怎样确认和怎样撤销”。

模块级测试应在整条工作流之前完成。给检索模块一个不存在的问题,它应返回无命中而不是相似段落;给建议模块一份固定证据,它应只输出受支持内容;给规则模块缺字段和越界分数,它应稳定拒绝;给权限模块错误角色,课堂实现会抛出明确PermissionDenied但不写越权审计事件。真实身份系统还应记录主体和拒绝动作。只有单个模块的合同成立,整条链路中的错误才有可能被准确定位。

还要检查模型输出是否污染事实字段。模型可以生成summary或uncertainty,但事件编号、时间、地点、分数和来源编号应来自上游结构化数据,不能由模型重新书写。界面展示时把“原始观察”“命中证据”“模型候选”和“人工决定”分区,防止使用者把语言流畅的候选说明误认为已经批准的事实。

第三节 设置权限、确认、停止和重复提交保护

一、权限必须针对动作

“已经登录”不等于拥有全部权限。权限矩阵按动作区分提交、查看本次返回、恢复确认预览、确认和重放。确认人必须看到将写入的完整变更预览,包括来源、模型分数和不确定项。课堂角色字符串只是接口断言,不是账号认证;生产接入必须由身份系统提供不可冒充的主体。模型建议不能用醒目的默认按钮诱导人员直接同意。

密钥和凭据放在运行环境中,不写入Notebook、日志或项目压缩包。协助开发的AI若生成读取全部文件、上传整个目录或请求管理员权限的代码,学生应拒绝并缩小授权范围。最小权限不仅是安全原则,也能减少误操作后的影响范围。

二、停止是正常路径,撤销与超时处理是生产扩展

低置信度、资料无命中和高风险类别在参考工程中进入人工复核;多余或缺失输入字段由接口直接抛出ValueError,不形成事件状态。当前三条资料每类只有一条,尚未实现同类来源冲突检测。停止或拒绝不是程序失败,而是符合合同的输出。本工程只提交、接受或拒绝本地教学记录,不实现已提交记录的撤销,也没有外部工具超时查询路径;这些能力不能写成已经验收。

若以后接入可撤销的软件记录,撤销需要原记录、撤销人、理由和时间,且不删除审计轨迹;若外部工具返回超时,应先按幂等键查询是否已写入,再决定返回原结果、重试或转人工,不能盲目再次提交。这些是下一版生产合同与测试要求,不是当前JSONL工程的运行结果。

三、用幂等保护处理重复事件

幂等表示同一操作重复执行,结果不会产生额外提交副作用。课堂项目把事件编号和载荷摘要持久写入JSONL;程序重开后仍能识别同载荷重试,并能拦截同编号不同内容。它已经通过单进程重开测试,但JSONL没有数据库唯一约束,尚未证明两个进程并发写入安全。若接入真实系统,应使用具备唯一键与事务的正式存储,再测试双击、网络重试、程序重启和并发请求;不能把课堂单进程证据扩大成生产保证。

规则基线是不使用语言模型:模型结果和命中证据直接填入固定记录模板。若专业事件类型稳定、字段固定,模板路径可能比生成式说明更可靠。只有确实需要把多段证据组织成可读候选说明时,语言模型才有额外价值。

第四节 重放正常、失败、重试和交接流程

一、建立事件重放包

参考重放包由build_replay.py从7条流程样例现场生成36条事件:N01接受、N02拒绝、N03保持待确认,多意图、陌生、高风险和检索故障进入人工接管。验收在临时目录重建并逐字节比较。11项单元测试另覆盖语言输出缺字段/无依据动作、同载荷重试、同编号不同载荷、首次及中途写入故障、类别—证据错配和程序重开确认。每次核心代码或合同修改后,重建全部制品并比较状态、内容与记录数。

交接样例用N03模拟“换班”:事件停在AWAITING_CONFIRMATION。后一位复核者从持久日志恢复原事件、分析、完整证据和候选,核对preview_digest后才能确认,而不是重新猜测。课堂JSONL记录事件编号、顺序、状态、角色、载荷和结果;真实系统还应加入时间、软件/模型版本和操作者身份,同时避免无关个人隐私与密钥。

二、定位失败属于哪一层

模型误判由感知层处理;资料没找到由检索层处理;候选说明缺字段由生成接口处理;硬约束违反由规则层处理;状态跳转错误由工作流处理;无权限调用由权限层处理;重复记录由写入层处理。把所有错误都反馈成“模型不准”,会导致AI修改错误模块。

学生给协助开发的AI的有效反馈是:“事件EVT-006在检索无命中后仍进入AWAITING_CONFIRMATION,期望为MANUAL_REVIEW且原因为no_evidence;只修改检索失败转移,不改模型、资料和权限。修改后运行7个固定事件并列出差异。”这种限定比“把系统优化一下”更可审查。

对照基线可以完全不用语言模型:专业小模型输出、检索证据和人工选择直接填入固定模板。两条路径在同一事件集上比较字段正确率、来源错误、处理时间和人工修改量。如果生成式候选不能明显改善可读性或工作效率,就保留模板基线。工作流是否可靠取决于责任链和状态,而不是是否加入更多模型。

交接测试还应改变操作者而不改变系统。两名学生分别按照同一说明处理相同事件,比较状态、确认理由和最终记录。差异过大可能来自界面提示含糊、权限说明不足或专业规则没有写清,而不一定是模型性能问题。此类证据应进入第11章的验收门。

三、专业迁移卡

专业迁移卡A:商业贸易售后。 输入变为商品信息、客户描述和图片模型候选;资料为退换规则和保修条款。高代价错误是承诺不存在的权益或重复退款。交付物增加订单核验、金额只读字段和客服主管确认,模型不能直接退款。

专业迁移卡B:设计与数字媒体发布审核。 输入变为待发布文案、图片、音频和授权清单;资料为品牌规范和发布要求。高代价错误是事实错误、授权缺失或错误公开。交付物增加版本差异和权利检查,最终发布必须由内容责任人确认。

专业迁移卡C:园林养护事件。 输入变为第9章环境节点和植物视觉结果;资料为养护标准与现场记录。高代价错误是把传感器故障误判为缺水并自动灌溉。系统只形成待核查记录,由养护人员现场确认,不连接水泵控制。

四、交付工作流而不是演示画面

验收时,另一名学生应能从项目说明启动系统,重放失败事件,查到日志,解释停止原因并处理一条待确认记录。交付包还要说明资料如何更新、权限由谁维护、当前为何没有撤销接口,以及哪种变更必须重新验收。只能由原作者现场操作的演示,不是可交接工作流。

本章小结

专业工作流的可靠性来自职责分离。模型识别或生成候选,检索提供依据,规则守住确定条件,状态记录进展,权限限制动作,工具执行经过确认的写入,人员承担批准和专业责任。结构化接口使模块能够独立测试和替换。

停止、重复提交保护、中途写入恢复和审计日志不是附加功能,而是本项目工作闭环的一部分。学生应通过真实故障、限定AI修改和固定回归证明系统能在本章已实现的边界内恢复并被下一位人员接手;撤销、外部超时和并发事务必须作为扩展重新立项验收。

关键术语

目标测试

一、单项选择题

  1. 下列最适合交给确定性规则的是( )。A.生成候选说明 B.检查必填字段和置信阈值 C.理解含糊委托 D.归纳多段文字
  2. 检索模块的直接输出应当是( )。A.最终批准决定 B.命中材料及来源 C.用户权限 D.设备控制命令
  3. 幂等保护主要防止( )。A.模型训练过慢 B.同一事件重复产生副作用 C.资料过期 D.图像背景变化
  4. 工具写入超时后,正确做法是( )。A.立即无限重试 B.先查询是否已写入,再按规则处理 C.删除日志 D.让模型猜测结果

二、判断并改错

  1. “大语言模型能够协调流程,所以状态、权限和安全规则也可以由它临时决定。”请判断并改正。
  2. “检索找到了相关段落,就能证明生成的每个结论都有依据。”请判断并改正。

三、简答与操作题

  1. 为“识别—查依据—人工确认—记录”流程列出至少六个状态,并说明一个停止条件。
  2. 选择一个专业事件,分别写出模型、检索、规则、状态、权限和人员的职责。
  3. 设计三个重复提交测试,说明预期记录数量和日志结果。
  4. 阅读本章最小工程,说明把propose()换成语言模型后,哪些模块和责任仍不能交给模型。

答案编号:A2-10-01—A2-10-10。完整答案与评分要点统一放入书后“目标测试参考答案”。

第11章 验收、试运行并持续监测AI应用

工作阶段: 可靠交付——在正式使用前建立验收门,在有限试运行中观察真实表现,并准备更新与回滚。
公共核心项目: 完成“AI应用验收与试运行台”,在同一封存包上比较人工基线与两个候选版本,用独立发布门拦截高代价退步,并从有限试运行日志发现漂移、确定回滚目标。
核心技术: 人工与规则基线、错误成本、分类与系统指标、版本化测试集、回归门、试运行、漂移监测、受控更新和回滚。
输入输出链: 任务合同与风险 → 版本化测试集 → 系统运行结果 → 指标与高代价错误 → 验收门 → 有限试运行 → 监测证据 → 保持、限用、更新或回滚。
应用中的AI: 被验收的视觉、声音、时序或语言模型及其组合系统。
协助开发的AI: 帮助生成测试入口、归类日志、计算指标、提出小范围修复和补充回归,但不裁定风险等级或验收结论。
人的责任: 定义高代价错误、批准测试数据、设置门槛、监督试运行、审查更新并决定上线、限用、回滚或停止。
主要交付物: 可运行验收工程、任务合同、封存测试与哈希、基线和候选制品、现场评测输出、门槛配置、试运行报告、发布决定、系统卡和回滚预案。
明确边界: 运行反馈不能未经审核直接成为训练数据,系统不能在现场自行改变关键模型、规则、权限或设备行为。
跨章关系: 使用第1章验收合同、第2章版本化数据和第10章可重放系统;为第12章交付和维护建立质量门。

学习目标

学完本章,你将能够:

  1. 从专业后果出发定义高代价错误、人工或规则基线及验收门槛;
  2. 建立包含正常、边界、陌生、诱导、故障和权限变化的版本化测试集;
  3. 区分模型离线测试、系统验收和有限试运行,说明三者证据不能互相替代;
  4. 监测错误、拒绝、延迟、费用、人工修改和输入分布变化;
  5. 按受控流程更新模型、规则或代码,并在回归失败时恢复已验收版本。

项目导入

每章都已经做过固定测试,但“模型在测试集上表现不错”不等于整个工作系统可以投入使用。模型可能准确,检索却引用错资料;模块分别通过,权限组合后仍可能越权;实验室样本稳定,真实使用者输入却不断变化。系统验收要把专业后果、模型指标、状态、权限、恢复和人工工作量放在同一个结论中。

本章不重新训练一个模型,而是使用与第10章工作流相同的“文本输入→路线输出”接口,建立验收与试运行台。配套资源采用三份冻结的低复杂度可执行候选,不直接导入或调用第10章源码,因此这里只证明验收机制能够运行,不能虚构为已经验收第10章真实系统。学生先从错误后果定义门槛,再冻结测试集和版本,运行回归并决定是否进入有限试运行。试运行只开放给少量授权使用者,保留人工复核,持续记录系统真实表现。发现问题后不能直接让系统“边用边学”,而要形成变更申请、在副本上修改、重新回归、批准发布并保留可回滚版本。

验收结论允许是“限用”或“退回”。若规则基线已经满足任务,复杂模型没有明显价值,或者高代价错误无法降低,选择不使用模型是合格的专业判断。

本章成果

AI协同开发路线

学生把任务合同、被测版本、基线、历史失败和专业后果交给协助开发的AI。AI追问高代价错误、样例来源、门槛、试运行范围、监测频率和回滚负责人,生成测试清单和可运行入口。学生审核预期结果并冻结测试数据,再运行首轮验收。对于失败项,学生提交实际日志,要求AI只修改一个模块或参数;审查差异后重跑全部回归。达到门槛后进入有限试运行,学生根据监测证据提出变更申请,在隔离副本上更新并再次验收,最后决定保持、限用、发布新版本、回滚或停止。

第一节 根据专业后果定义指标和验收门槛

一、先问错误影响谁

验收从后果开始,而不是从可用指标开始。漏掉一条普通内容标签,与漏掉一条设备异常或发布授权缺失,不能用同样权重处理。学生先列出误报、漏报、错误生成、错误引用、越权执行、隐私泄露、超时和无法恢复等失败,说明受影响的人、严重程度、能否被发现以及谁负责确认。

高代价错误要单独设门,不能被较高的总准确率抵消。例如普通事件准确率达到90%,但“无证据仍生成确定结论”出现一次,就可能直接退回。对于低风险课堂项目,可采用“高代价错误为0、普通样例达到规定比例、所有权限和恢复测试通过”的组合门槛。

二、同时保留人工和规则基线

人工基线记录有经验或受过说明的人员完成同一任务的质量、时间和差异;规则基线使用固定阈值、关键词或模板。模型必须在相同样本和相同口径下比较。若模型只提高少量速度,却显著增加复核成本和维护风险,未必值得采用。

分类任务可以使用准确率、精确率、召回率和混淆矩阵;回归任务可以使用平均绝对误差;检索任务看相关材料是否进入前若干条;工作流还要检查状态、权限、重复写入、恢复、延迟和人工工作量。指标名称不是结论,必须与错误后果相连。

三、把门槛写成可执行规则

验收表至少包含:指标或事件、测试样例、门槛、失败后果、自动检查方式、人工复核点和批准人。门槛在测试前冻结,不能看见结果后为了“通过”临时放宽。若专业标准或法规给出硬性要求,以经核实的标准为准;教材示例门槛只能用于低风险教学项目。

控制变量实验固定测试集、程序和资料,只把感知置信阈值从0.75改为0.80,预测误报、漏报和人工复核量怎样变化,再运行同一测试。阈值选择应解释取舍,不能只追求一个最高综合分数。

第二节 建立版本化测试集和固定回归门

一、测试集必须能够追溯和冻结

每个测试样例记录唯一编号、来源、授权、输入版本、预期状态、是否高代价、适用模块和编写人。正常样例覆盖主要工作;边界样例位于阈值附近;陌生样例来自训练与开发之外;诱导样例尝试让语言模型忽略证据或越权;故障样例包括资料缺失、模型文件损坏、设备断开和工具超时;权限变化样例检查角色切换。

测试集一旦用于验收就冻结。失败样例可以进入后续训练候选区,但不能一边补进训练,一边仍把它计作独立验收。新版本需要保留旧测试,并在审核后增加新样例;删除测试必须说明理由和责任人。

二、完整最小验收链

下面代码使用标准库建立最小回归门。system_under_test()表示统一的被测接口;配套资源用冻结的可执行候选实现同一接口,并不直接调用第10章工作流。测试清单可保存为JSON,程序根据高代价失败数、普通通过率和最大延迟给出机器检查结果;最终结论仍由责任人签署。真实迁移时,应把该接口接到经过明确登记的真实系统适配器,再重新冻结制品和测试证据。

import json, time
from dataclasses import dataclass

@dataclass
class Case:
    case_id: str
    label: str
    confidence: float
    has_evidence: bool
    expected_state: str
    high_cost: bool = False

def system_under_test(case, threshold=0.75):
    started = time.perf_counter()
    if not case.has_evidence:
        state = "STOPPED"
    elif case.confidence < threshold:
        state = "NEED_REVIEW"
    else:
        state = "WAITING_APPROVAL"
    latency_ms = (time.perf_counter() - started) * 1000
    return {"state": state, "latency_ms": latency_ms}

def run_gate(cases, version, threshold=0.75,
             min_pass_rate=0.90, max_latency_ms=100.0):
    rows, high_cost_failures = [], 0
    for case in cases:
        result = system_under_test(case, threshold)
        passed = (result["state"] == case.expected_state
                  and result["latency_ms"] <= max_latency_ms)
        if case.high_cost and not passed:
            high_cost_failures += 1
        rows.append({"id": case.case_id, "passed": passed, **result})
    pass_rate = sum(row["passed"] for row in rows) / len(rows)
    gate_passed = high_cost_failures == 0 and pass_rate >= min_pass_rate
    return {"version": version, "threshold": threshold,
            "pass_rate": pass_rate,
            "high_cost_failures": high_cost_failures,
            "gate_passed": gate_passed, "rows": rows}

cases = [
    Case("T-001", "surface_damage", 0.85, True,
         "WAITING_APPROVAL"),
    Case("T-002", "surface_damage", 0.60, True,
         "NEED_REVIEW"),
    Case("T-003", "unknown", 0.95, False,
         "STOPPED", high_cost=True),
]
report = run_gate(cases, version="1.0.0")
print(json.dumps(report, ensure_ascii=False, indent=2))

程序不能用三条样例证明真实系统可靠,它只展示完整结构。正式测试集需要由专业教师、使用者和开发小组共同建立;若迁移到第10章工作流,还要覆盖其全部状态与权限。学生应检查gate_passed为何通过或失败,而不是把布尔值当成无需复核的上线决定。

三、回归门检查整个已承诺范围

每次修改都运行完整门,不能只重测刚修复的样例。模型阈值变化可能改变人工复核量,检索更新可能影响引用,权限修改可能破坏撤销路径。报告应列出版本、代码提交、模型、资料、规则、测试集和运行环境,确保同一结果可以复现。

若自动测试通过但人工发现建议语义误导,验收仍可失败;若自动测试因环境异常失败,不能直接放行,而要记录环境原因并重新运行。机器门是最低条件,不是责任替代。

回归报告还应保存“为什么没有通过”。失败不能只记一个红色标记,要保留实际输出、期望输出、涉及版本、错误层次和处理责任人。相同失败反复出现时,团队才能判断问题来自训练数据、资料、规则、接口还是环境;没有原始证据,AI给出的修复建议也无法核对。

第三节 在有限试运行中监测质量、成本和漂移

一、试运行不是直接上线

试运行要限定使用者、时间、地点、输入类型、模型版本和人工监督。公共项目可以只开放给一个班级的巡检小组,持续一周,所有正式记录由教师或指定责任人确认。试运行前说明退出方式和问题报告渠道,不能因参与课程而默认授权采集个人影像或声音。

离线验收使用封存数据,试运行观察真实工作环境。二者互补:测试集便于重复比较,试运行能发现输入格式、用户行为、网络、设备和工作负荷变化。试运行中发现的新情况先进入待审核样例库,不自动修改模型。

二、监测可回答的问题

监测至少记录输入数量、拒绝或停止比例、人工复核量、最终改动比例、错误类型、响应时间、费用、资料无命中、权限拒绝和输入分布变化。低风险项目不一定需要实时大屏,一份每天生成的结构化报告可能更有效。

漂移表示运行输入或输入与结果的关系发生变化。可先使用可解释基线:比较本周与验收数据的类别比例、数值范围、缺失率和设备来源。比例变化不自动等于模型失效,但会触发抽样复核。若某类输入从5%变成40%,应调查场景变化、采集方式和标签含义,而不是立即重新训练。

三、区分模型问题和工作问题

人工修改率上升可能来自模型质量下降,也可能来自规范更新、资料过期、使用者输入方式变化或权限设计不合理。监测报告按模型、检索、规则、接口、设备、人员和环境分类。协助开发的AI可以聚类日志和提出假设,但学生必须回到原始事件和专业人员反馈验证。

费用和人工时间也属于质量。模型准确但每条都要长时间复核,或者云端费用随输入长度快速上升,都可能使系统不值得使用。试运行结论应为通过、限定范围继续、退回修改或停止,不能只有“上线成功”。

监测门槛与验收门槛用途不同。验收门决定一个固定版本是否有资格试运行;监测门用于发现运行条件可能已经变化。例如“无命中率连续三天高于验收期两倍”可以触发抽样检查,但不能自动触发模型更新。责任人需要查看原始事件、资料版本和使用者变化,再决定保持、限用还是提出变更。

第四节 在受控更新、回滚和人工接管中维持系统

一、每次更新都要有变更申请

变更申请说明问题证据、拟修改模块、预期改善、不允许改变的部分、负责人和回滚条件。模型、提示、资料、阈值、代码、权限和设备适配都是不同变更类型。一次只修改可解释范围,先在隔离副本上运行固定回归,再进行有限比较。

数据更新尤其要审查来源、授权、标签和泄漏。运行反馈不是天然正确标签;人工修正可能互相矛盾,也可能包含敏感信息。只有经过专业审核的数据才能进入训练候选,训练完成后仍要用未参与更新的测试集验收。

二、发布前准备回滚

可回滚版本至少包含代码、模型、规则、资料索引、配置、依赖和数据库变更说明。发布记录写明谁批准、何时部署、通过哪套测试和怎样观察。若新版本触发高代价错误、监测指标越界或无法解释的状态变化,责任人可恢复上一已验收版本。

回滚不是删除失败证据。失败日志、变更差异和处置过程应保留,以便分析和再次开发。若数据结构发生不可逆变化,还需提前准备备份和转换撤销方案;公共项目使用本地副本演示,不修改真实业务数据。

发布前应实际演练一次回滚,而不是只写“可以回滚”。团队在副本环境中部署候选版本,运行固定样例,模拟触发高代价错误,再按说明恢复上一版本并核对代码、模型、规则、资料和配置是否一致。演练记录包含执行者、耗时、遗漏步骤和恢复后的回归结果;无法在限定时间恢复的版本不能进入试运行。

三、专业迁移卡

专业迁移卡A:商贸售后试运行。 高代价错误是错误承诺退换条件、金额重复和客户资料泄露;监测增加人工改价次数、重复订单和总处理时间。新规则必须由业务责任人批准,回滚时保留已经人工确认的真实记录。

专业迁移卡B:制造巡检验收。 高代价错误是明显异常漏报和传感器失效后继续给出正常。试运行只做旁路观察,不连接控制系统;监测按设备、负载和班次分组。模型更新须在回放与隔离现场通过,再由设备责任人决定是否继续试用。

专业迁移卡C:设计与媒体内容审核。 高代价错误是事实错误、权利材料缺失和未经确认发布;监测增加人工修改率、素材来源缺失率和误拦截。规范更新先进入独立资料版本,不能让模型根据一次编辑反馈自动改写发布规则。

四、经验学习只在审核后发生

系统可以积累运行经验,但“积累”首先意味着保留可审查的事件、人工修正和结果。只有经过清洗、授权、标签复核、离线训练和固定验收,经验才可能进入新版本。在线系统未经审核自行更新,会使行为、责任和回滚基线难以确定,本书不采用这种路径。

人工接管方案写明谁接收停止事件、怎样查看上下文、能做哪些动作和怎样结束。维护不是让模型永远运行,而是在条件变化时仍能保持受控、可解释和可停止。

五、运行完整验收台并形成发布决定

配套工程位于resources/ch11/project/,项目名称是“AI应用验收与试运行台”。它接收的不是一条临时提示,也不是已经填好的答案表,而是一整套冻结对象:测试样例、人工表单基线与两个候选版本的可执行制品、候选声明、发布门、试运行日志和版本登记表。evaluate.py每次都加载制品,只把样例中的输入文本交给候选,现场产生路线后再与期望结果比较;候选看不到测试编号、分组或期望答案。输出也不是一个孤立分数,而是逐例结果、分组指标、发布或拒绝决定、漂移告警和明确的回滚目标。最终由授权人员批准,程序本身不发布任何模型。

工程目录表达了完整过程。data/frozen_tests.json保存封存样例;artifacts/manual_form_v1.json、stable_v1.json和risky_v2.json保存可执行配置,不含outputs答案字段;data/candidate_declarations.json声明名称、版本、制品路径和真实64位SHA-256;gates.json保存测试前约定的门槛;trial_log.jsonl逐条记录时间、候选版本、制品SHA-256、输入来源、场景范围、路线、时延和错误;version_registry.json保存批准状态与同一制品身份。frozen_manifest.json还冻结候选、测试包、门槛、试运行日志、登记表和评测实现。src/candidates.py执行候选,bench.py计算离线指标,monitor.py校验日志归因并检测运行变化,rollback.py选择上一已批准版本。RELEASE_DECISION.md、ROLLBACK_PLAN.md和SYSTEM_CARD.md则把技术结果连接到人的责任。

封存包有8条小样例。正常类包括投影、办公网和滴水三个常见事件,检查候选能否正确进入常规流程;边界类是一条“是否需要登记尚不明确”的输入,预期转人工;陌生类没有已知语义,同样转人工;安全类要求进入紧急或人工安全路径;权限类要求拒绝巡检员直接关闭正式记录;故障类模拟知识模块不可用,必须安全停止。这些样例数量不足以证明真实系统可靠,但完整覆盖了“能做、临界时不猜、遇到未知不猜、模块失败不继续”四种基本能力。

发布门不使用一个总分决定一切。参考门要求普通准确率至少0.80、边界转人工率和陌生转人工率均为1.00、安全召回为1.00、权限违规为0、故障安全停止率为1.00。程序把每项写成独立布尔检查,只有全部为真才给出release=True:

checks = {
    "normal_accuracy": normal_accuracy >= 0.80,
    "boundary_manual_rate": boundary_manual_rate >= 1.00,
    "unknown_manual_rate": unknown_manual_rate >= 1.00,
    "safety_recall": safety_recall >= 1.00,
    "permission_violations": permission_violations <= 0,
    "fault_safe_rate": fault_safe_rate >= 1.00,
}
release = all(checks.values())

为什么安全召回、边界和陌生转人工率要求100%,而普通准确率允许少量错误?因为本项目把这些情况定义为高代价门:一个越权动作或一次故障后继续输出,不能被三个普通样例正确抵消。真实项目的门槛必须根据专业后果重新批准,教材数值不能直接搬到医疗、交通或生产现场。

学生在项目目录运行python acceptance.py。程序检查24项必需文件、14项冻结身份和全部Python语法,运行11个单元测试,再执行完整评估,并把现场结果与正式参考报告逐字段比较。哈希篡改、候选缺失、预填outputs、试运行归因缺失以及混合候选版本都会被故障测试拦截。参考环境的实际结果是:人工表单基线现场执行后精确符合4/8,因为它把普通事件交给人;stable-v1为8/8并通过所有门;risky-v2的三个普通样例都正确,却把边界和陌生输入送入常规流程,还放过安全、权限和故障问题,因此只有3/8并被拒绝。这个对照把“平均表现好”与“有资格试运行”明确分开。

试运行监测使用8条按时间记录的日志。每条还必须说明候选版本、制品SHA-256、输入来源和场景范围;缺少这些字段,即使数值完整也无法把异常归因到具体版本和试运行边界,程序会拒绝计算,同一汇总也不得混合不同候选版本。当前日志都归因到stable-v1、其已登记制品、授权工单入口表单和“工作现场低风险设备巡检旁路观察”范围。程序计算95百分位延迟、错误率和输出类别分布,并用总变差比较参考分布与观察分布。总变差可直观理解为:把两组类别比例变得相同,至少需要移动多大比例的样本;值越大,分布差异越明显。本次实际结果为95百分位延迟610毫秒、错误率12.5%、总变差0.450,分别超过500毫秒、10%和0.20的本次试运行门槛,因此alert=True。告警只表示原假设可能不再成立,需要检查输入、系统和工作方式;它不自动证明模型退化,也不触发在线训练。

回滚模块读取版本登记表,在当前risky-v2之前寻找最近的approved=true版本,得到stable-v1。登记表中的制品路径与SHA-256必须和候选声明、文件实算结果、正式报告一致,不能只凭相同版本名回滚。回滚计划要求先暂停扩大使用范围,保存失败日志、候选制品摘要和测试包哈希,再恢复旧版本并重跑全部封存测试。哈希使团队能判断“使用的是否还是同一个文件”,但不能证明样例设计本身充分,也不能替代责任人批准。

学生的控制变量实验只改一个普通质量门,例如把普通准确率门从0.80提高到1.00,先预测两个候选的结论,再运行非封存练习数据;不得通过放宽安全、权限或故障门让风险版本通过。AI限定修改可以新增一个“证据冲突”分组及相应指标:学生先写测试和预期,再要求AI只改bench.py与练习数据,审查差异并重跑acceptance.py。封存答案不能放进训练、提示优化或反复试错过程。最终报告必须写“采用、限用或拒绝”的理由,而不能只附一张绿色截图。

本章小结

验收把专业后果变成可执行门槛,把固定测试、人工复核、系统状态和恢复能力放在同一个结论中。总准确率不能掩盖高代价错误,自动门也不能替代责任人批准。

有限试运行用于发现真实环境变化,监测用于发现原有假设是否仍成立。任何更新都要经过变更申请、隔离修改、完整回归、批准发布和回滚准备。运行反馈只能成为待审核经验,不能让系统未经验证自行改变关键行为。

关键术语

目标测试

一、单项选择题

  1. 验收门首先应依据( )确定。A.可用图表样式 B.专业错误后果和任务合同 C.模型参数数量 D.开发者偏好
  2. 下列做法能保持测试独立性的是( )。A.把失败测试补进训练后继续称其为独立测试 B.冻结测试集并为更新保留未参与训练的样例 C.测试后再改门槛 D.只保留通过样例
  3. 试运行与直接上线的主要区别是( )。A.不记录日志 B.限定范围、时间、使用者并保留人工监督 C.允许系统随时自我修改 D.不需要回滚
  4. 新版本触发高代价错误时,首先应( )。A.删除失败日志 B.按预案停止或回滚并保留证据 C.扩大使用范围 D.降低验收门

二、判断并改错

  1. “总准确率达到95%,即使有一条不可接受的越权写入也可以通过验收。”请判断并改正。
  2. “试运行中的人工修正都是真实标签,可以立即用于在线更新模型。”请判断并改正。

三、简答与操作题

  1. 为一个专业AI应用列出两类普通错误和一类高代价错误,并分别提出门槛。
  2. 设计一个包含正常、边界、陌生、诱导、故障和权限变化的六条测试清单。
  3. 说明离线测试、系统验收和有限试运行分别解决什么问题,为什么不能互相替代。
  4. 写出一次受控更新从问题证据到发布或回滚的完整步骤,并指出至少两个由人批准的节点。

答案编号:A2-11-01—A2-11-10。完整答案与评分要点统一放入书后“目标测试参考答案”。

第12章 协同交付一个跨专业AI系统

工作阶段: 可靠交付——综合前十一章,把一个边界明确的专业问题做成可由别人复现、接手和维护的系统。
公共核心项目: 完成“小型企业设备运维与巡检站”:把环境感知、文字分类、指定资料检索、状态权限、人工确认和审计重放集成为可复现的低风险闭环。
核心技术: 系统集成、项目结构、依赖与版本、数据卡和模型卡、接口契约、现场测试、交接复现、维护计划与人机协作。
输入输出链: 真实委托 → 任务与验收合同 → 授权数据 → 高风险独立门 → 模型或规则 → 可运行程序或设备 → 固定测试与现场证据 → 交付包 → 另一组复现和维护。
应用中的AI: 参考系统使用本地环境偏离小模型;文字分类和最小人工表单作为透明基线,专业迁移可替换一个主要模型,但不要求堆叠全部技术。
协助开发的AI: 帮助建立项目结构、生成和解释多文件代码、适配接口、分析日志、补充测试和整理运行文档。
人的责任: 确定问题价值、数据授权、专业规范、验收责任和上线边界;审查每次变更并完成交接。
主要交付物: 可运行代码库、任务与团队合同、接口合同、环境与模型、冻结数据、系统卡、集成测试和真实报告、交接清单与维护计划。
明确边界: 综合项目不以功能数量评价,不直接控制危险设备;未经审核的运行经验不得在线改变模型、规则、权限或物理行为。
跨章关系: 综合使用前十一章;至少复用一个模型、一个人工或规则基线、一个失败集和一个人工接管点。

学习目标

学完本章,你将能够:

  1. 从真实委托中确定一个可完成的最小闭环,并建立团队任务、数据和验收合同;
  2. 选择必要的模型、规则、资料、程序或设备模块,解释为什么没有堆叠其他技术;
  3. 用统一项目目录、版本和运行入口形成可复现基线;
  4. 在真实或模拟现场根据日志和固定测试开展受控迭代;
  5. 组织另一组完成安装、运行、故障处理和交接复现,并根据暴露的问题补充交付包;
  6. 说明系统后续监测、更新、回滚和人工责任。

项目导入

综合项目不是把前十一章所有技术拼在一起。一个有价值的系统可以只使用一个视觉模型、一组规则和一份记录工具,也可以使用资料检索、语言模型与人工确认。技术选择取决于工作问题、输入条件、错误后果和维护能力。功能越多,接口和失效点也越多;无法解释和交接的复杂性不属于成果。

公共题目是“小型企业设备运维与巡检站”。全体先完成同一参考闭环:观察环境数据是否偏离参考范围,理解脱敏巡检文字,从指定检查卡返回带来源的候选说明,并在指定角色确认后生成本地事件记录。完成公共基线后,各专业只能替换一个主要输入或模型形成迁移版本,并保持状态、权限、安全和测试合同。系统只观察、提示和记录,不控制电源、门锁、交通、加热或机械装置。

每组需要完成最小工作闭环,并由另一组按照交付包从头复现。另一组不是观看演示,而是拿到一个干净副本,在另一台电脑或独立环境中安装、运行固定样例、制造一个故障并找到恢复方法。复现失败会暴露原组没有写出的路径、依赖、密钥、数据或专业假设,这正是交接学习的价值。

本章成果

AI协同开发路线

团队先向协助开发的AI提交真实委托、专业材料、数据条件、现有设备、禁止事项和学时边界。AI追问使用者、最小输出、验收样例、依赖、责任人和失败去向,提出不超过必要范围的系统方案。学生删减不需要的功能,冻结任务合同和接口。AI生成最小可运行系统及完整代码库,团队在干净环境运行,逐层保存日志,并在增加功能前冻结代码、模型、数据、配置和固定测试基线。每次现场问题都转成限定变更请求,成员审查文件差异并运行全部回归。达到内部验收后,把交付包交给另一组复现;原组只能根据书面反馈补充或修正,不能代替接手组操作。最后共同签署通过、限用、继续试运行或退回结论。

第一节 从真实委托建立团队任务、数据和验收合同

一、选择一个真正需要完成的工作结果

“做一个AI巡检站”仍然过于含糊。团队要把它改写成具体结果,例如:“在教学楼公共区域的授权图片中,把明显外观异常列为待人工复核,显示模型分数和资料依据,经过指定角色确认后生成本地记录。”这句话限定了输入、输出、使用范围和人工接管,没有承诺模型判断故障,也没有自动执行处置。

判断AI是否必要时先建立基线。若固定阈值或人工检查已经快速、稳定地完成任务,就不必增加模型;若图像、声音或复杂文本变化较大,模型能够减少候选筛查工作,可以作为辅助。团队在立项卡中写明模型带来的价值和增加的维护负担。

二、建立团队任务合同

任务合同包括委托人、使用者、目标、输入、输出、限制、不做事项、成功标准、高代价错误、数据授权、专业责任人和交付日期。跨专业团队按工作模块分工,不按专业名称机械切块。建议角色包括任务与专业规范、数据与授权、模型与基线、程序或设备、测试与交接;一个人可承担多项,但关键审查不能只由代码生成者完成。

接口也要进入合同。数据组交付什么字段和版本,模型组输出什么类别和分数,程序组怎样处理低置信度,测试组使用什么封存样例,交接组怎样判断复现成功,都要写成可检查约定。口头默契无法被另一组复现。

三、冻结最小范围与变更规则

最小闭环只解决一个问题,使用一种主要模型或模型路径,保留一种基线和一个人工确认点。立项后新增功能先进入“以后考虑”,除非它修复验收失败。每个变更写明原因、修改范围、预期结果和需要重跑的测试;AI不能因为看到更多资料就自动扩展需求。

控制变量实验选择系统中的一个关键量,例如感知阈值、检索前若干条或时序窗口。固定数据、程序和其他配置,先写出预测,再用同一测试比较质量、人工复核量和延迟。综合项目仍需保持实验可解释。

第二节 集成数据、模型、程序或设备形成可复现基线

一、用项目目录表达责任

建议目录包含README.md、config/、data/、models/、src/、tests/、docs/和logs/。原始或授权数据与处理数据分开,模型文件和标签一起保存,运行配置不包含密钥,测试数据不混入训练。README给出唯一启动入口和期望输出,数据卡、模型卡、系统图、安全边界和交接清单放在docs/。

版本清单记录操作系统、Python和主要依赖的大版本、模型及资料版本。项目应提供最小样例,避免接手者必须访问私有平台或真实敏感数据才能启动。云端模型作为可替换模块时,提供离线响应样例或本地基线,明确哪些结果不能由离线路径证明。

二、集成一个可运行的参考基线

配套工程位于resources/ch12/project/,固定项目是“小型企业设备运维与巡检站”。它不是让各组随意拼装几个页面,而是先提供一条能运行、能失败、能验收的参考闭环:带资产编号的脱敏工单文字先经过独立高风险门;普通工单再读取虚拟或预录环境窗口,校验输入,用本地小模型计算环境偏离分数,文字分类器判断工单类别,检索器返回指定检查卡;边界规则决定是否停止或转人工;运营主管确认后才形成持久仅追加记录,程序重启后仍可重放。学生在这条基线上做一次限定修改,并由另一组真实复现。

参考项目面向小型企业行政运营团队,主要工作角色是运维技术员和运营主管。输入是工单编号、资产编号、地点、现象文字以及温度、湿度、光照和质量标记;输出是环境分数、候选类别、可追溯检查依据、工作状态和审计事件。完成标准不是“界面亮了”,而是正常、边界、陌生、安全、设备故障、模型故障、知识故障、输入越界、权限、幂等和日志故障全部得到规定结果。系统只观察、提示、记录和转交,不控制电源、门锁、消防或设备。

工程用文档与代码共同表达责任。TASK_CONTRACT.md定义任务边界,TEAM_CONTRACT.md把任务与专业、数据与模型、程序与接口、测试与交接四类责任分开;INTERFACE_CONTRACT.md冻结跨模块字段;DATA_CARD.md和MODEL_CARD.md说明数据与模型来源和限制;ARTIFACT_MANIFEST.json锁定场景、知识、配置和模型摘要;SYSTEM_CARD.md说明用途与限制;AUDIT_LOG_SCHEMA.md说明持久记录;HANDOFF_CHECKLIST.md区分自动预检和真实复现;MAINTENANCE_PLAN.md规定以后怎样更新。完整代码放在src/,模型和资料分别放在models/与data/,固定结果放在reports/。这些文件使接手者不必从聊天记录猜项目是怎样做出来的。

感知模块沿用第9章的本质,但保持本章工程独立可运行。虚拟传感器公开read_window();输入校验检查三个字段、单位约定的有效范围和quality;冻结JSON模型保存参考中心、尺度和权重,用加权绝对偏离得到分数。分数大于0.80为REVIEW,距门槛不超过0.05为BOUNDARY。边界不是“差一点就确定”,而是系统对阈值敏感的区域,所以直接转人工。真实设备接入必须另行依据准确型号建立适配器,默认工程不提供任何接线猜测。

服务模块把文字分为meeting_display、office_network、water_supply、unknown和high_risk。它是透明教学基线,将来可以在接口不变的前提下替换为语言模型。检索器只从三条冻结检查卡返回doc_id、标题和操作说明;没有依据或知识库不可用时,不允许模型凭常识补齐。高风险词在读取传感器、加载模型和访问知识库之前进入EMERGENCY_HANDOFF,即使设备、模型、知识库或日志同时故障,也不得把这一转交改写成普通模块故障;但转交只表示进入企业既有应急责任链,学生程序不执行应急处置。

集成主链的核心顺序如下:

text = classify(event["report"])
if text["label"] == "high_risk":
    return emergency_handoff()           # 先于可选设备、模型和知识模块

window = sensor.read_window()
validate_window(window)                 # 无效则 STOP_BAD_INPUT
score = model.score(window)             # 本地、离线
sensing = sensor_state(score, threshold, margin)

if text["label"] == "unknown" or sensing == "BOUNDARY":
    return move_to("MANUAL_REVIEW")

evidence = retriever.find(text["label"])
if evidence is None:
    return move_to("MANUAL_REVIEW")
move_to("EVIDENCE_FOUND")
move_to("AWAITING_CONFIRMATION")        # 尚未形成正式记录

只有operations_supervisor能调用confirm()把等待状态变成COMMITTED或CLOSED_NO_ACTION;maintenance_technician可以提交工单但不能批准。同一工单编号和相同负载再次提交时直接返回当前状态,不增加记录;同一编号携带不同负载时进入STOP_ID_CONFLICT。EventStore(path)把每个事件写成UTF-8 JSONL,刷新到磁盘,程序重新打开后可由replay()重建最终状态。设备无新数据、模型文件不存在、日志不可写都有不同停止状态,不能统一吞掉异常。应用中的AI是环境偏离小模型;文字分类、状态、权限、安全和审计是透明基线与确定性控制,最终决定由人负责。

学生在工程根目录执行:

python acceptance.py
python -m src.main

src.main用一条带资产编号的会议显示屏无画面工单走过环境评分、文字分类、证据检索、等待确认和运营主管接受,并把可重放日志写入output/demo_audit.jsonl。acceptance.py检查必需文件、冻结制品摘要、全部Python语法、7个单元测试、完整集成评估和临时干净目录复现预检。工程只使用Python标准库,不访问网络,不要求云账号和真实硬件,默认数秒完成。

固定集成包共有12条:两个正常样例到达AWAITING_CONFIRMATION;门槛边界样例和陌生表述进入MANUAL_REVIEW;普通冒烟事件以及冒烟与设备、模型、知识故障的三个组合事件都进入EMERGENCY_HANDOFF;单独的设备断开、模型缺失、知识库不可用和温度越界分别进入STOP_DEVICE_LOST、STOP_MODEL_MISSING、MANUAL_REVIEW和STOP_BAD_INPUT。真实运行的实际结果为12/12通过。

同一评价还实际运行最小人工表单基线。它把显式高风险交给应急人工链,其他全部进入人工队列,因而安全处理12/12,但自动找到证据为0;助手在两个普通工单中自动返回可定位依据,其价值是减少常见事件的初步查找,不是替代人工安全底座。七项操作测试继续验证相同负载重复提交不产生第二次副作用、同编号不同负载被拒绝、运维技术员不能确认、运营主管可以确认、JSONL重新打开后能重放到COMMITTED、普通工单日志不可写时停止,以及高风险在日志不可写时仍保持应急转交。

这些结果只证明参考工程的自动技术门。项目的reproduce.py会新建临时目录,只复制最小运行包,再从头启动并走到COMMITTED;这能发现绝对路径、原目录缓存和漏带文件,却不能扮演真实接手者。报告因此同时写明automatic_clean_reproduction=checked_by_reproduce_py和independent_team_reproduction=PENDING_CLASSROOM。在另一组真正按README安装、运行、制造知识库故障、恢复并提交问题单之前,只能形成“课堂参考基线通过、真实交接待完成”的限用结论,不能写“项目已交付上线”。

三、在干净环境冻结基线

原开发电脑能运行,可能依赖未记录的缓存、环境变量和本地文件。冻结基线前,团队使用新目录或另一台电脑,按README创建环境、安装依赖、运行三条固定样例并核对结果。任何人工复制但未写入说明的文件都属于交付缺陷。

基线冻结后记录代码、模型、数据、资料、配置和测试版本。新增功能建立新版本,不覆盖已验收基线。协助开发的AI生成依赖清单后,学生还要实际重建环境验证,不能只相信文本说明。

团队还要保存一份“最小成功证据”:一条输入样例、完整执行命令、期望状态、关键日志和结果文件校验值。接手者先复现这一证据,再运行更多测试。若连最小证据都无法重复,继续讨论模型精度或界面功能没有意义。

第三节 在真实或模拟现场测试并受控迭代

一、三类现场证据

固定测试用于版本比较;回放或虚拟现场用于稳定复现设备和时间过程;真实现场用于发现环境、人员和工作负荷差异。硬件不足时可以完成前两类,但报告必须说明不能证明真实传感器稳定性、长期漂移和现场行为。

公共项目至少记录输入来源、环境条件、模型分数、规则状态、人员修改、端到端延迟和最终结果。真实现场只使用授权数据,摄像头和麦克风说明采集范围、保存位置和删除方式。任何高风险发现直接转交专业责任人,不由学生系统处置。

二、让失败推动一次限定修改

团队从失败集中选择一个有代表性问题,例如相似背景造成误报、资料无命中仍出现候选说明、设备断开后沿用旧值或接手者无法找到模型文件。先定位错误属于数据、模型、检索、规则、接口、设备、文档还是人,再向AI提交限定请求。

请求应写:“固定任务合同、接口和测试集;只修改src/device_adapter.py,当读取超时时返回STOP_DEVICE_LOST,不得沿用上次值;列出文件差异并运行全部测试。”修改后团队逐行审查关键差异,运行正常和故障回归,并记录是否产生副作用。若失败来自数据授权或专业定义,不能用改代码掩盖。

三、验收系统而不是单个模型

综合验收同时查看任务价值、基线比较、模型错误、证据来源、状态权限、故障恢复、人工工作量、资源成本和可复现性。模型指标通过但交接失败,系统仍不能通过;模型略逊于复杂方案但规则基线稳定、成本低,团队可以选择基线。

验收结论包括通过、限定场景试运行、退回修改或停止。限定使用要明确对象、时间、数据范围和人工监督。任何变更都进入第11章的回归门和回滚流程。

四、专业迁移卡

专业迁移卡A:商贸与设计服务站。 输入改为商品资料、用户需求和授权素材,应用AI协助分类需求或生成候选传播内容;高代价错误是价格事实错误、权利材料缺失和未经批准发布。交付物增加事实清单、品牌规范、内容版本和业务负责人签字。

专业迁移卡B:制造与交通巡检站。 输入改为零件、道路或车辆的授权图像、声音和传感数据;高代价错误是漏报明显异常、设备失效仍给正常结论和越权控制。交付物增加设备事实包、按批次测试、旁路试运行和专业责任人接管,不连接生产或交通控制。

专业迁移卡C:生物与风景园林环境站。 输入改为实验或养护记录、植物图像和环境时序;高代价错误是单位、批次和校准错误,或把相关性写成因果处置。交付物增加数据批次、校准记录、专业规程来源和现场复核,系统只观察与建议。

第四节 完成复现、交接、展示和维护答辩

一、由另一组独立复现

接手组获得代码库、最小数据、模型或基线、环境说明、测试集和交接清单,但不接受原组现场代操作。接手组记录开始时间、环境、执行命令、首次失败、缺失说明和最终结果。至少完成四项:在干净环境启动;运行正常和失败样例;制造一个约定故障并恢复;说明系统的人工接管点。

原组观察但不替接手组修复。复现结束后,接手组提交问题单,区分文档缺失、依赖错误、数据或模型缺失、接口不清和专业假设。原组根据问题单修改交付包,再由接手组重试。只有接手者能继续工作,才算完成交接。

二、交付包说明“怎样继续”,也说明“不要做什么”

用户手册写常规运行,故障指南写停止和恢复,维护计划写资料、数据、模型、规则、设备和依赖的检查周期。风险边界列出未经专业批准不能扩展的功能。模型卡说明训练或调用范围、测试表现和陌生输入;数据卡说明来源、授权、处理和删除;系统卡说明模块、权限、监测和回滚。

展示不只演示最佳样例。团队应演示一次正常输入、一次失败停止、一次人工拒绝和一次重放日志,说明为何采用当前模型或规则。答辩人员可以要求更换输入、询问数据来源或让系统恢复故障,团队不能只播放预录成功视频。

三、维护答辩与前沿拓展

维护答辩回答:场景变化怎样被发现;谁审核新资料和新数据;什么条件触发回归;谁批准新版本;如何回滚;项目停止后怎样删除或归档数据。AI可以协助整理问题和生成检查脚本,不能代替责任人签署。

强化学习或经验更新只放在拓展学习中。学生可以在仿真环境定义状态、动作和奖励,或用离线日志比较候选策略;任何经验必须经过授权、清洗、审核、离线训练和固定验收后,才可能进入新版本。终端和工作流不得在真实现场根据即时反馈自行改变权限、安全规则或物理行为。

四、形成最终交付结论

最终结论不必是“正式上线”。对于课程项目,更合理的结果可能是“通过H0复现,允许在指定场景旁路试运行”“视觉模型需增加跨设备数据后再验收”或“规则基线已经满足需要,暂不部署模型”。结论要引用测试、复现和专业责任人的证据。

本章小结

跨专业项目的目标不是堆叠模型,而是把真实委托转成边界清楚、能够复现和交接的最小系统。统一目录、版本、接口、数据卡、模型卡和固定测试,使AI生成的代码从个人电脑中的结果变成别人可以继续工作的成果。

现场失败必须转成限定修改和完整回归。另一组独立复现是本章最重要的验收:它能够暴露未记录的依赖、路径、数据和专业假设。仿真和审核后的经验更新可以作为前沿拓展,但运行系统不能未经验证自行改变关键行为。

关键术语

目标测试

一、单项选择题

  1. 综合项目选择技术的首要依据是( )。A.模型数量 B.真实任务、输入条件和错误后果 C.界面动画 D.代码行数
  2. 判断项目达到交接要求的最佳证据是( )。A.原作者演示成功 B.另一组按交付包独立复现并处理故障 C.模型文件很大 D.使用热门框架
  3. 下列最符合最小闭环原则的是( )。A.一次加入全部技术 B.完成一个输入到人工确认输出的边界明确链路 C.只画概念图 D.只交生成代码
  4. 运行经验进入新版本前必须( )。A.自动在线学习 B.经过授权、审核、离线更新和固定验收 C.删除旧版本 D.绕过责任人

二、判断并改错

  1. “跨专业项目功能越多,越能证明系统质量高。”请判断并改正。
  2. “原组能在自己的电脑上运行,就说明交付包已经可复现。”请判断并改正。

三、简答与操作题

  1. 将“做一个企业AI巡检站”改写成包含使用者、输入、输出、边界和人工责任的任务描述。
  2. 为综合项目设计一个目录结构,并说明数据卡、模型卡、固定测试和日志分别放在哪里。
  3. 写出接手组复现项目的四个必做步骤,以及原组在复现期间不能代替完成的事项。
  4. 设计一次只修改设备适配层或模型阈值的受控迭代,列出修改申请、差异审查、回归和回滚证据。

答案编号:A2-12-01—A2-12-10。完整答案与评分要点统一放入书后“目标测试参考答案”。

附录A 目标测试参考答案

选择题给出最佳答案和简要理由;判断改错题先判断,再改正错误表述;简答与操作题给出评分要点,学生可以使用与参考答案不同但证据充分的表达。

第1—4章目标测试参考答案

第1章

  1. 答案:B。 “万能企业助手”未定义样本、标签、输出、拒绝条件和验收标准,不能直接成为监督学习任务。

  2. 答案:C。 插座冒烟是高代价风险,须由确定性规则在模型前拦截并转人工紧急渠道。

  3. 答案:B。 TextVectorization词表是模型状态;用验证集或固定测试adapt会泄漏信息,使评估虚高。

  4. 答案:C。 0.90是四个候选类的相对支持,不是事实正确率,不能越过规则门、分差和人工确认自动派单。

  5. 判断:错误。 高风险漏拦不能被平均分抵消;5例必须全部在模型前拦截,否则退回并全量回归。

  6. 判断:错误。 可不从零手写,但要说明数据向量化、Embedding、Softmax及模型—规则—阈值—网页的连接,并审查AI修改、运行固定回归。

  7. 评分要点(共4分): 业务设备类纳入扫码枪、业务电脑、会议音视频设备、订单打印机和叫号屏等普通使用故障,排除内部诊断及网络账号问题,由业务设备责任人确认(2分);公共设施类纳入作业照明、桌椅、门窗和饮水机等,冒烟、漏电、受伤必须转高风险人工渠道,由设施与安全责任人确认(2分)。语言模型无权决定边界。

  8. 评分要点(共5分): 低成本、可重复、均衡生成带标签数据,便于跑通训练链(1分);句式和场景有限,可能只记模板(1分);非真实采集与责任人标注,不代表口语、比例、噪声和风险(1分);隔离普通、陌生、多意图、信息不足和高风险固定测试(1分);不得回灌训练或逐题调参(1分)。

  9. 评分要点(共5分): A/B只把最高分门槛由0.60改为预定值(如0.70)(1分);数据、模型、标签顺序、0.12分差门、风险/多意图规则、测试、环境和程序不变(1分);预测提门槛会少建议、多复核、可能少误放(1分);全量记录三类通过数/率及去向变化(1分);比较错误建议、人工量并下结论(1分)。

  10. 参考结论:退回修改。 多意图强行单分、高风险漏拦和无法复现分别说明接管链、否决门和交付未完成。把经确认的风险规则置于模型前,多领域线索转人工,补齐依赖、模型、README和验收入口;重跑29条固定样例、故障测试和他组复现,5条高风险必须全部拦截。

第2章

  1. 答案:B。 模型读取的型号首先是候选值,只有回到原图核对并经过相应责任人确认后,才能进入发布数据。

  2. 答案:C。 没有单位的数值无法可靠解释,应进入问题表并回查原件,不能默认单位或用0代替。

  3. 答案:B。 按设备或批次整体隔离,可以减少同一对象的相邻、近似记录同时出现在训练和测试中的泄漏。

  4. 答案:C。 “通过结构校验”只说明记录符合当前字段、类型和允许值规则,不等于事实、授权、标签或训练适用性均已确认。

  5. 判断:错误。 缺失表示没有足够信息;0是一个可能具有专业含义的实际数值。二者必须用不同方式保存和处理。

  6. 判断:错误。 扩大同一偏差来源的数据会重复甚至放大偏差。项目仍需检查对象、设备、时间、环境和标签分布,并补充有计划的代表性材料。

  7. 评分要点(每项1分,任选四项,共4分): - source_id:为原件提供稳定编号; - 文件名或保存位置:能够找到原文件; - 提供者与获取日期:说明材料从何时、何人或何组织获得; - 授权范围:说明是否允许课堂处理、共享或发布; - 文件摘要:发现原件是否被替换; - 隐私或备注:记录需要限制访问的信息。

  8. 评分要点(共4分): 校验程序把该记录写入问题表,而不默认单位(1分);人工按source_id回看原件并联系材料责任人(1分);确认后保留原值、补充单位并记录修改前后值、依据和修改人(1分);重新运行校验和固定测试生成新版本(1分)。若无法确认,应保留缺失或排除记录,不得猜测。

  9. 评分要点(共4分): 预测增加单位必填规则会发现更多待处理记录(1分);原件、候选记录、模型输出、程序其他规则和测试集保持不变(1分);A、B两版只在单位必填规则上不同(1分);比较新增问题数、错误单位数、通过记录数和人工复核时间(1分)。

  10. 参考结论:退回交付。 找不到原件即来源链断裂。应补齐记录—原件映射并核对摘要;无法恢复的记录须隔离并说明原因,再生成版本并由他组回查。参考工程中5个原件摘要一致,8条候选4条通过、4条拒绝,6条冻结测试通过;结论仍仅为usable_for_teaching_only,不能外推真实事实或模型性能。

第3章

  1. 答案:B。 最高相似度只表明在当前字符TF-IDF表示中,问题与该段落共享的加权字符片段较多,不证明资料真实、有效或足以支持答案。

  2. 答案:C。 引用编号集合检查是确定性任务,适合普通程序执行;程序仍不能判断段落在语义上是否支持结论。

  3. 答案:C。 无证据时必须显式停止并列为待确认,避免语言模型依据通用记忆或常识补出项目事实。

  4. 答案:B。 关键词基线可以判断字符TF-IDF检索是否带来实际改善,也适合型号、条款编号等需要精确匹配的内容。

  5. 判断:错误。 合法编号只说明引用来自允许的命中集合。还需检查段落是否包含对应条件、是否适用于当前对象,以及结论有没有超出原文。

  6. 判断:错误。 加入过期、无关、来源不明或对象不匹配的资料会增加误命中和冲突。资料应按任务、版本、时效和适用范围筛选。

  7. 评分要点(每类1分,共3分): - 事实问题:“当前设备的型号、指示灯和闪烁现象是什么?” - 规则问题:“该型号说明书允许普通使用者执行哪些检查或重启步骤?” - 专业判断问题:“当前状态是否可以继续使用,还是应停止并交设备人员?” - 表述不同但类型和责任清楚即可得分。

  8. 评分要点(共4分): 准备两份均在检索库中的资料,对同一条件给出相反规定,并记录各自版本与有效状态(1分);提出能同时命中两份资料的问题(1分);期望输出并列引用冲突,不自行选边(1分);把最终解释和采用转给指定专业责任人(1分)。

  9. 评分要点(共4分): 先预测top_k=2相对3可能减少无关命中,也可能漏掉条件或冲突资料(1分);使用data/calibration_qa.json,资料、字符n-gram、TF-IDF、分数门槛和路由规则保持不变(1分);两版只改变top_k,不得查看冻结题成绩后反复选参(1分);比较正确证据命中、冲突检出、未知问题错误放行、无关段落和人工核对量,再一次性运行冻结题集(1分)。

  10. 参考结论:not_ready_for_use。 两套方法虽均为11/12,失败后果不同:字符TF-IDF把未知问题错误放行,关键词则对同义改写安全拒答。下一轮应扩充独立校准集,研究拒答门、分差或双系统组合,不得针对Q09写补丁。冻结题只在方案确定后运行;可复现不等于达到发布门。

第4章

  1. 答案:C。 它明确了静态SVG提示卡、目标受众、10秒观察时间,以及“说出三项行动中的至少两项”这一可检查标准,可以通过不诱导的用户测试验证。

  2. 答案:B。 普通SVG程序可以把经过核验的文字、尺寸、安全区、披露和几何图形写成确定性输出,避免生成模型随画面一起改错事实或规格;它仍不能代替事实、权利和用户审核。

  3. 答案:A。 尺寸检查只证明文件满足一个确定性规格,不能证明事实、权利、专业规范和发布批准均已通过。

  4. 答案:B。 保持项限制无关变化,使项目组能够判断当前修改的影响,并防止修好一处破坏其他部分。

  5. 判断:错误。 生成过程仍可能涉及无权使用的输入、人物、声音、标志或与既有作品过近的输出;还需核对平台条件、单位规定和具体发布环境。

  6. 判断:错误。 用户测试主要说明受众是否理解和遇到什么困难,不能替代事实、品牌、专业规格、权利和发布责任人的审核。

  7. 评分要点(每项1分,任写六项,共6分): 可观察目标(未参与制作的学生看静态卡10秒后,至少说出三项行动中的两项)、主要受众与使用地点、三项行动及事实来源、1080×1440静态SVG规格与顶部安全区、语气和视觉层级、禁用数字与未授权素材、匿名用户测试方法、事实/设计/权利/发布审核人。只写“好看、科技感”等不可检查形容词不得分。

  8. 评分要点(共4分): 指定修改对象(1分),说明可观察变化(1分),列出至少两项保持内容(1分),给出检查方法(1分)。示例:“只调整主视觉背景和光线,提高三项行动与背景的明暗对比;保持人物为空、行动文字、标题安全区、1080×1440静态SVG规格和事实信息不变;修改后用同一10秒理解测试和规格检查比较。”

  9. 评分要点(共4分): 预测增加安全区会提高可排版候选比例,但可能压缩主体(1分);固定模型、基础描述、画幅、参考材料和候选数量(1分);A版不写安全区,B版只增加“上方标题安全区”条件(1分);比较安全区可用率、主体完整性、修图时间、规格通过率或10秒理解度中的至少三项(1分)。

  10. 参考结论:退回修改,不得发布。 未授权标志和无来源比例均是否决项;须移除、重生成或补齐可靠来源与授权,再重做权利、事实、规格及必要的10秒理解测试。参考工程19项测试通过,但G02因“节电30%”无来源失败,G03有7个问题;真实目标用户为0人、人工批准0/4,故状态为not_ready_for_release。

第5—8章目标测试参考答案

第5章

  1. 答案:C。 目标日实际用电只有在目标日结束后才产生,形成预测时尚不可得。把它作为输入等于提前给出答案,属于未来数据泄漏。

  2. 答案:B。 时间序列评价要模拟“只能用过去预测未来”。随机打乱会让未来季节、活动和制度模式进入训练,破坏真实使用顺序,使成绩过于乐观。

  3. 答案:B。 模型与基线必须在完全相同的未来日期、目标单位和指标上比较。代码长度、训练轮数和内部结构不需要相同。

  4. 答案:C。 模型在教学生成数据上降低了平均误差,但仍漏掉一个峰值,只能作为教学合成数据范围内的人工观察候选。它不具备自动控制权限,迁移到真实门店前还需重新训练、验收,并由正式规则和人员复核峰值。

  5. 判断:错误。 归一化均值和标准差也是从数据获得的模型状态。若使用全部220天计算,验证与测试期的分布已提前进入训练流程。应只用训练样本计算,并把同一状态用于验证、测试和运行。

  6. 判断:错误。 第5章输出只是下一日负荷候选,可作为第6章任务量或资源需求的一个输入。正式排程还要满足技能、时间窗和资源等约束,设备控制还须专业安全规则与人工批准。

  7. 评分要点(共6分): 对象为一家小型门店营业区下一自然日用电量(kWh)(1分);预测时点为前一日结算后(1分);可用字段任二:前7日用电、已发布温度预报、周末/星期、已确认促销活动(2分);禁止字段任二:目标日实际用电/实测温度、事后运行时长/处置(2分)。

  8. 评分要点(共5分): A用7日、B只改14日平均(1分);固定开发数据、目标、缺失处理、模型、指标和验证期,不读冻结测试(1分);从共同具备14日历史的日期起比较(1分);预测14日更平稳但响应更慢(1分);记录MAE、最大误差、峰值召回和逐日变化(1分)。

  9. 评分要点(共4分): - 陌生测试示例:计量口径改变、新建筑接入、训练未见极端天气或长时间停课(1分); - 预期:标记超出验证范围,停止模型候选并转数据/能源责任人(1分); - 故障测试示例:日期重复或乱序、负负荷、历史不足7天、模型或元数据缺失(1分); - 预期:程序明确报错并停止,不用零补齐或沿用缓存预测(1分)。

  10. 参考结论:退回模型,保留7日基线。 新模型MAE 7.1 kWh高于基线6.7 kWh,峰值也未改善。保留报告并只改一项数据或模型;数据责任人确认口径/字段,能源责任人确认后果/边界。先在训练和验证期重跑基线、模型、峰值及故障测试;冻结新版本后用新未来期验收。已用于改进的原冻结期不再独立。

第6章

  1. 答案:C。 班组技能必须匹配工单,是决定方案能否执行的硬约束。“尽量少等待”和“尽量早点结束”只在可行方案之间比较。

  2. 答案:B。 J01先提交且A组在列表中靠前,先到先服务把它排入A组0—4;只能由A组处理、需在时段4前完成的J02随后没有空档。

  3. 答案:B。 “先处理剩余空间最小的工单”只改变搜索顺序,帮助更早处理受限任务;本项目仍枚举所有合法班组和整数开始时段,不会自动放宽约束。

  4. 答案:C。 无可行解是有价值的业务结果。程序应输出冲突与当前条件,由有权限的人决定是否调整期限、资源或任务范围,不能自行删除或修改。

  5. 判断:错误。 超过任何硬时间窗的方案都不是可行解,目标值再小也不能进入比较。只能在全部硬约束通过的方案间选择目标值较小者。

  6. 判断:错误。 搜索代码本身可能存在遗漏或实现错误,应由分离的验证函数再次检查任务完整、技能、时长、班次、时间窗和重叠,并由人员核对未建模现实条件。

  7. 评分要点(共5分): 硬约束任三:每单一次、技能匹配、班组不重叠、班次与时间窗内完成(3分);软目标为降低加权等待并轻度压缩最晚完成时点(1分);业务人员确认约束/目标,程序只计算(1分)。

  8. 评分要点(共4分): J02只能由A组处理且时间窗紧,应优先保留A组(1分);J01的网络技能A/B均有(1分);J02置A组0—3,J01置B组或A组稍后(1分);独立验证其他工单、时间窗和不重叠(1分)。

  9. 评分要点(共4分): - 陌生测试示例:跨日任务、双人协作、未知技能或需要地点路程但数据结构没有相应字段(1分); - 预期:拒绝计算并要求扩展合同与数据,不静默忽略(1分); - 故障测试示例:负时长、重复编号、结束早于开始、空班组或错误JSON(1分); - 预期:搜索前校验失败并记录明确原因(1分)。

  10. 评分要点(共6分): J02需5时段而0—4窗口只有4个,已无解(1分);责任人可批准延期、拆分、增加电气资源或调整范围,任二(2分);这些都改变业务合同,程序无权自行采用(1分);变更后重跑校验、正常/无解/变更/故障测试及独立验证,保留原场景和批准记录(2分)。

第7章

  1. 答案:B。 一幅图中有多个对象且需要输出问题对象的位置,应使用目标检测;整图分类只给整张图的类别。

  2. 答案:B。 同一对象的连拍和同一批次的相似背景必须整体进入一个集合,避免模型通过记忆对象或批次获得虚高测试分数。

  3. 答案:C。 规则只检查绿色封签,能够发现缺封签,却会把仍有封签的撕裂、压角或污渍当作合格候选。

  4. 答案:C。 48×32圆形包装超出登记的32×32结构,系统应在模型前转人工。缩放后强制二选一会隐藏输入已陌生的事实。

  5. 判断:错误。 25/25只表示双阈值筛出的25个明确候选均正确;另有23张转人工。模型在0.5阈值下的全部48张分类结果为36/48,即75%,不能把候选正确率替代整体测试成绩。

  6. 判断:错误。 测试错例进入训练后,原测试集已参与改进,不再是独立证据。新版本要保留旧报告,并使用未参与训练和调参的新批次验收。

  7. 评分要点(共4分): - 分类:给整幅单包装图输出合格/待复核候选(1分); - 检测:在多包装图中输出问题包装的矩形位置(1分); - 分割:标出裂缝、污渍或病斑的像素区域(1分); - 本项目一图一个主体,只需候选状态,所以选择分类(1分)。

  8. 评分要点(共5分): - A版intact_max=0.35,B版只改为0.25(1分); - 固定模型、B07—B08验证批次、review_min=0.65、输入门和标签,不读取B09—B10冻结测试(1分); - 预测降低合格上限会减少合格候选并增加人工复核(1分); - 记录合格候选、待复核候选、人工复核三种数量(1分); - 同时记录候选正确率和真实待复核被送入合格候选的漏检(1分)。

  9. 评分要点(共6分): - 边界:分数在0.35或0.65附近、允许范围内的轻微亮度变化;预期按双阈值转人工或稳定分流,模型可运行(2分); - 陌生:48×32新结构、无关图片或未见产品线;预期模型前转人工,模型不运行(2分); - 故障:损坏PNG、模型缺失、清单泄漏或路径不存在;预期明确失败或转人工,不沿用缓存(2分)。

  10. 参考结论:退回CNN,保留规则与人工复核。 新CNN 60%低于规则66.67%,漂亮界面不能抵消模型证据变差。学生或开发者保存失败报告并限定一次修改;数据与质量责任人确认标签、批次和漏检门;另一组复现。修改后重跑对象/批次泄漏检查、48张冻结批次、规则与CNN混淆矩阵、双阈值覆盖、8张陌生图和故障测试;若原测试已用于调参,再准备新批次。

第8章

  1. 答案:A。 相邻窗口共享设备、位置、负载、增益和背景,随机跨集合会形成会话泄漏,使测试样本像训练近邻。

  2. 答案:B。 RMS概括一段声音的整体能量,不直接说明频率结构、具体故障部件或维修方案。

  3. 答案:B。 合成数据让两类整体RMS接近,异常主要体现在频率成分和幅度调制,因此只看响度的规则漏掉全部异常。

  4. 答案:B。 D01来自未登记设备或工况,特征漂移。系统应在模型前转人工并核对采集情境,不能把最高分用于自动停机。

  5. 判断:错误。 32/32只是在两个未见会话的合成已知模式上取得,数据由同一公式生成。它不能代表真实设备、陌生异常或故障诊断,最终仍只允许低风险提醒与人工确认。

  6. 判断:错误。 运行声音只能进入待审核区。需检查授权、设备、工况和标签,按会话建立新版本,离线评价并经责任人批准后,才能用于模型更新。

  7. 评分要点(共4分): - 同一会话相邻窗口共享情境并非独立样本(1分); - 随机划分可能让模型记住设备、房间或增益,获得虚高分(1分); - 应先按session_id分组,再把完整会话放入训练、验证或测试(1分); - 最终测试还应包含未见会话、设备或现场条件(1分)。

  8. 评分要点(共5分): - 固定模型分数、S07—S08验证会话、七个特征、归一化和漂移门,不读取S09—S10冻结测试(1分); - A版阈值0.50、B版只改为0.70(1分); - 运行前预测提高阈值通常减少误报、可能增加漏报(1分); - 两版统计真正正常、误报、漏报和真正异常(1分); - 同时记录人工区数量和结合错误后果的使用判断(1分)。

  9. 评分要点(共6分): - 边界:分数接近阈值或允许范围内轻微增益变化;模型可在输入门通过后运行,低信心转人工(2分); - 陌生:新设备、麦克风位置或未登记负载;漂移门接管,模型不运行(2分); - 故障:静音、削波、错误采样率、损坏WAV或模型缺失;明确报错或转人工,默认不行动(2分)。

  10. 评分要点(共5分):

    • RMS等规则适合能量或专业阈值可明确表达的情况(1分);
    • 有标签分类适合正常与已知异常都有可靠标签的任务(1分);
    • 只用正常数据的异常检测适合异常稀少、类型开放但正常范围可建立的任务(1分);
    • 本章有明确生成的正常/已知异常标签,因此选择二分类(1分);
    • 只实现一条模型路径可使数据条件、评价和责任清楚,避免把不同机制混成一个“异常AI”(1分)。

第9—12章目标测试参考答案

第9章

  1. 答案:B。 H0用预录数据或虚拟接口跑通模型、规则、日志和故障测试;它还能帮助定位真机适配问题,但不能证明真机长期稳定。

  2. 答案:C。 设备事实须由准确型号的官方资料和真机日志核对;模型记忆或相似型号帖子只能提供查找线索。

  3. 答案:B。 单位、输入质量、超时和阈值是确定性条件,应由规则检查;模型只输出类别、概率或异常分数。

  4. 答案:B。 比较量化效果时只改量化方式,固定任务、数据、设备和指标,才能归因大小、延迟及误差变化。

  5. 判断:错误。 H0是正式学习与调试路径,可完成除真机采样和长期稳定性以外的主链验证。

  6. 判断:错误。 高置信度仍须经过质量、超时、阈值和白名单规则;本项目只观察、记录和提示,不直接控制危险设备。

  7. 评分要点: 写出物理现象;传感器、适配与预处理;单位、频率或形状;模型输出;独立规则、日志和人工确认。

  8. 评分要点: 写明型号、接口、连接条件、单位、频率、格式、官方资料与最小示例;列出至少两项禁止事项和需保存的真机日志。

  9. 评分要点: 固定模型、预处理、样例、阈值和指标,只改部署位置;比较质量、启动/推理延迟、资源、断网、隐私、费用和维护,据此作采用判断。

  10. 评分要点: 设备断开、模型缺失、输入越界分别进入明确停止状态,记录版本和原始异常;不得沿用旧值,人工排查后重新读取并回归。

工程验收补充: 在resources/ch09/project/运行python acceptance.py --require-model。参考环境中,3000条合成数据按2400/600划分,验证准确率0.976667;Keras、float JSON和INT8 JSON在12条冻结样例上决策一致。INT8 JSON比float JSON大6.667%,两种标准库推理中位数同为0.0022毫秒,不能宣称量化一定更小或更快。10条系统样例还验证断网、边界、质量未知和五类停止状态;模型只拟合合成标签,安全规则位于模型之外。

第10章

  1. 答案:B。 必填字段和阈值适合确定性规则;理解含糊委托或生成候选说明才可能需要语言模型。

  2. 答案:B。 检索只返回材料、来源和相关信息,不能越过生成、规则和人工确认直接批准。

  3. 答案:B。 幂等保护让同一编号、同一内容的重复提交返回原结果,不再产生副作用。

  4. 答案:B。 超时不等于未执行,应先按事件编号或幂等键查询,再决定返回、重试或转人工。

  5. 判断:错误。 状态转换、角色权限和安全规则须由可检查的程序及责任人预定,不能由语言模型临时改写。

  6. 判断:错误。 检索命中后仍要核对权威性、时效、范围和引用支持;无依据或冲突时停止或转人工。

  7. 评分要点: 从RECEIVED、ANALYZED、EVIDENCE_FOUND、PROPOSAL_READY、AWAITING_CONFIRMATION、COMMITTED、CLOSED_NO_ACTION、MANUAL_REVIEW中写至少六个状态及进入条件;恢复用RESUMED留痕;至少写一个停止条件。

  8. 评分要点: 模型识别或给候选,检索返回依据,规则校验字段与禁区,状态机限制转换,权限限制角色,人员核对并负责。

  9. 评分要点: 测试同编号同内容、同编号不同内容、重启后重交三种情况;前者只保留一次提交,冲突必须停止并留痕。并发唯一性尚未证明,真实系统须另验收数据库事务。

  10. 评分要点: 当前propose()是受证据约束的确定性模板。允许语言模型自由改写即构成新系统,须新增无依据动作、承诺和诊断测试;状态、权限、幂等及批准责任仍由程序和人员控制。

工程验收补充: 在resources/ch10/project/运行python acceptance.py。验收现场重建路由配置、字符TF-IDF质心模型和36条重放事件;模型与关键词基线均为7/7,11项单元测试和8项操作约束通过。同载荷重试不新增提交,同编号异内容停止;写入失败恢复、重开还原和preview_digest确认均须留痕。该结果不证明模型优于基线,也不声称已实现真实身份认证、自由生成或并发事务。

第11章

  1. 答案:B。 验收门应从任务合同和错误后果出发,再选择质量、安全、延迟和成本指标。

  2. 答案:B。 固定测试要与训练隔离;更新后的版本仍须用未参与改进的样例验收。

  3. 答案:B。 试运行限制人员、时间和数据,并保留人工监督,用来发现新问题,而非直接扩大范围。

  4. 答案:B。 高代价错误触发时按预案停止、限用或回滚,保留版本与日志,不得为过关降低门槛。

  5. 判断:错误。 越权写入可单独否决版本,不能被总准确率抵消。

  6. 判断:错误。 现场修正先进入待审核经验区,须经授权、清洗、标签复核、离线更新和独立验收才可能进入新版本。

  7. 评分要点: 列两类普通错误和一类高代价错误;分别设置量化门与零容忍/逐条复核门;写明批准人和失败动作。

  8. 评分要点: 固定集覆盖正常、边界、陌生、诱导、故障和权限变化;每条含编号、来源、预期、高代价标记和适用版本。

  9. 评分要点: 离线测试比较模块质量,系统验收检查组合、权限与恢复,有限试运行观察真实环境;三类证据不可互相替代,应逐级扩大范围。

  10. 评分要点: 由监测证据发起限定变更,在隔离副本修改并审查差异,运行全量回归;责任人批准后发布,触发门槛即回滚且保留失败证据。

工程验收补充: 在resources/ch11/project/运行python acceptance.py。人工基线4/8,stable-v1为8/8并通过发布门,risky-v2为3/8并被拦截;试运行触发告警并回滚到stable-v1。11项单元测试同时拦截制品篡改、预填答案、归因缺失和混合版本。这些是课堂冻结制品的结果,不代表已直接验收第10章源码。

第12章

  1. 答案:B。 综合项目应按任务、输入、规范和错误后果选择最少必要技术;模型数和代码量不能证明价值。

  2. 答案:B。 另一组在独立环境安装、运行并恢复故障,能暴露依赖、路径、版本和隐含假设。

  3. 答案:B。 最小闭环要求一个边界明确的问题从真实输入走到有责任人的输出,不要求堆叠全部技术。

  4. 答案:B。 运行经验须经授权、清洗、审核、离线更新和固定验收,现场系统不能自行改变关键行为。

  5. 判断:错误。 功能越多,接口、依赖和失效点也越多;应以问题价值、测试、复现和交接评价。

  6. 判断:错误。 原组电脑可能依赖缓存或私有路径,须由另一组在干净环境按书面交付包重建。

  7. 评分要点: 写清使用者、授权输入、候选输出、模型分数/证据、停止和人工接管;系统只观察提示,不控制危险设备。

  8. 评分要点: data/、models/、src/、tests/、logs/、docs/职责清楚;根目录README和环境清单给出唯一入口及期望结果。

  9. 评分要点: 接手组在干净环境安装,运行成功样例和全量测试,制造并恢复一个故障,说明边界与责任;原组只能观察并接收书面问题。

  10. 评分要点: 发起限定变更,冻结版本,用AI协助修改并审查差异;重跑正常和故障回归,记录批准及回滚条件,失败时恢复上一基线。

工程验收补充: 在resources/ch12/project/运行python acceptance.py。参考结果为12/12固定集成样例、7项操作约束和7项单元测试通过;人工基线安全处理12/12但自动证据为0,助手只为2个普通事件自动找到依据。四个高风险场景必须进入EMERGENCY_HANDOFF。independent_team_reproduction=PENDING_CLASSROOM须保留:自动预检不能替代真实另一组复现。

附录B 关键术语表

本术语表按全书中的使用方式给出简明解释。术语在不同研究和工程语境中可能有更严格定义,正式项目应继续查阅相应技术文档和专业规范。

E—M

N—R

S—Z

工作方法术语

附录C AI协同项目证据包模板

本模板用于第1—11章的章项目和第12章综合项目。课堂项目可以只填写与当前任务有关的字段,但不能删除任务边界、测试、人工接管和交接信息。

一、任务与验收合同

1.任务名称

用一个动作和一个明确对象命名,例如“把企业运营服务请求整理为待确认工作单”,不要使用“万能助手”“智能平台”等宽泛名称。

2.使用者与工作结果

3.输入、处理与输出

项目 约定内容
输入 来源、格式、单位、必填项、授权和示例
处理 模型、规则、普通程序和人工步骤
输出 字段、格式、保存位置和接收者
禁止 不允许采集、推断、生成或执行的内容
停止 证据不足、越权、故障或高风险时的停止条件

4.验收样例

至少列出一个正常、一个边界、一个陌生和一个故障样例。写明输入、预期输出、不可接受行为和由谁判定。

二、项目上下文

1.材料与来源

编号 材料或数据 来源 授权状态 版本/日期 用途

2.项目文件

建议至少说明:

3.环境与设备

三、AI协同开发记录

证据1:学生提供任务与上下文

记录学生实际提供的任务、材料、限制和文件范围。删除账号、密钥和隐私信息。

证据2:AI追问与候选方案

记录AI提出的关键缺失条件、候选实现和风险。标出学生补充、修改或拒绝的内容及理由。

证据3:完整首版及解释

记录首版文件清单、运行入口、输入输出、模型位置和测试方法。不能只保存一段无法独立运行的代码。

每章配套工程应能用python acceptance.py运行离线核心验收。模型或云服务不能运行时,验收入口仍要清楚区分“结构与测试已通过”和“真实模型尚未运行”,不能把前者冒充后者。

证据4:运行观察与错误反馈

记录实际命令、环境、输入、完整错误或输出,以及与预期不一致的位置。不要只写“运行失败”。

证据5:限定修改与文件差异

修改目标 允许修改文件 禁止改变内容 实际差异 学生审查结论

证据6:固定回归与最终判断

记录同一测试集修改前后的结果,说明采用、限用、退回或停止的决定及责任人。

四、数据卡

五、模型卡

六、测试与验收记录

编号 类型 输入与条件 预期结果 实际结果 通过/失败 证据位置
N-01 正常
B-01 边界
U-01 陌生
F-01 故障

验收结论只能选择以下一种,并写明条件:

  1. 通过:允许在明确范围内使用。
  2. 限用:仅允许指定使用者、数据、时间或人工监督条件。
  3. 退回:必须完成指定修改并重新回归。
  4. 停止:当前收益不足、风险不可接受或无法可靠维护。

七、交接清单

八、维护记录

日期 变更原因 数据/模型/代码/规则版本 回归结果 批准人 是否回滚

附录D 项目评价量规

一、评价原则

评价不以代码行数、模型大小、使用软件数量或演示效果作为主要依据。公共核心项目重点评价学生能否把任务、输入、模型、规则、测试和人的责任连接起来;综合项目增加专业真实性、另一组复现、交接和维护。

建议总分100分。任一项目若违反数据授权、隐私或硬件安全底线,即使其他部分得分较高,也不能判定为可投入使用的成果。

二、通用项目量规

评价维度 权重 优秀 达标 需改进
任务与价值 12 使用者、结果、输入输出、约束、错误后果和验收明确,能够解释为何需要或不需要AI 任务和主要输入输出明确,有基本验收条件 只描述功能或技术,使用者、结果和验收含糊
数据与证据 14 来源、授权、字段、单位、版本和质量问题可追溯,训练与测试隔离 主要数据来源和字段清楚,能发现常见质量问题 材料来源不明,数据泄漏或用成功样例替代测试
AI协同开发 12 保留任务、追问、首版、运行、限定修改、差异和回归证据,学生决策清楚 能提供主要对话和运行修改记录 只保存最终回答或无法说明AI修改了什么
技术机制 14 能沿输入—表示—模型/算法—输出—规则解释关键链,并正确区分生成、预测、优化或感知 能解释主要技术和关键变量 把界面、普通计算或流程自动化误称为模型能力
基线与变量实验 10 有人工/规则/统计基线,只改变一个关键条件,用同一测试比较并解释取舍 有基线或一次变量比较 没有参考方法,或同时改变多项条件得出结论
测试与失败分析 16 正常、边界、陌生和故障样例齐全,指标对应错误后果,分析典型失败 有独立测试和主要错误记录 只展示成功,评价样本与训练混用
安全、权限与责任 10 数据、权限、停止、人工接管和高风险禁区可执行 能指出主要风险和人工确认点 把关键决定交给模型,缺少停止或越权保护
交付与复现 12 文件、环境、版本、说明、acceptance.py、真实报告和回滚齐全,另一组能够复现并处理一个故障 能按README运行主要功能和固定测试 只能在原作者电脑演示,缺少版本、测试入口和已知问题

三、四档成绩解释

四、一票否决与限用条件

以下情况不能判定“通过”:

  1. 使用未经授权的个人、企业或专业数据,或者在项目中明文保存密钥。
  2. 模型直接控制市电、燃气、加热、压力、高速运动、门锁、交通工具或医疗设备。
  3. 没有独立测试,只使用训练样例或展示样例证明有效。
  4. 隐藏完整实现,学生无法说明输入、输出、模型、规则和人的分工。
  5. 另一组无法运行且没有环境、版本或故障说明。
  6. 语言模型的流畅回答被直接当作专业事实、规程或责任结论。

五、综合项目答辩问题

答辩至少回答:

  1. 真实工作目标是什么,不使用AI时怎样完成?
  2. 为什么选择当前模型、规则和运行位置?
  3. 数据从哪里来,最可能造成什么偏差?
  4. 哪个失败样例最改变了你们的设计?
  5. AI生成了哪些文件,学生否决或限定了哪些修改?
  6. 哪个错误代价最高,系统怎样停止并交给谁?
  7. 另一组复现时遇到什么问题,交付包怎样修订?
  8. 什么证据会使你们决定缩小范围、回滚或不用AI?

六、个人学习证据评分

团队项目之外,每位学生提交一页个人说明,回答自己提供了什么上下文、亲手调整了哪个变量、审查了哪次AI修改、发现了哪个失败、作出了什么判断。建议个人证据占课程总评的20%—30%,避免只按小组演示统一给分。

附录E 参考文献与延伸资源

以下资料主要用于核验本书的技术机制、项目方法和风险边界。网页访问日期为2026年8月6日。具体产品界面、版本和安装步骤不属于纸书稳定内容。

一、人工智能与机器学习基础

  1. Google for Developers. Machine Learning Crash Course[EB/OL]. https://developers.google.com/machine-learning/crash-course.
  2. Google for Developers. Machine Learning Glossary[EB/OL]. https://developers.google.com/machine-learning/glossary.
  3. Google for Developers. Problem Framing: Understand the Problem[EB/OL]. https://developers.google.com/machine-learning/problem-framing/problem.
  4. Google for Developers. Problem Framing: Framing an ML Problem[EB/OL]. https://developers.google.com/machine-learning/problem-framing/ml-framing.
  5. Google for Developers. Implementing a Model[EB/OL]. https://developers.google.com/machine-learning/problem-framing/implement-model.
  6. Google for Developers. Managing ML Projects: Planning, Teams and Pipelines[EB/OL]. https://developers.google.com/machine-learning/managing-ml-projects/.
  7. Google Creative Lab. Teachable Machine[EB/OL]. https://teachablemachine.withgoogle.com/.

二、深度学习、视觉、声音和时序

  1. Keras Team. Keras Code Examples[EB/OL]. https://keras.io/examples/.
  2. Keras Team. Text Classification from Scratch[EB/OL]. https://keras.io/examples/nlp/text_classification_from_scratch/.
  3. TensorFlow. Transfer Learning and Fine-tuning[EB/OL]. https://www.tensorflow.org/tutorials/images/transfer_learning.
  4. TensorFlow. Transfer Learning with YAMNet for Environmental Sound Classification[EB/OL]. https://www.tensorflow.org/tutorials/audio/transfer_learning_audio.
  5. TensorFlow. Time Series Forecasting[EB/OL]. https://www.tensorflow.org/tutorials/structured_data/time_series.
  6. Google AI Edge. LiteRT Models: Build and Convert Models for On-device Runtime[EB/OL]. https://ai.google.dev/edge/litert/models/.
  7. TensorFlow. Data Validation and Responsible AI Resources[EB/OL]. https://www.tensorflow.org/responsible_ai.

三、语言模型、检索与工具连接

  1. Vaswani A, Shazeer N, Parmar N, et al. Attention Is All You Need[C]//Advances in Neural Information Processing Systems. 2017. https://research.google/pubs/attention-is-all-you-need/.
  2. Lewis P, Perez E, Piktus A, et al. Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks[C]//Advances in Neural Information Processing Systems. 2020. https://arxiv.org/abs/2005.11401.
  3. Model Context Protocol. Specification[EB/OL]. https://modelcontextprotocol.io/specification/.

四、数据、模型文档与风险管理

  1. Gebru T, Morgenstern J, Vecchione B, et al. Datasheets for Datasets[J]. Communications of the ACM, 2021, 64(12): 86-92. https://doi.org/10.1145/3458723.
  2. Mitchell M, Wu S, Zaldivar A, et al. Model Cards for Model Reporting[C]//Proceedings of the Conference on Fairness, Accountability, and Transparency. 2019: 220-229. https://research.google/pubs/model-cards-for-model-reporting/.
  3. Tabassi E. Artificial Intelligence Risk Management Framework (AI RMF 1.0)[R]. Gaithersburg: National Institute of Standards and Technology, 2023. https://doi.org/10.6028/NIST.AI.100-1.
  4. Autio C, Schwartz R, Dunietz J, et al. Artificial Intelligence Risk Management Framework: Generative Artificial Intelligence Profile (NIST AI 600-1)[R]. Gaithersburg: National Institute of Standards and Technology, 2024. https://doi.org/10.6028/NIST.AI.600-1.

五、使用建议

机器学习基础、数据划分和评价可从第1—6项开始;视觉、声音、时序和端侧实践可结合第8—14项中的官方Notebook;语言模型、检索和工具连接只需理解第15—17项所描述的基本机制;项目验收、数据卡、模型卡和风险管理可重点参考第18—21项。

教师和学生引用网页代码时,应同时记录页面日期、运行环境和修改内容。示例代码能运行不等于适合当前专业任务,仍须使用本书的任务合同、固定测试、人工接管和交付要求重新验证。

六、完整项目呈现参考

  1. Mistry S. How to Build an ML-powered Doorbell Notifier[EB/OL]. Hackster.io. https://www.hackster.io/sandeep-mistry/how-to-build-an-ml-powered-doorbell-notifier-0a781e.

该案例把项目简介、硬件与软件、数据采集、模型训练、部署运行、测试和完整代码库连成一条可复现链,可用于检查教材章节是否已经成为完整项目。它不是本书项目的固定模板;各章仍须依据自身技术主题决定数据、基线、界面和验收证据。