- Authors

- Name
- Youngju Kim
- @fjvbn20031
- はじめに — 文章は滑らかなのに記事が間違っています
- 失敗タイプを一目で見る — 検知可能性で分けた地図
- 捏造された出典と引用 — 形式は完璧で中身だけがありません
- 古い情報 — モデルは知らないと言う代わりに、昔のことを現在形で語ります
- 引き延ばされた段落と根拠のない断定 — 文単位の二つの失敗
- 薄い記事と反復表現 — 読者と検索が実際に罰するもの
- 盗用と著作権 — 出力が原文にどれだけ似ているか
- おわりに — ガードレールの目的は通過ではなく、どこを見るか決めることです
- 参考資料
はじめに — 文章は滑らかなのに記事が間違っています
人が書いた悪い文章と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語の断片がよく合います。CJKテキストなら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が書いたか」ではなく「価値を加えたか」であることが重要です。人を十人雇って同じことをやらせても、同じポリシーに引っかかります。
そして検索エンジンより先に罰するのは読者です。薄い記事の症状は明確です。スクロールは長く、最後まで読んでも検索する前に知っていたことから増えたものがありません。こういう記事は順位が落ちる前に再訪問が途絶えます。
自己診断に使える質問を三つ挙げておきます。
- この記事にしかないものは何か。自分でやってみた結果、実際に遭遇した失敗、確認して分かった事実のうち一つもなければ、それは薄い記事です。
- 上位結果三つを読んだ人が、この記事もまた読む理由があるか。同じ内容を違う言葉で書いただけなら理由がありません。
- ある節を丸ごと消したとき、読者が失うものがあるか。なければ、その節は分量のためだけに存在します。
反復表現はこの問題が表に出た形です。特定のキーワードを無理に繰り返すと文が不自然になり、その不自然さは人が先に気づきます。検査自体は単純です。本文全体で単語の頻度を数え、上位項目が文脈上必要な分だけ出ているか見ればよいのです。ただし日本語は助詞や活用が付いて表記が分かれるため、単純な文字列カウントは実際の頻度を低く見積もります。語幹基準で数えるか、目で通読するほうが正確です。
盗用と著作権 — 出力が原文にどれだけ似ているか
この項目は自動検知がもっとも難しく、だからこそルールで扱わなければなりません。
まず争点を正確に置きます。実務で問題になるのはモデルが何を学習したかではなく、出力物が特定の原文をどれだけ再現したかです。学習データの適法性は訴訟と立法の領域でまだ整理中ですが、自分の記事に他人の表現がそのまま入っているかどうかは、今この時点で自分がコントロールできる問題です。
リスクが高まる条件は予測できます。原文が広く引用された有名なテキストであるとき、依頼が「この文章をまとめて」のように原文一つに密着しているとき、そして表現が定型化された領域(定義文、法律文、製品説明)であるときです。こうした条件では、モデルが原文の文の構造をほぼそのまま再生産することが実際に起こります。
実務のルールは単純に保つほうがよいです。
- 引用には必ず引用符と出典を付け、長さを短く保ちます。要約に置き換えられるなら要約します。
- 原文一編だけを入れてまとめさせません。最低二、三の出典を一緒に入れると、特定の表現に密着する確率が下がります。
- 翻訳は盗用回避の手段ではありません。翻訳しても表現の実質的な類似性は残ります。
- 画像、表、図も同じ基準で見ます。出典のある表を移すときは出典を書きます。
- ライセンスが明示された資料は、その条件を守ります。これは判断ではなく遵守の問題です。
検知は部分的にしか可能ではありません。特徴的な文を選んで検索してみる手動検査が今でももっとも確実で、自動化ツールは参考程度です。ただし上のルールを守れば、事故が起きる確率自体が大きく下がります。この項目は検知より予防のほうが圧倒的に安い領域です。
おわりに — ガードレールの目的は通過ではなく、どこを見るか決めることです
六つを改めて並べると共通点が見えます。すべて文の品質ではなく文の外の事実で崩れます。引用が原文にあるか、情報が今も正しいか、この段落が前の段落と違う話か、この断定に根拠があるか。文だけを読んでもどれ一つ判定できず、だからどれだけ丁寧に読んでも、ふるい落とせません。
ガードレールを付ける目的もここから来ます。検査を通過したから安全だと言うためではなく、人がどこを見るべきかを絞り込むためです。逐語引用照合は捏造された引用を消して残った引用だけを読ませてくれ、重複検知は疑わしい段落のペアだけを見せてくれます。その先の判断は依然として人の仕事であり、その仕事をなくそうとすると、ガードレールが検証の代替物になってしまいます。
一行にまとめるとこうです。AIが書いた記事で直すべきものの大半は文ではなく、その文を事実だと信じる根拠です。
参考資料
- Google Search Central — AI生成コンテンツに対するGoogleの立場
- Google Search Central — スパムポリシー: 大量生成コンテンツの濫用
- Google Search Central — 役立つ、信頼できる、人間第一のコンテンツを作る
- Survey of Hallucination in Natural Language Generation — 幻覚の類型分類と評価方法
- A Survey on Hallucination in Large Language Models — 原因、検知、緩和手法の整理
- AIでブログ記事のパイプラインを作る — 検証を中心に据えた全体の流れ(関連記事)