三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

内容安全三道防线:内容审核API的多场景接入与响应解读

内容安全三道防线:内容审核API的多场景接入与响应解读

从业务痛点说起

内容审核几乎是每个带有用户生成内容(UGC)产品的公共话题。社区评论、用户昵称、弹幕、私信、商品评价……任何一处用户可输入文本的地方,都有可能被夹带敏感信息。如果完全靠人工审核,维护复杂度和时效都难以跟上;如果只依赖简单的关键词黑名单,又很容易被谐音、拼音、符号插入等变体绕过。

本文以一个具体的文本审核API为例,展示如何通过一套接口在一个或多个业务场景中落地内容安全能力。API基于"敏感词库 + 正则规则 + AI 特征评分"三重策略,对文本中的色情、政治、广告、联系方式、、谩骂六大类内容进行检测,输出 low / medium / high 风险等级,并且可以按需返回脱敏后的文本。

接口能力边界

在接入前先明确这个接口能做什么、不能做什么。这一点对后续的架构设计很重要。

支持的操作类型:

action用途限制
moderate单条文本审核文本长度 1-5000 字
batch批量文本审核最多 50 条
categories查询支持的敏感分类

检测范围:

  • 色情内容
  • 政治敏感内容
  • 广告信息
  • 联系方式(手机号、微信号、QQ 等)
  • 话术
  • 谩骂攻击

能力边界:

  • 接口只处理文本内容,不处理图片、音视频;
  • 限流为 10 QPS,超出后需要等待或做客户端限速;
  • 接口不负责业务层的决策,最终是放行、拦截还是转人工,需要业务方根据risk_levelis_pass自行决定。

请求参数与鉴权

鉴权方式

接口使用 Header 传递 API Key,字段名为Authorization。从 API 事实卡来看,该字段在文档中标记为非必需,但实际调用时建议务必携带,未携带或 Key 无效通常会返回 401 或 403。

Authorization: Bearer <你自己的 API Key>

需要说明的是,API 事实卡中未给出具体的鉴权格式细节(是否带 Bearer 前缀、Key 从哪里获取),这部分以官方文档为准。

请求体字段

请求体是一个 JSON 对象,核心字段如下:

参数类型必须说明
actionstring操作类型:moderate(默认)/batch/categories
textstringcondition待审核单条文本,仅moderate模式使用,1-5000 字
textsarraycondition批量文本数组,仅batch模式使用,最多 50 条
maskboolean是否返回脱敏文本,默认false

注意texttexts是互斥的,取决于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" }

逐项说明:

字段类型说明
codeint业务状态码,0表示请求成功
msgstring结果描述
request_idstring请求追踪 ID,排查问题时建议记录下来
data.categoriesarray命中的敏感分类列表,可能为空数组
data.detailsarray每个分类的检测细节
data.details[].categorystring分类名
data.details[].countint命中次数
data.details[].matchesarray命中的具体词或模式
data.details[].methodstring命中方式:敏感词/正则/AI特征
data.is_passboolean是否通过,false表示存在风险
data.masked_textstring脱敏后的文本,仅在mask=true时返回
data.original_lengthint原始文本长度
data.risk_levelstring综合风险:low/medium/high

method字段值得特别关注。如果检测结果显示正则,说明命中了变体规则(如谐音、拼音、符号插入);如果显示AI特征,说明没有匹配到具体词库,但 AI 打分认为文本有风险。可以根据生产环境的误判率,对不同method的结果采取差异化策略。

风险等级与业务策略

risk_levelis_pass是两个不同的维度。is_pass是一个简单的布尔值,risk_level则提供了更细的粒度。建议的映射策略:

risk_level建议处理方式
low放行
medium人工复核队列,或限制可见范围
high直接拦截,或要求用户修改

这只是参考,具体阈值可以根据业务容忍度调整。如果误判代价高,可以把medium也纳入人工审核;如果内容量极大,可以只对high做拦截。

常见错误与排查路径

以下是根据 HTTP 状态和返回结构整理的排查思路。API 事实卡没有给出完整的错误码表,以下部分为通用经验,具体的错误码字段以文档为准。

401/403:鉴权失败

  • 确认AuthorizationHeader 是否携带;
  • 确认 API Key 是否有效,是否过期;
  • 如果文档要求 Bearer 前缀,检查是否拼写正确。

400:参数错误

  • action=moderatetext不能为空;
  • action=batchtexts不能是空数组;
  • 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 的定位很清晰:用三重策略降低变体绕过的风险,通过风险等级和脱敏能力让业务侧有灵活的处理空间。接入时重点把握好三点:参数语义要理解准确(尤其是moderatebatch的互斥关系)、风险等级要映射到明确的业务动作、工程上要做好超时和降级。

对于内容审核这件事,没有哪个接口能做到百分百准确。合理的做法是让 API 承担第一道过滤,把明显违规的内容挡掉,把模糊的内容交给人工或更精细的策略处理。

参考文档

  • API 文档页:https://apizero.cn/aidocs/content-moderation
  • 原始文档(Markdown):https://apizero.cn/aidocs/content-moderation/raw.md
← 返回列表