内容批量生产场景下的降AI率踩坑记录
上周接了运营侧的需求,要把300篇知识库问答的AI生成原稿过审后上线,卡我3天的核心问题就是降AI率的达标率死活上不去。
最开始我图省事,直接套了网上到处传的野路子:同义词替换、句子前后调语序、把“的地得”乱换。
跑了50篇测完直接傻了,原本基线检出率是42%的稿子,改完之后平均检出率反而升到了61%,有几篇甚至直接标了100%AI生成。
当时第一反应是我替换词的词表有问题,换了3套不同的同义词库重跑,结果检出率波动都没超过5%,等于白做。
后来翻了检测模型的开源实现论文才反应过来,完全走偏了。
现在主流的AI内容检测模型,抓的根本不是单个词汇的匹配度,而是token序列的联合概率分布。说白了,AI生成的内容,下一个词出现的“合理程度”太平均了,人类写内容偶尔会跳脱,会插点无关的细节,会用点奇奇怪怪的个人表述。
网上传的那些批量替换同义词的操作,反而会把原本还算自然的序列,改成AI模型最容易识别的“人工篡改样本”,特征反而更明显。
摸清楚根因之后我直接把之前的垃圾脚本全删了,从零搭新的预处理逻辑。
第一个核心模块是3-gram重复片段清洗,这个点很少有人提,但我实测是效率最高的方案。
逻辑很简单,先把所有待处理的文本切分成连续3个词的片段,统计全量文档里每个3-gram的出现频次,只要频次超过阈值,就判定是AI生成内容里的共性特征,必须改写。
from collections import defaultdict
import jieba
def collect_ngram(texts, n=3):
ngram_count = defaultdict(int)
for text in texts:
tokens = list(jieba.cut(text))
for i in range(len(tokens) - n + 1):
ngram = "".join(tokens[i:i+n])
ngram_count[ngram] += 1
# 过滤掉出现超过5次的高风险ngram
high_risk_ngram = [k for k,v in ngram_count.items() if v > 5]
return high_risk_ngram
这个脚本跑出来之后,我直接筛出了全量300篇稿子里的1200多个高重复3-gram片段,这些都是所有AI生成内容共有的“样板句”,改完这些,整体检出率直接掉了15%。
第二个模块是长句拆分逻辑,我之前统计过几百份检测结果的对照数据,所有检出率低于30%的人类写内容,平均句长基本都在12-18个token之间。
而AI生成的内容,为了逻辑严谨,动不动就写25个token以上的长定语从句,序列平稳性太高,太好识别。
import re
def split_long_sentence(sentence, max_len=18):
tokens = list(jieba.cut(sentence))
if len(tokens) <= max_len:
return sentence
# 按常见断点切分,不改动核心语义
split_points = re.finditer(r"(的|了|是|就|可以)", sentence)
for sp in reversed(list(split_points)):
if sp.start() > max_len:
return sentence[:sp.start()+1] + "。" + sentence[sp.start()+1:].strip()
return sentence
亲测这两个小脚本跑一遍,降AI率的整体效果比单纯调用大模型改写要稳得多。
这个拆分不是乱切句子,我限定了只能在修饰性的助词后面切,绝对不能动核心的主谓宾结构,避免把知识库内容的原意改歪。
这里踩过一个坑,最开始我直接硬切所有超过长度的句子,结果有几篇技术文档里的参数说明,被我拆得支离破碎,运营那边审直接打回了20多篇,白干一下午。
后面我还加了个自定义规则,所有涉及接口参数、版本号、报错码的固定表述,完全跳过拆分逻辑,一点都不能动。
避免无效降AI率的几个底层逻辑
很多人折腾半天效果差,本质是对着AI检测的表层特征改,根本没触碰到核心的分布差异。
比如之前我试过网上传的插入隐藏字符、随机加几个乱码字再删的野路子,亲测跑了3篇就被平台的反作弊模块标记了整批文档,7天内的内容流量直接被限制,完全得不偿失。
后来我给整套预处理流程加了个“人工特征注入”的模块,就是随机在非核心信息区加入占比不超过5%的个人表述碎句。
比如讲“接口响应时间200毫秒”,我可以在旁边补一句“之前线上调这个参数的时候还出过一次小故障”,完全不影响核心语义,但能把整段内容的序列分布直接拉到人类写作的区间里。
我特意把这个注入的占比卡得很死,最高不能超过5%,不然运营侧说内容冗余度太高,用户体验差,照样过不了审。

改写完所有高风险片段之后我习惯性地丢到团象AI检测里跑一遍,确认检测率降到阈值以下再往下走。
跑完之后我拉了结果集做分层,把检出率高于25%的17篇单独拎出来走人工二次微调,剩下的直接过格式化校验。
我后来统计了下这批稿子的token分布,凡是低于阈值的内容,单句的平均长度都不会超过18个token,超过22个token的长句占比都压在了10%以下,这个是之前没人跟我说过的实操细节。
之前试过把长句拆成短句的方式,反而一开始踩了坑,我直接按句号把所有长句切了,结果出来一堆碎句,语序逻辑全断了,后来才改成按依存语法树的断点拆,把修饰成分单独成小分句,主干留着不动。
还有个很多人忽略的点,AI生成的内容,标点符号的分布太均匀了。
比如平均每30个字就出一个句号,感叹号问号这些符号的出现占比几乎为0,连换行都是每3行换一次,这种均匀性在人类写的内容里几乎不可能出现。
我后来在脚本里加了个小逻辑,随机调整10%左右的标点,比如把个别句号改成逗号,偶尔把两个短句合并成一个带破折号的补充说明句,效果又提了一大截。
之前有人跟我说,用大模型把全文重写一遍就能过,我试过,300篇文档调用大模型的成本要几百块,而且改出来的内容核心语义偏差超过10%,后续人工校对的时间比我自己写脚本处理多3倍都不止。
我现在这套全流程跑下来,300篇文档全量预处理的时间不超过20分钟,除了十几篇高风险的要微调,剩下的直接过审就行。
上周我拿这套逻辑跑了另外一批给技术社区投的文档,全量检出率都压到了20%以下,到现在没有一篇被标记成AI生成内容。
更多推荐
所有评论(0)