5.2 KiB
5.2 KiB
内容安全与本地敏感词过滤
T-604 的实施口径与实现记录。目标是先做「中文 prompt 本地敏感词快筛」,命中在扣点和调上游之前拦截;云内容安全与输出审核不在本任务做实。
定位
- 本地敏感词过滤是免费快筛和运营自定义黑名单,不替代合规内容审核。
- T-604 只处理输入 prompt 的关键词拦截;图片审核、输出文本审核、输出图片审核、云厂商内容安全属于后续任务。
- 默认关闭:
MODERATION_ENABLED=false时必须 no-op,现有生成接口行为不变。 - 打开后使用
MODERATION_PROVIDER=keyword;未配置或配置错误时按 fail-closed 处理。
请求时序
生成接口必须按这个顺序执行:
- DRF serializer 校验基础字段。
- 先审核 prompt 文本,不得先下载
image_url或预扣点。 - prompt 命中敏感词:返回
400 content_blocked,不下载图片、不解析别名、不计费、不写CallRecord/PointsLedger、不调上游。 - prompt 通过后,才允许读取
image_base64或下载公网image_url,并继续 SSRF 防护。 - 别名解析、能力校验、计费规则查询。
- 预扣点、写 pending 调用和 consume 流水。
- 调上游,成功后写成功记录;失败走既有退点路径。
说明:T-604 已清理早期骨架里的 moderate_output_* 钩子和云厂商 provider stub,只保留 moderate_prompt() 本地关键词入口。输出审核若后续落地,必须重新定义「命中是否退点」的产品策略,并让对应配置真的生效;在 T-604 中不要暴露一个未实现的配置。
数据模型
新增 SensitiveWord 模型:
| 字段 | 说明 |
|---|---|
word |
原始敏感词,唯一或按 category 唯一;不能为空 |
normalized_word |
归一化后的词,用于构建 matcher;保存时生成,便于排查和唯一约束 |
category |
分类,如 politics / violence / porn / custom |
action |
MVP 只支持 block;后续再扩展 review / flag |
is_active |
是否启用 |
created_at / updated_at |
时间戳 |
admin 要求:
- 支持按
word/normalized_word/category搜索。 - 支持按
category/action/is_active过滤。 - 修改词库后触发 matcher 版本失效。
归一化
匹配前对 prompt 与词库统一归一化:
- Unicode NFKC,把全角转半角。
- 去零宽字符。
- 去空白和常见分隔标点,用于拦截「敏 感 词」「敏-感-词」这类低级绕过。
- 英文字母小写。
- 繁简转换可选;如果
opencc安装或运行失败,跳过繁简,不影响其他归一化。
风险:过度归一化会提高误伤概率。测试必须包含至少一条例外/普通文本样例,避免明显正常内容被误拦。
匹配与缓存
- 使用 Aho-Corasick 自动机做多词匹配;
ahocorapy作为候选依赖,但实现前必须验证 PyPI 包可用性和 API 形状。 - 禁止每请求重建 matcher。
- 每个 worker 进程内缓存 matcher;生产多 worker 下不能只依赖 Django
post_save/post_deletesignal,因为 signal 只影响当前进程。 - 采用共享版本号失效:词库变更后把
moderation:sensitive_words:version写入共享 cache;每次请求只做轻量版本检查,版本不一致时当前进程重建 matcher。 - 生产必须使用共享 cache(DatabaseCache / Redis / Memcached),不能依赖
LocMemCache完成跨 worker 失效。
错误与留痕
命中后对外响应:
{
"error": {
"code": "content_blocked",
"message": "输入内容未通过安全审核"
}
}
留痕原则:
- 不保存违规 prompt 原文。
- 可记录分类、命中词 ID、请求用户、API Key 前缀、时间、阶段、处理结果。
- MVP 若不建
ModerationRecord,至少测试中确认不会把 prompt 原文写入日志或数据库的新字段。
验收
当前实现状态:DONE。已落地 apps.moderation、SensitiveWord 模型/admin/迁移、ahocorapy keyword provider、归一化管线和共享 cache 版本号失效;生成接口已改为 serializer 后先审 prompt,命中时不会下载 image_url、不会扣点、不会写调用/流水、不会调上游。
T-604 完成前至少覆盖:
MODERATION_ENABLED=false时生成接口 no-op,既有用例不变。MODERATION_PROVIDER=keyword且命中 prompt 时返回400 content_blocked。- 命中时不扣点、不创建
CallRecord、不写PointsLedger、不调用上游 provider。 - 命中时不会下载
image_url。 - 归一化命中:空格/分隔符/全半角/零宽字符。
- 繁简归一化若启用则有测试;未安装
opencc时测试跳过或断言 graceful fallback。 - 词库变更后 matcher 版本号变化,当前进程下一次请求能重建 matcher。
- 多 worker 口径在文档和测试中说明:跨进程刷新依赖共享 cache 版本号,不依赖本地 signal。
不在 T-604 范围
- 云内容安全真实厂商接入。
- 输出内容审核与输出命中退点/照扣策略。
- 图片内容审核。
- 脱敏、人工复审、灰度放行。
- 大规模开源词库入库;可提供导入命令,但真实词库数据不进仓库。