Content Moderation — UGC 平台的内容审核栈
面向社区 / 论坛 / 短视频 / 电商等 UGC 平台 trust & safety 负责人的内容审核工具包。按顺序铺五层:文本 → 图片 → 视频 → 音频 → 人审申诉 + 误判反馈。开源基础设施优先,避免单一 vendor 锁定。多语言默认。模型负责建议,人类决定边界判定,每一次决策(包括申诉)都要落日志,下个季度才能拿自己的错样本重训模型。
这个 pack 包含什么
这是 2026 年一个 UGC 平台(社区、论坛、短视频、电商、评论系统,只要用户能发内容)的 trust & safety 负责人真的会搭的栈。明确不是一个 vendor moderation API 的封装。单一 vendor 第一页 PPT 没问题,第八页就崩:按调用收费在量大时撑不住;英文优先的模型在多语种平台漏掉大半;没人公布 false positive 率;最后申诉队列变成挂在 Notion 上的一个 Google Form。
栈刻意分成五层,因为一个用户上传 30 秒视频带文案、缩略图和背景音乐时,工作流真的就是这个样子:
- 文本层 — 文案、评论、标题、bio、私信。量最大、单条成本最低、误判反馈最快。
- 图片层 — 封面、头像、消息附件。量比文本低,但单条风险高得多。
- 视频层 — 单条最贵。不要每帧都分类,要采样。
- 音频层 — 背景音乐、画外音、语音消息。几乎所有音频审核都是先转文本,再丢回文本层。
- 申诉 + 反馈层 — 人审队列、审核员早 9 点打开的 dashboard、把每一条被推翻的决策变成训练样本的 pipeline。
三条贯穿所有 pick 的原则:
- 开源基础设施优先。每一层都要有可以自托管的选项。Vendor API 可以做英文文本的第一道防线,但绝不能成为唯一的那道 — 多语种覆盖、定价风险、决策不透明这三个问题在规模上必爆。
- 模型提议,人类决定灰区。置信度阈值把流量切成自动放行 / 自动拦截 / 人审三条队列。中间那条队列才是 trust & safety 团队拿工资的地方。
- 每条决策和每条申诉都写日志。False positive 率是你无法造假的那个指标。没有「模型说拦截、人在申诉里说放行」的不可篡改记录,你既改不了模型、也没法在监管面前为一次决策辩护。
本 pack 不引用任何准确率百分比。任何 vendor 或开源项目敢公布单一数字「99.2% 准确!」 — 它在卖你 benchmark,不是审核系统。你自己的内容、你的语种、你的政策下的准确率是唯一重要的数,并且你必须自己测。
推荐安装顺序(文本 → 图片 → 视频 → 音频 → 申诉 + 误判分析)
- NeMo Guardrails — Programmable Safety for LLM Applications (id: 4258) — 文本层从这里起。NVIDIA 开源框架,让你用 Colang 声明式地组合 input rails / output rails / topic rails,并接任意 OpenAI 兼容 LLM 当分类器。对 UGC 文本审核特别有价值的是:同一套 rail 定义可以同时覆盖用户生成内容、你自己出站的文案、以及你的 bot 的回复。一套政策、三个面。
- llm-guard — Secure LLM Inputs & Outputs (id: 3103) — 文本层的姐妹扫描器,Python 库,内置 toxicity / prompt injection / PII / 禁话题等一堆现成 scanner。和 NeMo 配套用:NeMo 是编排器和政策语言、llm-guard 是你往 rail 里塞的那套现成检测器。两个库一起覆盖「我怎么定义审核政策」和「政策里具体跑哪些分类器」这两个问题。
- Guardrails AI — Validate LLM Outputs in Production (id: 773) — 给你自己产出的 AI 内容做 schema 校验(自动生成的描述、给审核员的建议文案、给用户的 AI 写的安全回复)。防你自己的 AI 编出不存在的政策类别或不存在的处置建议。审核系统本身上线前,先给它套上 guardrails。
- Presidio — Detect and Anonymize PII (id: 3106) — PII 检测和脱敏层。UGC 平台天天看到用户漏手机号、邮箱、住址、身份证。Presidio 本地跑、多语言开箱、既给检测(「这条评论里有手机号」)又给脱敏(「送给下游服务前替换成
<PHONE>」)。任何用户生成内容送到外部审核 API 之前接上。 - OpenCV — Open-Source Computer Vision Library (id: 1828) — 图片层的工兵。哪怕你最后还是会调云端视觉 API 做 NSFW / 暴力分类,OpenCV 是你做预处理的工具:缩到模型输入尺寸、剥 EXIF、降采样、抽感知哈希(pHash)让重复图片滥用第一次抓住、永久拦截。便宜、本地、快。
- FFmpeg — The Universal Multimedia Processing Toolkit (id: 1157) — 视频层地基。你不要在每一帧上跑分类器 — 那就是烧钱。用 FFmpeg 抽关键帧(每 1-2 秒一帧是可辩护的默认)、分离音轨给下一步、并降采样到你图片分类器实际需要的分辨率。FFmpeg 也是你做场景切换检测的工具,让采样帧落在视觉上有区分度的帧上,而不是 24 张几乎一样的复印件。
- Whisper — OpenAI Speech-to-Text (id: 105) — 音频层。背景音乐、画外音、语音消息、直播音频 — 几乎所有音频审核都归约为「先转写、再跑文本层」。Whisper 本地跑、多语种开箱、是开源默认。实时 / 直播音频用同一血统的更快服务端变体。
- HumanLayer — Approval Loops for Coding Agents (id: 3036) — 人审申诉层。原本为 agent 审批流做的,同一个原语(「暂停、路由到人、根据决策恢复」)刚好就是审核员要的那个队列模型。模型出分类,自动拦截阈值以上拦掉,自动放行阈值以下放过,中间那段 — 加上用户的所有申诉 — 全部进 HumanLayer 队列,带全上下文。
- doccano — Open-Source Text Annotation Tool for Machine Learning (id: 4763) — 误判分析层。每一条被推翻的审核决策(模型说拦截、人在申诉里说放行)都是一条你已经付过钱的有标签训练样本。doccano 给 trust & safety 团队一个干净的标注界面、导出标准格式、喂给下一轮微调。真正在迭代的平台是那些把申诉队列变成训练数据的平台。
- Discourse — Open Source Community Forum Platform (id: 1745) — UGC 平台本体,如果你还没有的话。值得收进来是因为 Discourse 自带成熟的审核面(举报、信任等级、帖子审查队列、用户禁言 / 封号、审计日志),被多年真实社区使用淬炼过。哪怕你不真在生产里跑 Discourse,去读它的审核管理页面 — 数据模型和工作流是个非常好的参考标尺。
它们怎么协同
用户上传(文案 + 图片 / 视频 + 音频)
│
▼
┌───────────────────────────────────────────────────────┐
│ Presidio (id 3106) — 文案 + bio 的 PII 脱敏 │
└───────────────────────────────────────────────────────┘
│
┌─────┴───────────────┬──────────────────┬─────────────┐
▼ ▼ ▼ ▼
文本层 图片层 视频层 音频层
NeMo Guardrails OpenCV FFmpeg FFmpeg 分轨
(id 4258) (id 1828) (id 1157) │
llm-guard + 云端视觉 每 1–2 秒 ▼
(id 3103) 做 NSFW / 抽关键帧 Whisper
⤷ 置信度 暴力分类 │ (id 105)
0–1 ▼ │
(帧 → 图片层) (文本 → 文本层)
│
▼ 分类 + 置信度
┌───────────────────────────────────────────────────────┐
│ 阈值路由 │
│ 置信度 > T_block → 自动拦截 │
│ 置信度 < T_allow → 自动放行 │
│ 中间 或 用户申诉 → HumanLayer 队列 (3036) │
└───────────────────────────────────────────────────────┘
│
▼
审核员决策(放行 / 拦截 / 升级)
│
▼
┌───────────────────────────────────────────────────────┐
│ append-only 决策日志 │
│ {item_id, model_label, confidence, human_label, │
│ appeal_outcome, moderator_id, timestamp, language} │
└───────────────────────────────────────────────────────┘
│
▼
doccano (id 4763) — 给每一条被推翻的决策打标
│
▼
下一季度的回训集
最重要的箭头是底部那条回路:申诉结果 → doccano → 回训。没闭这个环的审核栈会漂移;闭上了的会复利。
你会遇到的取舍
- False positive vs false negative。每个审核系统都在这两者间取舍,正确的取舍取决于你在审什么。儿童产品宁可多 false positive(多拦)也不要 false negative。成人内容市场可以容忍更多 false negative 来换更少创作者投诉。阈值路由器(上图)是你调这个的地方,按政策、按面调 — 不是去调模型。
- Vendor moderation API vs 开源栈。云端 vendor(OpenAI Moderation / Perspective / Hive / Sightengine / Clarifai / Amazon Rekognition / Azure Content Safety)上手快、英文覆盖好、把运维抽掉。它们也按调用收费、拒绝公布按语种的错误率、把你的申诉证据锁在它们 dashboard 里。大多数平台落到的实用模式:选一家 vendor 在它最强的面上做第一道过滤,把本 pack 的开源栈放在下面作为你自己控制的可辩护层。两个一起跑。
- 多语种覆盖。大多数商业审核 API 悄悄是英文优先的 — 西语 / 法语 / 葡语过得去;中文 / 阿拉伯语 / 印地语 / 越南语 / 他加禄语 / 长尾差异很大且很少披露。Whisper 和 Presidio 设计上就是多语种、多语种里表现可用;基于 LLM 的 rail(NeMo / llm-guard 接 LLM scanner)继承底层模型的语种覆盖 — 2026 年的前沿模型覆盖广但仍不均匀。按语种分别测 false positive / false negative。整体 95% 但英文 99% 越南语 70% — 在 40% 用户发越南语的平台上不是一个 95% 的系统。
- 延迟预算。文本审核 ~ 几十到一百多毫秒;图片审核几百毫秒到秒级;视频审核因为抽帧到秒级到几十秒。写路径要做成乐观接收 + 异步审核,对用户显式显示「审核中」状态。同步阻塞的上传审核哪怕工作正常也让人觉得坏了。
- 成本。Vendor 审核 API 规模化之后是真烧钱、视频按帧尤其烧。开源栈跑自己 GPU 上经济学不一样:固定成本高(硬件 + 运维)、单条边际低、跑好的人力成本高。Series A 之后的平台大多是混合:spiky / 低量面用 vendor,稳定高量面用自托管开源栈。
常见踩坑
- 只信英文训出来的模型。英文 benchmark 漂亮的模型在印尼语 / 阿拉伯语 / 印地语上可能差得很。如果你平台是多语种,你的审核评估集也必须是多语种 — 从你真实流量里采,不是英文种子翻过去。
- 完全没有申诉渠道。被下架但无处申诉的用户要么流失、要么换号再发同一条、要么把投诉搬到社交媒体上。申诉队列(HumanLayer 这种)不是 nice-to-have,是你唯一能看到自己 false positive 率的机制。
- 没有 false positive 日志。「模型说拦截、人在申诉里说放行」是你能产生的最有价值的一条数据点。这些决策没写进不可篡改、可查询的存储 — 你审核花了两次钱(模型 + 人)、什么都没学到。
- 每帧都分类视频。60 秒视频 30 fps 跑分类器 = 每条上传 1800 次分类调用。按场景切换 + 每 1-2 秒一帧采样,记录哪一帧触发,接受你偶尔会漏一个瞬时的 5 帧违规。另一个选项是破产。
- 把审核放在同步上传路径里。用户看到 spinner、上传感觉坏了;vendor 一抖整个写路径躺平。乐观接收,标「审核中」,异步跑,只有判定是拦截时再反向下架。
- 把审核政策当模型参数。政策决策(「公众人物讽刺允许吗」「私信里医疗建议允许吗」)属于一份 trust & safety 团队拥有的书面政策文档。模型实现政策;不定义政策。改政策时,你改的是 rail(NeMo Colang)和阈值(路由器),不是底层分类器权重。
10 个资产打包就绪
常见问题
Hive vs Sightengine vs OpenAI Moderation — 第一道 vendor 过滤选哪家?
选定价、延迟、语种覆盖匹配你真实产品的那家,不是 marketing benchmark 漂亮的那家。OpenAI Moderation API 调用免费、英文文本上够用、其他模态覆盖有限;如果你已经是 OpenAI 客户、流量主要是文本,这是合理的零成本起点。Sightengine 和 Hive 收费、图片视频强、多语种程度不一、运维上很认真;图片视频是主要面的平台它们物有所值。Perspective API(Jigsaw)只做文本、免费、专注 toxicity、很多非英语弱 — 当英文评论的第二意见有用,不能当唯一过滤。可辩护的模式:选一家 vendor 在它最强的面上做第一道过滤,本 pack 的开源栈放在下面作为你真正控制的那层。别把整个平台压在任何单一 vendor 身上。
中文 / 阿拉伯语 / 其他非英语内容的效果怎么样?
不均匀,而且你必须自己测。Whisper 和 Presidio 设计上就多语种、在多语种上表现可用 — Whisper 处理声调语言和阿拉伯语都不错;Presidio 的 PII 检测在有正规训练数据的语言(英 / 西 / 法 / 德 / 中 / 日)最强,低资源文字弱。基于 LLM 的 rail(NeMo / llm-guard)继承底层前沿模型的语种覆盖 — 当下前沿模型覆盖广但不均匀。两条不可妥协的实践:(1) 按语种分别测 false positive / false negative 率,样本从你真实流量采、不是英文种子翻过去;(2) 当某个语种掉到可辩护阈值以下,把那个语种的更高比例路由到人审,直到模型改进,不要拿统一数字盖过去。
视频审核 — 抽多少帧合理?
没有通用答案;正确的数字取决于政策和视频时长。一般 UGC 的可辩护起点:前 30 秒每 1-2 秒抽 1 帧关键帧,30 秒之后每 5 秒 1 帧,场景切换检测(FFmpeg 原生支持)优先于均匀采样,让采样帧落在视觉上有区分度的帧上。配合强制分析前 3 秒(缩略图 + 开场)和后 3 秒(「头甜尾毒」的内容常出现在这里)。高风险政策(CSAM / 严重暴力)密采、接受成本;低风险政策(文案里的轻度脏话)少采或直接跳过帧、依赖文本层。最想避免的错误是 30 fps 全帧分类 — 那个让账单涨得比安全涨得快。
未成年保护怎么做?
本 pack 不打算做完整的儿童安全方案,因为那个问题需要法律、运营、上报工作,没有任何软件栈能单独搞定。本栈适用的基础设施部分:图片视频上传按未成年不当内容做严阈值分类(接近 T_block 而非 T_allow);维护已确认有害内容的感知哈希(OpenCV pHash),让二次上传在 hash 比对阶段就拦掉、不用走分类器;任何潜在 CSAM 路由到专门的升级队列(不是普通审核队列)、由专门训练的人审查、并明确移交给所在司法辖区的上报机构(美国是 NCMEC CyberTipline,其他辖区有对等机构)。工具替代不了项目 — 年龄判定、地区规则、家长同意、执法上报都是项目工作。先建项目,栈支撑它。
申诉率和推翻率应该控制在什么范围?什么各自说明什么?
没有放之四海皆准的数,但两个比率是值得长期追踪的健康信号。(1) 申诉率 = 申诉数 / 决策数。极低(远低于 1%)经常不是模型完美,而是用户不知道能申诉、或申诉入口被埋深了。极高(双位数往上)通常意味着模型过度拦截、政策对用户不清晰、或申诉表被当成了帮助渠道。(2) 推翻率 = 推翻的申诉 / 已裁决的申诉。推翻率高 = 模型在当前阈值上太激进,应该拿被推翻的样本回训或提高 T_block。推翻率极低有时是模型校准好了,有时是人审在锚定模型判定;做盲审抽查 — 让第二个审核员对随机样本盲判一次。按语种、按政策、按面各自追踪两个比率 — 总量会掩盖真正重要的差异。