用 Jev 做内容审核:一致、可解释的判定
更新于 适用版本 Jev 1.13
TL;DR: 内容审核不是一个难题,而是很多个小决策。用
choice调用对扁平类别列表做分诊,置信度不足时对具体政策规则降级为judgment调用,每次删除都把rationale存成审计记录。一致性来自固定的问题格式,可解释性来自 rationale。下文给出流程、阈值与申诉路径。
先设计类别
分两层,刻意保持简单:
- 第一层——choice 调用:从固定列表里选恰好一个类别,例如
spam(垃圾信息)、harassment(骚扰)、adult(成人内容)、violence(暴力)、none(无违规)。 - 第二层——按规则的 judgment 调用:当第一层结果是
unclear或置信度低于阈值时,针对一条具体规则提是/否问题(“这段文字是否包含可信的威胁?”)。示例数据(example fixture):
{"answer":"yes","confidence":0.97,"rationale":"该消息以付款为条件威胁人身伤害。"}
这与人审团队的实际工作方式一致:先分诊,难例逐条规则复核。同时每个问题都很小——这正是判断模型(judgment model)最喜欢的输入形态。
审核流程图
内容提交
|
v
Jev choice 调用(类别:spam / harassment / adult / violence / none)
|
+--> 类别 = none 且置信度高 --> 发布
|
+--> 置信度低或类别不确定
| |
| v
| Jev judgment 调用(针对具体规则:yes / no / unclear)
| |
| +--> 明确 yes / no --> 执行动作,存 rationale
| |
| +--> 仍不明确 --> 人工审核队列
|
+--> 明确违规 --> 删除,存 rationale,附带申诉链接通知用户
每次删除固定存储五元组:内容 id、类别、answer、confidence、rationale、模型版本。这就是你的审计记录(audit trail)。
最小实现
import os, json, requests
URL = "https://openrouter.ai/api/v1/chat/completions"
# Confirm the exact model slug on the OpenRouter model page.
MODEL = "typesafe/jev-1.13"
CATEGORIES = ["spam", "harassment", "adult", "violence", "none"]
def call(system: str, text: str) -> dict:
resp = requests.post(
URL,
headers={"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}"},
json={"model": MODEL, "temperature": 0, "messages": [
{"role": "system", "content": system},
{"role": "user", "content": text}]},
timeout=30,
)
resp.raise_for_status()
# 示例数据(example fixture,judgment):
# {"answer":"yes","confidence":0.97,"rationale":"..."}
return json.loads(resp.json()["choices"][0]["message"]["content"])
def moderate(text: str, low=0.85) -> dict:
c = call("Pick exactly one category from: "
+ ", ".join(CATEGORIES) + ".", text)
if c["answer"] != "none" and c["confidence"] >= low:
return {"action": "remove", **c}
if c["confidence"] >= low:
return {"action": "publish", **c}
j = call("Does this text violate the harassment policy? "
"Answer yes, no, or unclear.", text)
if j["answer"] == "unclear" or j["confidence"] < low:
return {"action": "human-review", **j}
return {"action": "remove" if j["answer"] == "yes" else "publish", **j}
官方 API 的端点与字段请以 typesafe.ai 官方文档为准。
阈值与申诉路径
| 阶段 | 配置项 | 建议 |
|---|---|---|
| 第一层 choice | 自动执行阈值 | 删除与发布统一用 confidence >= 0.85 |
| 第二层 judgment | 边界规则复核 | 第一层低置信度时触发;仅对明确的 yes/no 执行动作 |
| 人工队列 | 触发条件 | 任何 unclear 结果,或第二层后置信度仍低于阈值 |
| 审计记录 | 一律存储 | 内容 id、类别、answer、confidence、rationale、模型版本 |
| 申诉 | 用户可见 | 通知里附 rationale 摘要与一键申诉入口 |
为什么问题格式这么重要,见状态与问题(state and questions)指南;阈值调优见置信度与兜底(confidence and fallback)指南。多语言审核案例展示了这套两层设计在跨语言场景下的表现。
本文适用版本:Jev 1.13。
FAQ
- 审核类别怎么组织? 第一层 choice 用扁平列表(spam、harassment、adult、violence、none),边界情况用按规则的 judgment 复核,不要写一个巨型多标签提示词。
- 为什么要保留 rationale? 它是审计记录:向用户、申诉审核员和监管方解释每次删除,比人工备注一致得多。
- 置信度低怎么办? 针对具体规则做第二次 judgment,仍不明确就进人工队列——无论哪一步都附带 rationale。