"这段文字有AI味"到底怎么判断?6项量化指标详解
前言
你一定见过这样的场景:有人贴出一段AI生成的文字,评论区有人说"明显是AI写的",也有人说"我觉得挺自然的"。谁说了算?没有标准,全靠感觉。
上一篇讲了8级门禁中的G6------反AI味检测。当时只给了一个结论:当6项指标全部达标时,读者基本无法分辨这是AI写的还是人写的。但那篇的主角是门禁系统,G6只是其中一道关卡。
这篇把G6拆开讲透。
因为在整个8级门禁里,G6是最特殊的一道。G3检查大纲对不对,G4检查人设对不对,G5检查节奏对不对------这些都有明确的"对错标准"。但G6检查的是**"像不像人写的"**,这个问题天然带有主观性。
所以关键问题是:怎么把"AI味"这种主观感受,变成一组可计算的数字?
"AI味"到底是什么
在设计指标之前,得先搞清楚一件事:读者说"这段文字有AI味"时,他们到底在说什么?
我收集了200多条读者对AI生成小说的负面评价,做了聚类分析。发现所谓"AI味"并不是一个单一问题,而是6类不同问题的混合体。读者可能说不清具体是哪一类,但他们的"不舒服感"总能归到以下6个来源之一。
01 · 句式重复
AI喜欢在连续段落中使用相同的句式骨架。最典型的是"她不禁......""他微微......""缓缓开口道"这种模式反复出现。人类作者也会偶尔重复,但不会像AI这样机械地高频重复同一种结构。
02 · 词汇贫乏
AI生成3000字,可能只用到800个不同的词。人类作者写同样长度的章节,词汇量通常是AI的1.5到2倍。词汇多样性低会让读者产生**"翻来覆去就那几个词"**的疲劳感。
03 · 情绪直白
AI习惯直接"说"情绪------"她很愤怒""他感到震惊""她心中一阵无奈"。人类作者更倾向"演"情绪------用动作、表情、环境来暗示。直白的情绪词堆叠多了,文字会变得像心理报告而不是小说。
04 · 段落均匀
AI生成的段落长度高度均匀,每段几乎都是120-150字。人类作者的段落长度方差很大------有时一句话成段,有时一大段铺陈。均匀的段落节奏会让读者产生机械的催眠感。
05 · 对话过多
AI倾向于用大量对话推进剧情,因为对话是最"安全"的叙事方式------不容易出错,也省去了描写环境的麻烦。但当一章80%都是对话时,读者会觉得场景感稀薄,像在读剧本而不是小说。
06 · 缺乏细节
AI生成的场景描写往往是"功能性"的------只写推动剧情必要的信息,缺少闲笔、感官细节和氛围烘托。人类作者会写"窗外的梧桐叶被风吹得翻了个面"这种和剧情无关但有呼吸感的细节。
这6个来源有一个共同特征:它们都可以通过文本统计来量化。句式重复可以数,词汇多样性可以算,情绪词密度可以统计,段落长度可以测方差。这意味着"AI味"虽然听起来主观,但它的根源是客观的、可计算的。
6项量化指标的设计原理
基于上面6个来源,我设计了6项对应的量化指标。每一项都有明确的检测内容、阈值和超标后果。
M1 · 句式重复率
阈值:≤ 3次连续
检测同一句式骨架在正文中连续出现的次数。"句式骨架"的定义是:去掉主语和宾语后保留的句法结构。比如"她不禁笑了笑"和"她不禁皱了皱眉"骨架相同,属于重复。
| 检测内容 | 超标后果 |
|---|---|
| 连续段落中相同句式骨架的出现次数 | 读者产生"复读机"感,文字机械 |
来看典型超标案例:
超标(连续4次相同骨架)
她不禁笑了笑。她不禁摇了摇头。她不禁叹了口气。她不禁闭上了眼。
修正后
她笑了笑,没接话。摇了摇头,像是想甩掉什么。叹了口气,又觉得不妥,硬生生咽了回去。最后她只是闭上眼,靠在椅背上不说话了。
M2 · 词汇多样性 TTR
阈值:≥ 0.45
TTR(Type-Token Ratio)= 不同词的数量 / 总词数。TTR越高,词汇越丰富。AI生成的中文文本TTR通常在0.30-0.38之间,人类作者通常在0.45-0.60之间。
| 检测内容 | 超标后果 |
|---|---|
| 全章去重词数 / 全章总词数 | 词汇贫乏,翻来覆去就那几个词 |
这个阈值不是拍脑袋定的。我统计了30篇人类作者网文章节和30篇AI生成章节的TTR,人类作者的TTR中位数是0.52,AI的中位数是0.34。0.45刚好在两者中间偏人类一侧------通过这条线,就进入了人类作者的统计区间。
M3 · AI高频词密度
阈值:≤ 5次/千字
统计一组"AI特征词"在正文中的出现频率。这些词是人类作者很少用、但AI高频使用的"指纹词"。
| 检测内容 | 超标后果 |
|---|---|
| AI特征词表命中次数 / 千字 | AI指纹暴露,读者一眼识别 |
AI特征词表(部分):
| 特征词 | AI文本均值(次/千字) | 人类文本均值(次/千字) |
|---|---|---|
| 缓缓 | 4.2 | 0.3 |
| 微微 | 3.8 | 0.5 |
| 淡淡 | 3.1 | 0.2 |
| 不禁 | 2.7 | 0.4 |
| 嘴角微扬 | 1.9 | 0.0 |
| 眸光 | 1.5 | 0.1 |
| 心中一凛 | 1.2 | 0.0 |
这张表是不断迭代的。每当我发现某个词在AI文本中异常高频,就加入词表。目前词表已有87个词,覆盖了大多数中文AI生成文本的典型指纹。
M4 · 段落长度方差
阈值:≥ 80
计算每个段落的字数,然后求方差。方差越大,段落长度越不均匀,节奏越有变化。AI生成的段落方差通常在20-40之间,人类作者通常在100-300之间。
| 检测内容 | 超标后果 |
|---|---|
| 各段落字数的方差 | 段落机械均匀,催眠感强 |
为什么人类段落方差大?因为人类作者有"呼吸感"。一个重要的转折会用一句话单独成段制造冲击力,一大段环境描写可能铺满半个页面。AI没有这种节奏意识,它倾向于把每段写得差不多长------因为这样"最安全"。
M5 · 对话占比
阈值:30% - 60%
统计正文中引号内文字(含引号)占总字数的比例。对话是双刃剑------太少显得沉闷,太多缺乏场景感。30%-60%是网文章节的舒适区间。
| 检测内容 | 超标后果 |
|---|---|
| 对话字数 / 全章总字数 | <30%沉闷 / >60%像剧本 |
M5是唯一一个有上下限的指标。其他指标都是"不超过某值",M5是"在30%到60%之间"。低于30%说明对话太少,环境描写和心理独白过多;高于60%说明对话太多,场景感和叙事厚度不足。
M6 · 情绪词密度
阈值:≤ 8次/千字
统计情绪类词语("愤怒""震惊""无奈""悲伤""欣喜"等)的出现频率。人类作者用动作和细节暗示情绪,AI习惯直接"说"情绪。情绪词密度高是AI文本最容易被识别的特征之一。
| 检测内容 | 超标后果 |
|---|---|
| 情绪词表命中次数 / 千字 | 文字像心理报告,缺少"演"的层次 |
来看对比示例:
人类写法(演情绪)
她把杯子放在桌上,力气不大,但瓷底磕在桌面上发出一声脆响。手指在杯壁上停了两秒,才慢慢收回来。
AI写法(说情绪)
她感到一阵愤怒 ,心中震惊 不已。同时又有一种无奈 涌上心头,让她一时悲伤得说不出话来。
左边没有一个情绪词,但你能感受到她在压抑怒火。右边堆了4个情绪词,反而什么都感受不到。这就是M6检测的核心------好小说"演"情绪,AI小说"说"情绪。
阈值不是拍脑袋定的
6项指标的阈值怎么定?这直接决定了G6门禁的有效性------阈值太松,AI味检测形同虚设;阈值太严,人类作者的正常文本也会被拦下来。
我的方法很直接:对比统计。收集人类作者和AI生成文本各30篇,计算每篇在6项指标上的数值,画分布图,找到两者的分界线。
雷达图很直观地展示了人类作者和AI生成文本的统计差异。在6项指标上,两者的分布区间几乎没有重叠------这意味着只要阈值设在分界线附近,就能有效区分。
| 指标 | AI均值 | 人类均值 | 设定阈值 | 阈值位置 |
|---|---|---|---|---|
| 句式连续重复(M1) | 5.8次 | 1.7次 | ≤3次 | 偏人类侧 |
| 词汇多样性TTR(M2) | 0.34 | 0.52 | ≥0.45 | 分界线偏人类 |
| AI高频词密度(M3) | 12.3次/千字 | 1.1次/千字 | ≤5次/千字 | 偏人类侧 |
| 段落长度方差(M4) | 32 | 165 | ≥80 | 分界线偏人类 |
| 对话占比(M5) | 72% | 47% | 30%-60% | 人类区间内 |
| 情绪词密度(M6) | 14.6次/千字 | 3.2次/千字 | ≤8次/千字 | 偏人类侧 |
阈值设定的三条原则:
第一,偏人类侧。 所有阈值都设在分界线偏人类一侧,宁可偶尔误杀,也不放AI味过关。误杀可以通过退回重写修复,但漏网之鱼会直接流入读者眼中。
第二,可调。 所有阈值定义在配置文件中,不写死在代码里。随着AI模型的迭代,AI生成文本的质量会提升,阈值需要动态收紧。
第三,有据可查。 每个阈值旁边都记录了统计样本数量和分布数据。这不是经验法则,是数据驱动的决策。
深挖一项:段落长度方差,最被低估的AI指纹
6项指标中,M4(段落长度方差)是最容易被忽略的------很多人在做"去AI味"时只关注词汇和句式,不会想到段落长度也是一个信号。但它其实是最稳定的区分指标之一。
原因是:句式和词汇可以通过prompt引导来改善(比如告诉AI"不要用'缓缓'这个词"),但段落长度的均匀性是AI生成机制的内禀特征------大语言模型在生成时倾向于保持输出节奏的一致性,这种倾向很难通过prompt消除。
柱状图显示了30篇人类作者样本和30篇AI生成样本的段落长度方差。人类作者的方差分布在100-300之间,中位数165;AI生成的方差分布在15-50之间,中位数32。两者的分布区间完全不重叠。
这意味着M4是一个几乎零误判的指标------只要方差低于80,几乎可以100%确定这段文字是AI生成的。在我的实测中,M4的准确率是6项指标中最高的。
不要只盯着"写了什么"(词汇、句式),也要关注"怎么排列"(段落结构)。有时候,把AI生成的均匀段落手动打散成参差不齐的长度,就能显著降低AI味。这是成本最低、效果最好的"去AI味"操作之一。
metrics.py 的实现细节
6项指标的设计原理讲完了,接下来是实现。整个检测脚本metrics.py的核心流程可以概括为:分词 → 逐项检测 → 汇总报告。
检测流程
python
# metrics.py 核心检测流程(伪代码)
def run_metrics(chapter_text, config):
"""对一章正文执行6项反AI味检测"""
# 1. 预处理:分词 + 段落切分
tokens = tokenize(chapter_text) # 全文分词
paragraphs = split_paragraphs(chapter_text) # 段落切分
total_chars = len(chapter_text)
total_words = len(tokens)
results = {}
# 2. M1: 句式重复率检测
skeletons = [extract_skeleton(p) for p in paragraphs]
results["M1"] = check_consecutive_repeat(
skeletons, max_consecutive=config.M1_THRESHOLD # 默认3
)
# 3. M2: 词汇多样性 TTR
unique_words = set(tokens)
ttr = len(unique_words) / total_words
results["M2"] = {
"value": round(ttr, 4),
"pass": ttr >= config.M2_THRESHOLD # 默认0.45
}
# 4. M3: AI高频词密度
ai_hits = count_ai_words(chapter_text, config.AI_WORD_LIST)
density_m3 = ai_hits / (total_chars / 1000)
results["M3"] = {
"value": round(density_m3, 2),
"pass": density_m3 <= config.M3_THRESHOLD # 默认5
}
# 5. M4: 段落长度方差
para_lengths = [len(p) for p in paragraphs]
variance = calculate_variance(para_lengths)
results["M4"] = {
"value": round(variance, 1),
"pass": variance >= config.M4_THRESHOLD # 默认80
}
# 6. M5: 对话占比
dialogue_chars = count_dialogue(chapter_text)
dialogue_ratio = dialogue_chars / total_chars
results["M5"] = {
"value": f"{round(dialogue_ratio*100, 1)}%",
"pass": 0.3 <= dialogue_ratio <= 0.6
}
# 7. M6: 情绪词密度
emotion_hits = count_emotion_words(
chapter_text, config.EMOTION_WORD_LIST
)
density_m6 = emotion_hits / (total_chars / 1000)
results["M6"] = {
"value": round(density_m6, 2),
"pass": density_m6 <= config.M6_THRESHOLD # 默认8
}
# 8. 汇总
all_pass = all(r["pass"] for r in results.values())
failed = [k for k, r in results.items() if not r["pass"]]
return MetricsReport(
passed=all_pass,
failed_metrics=failed,
details=results,
suggestions=generate_suggestions(failed, results, chapter_text)
)
关键实现细节
M1的句式骨架提取是最tricky的部分。中文没有自然的空格分词,句式骨架需要依赖分词工具(jieba)做词性标注,然后保留动词结构和助词结构,去掉名词和代词。两句话的骨架相同,就算重复。
python
# M1: 句式骨架提取
def extract_skeleton(sentence):
"""提取句式骨架:保留动词/助词,去掉名词/代词"""
pos_tags = jieba.posseg.lcut(sentence)
skeleton = [
word for word, flag in pos_tags
if flag.startswith('v') # 动词
or flag.startswith('u') # 助词
or flag.startswith('d') # 副词
or flag.startswith('a') # 形容词
]
return ''.join(skeleton)
# "她不禁笑了笑" → 骨架 "不禁笑了笑"
# "她不禁皱了皱眉" → 骨架 "不禁了皱" → 相似度高 → 判定重复
M3的AI特征词表维护在一个独立的JSON文件中,方便随时增删。每当发现新的AI指纹词,只需更新词表文件,不需要改代码。
M5的对话统计需要注意中文引号的两种写法(""和「」),以及引号嵌套的情况。实际实现中用正则匹配最外层引号对,统计引号内字数。
检测一章3000字的正文,6项指标全部跑完大约0.3秒。瓶颈在jieba分词。对270章的体量来说,全量检测一次只需不到2分钟------完全可以作为门禁的常规检查项,不会拖慢写作流程。
检测结果如何反馈给AI
检测出AI味只是第一步。更关键的问题是:检测出问题后,怎么让AI改?
如果你只是告诉AI"你的文字有AI味,请重写"------它大概率会换一批词重写,AI味依然在。因为AI不知道"AI味"具体指什么,不知道哪句话有问题,不知道应该怎么改。
所以G6门禁的反馈机制不是简单的"不通过",而是生成一份结构化的修复指令,精确到每一处超标项,附上具体的替换建议。
反馈流程
-
检测超标:metrics.py报告M3(AI高频词密度)超标,值为8.2次/千字,阈值5次/千字。
-
定位超标词:扫描全文,列出所有命中的AI特征词及其位置。
text"缓缓" 出现3次 (第2段, 第5段, 第8段) "微微" 出现2次 (第3段, 第7段) "嘴角微扬" 出现1次 (第6段) "眸光" 出现1次 (第9段) -
生成替换建议:为每个超标词提供人类化的替换方案。
text"缓缓开口" → "顿了顿才说" 或 "沉默了两秒才开口" "微微一笑" → "嘴角动了动" 或 "没什么表情,但眼底柔和了一点" "嘴角微扬" → 删除,改用动作暗示 "眸光一闪" → "眼神变了变" 或 直接删除 -
组装退回指令:将超标项和替换建议打包成结构化JSON,退回DRAFT阶段。
json{ "gate": "G6", "action": "REVISE_DRAFT", "failed_metrics": ["M3"], "details": { "metric": "AI高频词密度", "value": 8.2, "threshold": 5.0, "exceeded_by": 3.2 }, "suggestions": [ { "word": "缓缓", "location": "第2段, 第5段, 第8段", "replace_with": "顿了顿才说 / 沉默了两秒才开口", "reason": "'缓缓'为AI高频特征词,人类作者极少使用" }, ... ], "max_retries": 3 } -
AI重写:AI收到退回指令后,针对超标项逐个修改,然后重新提交检测。通常1-2轮就能通过。
**不要只说"不合格",要说"哪里不合格、不合格多少、怎么改"。**这三层信息缺一不可。"哪里不合格"让AI定位问题,"不合格多少"让AI理解严重程度,"怎么改"给AI修复方向。这就是门禁从"拦截器"升级为"修复指导器"的关键。
退回前后对比
退回前(AI高频词密度 8.2次/千字)
林知晚缓缓 开口,声音里带着一丝不易察觉的颤抖。沈婧微微 一笑,嘴角微扬 ,似乎并不在意。眸光 流转间,她端起茶杯缓缓 送至唇边。林知晚看着她这副做派,心中一凛。
退回后重写(AI高频词密度 1.3次/千字)
林知晚开口时停了一下,声音里有什么东西在发抖,很轻。沈婧没什么表情,嘴角动了动,端起茶杯,慢慢送到嘴边,没喝,又放下了。林知晚盯着她的手------稳得很。这女人从来不在该慌的时候慌。
修改后的版本没有一个AI特征词,但情绪反而更强了------"稳得很""这女人从来不在该慌的时候慌"比"心中一凛"有冲击力得多。这就是量化反馈的价值:它不只去掉了AI味,还逼迫AI用更好的方式表达。
这6项指标不是万能的
诚实地说说这套系统的局限。量化检测解决了80%的问题,但还有20%是它管不了的。
- 80% 可量化AI味覆盖
- 20% 主观感受残留
- 1.5轮 平均退回重写次数
局限一:6项指标覆盖不了"缺乏细节"
6个AI味来源中,"缺乏细节"是最难量化的。你不能简单统计"有没有写梧桐叶"------细节的价值不在数量,在于是否在合适的时机出现。目前G6不检测这一项,靠G8人工关卡兜底。
局限二:阈值需要随模型迭代调整
今天的AI特征词表是基于当前模型统计的。当模型更新后,"缓缓"可能不再是高频词,新的指纹词会出现。这意味着词表和阈值需要定期重新校准。目前我每跑完30章会做一次校准。
局限三:文体差异未被考虑
不同题材的网文,对话占比和情绪词密度的正常区间不同。都市文对话多,玄幻文描写多。目前的阈值是"一刀切"的通用值,更精确的做法是为每个题材设定不同的阈值。这是下一步的改进方向。
局限四:无法检测语义层面的套路
AI味不只是词汇和句式的问题,还有叙事套路的重复------比如每次打脸都是"反派嘲讽→主角沉默→真相揭露→反派震惊"这个模板。这种语义层面的套路,靠统计指标检测不了,需要更复杂的语义分析。
下一步计划引入语义嵌入相似度检测------用embedding模型计算相邻章节的叙事结构相似度,如果连续多章的叙事弧线高度相似,即使6项指标全过,也发出预警。这将把"去AI味"从词汇层面推进到结构层面。
总结
回到开篇的问题:"这段文字有AI味"------从主观判断到客观指标,我们走了多远?
答案是:很远,但还没到终点。
"去AI味"不是一个主观判断,是一组客观指标。当6项指标------句式重复率、词汇多样性TTR、AI高频词密度、段落长度方差、对话占比、情绪词密度------全部达标时,读者基本无法分辨这是AI写的还是人写的。
这套系统的价值不在于"完美检测AI味",而在于把一个模糊的主观问题,转化成了一组可执行的工程任务:
| 阶段 | 状态 | 解决的问题 |
|---|---|---|
| 量化前 | "感觉有AI味" | 无法定位、无法修复、无法验证 |
| 量化后 | "M3超标,值8.2,阈值5.0" | 可定位、可修复、可验证 |
核心要点提炼:
- "AI味"不是玄学,是6类可量化问题的混合体 --- 句式重复、词汇贫乏、情绪直白、段落均匀、对话过多、缺乏细节
- 6项指标都有数据驱动的阈值 --- 不是拍脑袋定的,是30篇人类文本+30篇AI文本对比统计出来的
- M4段落长度方差是最被低估的AI指纹 --- 几乎零误判,因为段落均匀性是AI生成机制的内禀特征
- 反馈机制的核心是"精确退回" --- 不只说不合格,还要说哪里不合格、不合格多少、怎么改
- 6项指标覆盖80%的问题,剩下20%靠人工兜底 --- 不是万能的,但把主观问题变成了工程任务
这正是工程化方法论的核心------把质量从"主观感觉"变成"系统保证"。在软件工程中,代码质量从"靠程序员自觉"变成了CI/CD流水线保证。在AI写作中,"去AI味"从"靠作者感觉"变成了metrics.py的6个数字。
当然,6项指标不是终点。随着AI模型越来越强,"AI味"的表现形式会变化,检测方法也必须迭代。但方法论是不变的:找到可量化的特征,设定有据可查的阈值,用数据驱动的方式持续校准。
下一篇,我会讲Soul Field------如何给AI角色注入"灵魂",让角色不只是人设卡上的一组属性,而是一个有记忆、有偏好、有行为逻辑的"人"。这是G4人设一致性检测背后的数据基础。
本文是「AI写作工程化」系列第6篇。如果觉得有帮助,点个赞吧。你觉得"去AI味"能不能完全靠量化指标搞定?评论区聊聊你的看法。