提示词实验项目与自测

项目目标与证据边界

构建一个不调用真实模型的“工单分类提示实验台”:渲染分角色消息,把代码内提示、案例和 schema 版本绑定,读取模拟响应,依次验证严格 JSON、字段契约、业务规则、证据落地和期望标签,再按标签、业务切片与风险等级统计结果。报告同时记录三类资产的 SHA-256,避免只有版本名却无法定位实际内容。

这个实验能证明本地契约和失败路径可运行,不能证明任何线上模型会达到同样质量。mock_response 是测试夹具,不是模型输出;接入真实 API 后必须另做重复评测、成本与安全验证。

项目文件

文件职责
prompt_lab.py严格加载案例,绑定代码内提示与 schema,分离策略和不可信输入,校验响应,生成可追溯报告与退出码
cases.json12 条版本化案例,记录期望标签、标注依据,并覆盖三个标签、五类切片与三个风险等级
response.schema.jsonDraft 2020-12 教学契约;运行时检查其关键字段未与手写验证器漂移,再补业务语义校验
test_prompt_lab.py19 项单元测试,覆盖成功、畸形输入、版本错配、schema 漂移、结果篡改、注入、CLI 和 -O 安全性

案例中的 slice 表示失败场景类别:typical、boundary、insufficient、adversarial、multilingual。risk 表示该案例失败的业务影响,不是模型置信度;annotation_reason 记录期望标签的人工依据,不会发送给模型。

mock_response 刻意保存为“包含 JSON 的字符串”,而不是已经解析好的嵌套对象:真实模型首先返回文本,实验必须能覆盖无效 JSON、重复字段和错误类型,而不能让案例文件的解析器提前替模型修好这些问题。

运行环境

本项目只使用 Python 标准库,因此不需要安装第三方包,也不需要 API key。在 Windows 11 的 PowerShell 7 中,以下代码块按顺序从同时包含 docs/ 与 .website/ 的项目根目录开始执行;生成报告后会返回项目根目录:

Push-Location -LiteralPath 'docs\提示词工程'  # 临时进入课程目录,让后续相对路径指向 examples。
py -3.11 --version  # 先确认 Windows Python Launcher 找到的是教学要求的 Python 3.11。
py -3.11 -B -W error -m unittest discover -s .\examples -p 'test_prompt_lab.py' -v  # 正常模式运行测试,并把警告升级为错误。
py -3.11 -B -O -W error -m unittest discover -s .\examples -p 'test_prompt_lab.py' -v  # 在移除 assert 的 -O 模式复跑,验证关键检查不依赖 assert。

普通项目应先学习 Python 基础中的 venv + pip 隔离方式;这个零依赖实验直接使用已安装的 Python,是为了避免在 vault 内生成 .venv。若要练习虚拟环境,请把它建在 $env:TEMP 等 vault 外目录。不要把虚拟环境、缓存或报告提交到知识库。

分步骤实验

1. 检查消息边界

py -3.11 .\examples\prompt_lab.py --show-prompt billing-refund-pending  # 只渲染指定案例的消息边界,不执行全部评分。

观察打印出的消息数组:稳定分类策略位于 developer 消息,工单由 JSON 序列化后位于 user 消息。再查看 technical-injection-login 案例;其中的“忽略规则”仍只能作为工单数据出现。这个结构有助于表达信任边界并防止字符串拼接破坏 JSON 结构,但不是安全隔离。案例声明的 prompt_version 若不等于代码内版本,程序会在渲染前停止。

2. 运行全部案例

py -3.11 .\examples\prompt_lab.py  # 运行所有教学案例并让 CLI 按质量合同返回退出码。
$LASTEXITCODE  # 查看上一条外部命令的退出码,0 表示所有案例通过。

当前夹具应得到 12/12 passed,退出码为 0。启动时先核对案例声明的提示/schema 版本,并确认教学 schema 的根对象、字段和 anyOf 分支只使用运行时已实现的精确关键字集合;pattern、allOf 或其他额外约束不会被静默忽略。响应验证器会拒绝重复 JSON key、NaN/Infinity、未知字段、非法枚举、空理由、超长文本和未落在原工单中的证据。对于 billing 与 technical,evidence 必须是原工单的逐字子串;这比“JSON 能解析”多了一层业务校验。

本项目没有引入第三方 JSON Schema 实现,因此不能声称执行了 Draft 2020-12 的全部语义。它只验证当前教学 schema 使用的有限关键字与运行时代码相等;接入真实应用时应使用维护良好的 schema 验证器,并按供应商支持的子集转换 API 参数。

3. 生成可审计报告

$report = Join-Path $env:TEMP "prompt-lab-report.json"  # 在系统临时目录生成报告路径,不污染 vault。
py -3.11 .\examples\prompt_lab.py --json-report $report  # 把本次案例结果写成可审计的 JSON 报告。
Get-Content -LiteralPath $report -Raw -Encoding utf8  # 以 UTF-8 原样查看报告,便于核对字段与失败明细。
Pop-Location  # 回到运行前的项目根目录,配对前面的 Push-Location。

报告记录 dataset_version、prompt_id、prompt_version、schema_version、三类资产 SHA-256、总体通过数、逐标签/切片/风险结果和带元数据的失败明细。它没有把提示文本、密钥或真实客户数据写入报告。build_report() 会从 fixture 重新计算每个完整 CaseResult,再逐项比较 ID、标签、切片、风险、错误内容、通过状态与 prompt_chars;任何篡改都会在统计前失败。

4. 证明测试真的会失败

测试套件中的 test_cli_returns_failure_for_broken_mock_response 会临时构造一个错误响应,要求 CLI 返回非零状态;临时文件位于系统临时目录,不会修改正式案例。你也可以复制 cases.json 到 vault 外,故意改错一个 mock_response.label,再用 --cases <副本路径> 运行。不要直接破坏作为回归基线的正式夹具。

退出码合同如下:0 表示全部案例通过,1 表示案例响应未通过质量合同,2 表示案例/schema 文件畸形、版本错配、未知 --show-prompt ID 或报告写入失败。输入错误会写入 stderr,不输出 Python traceback;这让 CI 能区分“模型质量回退”和“实验配置本身无效”。

本机验证记录

2026-07-21 在 Python 3.11.9 上完成:

  • py -3.11 -m py_compile:脚本与测试均通过。
  • 普通模式:19 项测试全部通过,warnings-as-errors。
  • python -O 模式:同一 19 项测试全部通过,证明关键校验不依赖会被优化移除的裸 assert。
  • CLI:12 条案例全部通过,覆盖 5 类切片和 3 个风险等级。
  • 普通模式与 -O 模式的 CLI 文本和 JSON 报告逐字一致。

这些结果只覆盖离线夹具;未调用外部 API,也未验证 Obsidian 阅读视图。

扩展任务

  1. 新增 12 条案例,保持标签平衡,并为每条写清切片、风险和 annotation_reason;修改数据后提升 dataset_version。
  2. 复制提示为 v2,只改变一项规则;同时更新代码内 PROMPT_VERSION 与案例声明,保留同一评测集并生成逐例差异报告。版本不一致应继续失败关闭。
  3. 为“信息不足”单独设计拒绝/澄清状态,更新 schema、验证器、案例和测试,观察为何契约必须整体迁移。
  4. 在学完 LLM API 集成后新增独立 adapter:密钥只来自环境变量,记录供应商、模型配置、提示版本和请求 ID;离线测试必须继续可独立运行。
  5. 在学完 评测体系后,增加重复采样、precision/recall、关键切片发布门槛和人工复核记录。

自测题

  1. 为什么 12 个 mock 全部通过不能证明线上模型质量?
  2. 严格 JSON、schema、业务规则和动作授权分别拦截什么错误?
  3. 为什么把工单放入 user JSON 字段仍不能消除提示注入?
  4. 同时更换提示、模型和检索会给归因带来什么问题?
  5. 为什么高风险切片不能被总体平均分“抵消”?
  6. 为什么生产 adapter 不应改写或替代离线测试路径?

掌握检查

  • 我能运行普通与 -O 两组测试,并解释 19 项测试覆盖的失败类型。
  • 我能让一个故意破坏的临时案例正确失败并返回非零状态。
  • 我能解释模板、案例、schema、业务规则和授权各自的职责。
  • 我能读懂按切片、风险输出的 JSON 报告,并定位失败案例。
  • 我不会把真实密钥、客户数据、虚拟环境或完整提示日志写入 vault。
  • 我能说明离线契约验证与线上模型评测之间仍缺哪些证据。

主要参考资料

回到目录

返回 提示词工程学习目录,或继续 上下文工程。