AI 文本审核 API:一段中文文本判风险等级、命中标签与处置建议

AI 文本审核 API:一段中文文本判风险等级、命中标签与处置建议

UGC 内容、评论、私信、商品描述、客服话术,只要允许用户自由输入,就绕不开内容风控。关键词库维护到几万条仍然漏判误判,"免费日入过万" 换个说法就绕过,"傻X" 中间插个符号就绕过。text.moderation 把这件事做成一个 GET / POST 都能调的接口:一段中文文本进去,返回风险等级(none / low / medium / high)+ 命中标签明细 + 置信度 + 处置建议 ,并且审核服务不可用时不收费。

  • api.xujian.tech
  • V:xujian_cq

接口速览

关键事实 说明
接口地址 https://api.xujian.tech/openapi/text/moderation
接口编码 text.moderation
请求方式 GET(content 放 Query)或 POST(JSON {"content":"..."}),二者等价
鉴权方式 请求头 X-API-Key,不做签名、时间戳或加密
入参 只有 content 一个字段,最长 1800 字符
返回核心字段 riskLevel(风险等级)/ labels(命中标签数组)/ suggest(处置建议)
标签体系 11 类违规标签 + nonLabel(未检测出风险)
计费方式 按次计费,0.01 元/次,先预鉴权、给出审核结论后再扣费
不计费场景 content 为空、超过 1800 字符、审核服务不可用、返回结果无法解析
建议超时 60 秒以上(含语义判定耗时)
单次耗时 通常 1 ~ 数秒,costMs 为真实耗时

注意:"未检测出风险" 属于一次成功的审核,正常计费。合规结论本身有价值,判定为"可以放行"也是一次有效调用。

一、哪些业务需要这一步

场景 具体用法
社区 / 论坛发帖 发布前先审,命中 high 直接拦截,medium 转人工
评论与弹幕 高并发短文本,建议先审后放,low 可抽样复核
私信 / 即时通讯 拦截诈骗导流、联系方式导流,防止用户被骗
商品标题与详情 拦截违禁品交易、极限词与医疗夸大宣传
用户昵称 / 签名 / 头像文案 注册与修改时校验,避免涉政、辱骂类昵称上线
客服与工单 识别用户辱骂、威胁,优先转人工处理
搜索词与反馈 拦截恶意灌入的违规内容
招聘与简历 识别歧视性表述与隐私泄露(身份证、手机号、住址)
内容平台审核后台 作为机审层,与人工复核形成两级队列
数据采集清洗 入库前批量过滤掉明显违规文本

二、请求参数

2.1 请求头

参数名 必填 说明
X-API-Key 是 开发者 API Key,缺失或无效直接返回失败(不计费)
Content-Type 否 POST JSON 时填 application/json;GET 与表单提交可不传

2.2 业务参数

参数名 位置 类型 示例 说明
content GET Query / POST JSON body String 加我微信 xxx666,带你日入过万 待审核文本,唯一入参,最长 1800 字符

长度口径:服务端会先把换行、制表符替换为空格、把连续空格压缩成一个,再 trim 后计算长度。也就是说长度按"清洗后"的文本算,一段带大量换行的文本不会因为换行符被误判为超长。

三、返回字段

3.1 顶层与 data

字段 类型 说明
code int 0 成功,非 0 失败(统一为 500)
msg String 成功为 success,失败为具体原因
data Object 业务数据,失败时为 null

data 字段:

字段 类型 示例 说明
riskLevel String high 风险等级:none 未检测到风险 / low 低风险 / medium 中风险 / high 高风险
riskLevelText String 高风险 等级中文名,直接展示用
suggest String 建议拦截并转人工核实 处置建议,可直接进审核后台的"处理意见"栏
summary String 疑似诈骗与广告导流内容 一句话结论,最多 100 字
labels Array 见下 命中标签明细,最多 10 条,按危险程度从高到低排列
apiCode String text.moderation 接口编码
apiName String AI文本审核服务 接口名称
chargeType String PER_CALL 计费类型
balance BigDecimal 99.9900 扣费后的账户余额(元)
costMs Long 860 本次调用耗时(毫秒)

3.2 labels 元素

字段 类型 示例 说明
label String fraud 标签编码,见标签表
labelName String 诈骗欺诈 标签中文名
description String 疑似返利诈骗内容 本次命中的具体说明,20 字以内
confidence BigDecimal 92.00 置信度 0 ~ 100,保留 2 位小数;可能为 null(把握不足时不给分值)

3.3 标签体系(对外承诺的完整取值)

编码 中文名 风险等级 典型内容
political 涉政敏感 high 危害国家安全、分裂国家、损害国家形象与领导人不当表述
pornography 色情低俗 high 淫秽描写、招嫖、性交易暗示
violence 暴恐极端 high 暴力血腥、恐怖袭击、极端主义宣扬
gambling 赌博相关 high 赌博平台推广、赌局邀约
drug 毒品违法 high 毒品交易、吸食引导
fraud 诈骗欺诈 high 刷单返利、冒充公检法、钓鱼链接
prohibited 违禁品交易 high 枪支弹药、管制刀具、野生动物交易
abuse 攻击辱骂 medium 人身攻击、侮辱诽谤、歧视性言论
ad 广告导流 medium 营销推广、联系方式导流、二维码拉群
privacy 隐私泄露 medium 他人身份证号、手机号、住址、银行卡号
other 其他违规 low 不属于以上任何一类但确实不宜发布
nonLabel 未检测出风险 none 占位标签 :没有命中任何违规时,labels 会返回这一条

风险等级不是逐个标签自评出来的,而是服务端取命中标签中的最高等级统一推导,保证同一段文本多次调用得到的等级口径稳定、可复现。

3.4 处置建议对照表

riskLevel riskLevelText suggest
none 未检测到风险 建议直接放行
low 低风险 建议放行;高召回场景可抽样转人工复核
medium 中风险 建议人工复核后再决定是否放行
high 高风险 建议拦截并转人工核实

四、调用示例

4.1 curl(GET)

bash 复制代码
curl -s -G "https://api.xujian.tech/openapi/text/moderation" \
  -H "X-API-Key: 你的APIKey" \
  --data-urlencode "content=加我微信 xxx666,带你日入过万,内部渠道稳赚不赔"

4.2 curl(POST JSON,推荐用于含换行、引号的长文本)

bash 复制代码
curl -s -X POST "https://api.xujian.tech/openapi/text/moderation" \
  -H "X-API-Key: 你的APIKey" \
  -H "Content-Type: application/json" \
  -d '{"content":"加我微信 xxx666,带你日入过万,内部渠道稳赚不赔"}'

4.3 Java(Hutool)

java 复制代码
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

public class TextModerationClient {

    private static final String API_URL = "https://api.xujian.tech/openapi/text/moderation";

    /**
     * 审核一段文本
     *
     * @param apiKey  开发者 API Key
     * @param content 待审核文本,最长 1800 字符
     * @return data 节点;服务不可用时返回 null,且不扣费
     */
    public static JSONObject moderate(String apiKey, String content) {
        JSONObject json = JSONUtil.parseObj(
                HttpRequest.post(API_URL)
                        .header("X-API-Key", apiKey)
                        // 段落文本交给 JSON,避免换行、&、= 等字符破坏 Query String
                        .body(JSONUtil.createObj().set("content", content).toString())
                        .timeout(60000)
                        .execute().body());
        if (json.getInt("code") == null || json.getInt("code") != 0) {
            System.out.println("审核失败(不收费):" + json.getStr("msg"));
            return null;
        }
        return json.getJSONObject("data");
    }

    public static void main(String[] args) {
        JSONObject data = moderate("你的APIKey", "你这个傻东西,脑子有问题吧,滚出这个群");
        if (data == null) {
            return;
        }
        System.out.println(data.getStr("riskLevel") + " / " + data.getStr("suggest"));
        data.getJSONArray("labels").forEach(item -> {
            JSONObject label = (JSONObject) item;
            System.out.printf("命中:%s(%s) %s%n",
                    label.getStr("labelName"), label.getStr("label"), label.getStr("description"));
        });
    }
}

4.4 Python

python 复制代码
import requests


def moderate(api_key: str, content: str):
    """返回 data 节点;服务不可用或参数非法返回 None,且不扣费"""
    resp = requests.post(
        "https://api.xujian.tech/openapi/text/moderation",
        json={"content": content},
        headers={"X-API-Key": api_key},
        timeout=60,
    )
    result = resp.json()
    if result.get("code") != 0:
        print("审核失败(不收费):", result.get("msg"))
        return None
    return result["data"]


if __name__ == "__main__":
    data = moderate("你的APIKey", "加我微信 xxx666,带你日入过万,内部渠道稳赚不赔")
    if data:
        print(data["riskLevel"], data["riskLevelText"], data["suggest"])
        for item in data["labels"]:
            print(item["label"], item["labelName"], item["confidence"])

4.5 JavaScript

javascript 复制代码
async function moderate(apiKey, content) {
  const resp = await fetch("https://api.xujian.tech/openapi/text/moderation", {
    method: "POST",
    headers: { "X-API-Key": apiKey, "Content-Type": "application/json" },
    body: JSON.stringify({ content })
  });
  const result = await resp.json();
  if (result.code !== 0) {
    throw new Error(result.msg);
  }
  return result.data;
}

五、返回示例

命中两个标签(诈骗 + 广告导流):

json 复制代码
{
  "code": 0,
  "msg": "success",
  "data": {
    "riskLevel": "high",
    "riskLevelText": "高风险",
    "suggest": "建议拦截并转人工核实",
    "summary": "疑似诈骗与广告导流内容",
    "labels": [
      {"label": "fraud", "labelName": "诈骗欺诈", "description": "疑似返利诈骗内容", "confidence": 92.00},
      {"label": "ad", "labelName": "广告导流", "description": "疑似联系方式导流", "confidence": 88.00}
    ],
    "apiCode": "text.moderation",
    "apiName": "AI文本审核服务",
    "chargeType": "PER_CALL",
    "balance": 99.9800,
    "costMs": 860
  }
}

完全正常的文本(同样算一次成功调用,正常计费):

json 复制代码
{
  "code": 0,
  "msg": "success",
  "data": {
    "riskLevel": "none",
    "riskLevelText": "未检测到风险",
    "suggest": "建议直接放行",
    "summary": "正常文本,未检测出风险",
    "labels": [
      {"label": "nonLabel", "labelName": "未检测出风险", "description": "未检测出风险", "confidence": null}
    ],
    "apiCode": "text.moderation",
    "apiName": "AI文本审核服务",
    "chargeType": "PER_CALL",
    "balance": 99.9900,
    "costMs": 720
  }
}

超长文本(不收费):

json 复制代码
{
  "code": 500,
  "msg": "content 长度不能超过 1800 个字符",
  "data": null
}

六、可直接复用的两段代码

6.1 按风险等级分流到"放行 / 复核 / 拦截"三个队列

python 复制代码
QUEUE = {"none": "pass", "low": "pass", "medium": "review", "high": "block"}


def route(data: dict) -> str:
    """审核结论 → 处理队列;labels 为空或只有 nonLabel 时按 none 处理"""
    return QUEUE.get(data["riskLevel"], "review")


def hit_labels(data: dict) -> list:
    """只取真实命中的标签,过滤掉 nonLabel 占位"""
    return [i["label"] for i in data["labels"] if i["label"] != "nonLabel"]

6.2 长文本按句拆分后批量审核(规避 1800 字符限制)

python 复制代码
def split_and_moderate(api_key: str, text: str, size: int = 1500):
    """长文按标点切成 <= size 的片段,返回最高风险等级与全部命中标签"""
    import re

    chunks, buf = [], ""
    for sentence in re.split(r"(?<=[。!?;\n])", text):
        if len(buf) + len(sentence) > size:
            chunks.append(buf)
            buf = ""
        buf += sentence
    if buf:
        chunks.append(buf)

    level_rank = {"none": 0, "low": 1, "medium": 2, "high": 3}
    top, labels = "none", []
    for chunk in chunks:
        data = moderate(api_key, chunk)
        if not data:
            continue
        if level_rank[data["riskLevel"]] > level_rank[top]:
            top = data["riskLevel"]
        labels += hit_labels(data)
    return top, labels

长文拆句会按片段数计费,建议只对确实需要全文审核的正文(如详情页、长帖)这么做,评论类短文本直接单次调用。

七、实践建议

  1. 超过 1800 字符先切分。超长直接失败且不计费,长文用第六节的拆句方案。
  2. 判定口径以 riskLevel 为准 。suggest 是给审核员看的建议文案,业务分流请读等级字段。
  3. confidence 可能为 null 。把握不足时不给分值,代码里要做判空,别直接 float(confidence)。
  4. nonLabel 不是命中。它只是"未检测出风险"的占位,过滤标签时要排除。
  5. 不要拿它当唯一防线。高风险内容(尤其涉政、暴恐)建议与人工复核、关键词黑名单组合使用。
  6. 超时设 60 秒以上。语义判定比字符串匹配慢,别用查询类接口的 5 秒超时。
  7. 结果可以缓存。同一段文本(去空格后哈希)的结论在短期内不会变,缓存 Key 用文本哈希可省掉重复调用。
  8. 别做高频轮询。0.01 元/次虽然便宜,但评论流里每条都调、并且重复调用同一条,量起来也很可观。
  9. 审核结论要留痕 。把 riskLevel + labels + suggest + costMs 一起写进自己的审核日志,便于事后追责与策略复盘。

八、错误码与排查

code msg 是否扣费 处理建议
0 success 是(0.01 元) 读取 data,按 riskLevel 分流
500 缺少请求头 X-API-Key 否 请求头补 X-API-Key
500 API Key 无效 / API Key 已停用 否 到控制台核对 Key 状态
500 客户不存在或已停用 否 联系平台开通
500 接口不存在或已停用 否 确认接口编码 text.moderation
500 余额不足,请先充值 否 预鉴权阶段就被拦下,不产生费用
500 content 不能为空(GET 传 Query 参数,POST 传 JSON {"content":"..."}) 否 检查参数位置:GET 只能走 Query
500 content 长度不能超过 1800 个字符 否 截断或按句拆分后重试
500 文本审核服务暂时不可用(...),本次调用不计费 否 稍后重试;连续失败可提交工单

所有失败场景统一返回 code=500,是否扣费以上表为准。判断"到底扣没扣费"最可靠的依据是响应 data.balance 是否减少。

九、计费与接入

项目 说明
单价 0.01 元/次
计费方式 按次计费,调用前先预鉴权(余额不足直接拒绝);给出审核结论后才扣费
计费判定 正常返回审核结论即计一次,包括"未检测出风险"
不计费场景 content 为空、超过 1800 字符、审核服务不可用、返回结果无法解析;鉴权失败与余额不足同样不扣费
建议超时 60 秒以上(含语义判定)

接入流程:注册开发者账号 → 控制台创建 API Key → 请求头带上 X-API-Key 即可调用,无需签名或加密。控制台可查看调用量、扣费流水与余额。

服务站点:api.xujian.tech(纯文本域名,不做跳转)。接口试用、数据与充值咨询可在控制台提交工单,或联系 Vxujian_cq。

十、小结

自建内容风控的成本不在"调用",而在"维护":词库要人跟、规则要人调、误判要人赔。做成接口之后,这段文本合规与否变成一分钱一次的判断,并且判定不出结论时不收费。

使用时要记住:

  • 一个入参、四个等级 :content 进去,none / low / medium / high 出来,按等级分流即可;
  • 读 riskLevel 而不是 summary:等级是服务端统一推导的稳定口径,文案只是说明;
  • "没风险"也计费:它是一次有效的合规判定,高频重复调用仍然要花钱;
  • 1800 字符是硬上限:长文先拆句,别指望一次塞进去。

配套接口:vehicle.license(0.1 元/次)用于识别机动车行驶证,二者组合即可覆盖"文字 + 证照"两类主流 UGC 材料的机审环节。

相关推荐
~~~4551 小时前
Java 数组详细笔记
java
Jinkxs1 小时前
Zookeeper - Java API 实现节点的创建与删除开发
java·zookeeper·java-zookeeper
liangshanbo12151 小时前
前端面试题:AI 对话中超长消息导致内存溢出,怎么解决?
java·开发语言·前端
草上飞95271 小时前
把前沿能力装进便宜产物,本身是多数模型还不会的能力
人工智能·深度学习·llm
林澈在路上1 小时前
2026生成后可发行的AI音乐工具怎么选
人工智能·版权·ai音乐·音乐发行·melo音乐
律宏阔1 小时前
Dart FFI 内存管理:用 using + Arena 替代嵌套 try-finally
前端·flutter
LoneEon1 小时前
CentOS7 部署 Nacos3.x 集群实战:从注册中心到 AI 管理中心
linux·人工智能·nacos
极客先躯1 小时前
高级java每日一道面试题-2026年01月20日-实战篇[Docker]-如何实现镜像的跨区域复制?
java·运维·docker·容器·架构图
跟我学机器学习1 小时前
Qwen3 Reranking原理与使用:重排模型在 RAG 中的作用
人工智能·深度学习·transformer