端到端 safety gate
生成前、生成中、生成后。三个检查点,一个 verdict,每个请求一条审计轨迹。
类型: Build 语言: Python 前置要求: 阶段 18 安全相关课程、阶段 19 Track A 第 25-29 课 预计时间: ~90 分钟
问题背景
本 Track 的第 82-86 课各自交付了一块:一个 taxonomy、一个输入 detector、一个评估框架、一个输出 classifier、一个规则引擎。一个真实的 safety gate 必须把它们组合起来,在请求生命周期的正确时刻运行它们,在它们意见不一致时决定采取什么动作,并产出一条审阅者周一早上能读懂的 trace。组合才是本课的重点。
gate 坐在三个检查点上。pre-gen 在模型被调用之前运行:第 83 课的 detector 看 prompt,要么放行、要么直接拦截(高置信度攻击)、要么打一个 flag 供下游各层权衡。during-gen 随着模型吐出 token 而运行:一个流式过滤器缓冲住若干 chunk,并在出现违禁短语时提前终止流(如果 gate 只做事后检查,prefix-injection 就能挺过这一关)。post-gen 在模型完成后运行:第 85 课的 classifier router 和第 86 课的规则引擎检查完整输出,gate 把它们的 verdict 与 pre-gen 信号聚合起来,并应用一个最终动作。
gate 是自终止的:第 82 课 taxonomy 里的每个 fixture 都端到端跑一遍,gate 为每个请求发出一条 trace,并且无论 gate 是否拦下每一个攻击,demo 都以 0 退出。重点是可观测性和结构正确性,不是一个完美的分数。
核心概念
三个检查点,一棵决策树。
flowchart TB
IN[用户 prompt] --> PG[pre-gen:detector]
PG -->|high 触发 block| OUT1[refusal + trace]
PG --> M[mock LLM]
M -->|stream| DG[during-gen:token 过滤器]
DG -->|提前终止| OUT2[部分输出 + trace]
DG -->|完成| POST[post-gen:classifier + 规则]
POST --> AGG[聚合]
AGG --> OUT3[最终动作 + trace]聚合器组合四路 severity 信号:detector 置信度(第 83 课)、token 过滤器触发(布尔)、classifier 最大 severity(第 85 课)、规则引擎最大 severity(第 86 课)。聚合函数是一张确定性的表。
| 信号状态 | 动作 |
|---|---|
| 任一 high severity | block |
| 任一 medium severity | redact |
| 任一 low severity | warn |
| 全为 none 且 detector 置信度 < 0.5 | allow |
| detector 置信度 0.5-0.85 且无其他信号 | warn |
block 返回一条 refusal。redact 发出 classifier 脱敏后的文本,并应用规则引擎的 fixer。warn 带一条软提示发出原文。allow 发出原文。每个请求发出一条 RequestTrace,含 request_id、prompt、pre_gen(detector verdict)、during_gen(token 过滤器触发)、post_gen(classifier 动作 + 规则报告)、final_action、final_output 和 latency_ms。
during-gen 过滤器是一个流式抽象。mock LLM 产出 chunk(默认每块 4 个 token)。过滤器最多缓冲两个 chunk,并对已知续写 token(Sure, here is the procedure、step 1: take 等)做一次正则扫描。命中时它终止迭代器,并返回标记为 terminated_early=True 的部分输出。下游聚合器把提前终止当作一路 medium severity 信号。
mock LLM 有两种行为,按 prompt 区分:它拒绝可识别的攻击(返回 I cannot ...),并回答 benign prompt(返回一个通用的有用字符串)。对于一小部分攻击(尤其是输入流水线没抓到的 encoding trick),它会产生一段部分有害的续写,正好让 during-gen 过滤器去抓。这是故意的。gate 的价值在于分层防御;demo 展示各层之间正确地相互作用。
safety-checkpoints动手构建
code/safety_gate.py 定义 SafetyGate 类。它通过相对文件路径,从前几课导入 detector、classifier router 和规则引擎。code/mock_llm_stream.py 定义一个流式 mock LLM,带三个脚本化人设(clean、attacker-honest、attacker-lazy)。code/main.py 把第 82 课的语料库端到端跑过 gate,并写出 outputs/gate_trace.json。
demo 跑全部 50 个 taxonomy fixture 外加 10 条 benign prompt。trace 摘要报告:block 数、redact 数、warn 数、allow 数、提前终止数、按类别的结果拆分,以及平均延迟。数字不是重点;每个请求的 trace 才是重点。
实际使用
python3 main.py。demo 加载所有东西,端到端跑一遍,打印摘要表,并写出 trace 产物。退出码为 0。demo 在字面意义上是自终止的:每个请求要么跑到完成、要么提前终止,然后 gate 移到下一个。
拿去用
outputs/skill-end-to-end-safety-gate.md 记录了请求生命周期、聚合表和 trace 格式。gate 的首要交付物是 trace 格式和组合逻辑,团队可以把这两样直接搬进自己的后端。
练习
- 增加第五个检查点:一个在 pre-gen 之前、针对原始 system prompt 运行的
policy-check。它必须拒绝那些瞄准某个已知内部 tool 名字的 prompt。 - 把确定性聚合器换成一个加权得分:每路信号贡献一个 0-1 的置信度,gate 在某个阈值上跳闸。扫这个阈值,并在第 82 课的语料库上报告 precision-recall 权衡。
- 增加一个异步流式变体,让 during-gen 在一个线程里跑;验证延迟影响保持在 50ms 预算之内。
关键术语
| 术语 | 通常用法 | 精确含义 |
|---|---|---|
| safety gate | 一个过滤器 | detector、流式过滤器、classifier 和规则的三检查点组合,配一张聚合表 |
| pre-gen | 输入检查 | 在模型被调用之前作用于 prompt 的 detector 层 |
| during-gen | 流式过滤器 | 对已发出 chunk 的缓冲扫描,可以提前终止流 |
| post-gen | 输出检查 | 作用于已完成响应的 classifier router 和规则引擎 |
| trace | 一行日志 | 一条结构化的每请求记录,含每个检查点的 verdict、最终动作和延迟 |
延伸阅读
本 Track 前面五课。gate 组合它们;它不增加新的安全原语。