AI が書いた日本語を機械に点検させる
はじめに
生成 AI に日本語の技術記事を書かせると、語彙はほぼ正しいのに途中で読み手が離脱する文章が出てきます。原因は語彙ではなく構造です。見出しの直後に「重要性」を宣言する一文が置かれ、箇条書きが太字ラベルとコロンで始まり、結びが曖昧な推量で終わる。日本語として壊れてはいないのに、数行で読まれなくなります。
この記事では、そうした構造的な癖をプロンプトで根気よくお願いするのをやめ、textlint で機械的に止める構成を紹介します。実際に組んで動かした結果と、その過程で見つかった「規格と実務が逆だった」事例も書きます。
プロンプトでの指示が効かない理由
「AI っぽい表現を避けてください」とプロンプトに書く方法は、次の 3 点で失敗します。
- 指示が会話の履歴に散らばり、どれが有効なのか分からなくなる。
- 書き手が交代すると、同じ指示を書き直す必要がある。
- 判定が毎回変わると、どこが直ったのかを比較できない。
規則を 1 箇所に集め、判定そのものを機械へ移すと、この 3 つが同時に消えます。人間が担うのは「どう直すか」の判断だけになります。
原稿が仕上がるまでの 5 層
日本語の原稿を仕上げる工程は、次の 5 層に分けて考えると整理できます。
- 第 1 層は原稿の作り方である。翻訳ではなく、最初から日本語で組み立てる。
- 第 2 層は視点を分けた見直しである。誤り、流暢さ、用語、読者適合を別々に点検する。
- 第 3 層は機械のゲートである。機械が判定できるものは全部ここへ落とす。
- 第 4 層は客観指標である。訳文の品質を数値で追う層である。
- 第 5 層は母語話者による最終確認である。ここだけは自動化しない。
この記事で組むのは第 3 層です。層を分けておくと、あとから第 2 層や第 4 層を足しても構成が壊れません。
リポジトリの構成
Zenn は GitHub リポジトリと連携して記事を書けます。つまり、公開の経路そのものにゲートを挟めます。追加のサービスも追加の認証情報も要りません。
articles/ Zenn の記事本文
.textlintrc.json ルールの設定
prh-ai-words.yml 表記と禁止語の正本
test/gate-selfcheck.md ゲートの自己点検用ファイル
package-lock.json バージョンの固定
.github/workflows/textlint.yml push のたびに検査
依存は 5 つで、いずれも MIT ライセンスです。
{
"devDependencies": {
"textlint": "^15.8.0",
"textlint-rule-preset-ja-technical-writing": "^12.0.2",
"textlint-rule-preset-jtf-style": "^3.0.3",
"@textlint-ja/textlint-rule-preset-ai-writing": "^1.7.0",
"textlint-rule-prh": "^6.1.0"
}
}
package-lock.json は必ずコミットします。理由は後述します。
ルールの役割分担
3 つの系統に分けると、どこを直せばよいかが決まります。
- 日本語の技術文書の基本は
preset-ja-technical-writingが担当する。文の長さ、読点の数、漢字の連続、助詞の重複などである。 - 構造的な「AI っぽさ」は
@textlint-ja/textlint-rule-preset-ai-writingが担当する。このパッケージは自らを「表現を縛るのではなく、構造を縛る」と説明している。 - 語句の言い換えと禁止は
prhが担当する。表記の正本を 1 ファイルにまとめ、執筆時と CI の両方から同じファイルを読ませる。
prh のファイルは次のような形になります。expected を空文字にすると、その語句は削除されます。
rules:
- expected: できる
pattern: /出来る/
- expected: してください
pattern: /して下さい/
- expected: ""
pattern: /と言えるでしょう/
禁止語を削除で表現できるところが重要です。「この語を別の語に置き換える」ではなく「この語は書かない」という規則を、そのまま書けます。
実測:全角と半角の間のスペースは、規格と実務が逆だった
ここで予想が外れた話を書きます。全角文字と半角英字の間にスペースを入れるかどうかは、日本語の組版では意見が割れる論点です。
- JTF 日本語標準スタイルガイド(翻訳用)は「原則としてスペースを入れない」と定めている。実際、
textlint-rule-preset-jtf-styleの 3.1.1 はスペースを検出して削除する。 - ある日本の企業が公開している textlint のルールパッケージも、同じく「入れない」を選んでいる。
ところが、公開されている記事の実勢は逆でした。ある日の Zenn の上位記事 10 本について、コードブロックを除いた本文で「和字とラテン文字の境界」を数えたところ、スペースを入れている例が 78.3% を占めました。10 本のうち 8 本は 9 割を超えています。
したがって、規格に従うか読者に合わせるかは、目的で決めるしかありません。翻訳の納品物なら規格に従うべきです。読者に読まれるための記事なら、読者の慣れに合わせるほうが合理的です。私たちは後者を取り、3.1.1 のルールを無効にしました。判断の根拠を残しておけば、あとから反転させるのも 1 行で済みます。
ゲートが黙って死ぬのを防ぐ
見落としやすい落とし穴がもう 1 つあります。検査そのものが静かに壊れる場合です。ルールパッケージは更新のたびに検出数が変わる可能性があり、その作者もロックファイルの使用を推奨しています。検査が止まれば、文章が良くなったのか、検査が効かなくなったのかを区別できません。
そこで、意図的に違反を含んだファイルをリポジトリに置き、各ルールが最低 1 回は発火することを CI で確認します。たとえば次のような入力です。
- **重要**: これは重要な項目です
出来る範囲で対応します。設定して下さい。
発火しなければゲートの故障とみなして失敗させます。文章の品質を測る仕組みでは、まずゲート自身が生きていることを確かめます。
自動化できない層
第 5 層の最終確認だけは自動化できません。機械のゲートは「規則に反している箇所」は見つけますが、「この段落は要らない」「この順番では伝わらない」という判断はできません。
この層は、外部の母語話者に依頼する方法と、後回しにして公開後に読者の反応から学ぶ方法があります。費用と待ち時間の見積もりは、実際の原稿で試してから決めるのが確実です。
まとめ
- プロンプトでお願いする代わりに、規則を 1 ファイルへ集約する。
- 機械が判定できるものは全部ゲートに落とし、判定できないものだけを人へ残す。
- ロックファイルを固定し、ゲート自身が動いていることを毎回確認する。
- 規格と実務が食い違う論点は、目的を決めてから選ぶ。
語彙を磨く仕事は最後まで残ります。ただ、語彙より先に構造を直したほうが、読まれる文章に近づくのは確かです。