数学参考書をOCRで全文DB化し、その日のうちにインタラクティブ教材へ変換した記録

朝、裁断済みの中学受験向け数学参考書(100トピック構成・328ページ)のPDFをOCRワークフローに投げた。夕方には、その本の中身から作ったクイズ教材13本がブラウザで動いていた。「本をDBに入れる」と「DBから教材を生み出す」を1日でつなげた記録。

午前: OCR取り込みとDB格納

yomitoku OCRで328ページを処理

いつもの /yomitoku ワークフローで取り込みを開始した。328ページあるのでOCRはバックグラウンドで回し、完了まで約31分かかった。

待ち時間も遊ばせない。OCRが回っている間に、書誌メタデータの登録を並行して進めてもらった。この本には原版と新装版の2つの版があったので、Amazonの表紙画像を見比べて版を特定したうえでASINと書誌情報を登録させた。OCR完了後は図ファイルのリネーム、DB格納(289チャンク)、全文検索テスト、書影の紐付け確認まで一気に通った。

/restructure-book でページ単位→トピック単位へ

OCR直後のチャンクはページ単位で、そのままでは検索の単位として使いにくい。/restructure-book で目次に基づいてセクション単位に統合してもらった。

レプリカ同期で一度待たされたが、HTTP直接接続・単一トランザクションのスクリプトで統合を実行。289チャンクが187チャンクになり、100個のトピックすべてが「トピックN タイトル(単元名)」のセクション名で検索できるようになった。

書籍ビューアでの表示整形

トピック内の構成崩れを一括整形

ローカルの書籍ビューアを立ち上げて(ポート3000は別プロジェクトが使っていたので3001で起動)、トピック1を開いてみたら中身がごちゃごちゃしていた。この本は全トピックが同じ型で構成されている:

  • トピックの解法
  • 例題 → 解答
  • 入試問題をチェック → 解答
  • 入試問題にチャレンジ(解答は別冊)

この型に合わせて一括整形スクリプトを書いてもらった。いきなり本適用せず、まずドライランで変更内容を確認する。最初のドライランではタイトル置換の誤爆が出たので、類似度1.00の完全一致のみ置換するよう絞らせてから本適用した。最終的に全100トピックが標準構成チェックに合格した。

別冊解答を各トピックの直下に統合

整形結果を眺めていて気づいた。紙の本なら「解答は別冊」に意味があるが、デジタルデータで解答が別の場所に分かれている意味はほぼない。そこで、全トピックの「入試問題にチャレンジ」の解答を各トピックチャンクの末尾に統合し、別冊部分は移動後に削除してもらった。

厄介だったのは、1つの解答チャンクが複数トピック分(例: トピック92〜93)を含んでいるケース。これは解答中の「本冊p.X」というページ参照マーカーを区切りに分割して、それぞれのトピックへ振り分ける方針で解決した。

289チャンク(ページ単位)
 → 187チャンク(トピック単位に統合)
 → 111チャンク(別冊解答76件を各トピック末尾へ統合・削除)

各トピックページの最後に「入試問題にチャレンジ!の解答」セクションが付き、問題から解答まで1画面で読み通せるようになった。

巻末の公式集はページ画像を見ながら手で書き直し

巻末付録の「例題付き公式集」(学年別3ページ分)は、OCRが数式を擬似テーブルに崩していて自動整形では救えなかった。ここは元PDFのページを画像化し、それを見ながら読みやすいMarkdownに全面的に書き直してもらった。OCRで取り込んだ書籍は、最後の数ページだけこういう手当てが要ることが多い。

午後: 目次からインタラクティブ教材を選定・量産

適性判定と試作3本

午後はmdx-playground側のセッションに切り替えて、「Turso DBに入っている目次をざっと見て、Webのインタラクティブコンテンツにしやすいトピックを選定してほしい」と依頼した。クイズ、あるいは動かせる解説コンテンツを想定している。

DBから100トピックの目次を全件レビューさせ、インタラクティブ化の適性を◎・○で判定。まず3本を試作してもらい、動作確認まで済ませた。

「1〜10番台はなぜ表にない?」

選定結果の表を見て引っかかった。トピックは1から100まであるのに、1〜10あたりの判定が表に載っていない。落としたのか、判定すらしていないのか。理由を問いただした。

答えは「表は上位候補の抜粋で、全100トピックの判定を載せていなかった」。落選ではなく省略だった。選定理由を表で受け取るときは、全件の判定が載っているのか抜粋なのかを最初に確認すべきだった。AIの出す一覧表は、黙っていると「見せたいところだけ」になる。

◎・○候補を全部作り切る

抜粋で済まされると不安が残るので、方針を変えた。「適性◎・○のトピックは一旦全部作り終えて」と指示。○候補8グループの本文をDBから作業用ファイルに展開させ、数学教材用コンポーネント群として実装を進めた。

途中、トピック9の本文取得でプレフィックスの誤マッチが起きてファイルが壊れたが、正確な条件で取り直して復旧。ハブページを試作11本に拡充し、全テストを一括実行した。CSS 3DやSVGの崩れリスクがある4ページ(立体の折りたたみアニメーションなど)はブラウザで実際に開いて確認した。

最後に残った◎候補2本(円錐、最短距離)は、並列のサブエージェント2体に分担させて実装。これで◎候補は全13本試作済み、○の残りはゼロになった。出来上がったのは展開図・放物線・規則性・約数と倍数・変域・水量グラフ・円錐・最短距離といった単元のクイズと動く解説のセットで、それぞれにユニットテストも付いている。

そして13本目の動作確認を終えた直後、月間の利用上限に当たってセッションが止まった。ちょうど作り切ったところで燃料が尽きた。

学び

  • 書籍のデジタル化は「取り込み」より「構造の作り直し」に価値がある。ページ単位のOCR結果をトピック単位に統合し、別冊解答を本体に吸収した時点で、紙では不可能な「問題と解答を1画面で読む」体験になった
  • AIの選定結果の表は全件か抜粋かを必ず確認する。今回は1〜10番台が「抜粋から漏れていただけ」だったが、聞かなければ判定漏れと区別がつかなかった
  • 一括更新スクリプトはドライラン必須。タイトル置換の誤爆は類似度1.00縛りで防げた。100チャンク全件更新を一発勝負でやっていたら巻き戻しに苦しんだはず
  • 朝に本をDB化して、午後にその中身から教材を13本生やす、という流れが1日で回った。書籍ナレッジベースが「読むためのアーカイブ」から「コンテンツの原料庫」に変わりつつある