Skip to content
Published on

AI 写的文章会在哪里崩掉 —— 六种失败模式与对应的护栏

分享
Authors

引言 —— 句子很流畅,文章却是错的

人写的烂文章和 AI 写的烂文章,烂的方式不一样。人写的文章通常先从句子层面开始崩塌 —— 有病句,逻辑断裂,读着读着很快就能指出哪里不对劲。AI 写的文章正相反:句子从头到尾都很流畅,段落匀称,语气始终自信。但引用的那句话那个页面上根本没有,三个段落说的是同一件事,还会在没有任何依据的情况下断言一件事。

这个差异在实务中之所以危险,是因为我们检验文字时习惯用"顺不顺"作为线索。读起来没有卡壳的地方就会放行,而 AI 的输出从一开始就没有那种信号。所以"我读过了"根本不构成核实,唯一构成核实的,是一份事先定好要看什么的清单。

本文就是这份清单。把六种失败模式分别按怎么检测、怎么修正来整理,也区分出哪些部分可以交给机器,哪些必须由人做到最后。这些检查该放在流水线的哪个环节,写在了讲整条流水线的文章里;这里只看检查本身。

一眼看懂六种失败模式 —— 按可检测程度排的地图

先把六种失败列成表。排序依据不是严重程度,而是机器能抓住多少,因为这才是设计护栏时真正需要的信息。

失败模式表面症状自动检测人必须亲自看的部分
编造的出处与引用链接听起来像真的但打不开,或者那句话根本不存在引用是否扭曲了上下文
过时的信息价格・版本・政策用现在时描述成了当下仍然如此的过去状态去当前文档核实到底变了什么
被拉长的段落篇幅在增加,但读者没学到任何新东西该合并还是该删
没有依据的断言数字、因果关系、最高级出现却没有出处补上依据,还是把说法放软
只为搜索排名堆砌的重复同一个表达以不自然的方式反复出现这篇文章对读者是否真有价值
抄袭与版权表达和原文过度相似引用范围与署名是否恰当

要读的是右边两列之间的关系。哪怕自动检测程度很高的项目,也会剩下需要人来看的部分,而剩下的那部分永远是判断。机器能告诉你"这句引文原文里没有",却告诉不了你"这句引用把原文的意思给扭曲了"。搭建护栏的时候一旦把这条边界模糊掉,"通过检查=没问题"这种错觉就会渗进流水线里。

编造的出处与引用 —— 形式完美,只是内容不存在

这是最常见、也最致命的一种失败。模型非常擅长生成格式规整的东西 —— URL、论文标题、作者姓名、文档编号。格式规整意味着容易学会,也意味着很容易编出一个新的、看起来像模像样的组合。所以一篇根本不存在的论文,会以精确的引用格式出现;一个带着失效锚点的 URL,也会带着完全自然的路径结构冒出来。

这里要先澄清一个误解:接上搜索功能,并不能让这个问题消失。哪怕模型确实通过搜索取回了一份真实文档,在总结的过程中,原文里根本没有的句子照样可能出现在引文的位置上。实际上最常见的形态并不是凭空捏造,而是把原文里好几句话拼成了一句话。内容大体没错,但那句话原文里并不存在。一旦你给它加上引号,这就是一个错误。

好在检测这件事机器很擅长。要求逐字引用,然后核对那段字符串是否存在于原文里就行。这个核对脚本已经放在流水线那篇文章里了,这里只讲怎么处理结果。

  • 引文原文里没有:去掉引号改成转述,或者把这条论断整个丢弃。不要去找一句听起来差不多的话硬塞进去 —— 那不是核实,是事后找补。
  • 链接打不开:把这条论断当作没有依据来处理。搜索找个别的链接补上是另一件事,和原来那条论断对不对没有关系。
  • 不是一手来源:从摘要文章一路追溯回原文。这个过程中经常会发现原文其实说的是另一回事。

在修正这一侧,投入产出比最高的一个习惯,是把顺序倒过来 —— 从"先写论断再找出处",变成"先看出处,只根据出处里有的内容来写"。这样就没有编造的空间了。

过时的信息 —— 模型不会说不知道,而是把过去说成现在

知识截止日期是众所周知的事,但真正出事的地方往往不是截止日期本身,而是截止日期没有被标注出来的方式。模型不会说"我知道的那个时间点之后我就不清楚了",而是把自己最后知道的状态用现在时描述出来。因为句子里没有时间戳,读者根本没法判断这是不是一条过时的信息。

高风险项目是固定的:价格与套餐、产品与型号名称、API 参数与默认值、版本号与停止支持日期、公司的政策措辞,以及人的所属机构与职位。它们的共同点是变化频繁,又容易验证。容易验证也就意味着读者会立刻察觉。

部分自动化是可行的:用机器标出依赖时效的表达,让人只去核实那些地方。

# 抽取依赖时效的表达,缩小需要复核的范围。诀窍是不要把它当成失败处理。
# 精确度低的检查一旦变成硬性门禁,很快就会被无视,而一个被无视的门禁比没有门禁还糟。
rg -n --no-heading \
  -e '最新|目前|现在|今年|去年|最近' \
  -e '最(快|便宜|大|多)的|业内首个|唯一' \
  -e '免费(的|提供)|[0-9]+ *(美元|元|USD)' \
  -e 'v?[0-9]+\.[0-9]+(\.[0-9]+)? *(版本|发布)?' \
  data/blog/**/*.mdx

修正的方法是把句子钉在一个具体的时间点上。把"目前是免费的"改写成"截至 2026 年 7 月,提供免费套餐",即便之后事实变了,这篇文章本身也不算撒谎。一句不愿意钉上时间戳的话,通常就是一句没有真正核实过的话。

还有一点:让模型"用最新信息更新一下",这不是解决办法。模型没法知道自己知识截止日期之后发生的事,收到这个要求后,它只会编出一句看起来很新的话。结果只是把过时的信息,换成了一句听起来不过时的过时信息。

被拉长的段落与没有依据的断言 —— 两种句子层面的失败

把同一个意思拉长写的段落

模型在被要求凑篇幅的压力下,往往不会补充新信息,而是用不同的措辞重复同一条信息。这不容易被察觉,是因为每个段落单独看都挺正常。三个段落分开读,每一个都说得通;连起来读,第二段和第三段其实只是在复述第一段。

机器能抓住这个。把段落切成碎片,测量重叠比例就行。

// find-duplicate-paragraphs.mjs —— 按相似度排序,抽取近似重复的段落。
// 目标是找出"实质上是同一句话",而不是完全匹配,所以 shingle + Jaccard 就足够了。
import { readFileSync } from 'node:fs'

const K = 5 // 英文散文用 5 词的片段效果不错; 中日韩文本建议降到 3-4。
const THRESHOLD = 0.35

const shingles = (text) => {
  const words = text
    .replace(/`[^`]*`/g, ' ') // 行内代码不参与比较
    .replace(/[^\p{L}\p{N}\s]/gu, ' ')
    .split(/\s+/)
    .filter(Boolean)
  const set = new Set()
  for (let i = 0; i + K <= words.length; i++) set.add(words.slice(i, i + K).join(' '))
  return set
}

const jaccard = (a, b) => {
  if (!a.size || !b.size) return 0
  let shared = 0
  for (const s of a) if (b.has(s)) shared++
  return shared / (a.size + b.size - shared)
}

const body = readFileSync(process.argv[2], 'utf8')
  .replace(/^---[\s\S]*?\n---\n/, '')
  .replace(/```[\s\S]*?```/g, '') // 排除围栏代码块
  .replace(/^\|.*\|$/gm, '') // 排除表格行: 表格本来格式就是重复的

const paras = body
  .split(/\n{2,}/)
  .map((p) => p.trim())
  .filter((p) => p.length > 120 && !p.startsWith('#') && !p.startsWith('-'))

const pairs = []
const sets = paras.map(shingles)
for (let i = 0; i < paras.length; i++) {
  for (let j = i + 1; j < paras.length; j++) {
    const score = jaccard(sets[i], sets[j])
    if (score >= THRESHOLD) pairs.push({ score, i, j })
  }
}

pairs.sort((a, b) => b.score - a.score)
for (const { score, i, j } of pairs.slice(0, 5)) {
  console.log(`\n相似度 ${score.toFixed(2)} —— 段落 ${i + 1} 与段落 ${j + 1}`)
  console.log(`  A: ${paras[i].slice(0, 90)}...`)
  console.log(`  B: ${paras[j].slice(0, 90)}...`)
}
console.log(`\n共 ${paras.length} 个段落,达到阈值的配对有 ${pairs.length}`)

阈值是个人偏好问题,从 0.35 附近开始,误报多了就调高。不过这个工具只负责标出来,不负责判断。重复有时候是刻意的 —— 前面立下的原则,后面用具体案例再讲一遍,那是结构,不是重复。

修正的方法是删掉段落,而不是打磨它。如果两个段落说的是同一件事,留下更具体的那个,删掉其余的。把它们合并成一个长段落,问题原样还在。

没有依据就断言的句子

人在写文章时,确信的程度会不自觉地渗进句子里。拿不准的时候,"也许""视情况而定""据我所知"这类说法就会冒出来。模型的输出里普遍没有这种信号 —— 一个被确认过上千次的事实,和一句刚刚编出来的话,会用同样的语气说出来。

所以断言本身就成了信号。下面是未经核实的初稿里反复出现的句子模式。

模式真实例子为什么是信号修正方向
没有出处的数字"生产力提升 40%"数字越精确越需要出处,但这里没有补上出处,或者删掉这个数字
没有依据的最高级"这是使用最广泛的方法"没有比较范围,也没有比较标准明确范围,或者把说法放软
因果断言"正因如此性能才会提升"把相关关系升格成了因果关系说明机制,或者只陈述观察结果
普遍性主张"每个团队都会遇到这个问题"只要有一个反例就不成立加上限定条件,缩小范围
没有实质内容的强调"这是一个非常重要的核心要素"强调本身信息量为零写清楚具体重要在哪里、怎么重要
对未来的断言"今后这将成为标准"把无法验证的预测当成事实来说标注为预测,并附上依据

这张表左边一列可以用机器搜索。用正则表达式抓出候选,交给人逐条判断,是比较现实的做法。不要让模型自动去修改。让模型"把断言的语气软化一下",它只会在一句没有依据的话上贴一个模糊限定词,结果是一句错话变成了一句措辞谨慎的错话。

内容单薄与重复表达 —— 读者和搜索引擎真正惩罚的是什么

这里先澄清一个流传很广的误解。Google 不会因为内容是 AI 制作的就予以处罚。搜索中心的官方立场是看质量,不看生产方式,而且这个标准早在自动生成成为问题之前就是这样了。

真正会被惩罚的是另一回事。垃圾内容政策文档把"以冲排名为目的、批量生产对读者没有增量价值的内容"明确定义为规模化内容滥用。这里重要的是判定标准不是"是不是 AI 写的",而是"有没有增加价值"。哪怕雇十个人手工做同样的事,一样会撞上这条政策。

而且比搜索引擎更早惩罚这类内容的是读者。内容单薄的症状很明显:滚动条很长,读到最后,除了搜索之前就知道的东西,什么也没多学到。这种文章还没等排名下滑,回访率就已经先掉了。

这里给出三个可以用来自我诊断的问题。

  1. 这篇文章有什么是别处没有的。如果亲自动手做过的事、真实遇到过的失败、亲自确认过的事实,一样都没有,那这就是一篇单薄的文章。
  2. 一个已经读过前三个搜索结果的人,有没有理由再读这一篇。如果只是把同样的内容换个说法,那就没有理由。
  3. 如果把某一节整个删掉,读者会损失什么吗。如果不会,那一节的存在只是为了凑篇幅。

重复表达是这个问题浮出水面的样子。硬要重复某个关键词,句子就会变得不自然,而这种不自然读者会最先察觉。检查方法本身很简单:统计全文的词频,看排在前面的词出现的次数是不是刚好符合语境需要。不过中文里很多常用表达可以用不同的近义词或句式替换,简单的字符串计数容易低估实际的重复程度,逐段通读来判断会更准。

抄袭与版权 —— 输出到底和原文有多像

这一项最难自动检测,也正因如此才必须靠规则来处理。

先把真正的争议点摆正。实务中要紧的不是模型用什么数据训练出来的,而是输出物到底在多大程度上复现了某个具体的原文。训练数据的合法性属于诉讼和立法层面的事,目前还在厘清当中;但自己文章里有没有原封不动地混进别人的表达,是此时此刻自己就能掌控的问题。

风险升高的条件是可预见的:原文是被广泛引用的知名文本时;请求紧贴单一原文,比如"帮我总结这篇文章"时;以及表达高度定型化的领域(定义性文字、法律条文、产品说明)。在这些条件下,模型确实会把原文的句子结构几乎原样再生产出来。

实务规则最好保持简单。

  • 引用一定要加引号并注明出处,而且要简短。能用转述代替的就用转述。
  • 不要只喂一篇原文让它做总结。同时喂进去至少两三个出处,能降低死死贴在某一种表达上的概率。
  • 翻译不是规避抄袭的手段。哪怕翻译过了,表达上的实质性相似依然存在。
  • 图片、表格、图示也按同样的标准处理。搬运带出处的表格时,要标明出处。
  • 明确标注了许可协议的材料,要遵守其中的条款。这是合规问题,不是判断问题。

检测只能做到部分程度。人工检查 —— 挑一句有特征的话去搜索 —— 目前仍然是最可靠的方法,自动化工具最多只能当参考。不过只要遵守上面这些规则,出事的概率本身就会大幅下降。这一项是预防比检测便宜得多的领域。

结语 —— 护栏的目的不是"通过",而是决定该看哪里

把六种失败重新摆在一起看,能看出一个共同点:全都崩在句子之外的事实上,而不是句子的质量上。引用是否在原文里、信息现在是否依然成立、这个段落是否说了和上一段不同的话、这条断言有没有依据。光读句子本身,一个都判断不出来,所以哪怕读得再仔细,也过滤不掉。

护栏存在的意义也正来自这里。它不是为了证明"检查通过了所以安全",而是为了帮人把该看的地方缩小范围。逐字引用核对清掉了编造的引文,让人只需要读剩下的部分;重复检测只把可疑的段落配对展示出来。剩下的判断依然是人的工作,一旦想把这部分工作也去掉,护栏就从核实的辅助变成了核实的替代品。

浓缩成一句话就是 —— AI 写的文章里需要修正的,大多不是句子本身,而是相信这些句子为真的依据。

参考资料