内容安全三道防线:内容审核API的多场景接入与响应解读
从业务痛点说起
内容审核几乎是每个带有用户生成内容(UGC)产品的公共话题。社区评论、用户昵称、弹幕、私信、商品评价……任何一处用户可输入文本的地方,都有可能被夹带敏感信息。如果完全靠人工审核,维护复杂度和时效都难以跟上;如果只依赖简单的关键词黑名单,又很容易被谐音、拼音、符号插入等变体绕过。
本文以一个具体的文本审核API为例,展示如何通过一套接口在一个或多个业务场景中落地内容安全能力。API基于"敏感词库 + 正则规则 + AI 特征评分"三重策略,对文本中的色情、政治、广告、联系方式、、谩骂六大类内容进行检测,输出 low / medium / high 风险等级,并且可以按需返回脱敏后的文本。
接口能力边界
在接入前先明确这个接口能做什么、不能做什么。这一点对后续的架构设计很重要。
支持的操作类型:
| action | 用途 | 限制 |
|---|---|---|
moderate | 单条文本审核 | 文本长度 1-5000 字 |
batch | 批量文本审核 | 最多 50 条 |
categories | 查询支持的敏感分类 | 无 |
检测范围:
- 色情内容
- 政治敏感内容
- 广告信息
- 联系方式(手机号、微信号、QQ 等)
- 话术
- 谩骂攻击
能力边界:
- 接口只处理文本内容,不处理图片、音视频;
- 限流为 10 QPS,超出后需要等待或做客户端限速;
- 接口不负责业务层的决策,最终是放行、拦截还是转人工,需要业务方根据
risk_level和is_pass自行决定。
请求参数与鉴权
鉴权方式
接口使用 Header 传递 API Key,字段名为Authorization。从 API 事实卡来看,该字段在文档中标记为非必需,但实际调用时建议务必携带,未携带或 Key 无效通常会返回 401 或 403。
Authorization: Bearer <你自己的 API Key>需要说明的是,API 事实卡中未给出具体的鉴权格式细节(是否带 Bearer 前缀、Key 从哪里获取),这部分以官方文档为准。
请求体字段
请求体是一个 JSON 对象,核心字段如下:
| 参数 | 类型 | 必须 | 说明 |
|---|---|---|---|
action | string | 否 | 操作类型:moderate(默认)/batch/categories |
text | string | condition | 待审核单条文本,仅moderate模式使用,1-5000 字 |
texts | array | condition | 批量文本数组,仅batch模式使用,最多 50 条 |
mask | boolean | 否 | 是否返回脱敏文本,默认false |
注意text和texts是互斥的,取决于action的值。如果action=moderate但没有传text,或action=batch但没有传texts,服务端会按参数校验失败处理。
三种操作模式的 curl 示例
模式一:单条文本审核
这是最基本的用法,适合审核用户提交的单个字段,比如评论内容、个人简介等。
curl -sS \ -X POST \ -H "Authorization: Bearer $APIZERO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "action": "moderate", "text": "今天天气不错,晚上一起吃饭吧", "mask": "true" }' \ "https://v1.apizero.cn/api/content-moderation"你需要在执行前先在环境变量中设置APIZERO_API_KEY,或直接将字符串替换到 Header 中。
模式二:批量审核
适合内容发布后台的定时巡检、存量数据清洗等场景。
curl -sS \ -X POST \ -H "Authorization: Bearer $APIZERO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "action": "batch", "texts": ["第一条待审核内容", "第二天带敏感词的内容"], "mask": "true" }' \ "https://v1.apizero.cn/api/content-moderation"模式三:查询分类
在接入初期,建议先调用一次categories模式,确认当前接口实际返回的分类集合,避免在代码里写死分类名。
curl -sS \ -X POST \ -H "Authorization: Bearer $APIZERO_API_KEY" \ -H "Content-Type: application/json" \ -d '{"action": "categories"}' \ "https://v1.apizero.cn/api/content-moderation"Python 代码接入示例
curl 适合调试,工程接入更推荐用 Python 等语言封装。以下示例使用requests库实现一次带超时与错误处理的调用。
import os import requests def moderate_text(text: str, mask: bool = True) -> dict: """ 单条文本审核 """ api_url = "https://v1.apizero.cn/api/content-moderation" headers = { "Authorization": f"Bearer {os.getenv('APIZERO_API_KEY', '')}", "Content-Type": "application/json", } payload = { "action": "moderate", "text": text, "mask": mask, } try: resp = requests.post(api_url, json=payload, headers=headers, timeout=5) resp.raise_for_status() # 非 2xx 会抛异常 return resp.json() except requests.exceptions.Timeout: # 工程上建议做重试或降级处理 return {"code": -1, "msg": "request timeout"} except requests.exceptions.RequestException as exc: return {"code": -2, "msg": str(exc)} if __name__ == "__main__": sample = "你这个傻逼,整天就知道打广告,加我微信xxxxx" result = moderate_text(sample, mask=True) data = result.get("data", {}) print("风险等级:", data.get("risk_level")) print("是否需要拦截:", data.get("is_pass")) print("命中的分类:", data.get("categories")) print("脱敏后文本:", data.get("masked_text"))响应字段解读
以一个成功的响应为例:
{ "code": 0, "data": { "categories": ["谩骂"], "details": [ { "category": "谩骂", "count": 2, "matches": ["傻逼", "脑残"], "method": "敏感词" } ], "is_pass": false, "masked_text": "你这个**,**吧", "original_length": 10, "risk_level": "high" }, "msg": "成功", "request_id": "abc123" }逐项说明:
| 字段 | 类型 | 说明 |
|---|---|---|
code | int | 业务状态码,0表示请求成功 |
msg | string | 结果描述 |
request_id | string | 请求追踪 ID,排查问题时建议记录下来 |
data.categories | array | 命中的敏感分类列表,可能为空数组 |
data.details | array | 每个分类的检测细节 |
data.details[].category | string | 分类名 |
data.details[].count | int | 命中次数 |
data.details[].matches | array | 命中的具体词或模式 |
data.details[].method | string | 命中方式:敏感词/正则/AI特征 |
data.is_pass | boolean | 是否通过,false表示存在风险 |
data.masked_text | string | 脱敏后的文本,仅在mask=true时返回 |
data.original_length | int | 原始文本长度 |
data.risk_level | string | 综合风险:low/medium/high |
method字段值得特别关注。如果检测结果显示正则,说明命中了变体规则(如谐音、拼音、符号插入);如果显示AI特征,说明没有匹配到具体词库,但 AI 打分认为文本有风险。可以根据生产环境的误判率,对不同method的结果采取差异化策略。
风险等级与业务策略
risk_level和is_pass是两个不同的维度。is_pass是一个简单的布尔值,risk_level则提供了更细的粒度。建议的映射策略:
| risk_level | 建议处理方式 |
|---|---|
low | 放行 |
medium | 人工复核队列,或限制可见范围 |
high | 直接拦截,或要求用户修改 |
这只是参考,具体阈值可以根据业务容忍度调整。如果误判代价高,可以把medium也纳入人工审核;如果内容量极大,可以只对high做拦截。
常见错误与排查路径
以下是根据 HTTP 状态和返回结构整理的排查思路。API 事实卡没有给出完整的错误码表,以下部分为通用经验,具体的错误码字段以文档为准。
401/403:鉴权失败
- 确认
AuthorizationHeader 是否携带; - 确认 API Key 是否有效,是否过期;
- 如果文档要求 Bearer 前缀,检查是否拼写正确。
400:参数错误
action=moderate时text不能为空;action=batch时texts不能是空数组;text超过 5000 字会被拒绝;texts超过 50 条会被拒绝。
429:触发限流
- API 限制为 10 QPS;
- 客户端需要做本地限速或请求排队;
- 更推荐的做法是批量模式合成一次请求,而不是高频调用单条审核。
500:服务端异常
- 记录
request_id,便于在联系技术支持时提供; - 对调用方而言,需要实现退避重试,建议指数退避,例如 1s / 2s / 4s / 8s,最多重试 3 次。
工程化接入注意事项
1. 区分同步与异步场景
像社区发帖这种场景,用户点了发布按钮,一般等不了 5 秒。如果接口响应时间长,建议改为异步:先把内容写入待审表,后台任务调审核接口,再回写审核结果。如果是私信这种实时性要求高的场景,可以对单条做同步调用,但要有超时兜底。
2. 高可用降级方案
任何第三方接口都可能抖动。业务上必须设计降级逻辑:
- 审核接口超时或 5xx 时,是放行还是拦截?
- 建议对高风险内容默认拦截(Fail-Closed),对普通场景默认放行(Fail-Open)并记录日志。
- 至少保证核心链路不因为审核服务不可用而整体瘫痪。
3. 合理利用批量模式
批量接口上限是 50 条,适合后台定时任务。例如每天凌晨跑全量存量内容的巡检,或者在高峰期把评论攒起来按批提交,减少 QPS 压力。
4. 缓存与去重
敏感词检测结果在一定时间段内是稳定的。对相同内容重复审核是浪费。可以做一个简单的缓存:以文本 hash 为 key,把低风险结果缓存 5-15 分钟,命中缓存直接返回。
5. 保留原始文本与审核日志
合规审计时需要回溯。建议在数据库里单独保存原始文本、审核结果、风险等级、请求 ID 和检测细节(JSON 序列化),这些数据对后续分析召回率和误判率非常重要。
小结
这个内容审核 API 的定位很清晰:用三重策略降低变体绕过的风险,通过风险等级和脱敏能力让业务侧有灵活的处理空间。接入时重点把握好三点:参数语义要理解准确(尤其是moderate和batch的互斥关系)、风险等级要映射到明确的业务动作、工程上要做好超时和降级。
对于内容审核这件事,没有哪个接口能做到百分百准确。合理的做法是让 API 承担第一道过滤,把明显违规的内容挡掉,把模糊的内容交给人工或更精细的策略处理。
参考文档
- API 文档页:https://apizero.cn/aidocs/content-moderation
- 原始文档(Markdown):https://apizero.cn/aidocs/content-moderation/raw.md