这是 Beta 探索课程,内容结构、实验步骤和示例可能会继续调整。
内容审核
一次线上事故
图片平台上线三个月后,我们遇到了一次严重的线上事故:有用户上传了违规图片,因为没有审核机制,图片直接对外可见,被监管部门通报。
那次之后,我们意识到:图片平台一旦允许用户上传内容,就必须把内容安全纳入主链路设计。内容审核不是一个外挂功能,而是决定图片何时可见、何时需要拦截、何时进入人工复核、何时保留证据的状态机。
审核状态机
图片从上传完成到对外可见,需要经过明确的状态流转:
上传完成 → 待审核 → 机审中 → 机审通过 → 可对外展示
↓ ↓
审核失败 低置信度 → 人审中 → 人审通过 → 可对外展示
↓
人审拒绝 → 已拦截 → 保留证据
每一步都要产生明确状态,而不是只留下一个模糊的通过或失败。CDN 加速、缩略图生成和业务展示都依赖这个可见性状态,避免”原图还没过审但链接已经被公开访问”的漏洞。
机审层
机审负责快速识别,目标是高召回、可接受的误杀率:
| 审核类型 | 识别内容 | 处理方式 |
|---|---|---|
| 色情识别 | 色情、低俗图片 | 高置信度直接拦截,中置信度转人审 |
| 暴恐识别 | 暴力、恐怖主义内容 | 高置信度直接拦截 |
| 政治敏感 | 政治敏感人物、事件 | 高置信度直接拦截,全部转人审复核 |
| 二维码/广告 | 引流二维码、广告图片 | 标记为广告,根据业务策略处理 |
| 低质内容 | 模糊、过暗、过曝 | 标记为低质,不拦截但降权 |
机审服务消费上传事件,读取原图或低分辨率预览图(降低传输成本),调用识别模型,写入审核记录。
def audit_image(image_id):
image = get_image(image_id)
# 用低分辨率预览图加速审核
preview = generate_preview(image, max_size=512)
results = {}
results['porn'] = porn_model.detect(preview)
results['terror'] = terror_model.detect(preview)
results['political'] = political_model.detect(preview)
results['qrcode'] = qrcode_detector.detect(preview)
# 综合判定
decision = make_decision(results)
# decision = 'pass' | 'reject' | 'manual'
save_audit_record(image_id, results, decision)
update_image_status(image_id, decision)
return decision
规则层
规则层负责处理业务语义,不能只靠模型:
- 用户等级:新用户上传的图片更严格,老用户可以适当放宽
- 业务场景:头像审核比内容图严格,营销素材走人工预审
- 历史风险:有违规记录的用户上传的图片全部转人审
- 灰度策略:新模型上线时先灰度 10%,观察误杀率后再全量
规则层在机审结果之上做二次判定,确保审核策略和业务目标对齐。
人审层
人审负责处理模型低置信度、用户申诉和高风险样本:
- 低置信度样本:模型置信度在 0.4-0.7 之间的,转人审
- 用户申诉:用户对审核结果有异议的,转人审复核
- 高风险样本:政治敏感、未成年人相关的,全部转人审
- 抽检:机审通过的样本按比例抽检,持续评估模型质量
人审后台需要支持:
- 快速浏览图片和审核建议
- 一键通过/拒绝/标记
- 审核结果反馈给模型,用于持续优化
- 审核员工作量和准确率统计
已发布图片召回
对于已发布后被召回的图片(比如用户举报、模型更新后重新识别),系统需要支持:
- 缓存刷新:通过 CDN 刷新接口清除该图片的所有边缘缓存
- 访问拦截:将图片状态改为”已拦截”,CDN 回源时返回 403 或占位图
- 审计追踪:记录召回原因、操作人、时间,保留原图作为证据
- 用户通知:如果是用户上传的图片,通知用户审核结果和申诉渠道
验收标准
完成本章后,你会得到一套可落地的图片审核模型:
- 状态流转清晰:待审核 → 机审 → 通过/拒绝/人审 → 最终状态
- 机审与人审有边界:机审高置信度自动处理,低置信度转人审
- 误杀和漏放有处理路径:用户申诉、抽检、模型迭代
- 所有对外可见的图片都能追溯:审核结论、模型版本、审核时间、操作人
内容审核是图片平台的生命线,设计时必须同时考虑准确性、时效性和可追溯性。
