--- title: "ふりがなAPIの精度を生成AIと一緒に追い込んだ話" description: "Discord読み上げBotのために開発したふりがなAPI。生成AIとの協業で精度を向上させたプロセスを紹介します。" url: https://ryuuneko.com/blog/furigana-ai-accuracy published: 2026-03-04 02:19:03.484436 updated: 2026-06-16 09:16:43.857888 --- 日本語テキストに自動でふりがなを振る — 簡単そうに見えて、実はとんでもなく奥が深い問題です。 私たちはDiscord読み上げBot「ずんだー」のために、Rustで独自のふりがなAPIを開発しています。形態素解析エンジン(Lindera)をベースに、辞書・文脈ルール・数値パイプラインを組み合わせた多層アーキテクチャです。 この記事では、**生成AI(Claude)をペアプログラマーとして活用し、ふりがな精度を地道に改善していったプロセス**を紹介します。 > ※本記事はふりがなAPIの**旧バージョン(DB辞書+独自ロジック時代)**を題材にした読み物です。記事中のテスト件数・辞書件数などの数値は**当時のもの**で、現在は構成(OSSライブラリ `ja-furigana` + TOML辞書)が変わっています。最新の仕様は[ふりがなAPIドキュメント](/?slug=furigana-api)や[OSS化の記事](/?slug=api-core-oss-ja-furigana-010-stable)を参照してください。 ## 日本語の「読み」はなぜ難しいのか ### 同形異音語 — 同じ漢字なのに読みが違う 日本語には、文脈によって読みが変わる単語が大量に存在します。 - **一日** → 「ついたち」(日付)or「いちにち」(期間) - **上手** → 「じょうず」(上手い)or「かみて」(舞台用語)or「うわて」(相撲) - **大人** → 「おとな」(成人)or「たいじん」(大人物) - **一人** → 「ひとり」(口語)or「いちにん」(文語) - **下手** → 「へた」(不得意)or「しもて」(舞台用語) 形態素解析器だけでは、これらを正しく区別できません。前後の文脈を見て判断する必要があります。 ### 助数詞 — 数え方で音が変わる 日本語の助数詞は、前の数字によって読みが変化(促音便・連濁)します。 **「本」の例:** | 数字 | 読み | 変化 | | --- | --- | --- | | 1本 | い**っぽん** | 促音便+半濁音 | | 2本 | に**ほん** | 変化なし | | 3本 | さん**ぼん** | 連濁 | これが15種類以上の助数詞それぞれにルールがあります。「匹」「分」「杯」「羽」...すべて変化パターンが異なります。 ### 不規則な日付読み 「1日〜31日」の読みはほぼ不規則です。 - 1日=ついたち、2日=ふつか、3日=みっか... - 10日=とおか、20日=はつか - 14日=じゅうよっか、24日=にじゅうよっか これらをすべてルール化するには、膨大なパターンを網羅する必要があります。 ## アーキテクチャ:多層パイプライン 私たちのふりがなAPIは、テキストを以下の多段パイプラインで処理します。 ``` 入力テキスト ↓ [1] 異体字正規化(NFKC + 互換文字マッピング: 髙→高, 﨑→崎 等) ↓ [2] 慣用数詞の先行確定(三日坊主, 二十歳, 一昨日 等 → 読み確定) ↓ [3] 数値チャンク分割(数字・日付・時刻・助数詞を検出 → 読み確定) ↓ [4] 非数値チャンクのみ形態素解析(Lindera / IPADIC) ↓ [5] 隣接トークン結合(最大5トークン結合で辞書マッチ: 所+謂→所謂) ↓ [6] 各トークンの読み解決: ① override辞書(文脈付き: 手動登録、最優先) ② 文脈ルール(前後トークンから同形異音語を判定) ③ promoted / auto 辞書(投票昇格・自動推定) ④ Lindera形態素解析の読み(フォールバック) ⑤ UniHan単漢字辞書(42,318字) ↓ [7] 後処理ルール(正規表現ベースの置換) ↓ [8] TTS正規化(ttsモードのみ: 句読点→休止挿入) ↓ 出力(ひらがな / TTS用 / ルビHTML / kanji) ``` ### 数値・慣用数詞パイプライン 数字の読みだけで1,500行以上のRustコードがあります。まず「三日坊主」「二十歳」「一昨日」などの慣用数詞を先行確定し、残りのテキストから数字・日付・時刻・助数詞を検出します。15種類以上の助数詞ごとの音便変化、1日〜31日の不規則読み、時刻の特殊読み(4時=よじ、7時=しちじ)をカバー。数値チャンクは形態素解析を通さず直接読みを確定するため、解析誤りの影響を受けません。 ### 読み解決パイプライン 形態素解析後、各トークンの読みは以下の優先度で解決されます。上位でマッチすれば即確定し、下位には進みません。 | 優先度 | ソース | 説明 | | --- | --- | --- | | 1(最高) | override辞書 | 管理者が手動登録した確定読み。文脈付きエントリ優先(例: 一日+中→イチニチ) | | 2 | 文脈ルール | 前後トークンの品詞・表層形から同形異音語を判定(一日/上手/大人 等13語) | | 3 | promoted/auto辞書 | ユーザー投票で昇格した読み・自動推定 | | 4 | Lindera読み | 形態素解析エンジンが文脈を見て選んだ読み(フォールバック) | | 5(最低) | UniHan単漢字 | 42,318字の単漢字読みデータベース(最終手段) | さらに、形態素解析の**前段階**で隣接トークン結合(最大5トークン)による辞書マッチを行います。「所」+「謂」が別トークンに分割されても、辞書に「所謂」があれば結合して正しい読みを適用できます。 ## 生成AIをどう活用したか ここからが本題です。Claude(Anthropic社の生成AI)をペアプログラマーとして、以下の4つのフェーズでふりがな精度を改善しました。 ### Phase 1: テストケースの網羅的生成 最初に取り組んだのは**テストの拡充**です。 Rustのユニットテストが35件、E2E(エンドツーエンド)テストが204件の状態でした。しかし、日本語の読みのエッジケースは無数にあります。Claudeに「助数詞の音便変化パターンを全列挙して」「不規則な日付読みのテストケースを生成して」と依頼することで、テスト対象を一気に拡大できました。 AIは人間が見落としがちなパターン — 例えば「0本」(ぜろほん? れいほん?)や「何日」(なんにち)のような境界ケースも提案してくれます。 ### Phase 2: 辞書エントリの一括生成 ふりがな辞書には、形態素解析器が苦手とする単語を登録します。 - **難読語**: 海豚(いるか)、案山子(かかし)、五月雨(さみだれ) - **四字熟語**: 疾風怒濤(しっぷうどとう)、一期一会(いちごいちえ) - **地名**: 各務原(かかみがはら)、喜連瓜破(きれうりわり) これらを一つずつ調べて登録するのは途方もない作業です。Claudeに「Linderaが間違えやすい難読語を100個、読みつきでリストアップして」と依頼することで、辞書を効率的に拡充できました。 ただし**AIの出力をそのまま信用してはいけません**。生成された読みを1件ずつ検証し、間違いを修正するプロセスは人間が担当します。実際、AIが自信満々に間違えるケースも少なくありませんでした。 ### Phase 3: 文脈ルールの設計 同形異音語の判定ロジックは、AIとの対話で設計しました。 例えば「一日」の読み分けルール。Claudeに「一日がツイタチになる文脈とイチニチになる文脈をすべて列挙して」と聞くと: - 月名の直後 → ツイタチ(一月**一日**) - 「中」「目」が後続 → イチニチ(**一日**中、**一日**目) - 「毎」「丸」が先行 → イチニチ(丸**一日**、毎**一日**) このように文脈条件を網羅的に洗い出し、Rustのパターンマッチに落とし込みました。人間だけでは「丸一日」のようなパターンを見落としがちですが、AIは大量の用例から抽出してくれます。 ### Phase 4: バグの発見と修正サイクル テストを実行 → 失敗を特定 → 原因を分析 → 修正 → 再テスト。このサイクルをAIと回すことで、修正のテンポを保ちやすくなりました。具体的には: 1. **テスト結果の分析**: 「この50件の失敗パターンを分類して」→ 数値パイプラインのバグ、辞書の欠落、文脈ルールの不足に自動分類 1. **修正コードの生成**: 「3匹がサンビキになるべきところサンヒキになっている。促音便ルールを修正して」→ Rustコードを直接生成 1. **回帰テスト**: 修正が他のテストケースを壊していないか即座に確認 ## 数字で見る成果 以下の数値は**当時(旧バージョン)のもの**です。現在は構成が変わっており(OSSライブラリ+TOML辞書)、件数や内訳も異なります。 | 指標 | Before | After | | --- | --- | --- | | テストケース数 | 0件 | 35件(Rustユニットテスト)+ 204件(E2E) | | テスト | — | 全テストが通る状態を維持 | | 辞書エントリ数 | 0件 | 1,640件(override)+ 435件(互換辞書) | | UniHan単漢字辞書 | 0件 | 42,318件 | | 文脈ルール | 0語 | 13語(一日/一人/二人/大人/上手 等) | | 助数詞対応 | 0種 | 15種以上(本/匹/分/人/回/個/歳/台/冊/枚/杯/羽/円/階 等) | | 後処理ルール | 0件 | 5件(正規表現ベース) | | 数値パイプライン | 0行 | 1,517行 | ## 学んだこと ### AIは「網羅性」に強い 人間は代表的なケースは思いつきますが、エッジケースの網羅は苦手です。AIは「他に似たパターンはない?」という問いに対して、人間が見落としがちな例を大量に列挙できます。 ### AIの出力は「仮説」として扱う AIが生成した読みや辞書エントリを鵜呑みにしてはいけません。特に日本語の読みはネイティブスピーカーでも迷うケースがあり、AIも間違えます。**AIの出力 → 人間が検証 → テストで確認**というサイクルが不可欠です。 ### テストファーストが効く 先にテストケースを大量に用意し、それを通すようにコードを書く。このアプローチはAIとの協業と相性が抜群です。「このテストを通して」という明確なゴールがあると、AIも的確なコードを生成しやすくなります。 ### 「口語読み」という方針が重要 読み上げBotという用途から、**口語(話し言葉)の読みを優先する**という方針を最初に決めました。 - 今日 → 「きょう」(✓)/ 「こんにち」(✗) - 昨日 → 「きのう」(✓)/ 「さくじつ」(✗) - 明日 → 「あした」(✓)/ 「あす」(✗) この方針がAIへの指示にも一貫性を持たせ、辞書やルールの品質向上につながりました。 ## 未解決語の自動収集 ふりがなAPIには、辞書にない単語を自動記録する仕組みがあります。 ``` テキスト入力 → 辞書にない語を検出 → 改善 signal log (JSONL) に記録 - 表層形(surface)の集計 (どの漢字 / 単語が何回 fallback されたか) - 文脈付き window (対象 token + 前後 2 トークン) ``` 集計結果を定期的にレビューし、OSS 辞書 [`ja-furigana-dict`](https://github.com/RyuuNeko1107/ja-furigana-dict) に手動 PR で反映する**継続的改善サイクル**を回しています。PR がマージされれば翌日のリリースで自動的に本番に取り込まれます。 ## まとめ ふりがなAPIの開発は、生成AIの「得意なこと」と「苦手なこと」を理解する良い教材でした。 **AIが得意なこと:** - パターンの網羅的列挙 - テストケースの大量生成 - コードの高速な修正サイクル - エッジケースの発見 **AIが苦手(人間が必要)なこと:** - 最終的な読みの正誤判断 - 方針の決定(口語 vs 文語) - アーキテクチャの全体設計 - ユーザー体験の判断 生成AIは「完璧な答えを出すツール」ではなく、**「人間の判断を加速する仕組み」**として使うのが最も効果的だと感じています。 ふりがなAPIは[こちらのページ](/?slug=furigana-api)でAPIドキュメントとデモを公開しています。Discord読み上げBot「ずんだー」で実際に動いている技術です。技術的な質問は[お問い合わせフォーム](/contact/)からお気軽にどうぞ。 --- *※本記事は2026年6月時点の情報をもとにしています。サービス・コマンド・仕様は予告なく変わることがあります。*