開発book-knowledge-base

書斎の床に積み上がっていた裁断済みの本の山を、今日は片付けた。スキャナーから吐き出されたPDFをClaude Codeに投げて、一方でyomitokuに5冊分のOCRを走らせる。人間は山を見て「これを今日中に消化する」と決めただけで、あとはAIが順番に処理を回してくれた。

OCRパイプラインに5冊を流す

book-knowledge-baseの/yomitokuコマンドで、書籍PDFをOCRしてTurso DBに突っ込む。今日流したのは5冊。

  • 統計年鑑(528ページ)
  • 決算書解説の参考書(218ページ)
  • 入門レベルの決算書解説書(200ページ)
  • 投資戦略の参考書(240ページ)
  • 投資手法のワークボック(216ページ)

統計年鑑が一番重く、yomitokuのOCRに約46分かかった。ページ数が多い書籍は素直に時間を食う。OCRが返してきたチャンクは514個。これを/restructure-bookで章節単位に統合し直すと、130チャンクまで圧縮された。細切れになった本文ブロックが章のまとまりに戻り、検索で当てたときに「どの章のどの節」かが復元される形に整う。

他の4冊も同じパイプラインを通した。200ページの決算書解説書は156チャンク→39セクション、投資戦略の参考書は167チャンク→53チャンク、ワークボックは161チャンク→33チャンクに統合。OCRが吐く生チャンクは1ページ複数個に分かれるので、3〜5倍に圧縮されるのが平均的な手応えだ。

WALロック問題、HTTP直結で逃げる

5冊を並行して流していたら、案の定Turso DBのWALロックに何度か当たった。Embedded Replicaで書き込もうとすると、別プロセスの書き込みと衝突してロック待ちが発生する。/yomitokuコマンド自体は再試行ロジックを持っているが、複数本のOCRを並走させているとリトライしてもロックが解けない場面が出る。

CLAUDE.mdのナレッジには「WALロックが頻発したらEmbedded Replicaを諦めてHTTP直接接続に切り替える」という教訓が残してある。前にハマったときに自分で書いた一文だ。それを今日も発動させて、書き込み経路をHTTP直結に切り替えた。Embedded Replicaのオフライン耐性は捨てるが、ロック衝突は消える。5冊並走でも書き込みが詰まらなくなった。

ナレッジを書き留めておくと、半年後の自分が30秒で同じ罠を回避できる。今日それを実感した。

amazon_metadata取得をWebFetchからagent-browserに切り替える

OCR後はAmazonから書籍メタデータ(著者・出版年・ISBN)を取りに行って、書籍レコードに紐付ける。これまで/yomitokuコマンドの後段でWebFetchを使っていたのだが、Amazonはbot対策が厳しく、WebFetchが失敗することが続いた。

今日も1冊目で失敗した瞬間に、自分から「agent-browserに書き換えて」と指示を入れた。.claude/commands/yomitoku.mdのStep 6.5を、agent-browserでAmazonの商品ページを開いてDOMから抽出する手順に書き換えてもらう。agent-browserはユーザーのログイン済みChromeを使うので、bot判定にほぼ引っかからない。書き換え後の2冊目以降は全件取得できた。

「WebFetchが落ちたらagent-browserにフォールバックする」というルールはCLAUDE.mdに書いてあるのだが、コマンド定義そのものを書き換えてしまえば、毎回フォールバックを意識せずに済む。コマンドを書き換える指示は人間が出すが、書き換え作業はClaude Codeが順に進めた。

Notion exportの取り込みでルートCSVを動的生成する

夕方、Notionから書き出したZIPアーカイブをDBに取り込む別タスクが入った。中身を展開するとHTML 25個、PNG 50枚、CSV 4つが入っている。普段のNotion exportはルート直下に「親ページの一覧CSV」と対応するHTMLが置かれているのだが、今回のZIPにはそれが見当たらない。

仕方ないので、Claude CodeにZIP内のテーブル構造(HTML内のリンクとCSVの参照関係)を解析させ、ルートCSVを動的に生成する処理を組んだ。HTMLのリンクから子ページのIDを引き、CSVに親ページの一覧として書き戻す。本来Notionが出してくれるはずのCSVを、こちらで合成して取り込みパイプラインに食わせる形になった。

並行でPDFリネームを9件こなす

OCRが回っている裏側で、mdx-playground側の/rename-pdfコマンドに裁断スキャン本のPDFを6件投入した。pymupdfで先頭ページを画像化し、Claudeの画像認識でタイトルを読み取り、ファイル名を書籍タイトル形式に揃える。サブエージェントを並列で立てて、6件をまとめて捌く。

途中で書斎の別の山から3冊出てきたので、追加で3件流した。合計9件のリネームが並走した。

副題の誤読を画像で拾って直す

サブエージェントが返してきたリネーム結果を眺めていて、1件違和感があった。「光の思想と実践」というタイトルを返してきたファイルがある。書名としては存在しそうだが、自分が裁断した本のラインナップに記憶がない。

pymupdfが画像化した先頭ページをClaudeに開かせて確認すると、副題部分の漢字を一文字読み違えていた。正しくは「その思想と実践」。書名冒頭の「その」を「光の」と読んだのだ。サブエージェントを呼び直して正しい書名でリネームし直した。

画像認識は便利だが、副題の細い字や曲がった裁断面では字形を取り違える。並列で動かしている分、人間が一覧を眺めて「これ違わないか?」と拾うフェーズが要る。電卓検算ではなく、「画面の文字列を見て違和感を拾う」という同じ筋肉だ。

給与計算マニュアルの年版は奥付で確定する

もう1件、給与計算マニュアルの表紙だけ見せても年版が判定できないファイルがあった。表紙に書かれているのは書名と監修者だけで、何年版かはどこにも書いていない。サブエージェントは「初心者にもよくわかる給与計算マニュアル」とだけ返してきた。

pymupdfに後ろの数ページも画像化させて、奥付ページを確認する。奥付に「2023年4月発行 第4版」と刷ってあった。正式書名は「初心者にもよくわかる給与計算マニュアル 4年版」だと特定できた。表紙の判定だけでは詰む書籍がある、というのを今日の収穫として記録しておく。

コマンドファイルの開始番号を更新する

9件のリネームが片付いたあと、.claude/commands/rename-pdf.mdに書いてある「次回リネーム時の開始番号」を更新した。複数回に分けて回しているので、次回の自分が前回どこまでやったかを引き継げるよう、コマンドファイル自体に状態を書き戻す形にしてある。

今日の積み上げ

  • Turso DBに5冊分の書籍OCRを取り込み、合計1,148チャンクを288セクションに統合した
  • WALロックはHTTP直結で逃げる、というナレッジを再発動させた
  • /yomitokuのamazon_metadata取得をWebFetchからagent-browserに書き換えた
  • 裁断スキャン本のPDFリネームを9件並列で捌いた
  • 画像認識の誤読を「画像を見直す」「奥付を確認する」の2手で詰めた

人間がやったのは「山を片付けると決める」「違和感を拾う」「コマンド書き換えを指示する」の3点だけ。OCR、チャンク統合、メタデータ取得、リネーム、コマンドファイルの更新までは、全部Claude Codeが順に進めた。AIが回せるパイプラインに、人間は判断と違和感検知だけを差し込む。書籍ナレッジベースの蓄え方が、ようやくこの形で安定してきた。