• #yomitoku
  • #OCR
  • #SQLite
  • #Claude Code
  • #Cloudflare Pages
  • #tokyo-onkei
  • #book-knowledge-base
  • #SSG
開発book-knowledge-baseメモ

書籍OCRバッチクリーンアップとtokyo-onkeiデプロイ修正

朝、yomitokuに75ページのPDFを投げたら113秒でOCR完了の表示が出た。75個のMarkdownファイルと184個の図ファイルがディスクに並んでいるのを見て、「今日は残りの書籍も全部片付けよう」と腹を決めた。午後はtokyo-onkeiのデプロイで本番サイトのCSSが崩れていることに気づき、リダイレクト設定まで手を伸ばすことになった。


yomitokuで新規PDFをOCR変換

75ページの専門書PDFをyomitokuに通した。GPU処理で113秒、1ページあたり約1.5秒のペースでMarkdownに変換された。

生成物:

  • 75個のMarkdownファイル(ページ単位)
  • 184個の図ファイル(図表・グラフ等)

図ファイルはOCR出力時のランダムな名前のままだったので、184ファイルすべてをページ番号ベースにリネームした。その後、SQLite DBに格納してFTS(全文検索)のテストまで確認した。検索クエリを投げてヒットしたチャンクが返ってくるのを見て、パイプラインが一本線としてつながった。


/cleanup-bookによる複数書籍のバッチクリーンアップ

前日に作った並列クリーンアップの仕組みを、今日は3冊分に適用した。1冊ずつ処理の流れと起きた問題を残しておく。

書籍1: 77チャンク

77チャンクを5バッチに分割し、サブエージェント並列で処理した。各バッチが独立してクリーンアップを実行し、結果をマージ。バッチ境界でのセクション分断もなく、スムーズに完了した。

書籍2: 52チャンク

同じく5バッチ並列で処理。チャンク数が少ない分、バッチあたりの負荷も軽い。境界マージの確認を挟んで、問題なく完了。

書籍3: 77チャンク -- コンテキスト溢れで中断

77チャンクの処理を開始したところ、途中でサブエージェントが「Prompt is too long」エラーを吐いて止まった。大量のチャンクを読み込んだ状態で並列処理を走らせると、コンテキストウィンドウの上限に達してしまう。

対処としてはセッションを一度切り、新しいセッションで途中から再開した。前のセッションで処理済みのバッチはDB上のフラグで判別できるので、未処理分だけを拾い直す形で復旧した。

コンテキスト溢れの教訓

クリーンアップ対象のチャンクが多い書籍では、チャンクの内容をすべてコンテキストに載せた状態でサブエージェントを5本走らせると、トークン上限に到達する。対策としては:

  • 1バッチあたりのチャンク数を減らす
  • 処理済みバッチのコンテキストを早めに捨てる
  • セッションを分けて処理する(今回の手動対処)

根本対策は「バッチサイズの動的調整」だが、今日は手動のセッション再開で乗り切った。


tokyo-onkei: デプロイコマンドとCSS崩れ修正

デプロイコマンドのデフォルト変更

これまでデプロイコマンドは site 単体がデフォルトだったが、all(サイト + ダッシュボード両方)に変更した。毎回 --target all を付けるのを忘れてダッシュボードが古いまま、という事故を防ぐため。

本番サイトのCSS崩れ対策

本番サイトを開いたらレイアウトが崩れていた。原因を追うと、SSGビルドでルート / にアクセスしたときのリダイレクトが効いていなかった。

問題の構造:

  • i18nのprefix strategy(/ja, /en)を使っている
  • SSGビルドではサーバーサイドのリダイレクトが動かない
  • ルート / にアクセスすると言語プレフィックスなしのページが返り、CSSの参照パスがずれていた

解決策: Cloudflare Pagesの _redirects ファイルを追加し、/ /ja 302 のリダイレクトルールを書いた。SSGの静的ファイルではサーバーリダイレクトが使えないが、Cloudflare Pagesの _redirects はCDNレベルで処理されるため、ビルド成果物に含めておけば動く。

i18nのprefix strategyとSSGの組み合わせは、ルートパスの扱いでハマりやすいポイントだった。


mdx-playground: 日記生成と移行計画確認

  • 2月19日の日記を /make-diary コマンドで自動生成した
  • Nuxt 2 → Nuxt 4 移行計画の確認。Vuetify依存をscoped CSSに置き換える方針の経緯を再確認

今日の学び

  • yomitokuのGPU処理は75ページを113秒で変換する。1冊あたり2分弱なら、手持ちの書籍を片端からDB化しても半日で終わる計算になる
  • コンテキストウィンドウには物理的な上限がある。並列サブエージェントを走らせるとき、親エージェントのコンテキストに全チャンクを載せたまま分岐すると破綻する。「処理済みデータは早めに手放す」設計が要る
  • SSGとi18nのprefix strategyを組み合わせると、ルートパスのリダイレクトが宙に浮く。Cloudflare Pagesの _redirects でCDNレベルのリダイレクトを仕込むのが確実な回避策だった

振り返り

朝の時点では「OCR変換して終わり」のつもりだった。だが1冊変換するとクリーンアップしたくなり、クリーンアップすると次の書籍に手が伸び、3冊目でコンテキスト溢れに遭遇して「並列処理の限界」を体で覚えた。午後のtokyo-onkeiデプロイでは、ローカルでは再現しないCSS崩れを本番で見つけ、SSG + i18nの組み合わせが生む死角を _redirects ファイル1つで塞いだ。手を動かす日は問題も見つかるが、問題が見つかるのは手を動かしている証拠でもある。