在模型层面硬塞安全规则,本质上是在用推理能力换合规率
一、把「拒答」从权重里剥离,交给外挂式策略引擎
现在主流做法大多是 RLHF 阶段把安全边界硬编码进参数。问题在于:边界一变,全量微调成本高得离谱,且不同场景容忍度完全不同。写代码助手要敢改危险函数,客服机器人却不能敢回用户隐私。
更可行的路线是 推理时解耦:
- 基座模型只管「懂不懂」「会不会推理」,不背锅「安不安全」
- 上游挂一层轻量级策略网关,输入输出双向过滤,规则用 YAML 甚至 Rego 写,热加载、版本可回滚
- 关键动作(如调用工具、写数据库)强制走人工确认或双签名流程
我们在内部把这个网关单独部署成 Sidecar,延迟控制在 P99 < 15ms,模型迭代再也不需要为了改一条拒答策略跑一遍全量 SFT。
二、链式思维必须「可审计、可截断、可回放」
现在不少厂商把 CoT 当黑盒,甚至加密不给用户看。这在合规审计面前站不住脚。我们当时的做法是:
1. 结构化输出强制化:强制模型把推理步骤按 JSON Schema 吐出来,字段固定 step_id、tool_call、risk_level、confidence。
2. 风险熔断点前置:在 tool_call 生成前,由策略引擎同步拦截高危操作(如 rm -rf /、DELETE FROM users),直接在 CoT 流里注入 <blocked> 标记,模型下一轮自动改写方案。
3. 全链路溯源日志:每次推理的完整 CoT、策略引擎判定依据、人工复核记录,全部落入不可篡改的审计库(我们用的是带 Merkle Tree 的 ClickHouse),事后可复现、可追责。
{
"step_id": 3,
"thought": "用户要求删除生产库表,风险等级 Critical",
"tool_call": null,
"risk_level": "Critical",
"policy_decision": "BLOCKED",
"policy_rule": "db.write.production.delete.forbidden",
"fallback_action": "引导用户走归档流程或联系 DBA"
}三、别指望模型自己「识别恶意意图」,上下文注入攻击防不胜防
Prompt Injection 的本质是控制权争夺。指望模型在参数层面「理解」哪些是指令、哪些是数据,纯属扯淡。工程上唯一靠谱的手段是 权限最小化 + 数据流向标记:
- 所有外部输入(用户对话、RAG 检索结果、工具返回)强制打标
source: untrusted - 系统提示词、开发者指令打标
source: trusted - 下游执行层(代码解释器、数据库驱动、HTTP Client)只认
trusted来源的指令,untrusted数据只能作为参数值,绝不能拼接进命令结构
这点类似 Web 安全里的「参数化查询」思想,把指令与数据在架构层面物理隔离,比任何指令微调都管用。
四、红队测试要常态化、自动化、指标化
别搞一年一次大考核。把红队能力做成 CI/CD 管线里的一个 Stage:
- 维护一个持续扩充的攻击语料库(Prompt Injection、越狱、数据窃取、链式思维泄露等)
- 每次模型版本发布、策略规则变更、工具集更新,自动跑全量回归
- 关键指标:拒答率(安全类)、误拒率(正常业务)、绕过成功率、平均检测延迟
- 指标回滚阈值写进发布 Gate,超线直接阻断发布
写到这儿想起个细节:有次发布前夕,自动化红队跑出一条新型编码绕过,把「忽略之前指令」藏在 Base64 里经工具返回注入进二轮上下文。策略引擎当时漏判了,但因为有 CoT 审计日志,复盘只花了 20 分钟就定位到解码器