晓语 · 中文 AI 检测
输入一段中文文本,输出两样东西:一个整篇概率,和每句话的句头概率。
模型是中文 RoBERTa(BERT-base 结构)微调而来的二分类器,单 logit → sigmoid 得概率。
当前模型版本 V3.3。默认 int4 权重 60.2MB:本包不附带权重文件,首次使用前跑一次 scripts/download.py 从魔搭拉取;之后纯 CPU 本地推理,不联网、不上传文本。
判决口径(唯一一套尺子)
| AI生成概率 | 判决 | |---|---| | ≥ 90% | AI特征明显 | | 50% – 90% | 疑似AI参与 | | < 50% | AI特征不明显 |
整篇和句头共用这一套线,显示的数字和判定用的线必须是同一把尺子, 否则会出现「45% 却判疑似AI参与」这种看不懂的输出。
概率是模型输出,判决是规则,两回事。要改判决线就改常量 T_AI / T_SUS,不要动模型。
整篇概率怎么算:两种聚合,刻度不同
模型一次只能吃 512 token(中文约 600 汉字)。超过就切窗再合并:
- 500 字/窗、步长 400(重叠 100 字,避免跨窗切断语义),滑过全文
- 窗级
sigmoid再聚合,两种方式可选
| 方式 | 算法 | 说明 |
|---|---|---|
| eq 等权 | Σp / n | 每窗一票,默认 |
| len 加权 | Σ(len·p) / Σlen | 按窗口字数加权,末窗短就少说 |
不满 500 字符的文本切不出第二个窗,自动退化为单窗,两种口径给出同一个数。 所以「单窗 / 多窗」的分界是 500 字符,不是 512 token——这两件事容易混。
★ 两种口径的概率刻度不同,禁止跨口径比大小。 把「认出 99% 的 AI 稿」对齐时, 两种口径需要的线分别约 0.52 与 0.68。 拿同一个 0.5 去横比两边,比出来的是刻度差异,不是判别力差异。 输出里永远带
agg字段就是为了防这个。
怎么选:默认等权(50% 这条常用线上冤枉真人更少);要压「扣掉刻度差异后的冤枉率」才用加权, 且必须配合把阈值重标到约 0.68,沿用 0.5 直接用加权反而更差。 实测读数(前两列的线都设在 50%,即判到「疑似AI参与」及以上就算): 等权冤枉真人 1.36% / 认出 AI 99.47%;加权 1.52% / 99.45%; 把「认出 AI 的比例」都拉齐到 99% 之后,冤枉率是等权 1.18% vs 加权 0.78%——这一列才是公平横比。 注意冤枉率是「疑似及以上」的宽口径,只算「AI特征明显」(≥90%)会更低。
这组数是内部标定记录,不是可独立验证的评测结果。 标定集的构成与规模不公开、不随技能包发布, 因此无法在包内复现。换语料(体裁、长度、渠道)请重新标定,别直接搬阈值。
句头概率:仅供参考
句头 = 以该句为中心取上下文窗(±2 句)喂给模型得到的概率。
它衡量的是「这一句所在的上下文读起来像不像 AI」,不是「这句由 AI 生成」。
三条必须守住的:
- 不能用它在篇内排序定位。句级信号在长篇里很弱,靠句分排 top-k 接近随机。
- 真人稿同样会有句子被标红,这是能力上限不是故障。
- 整篇分和句头分是两套统计量,别混着当同一个结论。
对外输出必须带上「仅供参考」这句话,不能只丢一串百分比。
何时使用
- 判断一段/一批中文文本整体像不像 AI 写的
- 想知道一篇文章里哪些句子「读起来像 AI」(作辅助线索,不作定位)
- 关键词:AI 味、像不像 AI、检测文本、判别 AI 生成、AI生成概率
不适用:揪出人稿里混入的 AI 段落(句级信号太弱),也不能当作者身份的证据。
权重三档:默认 int4,可按需换
同一份模型出了三个精度档,三档都是打包好的成品,不需要自己再打包或量化:
| 档 | 体积 | 怎么用 |
|---|---|---|
| int4 轻量档(默认) | 60.2 MB | 什么都不用写,detect.py 自动用 |
| int8 平衡档 | 101.0 MB | 先 download.py --bits 8,再 detect.py ... --bits 8 |
| fp32 原始精度档 | 390.1 MB | 先 download.py --bits 32,再 detect.py ... --bits 32 |
三档在同一批文本上的分数偏差最大 0.5448 个百分点(短句样本上最大;常规 AI 腔与真人口语只差 0.01–0.06 个百分点)。也就是说:换档基本不会改变判决结论,只影响极端边界样本。 除非要复现论文级读数或卡在 89%–91% 这种线上,否则用默认 int4 就够。
fp32 档是标准
safetensors目录,用from_pretrained直读;int4 / int8 是本仓库自带的打包格式, 需要unpack_blob解包,不支持 vLLM / ollama / llama.cpp / GPTQ / AWQ。
每次输出末尾都会打印实际用的档(权重 int4),避免记不清自己在看哪一档的分数。
怎么用
依赖:pip install torch --index-url https://download.pytorch.org/whl/cpu && pip install transformers
(首次拉权重还需 pip install modelscope)
单段,人话版(默认):先给整篇概率,再给句头概率列表。
python scripts/detect.py "要检测的文本"
整篇 AI生成概率 99.94% —— AI特征明显
句头概率(仅供参考,不代表该句由 AI 生成)
84.80% 10月16日下午,济南市历下区某珠宝玉石行业协会接到收藏爱好者赵先生咨询称…
99.93% 赵先生称,协议签订后他已通过银行转账支付全部货款…
────────────────────────────────────────────────────────────
共 21 句 | AI特征明显 15 | 疑似AI参与 3 | AI特征不明显 3
等权聚合 | 3 窗 | 句头邻窗 ±2 句 | 判决线 50% / 90%
句头仅供参考,不作篇内定位,也不代表该句由 AI 生成。
单段,JSON:
python scripts/detect.py "要检测的文本" --json
{
"agg": "eq",
"doc": {"ai_prob": 0.999429, "ai_prob_pct": "99.94%", "verdict": "AI特征明显",
"n_win": 3, "chars": 1205},
"sentences": [
{"i": 1, "text": "…", "ai_prob": 0.848, "ai_prob_pct": "84.80%", "verdict": "疑似AI参与"}
],
"summary": {"n_sent": 21, "n_ai": 15, "n_sus": 3, "n_low": 3},
"note": "句头概率仅供参考:…"
}
换聚合方式 / 只要整篇 / 两种都给:
python scripts/detect.py "文本" --agg len # 加权聚合
python scripts/detect.py "文本" --no-sent # 只出整篇概率,长稿快很多
python scripts/detect.py "文本" --json --both # 同时给出等权与加权两个整篇分
批量(jsonl,每行 {"id":"可选","text":"..."}):
python scripts/detect.py --file input.jsonl --out output.jsonl
每行输出结构同 JSON,多一个 id 字段。
必读纪律
- 整篇 ≠ 开头。 不要只截前 512 token 当整篇结论——长稿上那测的是「起手像不像 AI」,
不代表全文。本技能默认滑全文聚合;
--no-sent只是省掉句头,不改变整篇口径。 - 冤枉比漏放贵。 把真人稿判成 AI 的代价高于放过 AI。边界样本宁可按「疑似AI参与」报, 不要直接说「是 AI 写的」。
- 句头不是定位器。 禁止拿句分排序、做 top-k、「这三句最像 AI」。
- 概率会饱和。 分数堆在两端是模型特性,不是 bug;50%–90% 这段就是给人复核用的。
- 域敏感。 论文体、演讲体、短评体、日常口语的分数分布不同。跨域用之前, 先拿同体裁的真人样本看一眼冤枉率,再决定判决线要不要动。
- 别跨口径比数字。 等权和加权的分数只能各自跟自己比。
文件清单
scripts/detect.py— 打分入口(整篇 + 句头,两种聚合,--bits选档)scripts/download.py— 从魔搭拉权重(--bits 4|8|32选档,--check三档巡检)assets/int4_packed.pt— int4 权重(60.2MB);开源包内不附带,由 download.py 拉到缓存目录assets/model_cfg/config.json— 模型结构配置assets/tok/— 词表与分词器配置references/口径与边界.md— 两种聚合的取舍、句头的能力边界、对外表述模板
微信扫一扫