開発book-knowledge-base

朝5時40分、コーヒーをいれる前にターミナルを開いて /import-batch を叩いた。会計5thバッチ、10冊を一気にDBへ突っ込む回。終わったのは7時50分。約2時間で +3,354 チャンク、DB全体は 268冊 / 39,129 チャンクに着地した。

毎回バッチを回すたびに違う罠に踏むので、今回踏んだ罠と、それを避けるためにスクリプトに仕込んだ仕掛けを残しておく。

取り込んだ10冊

会計系の参考書・教科書類が中心。書名はぼかしておくが、内訳は以下の book_id。

choukousoku-kaikei-benkyo
bca-2kyu-koshiki-4th
mba-yori-kantan-kessan
setsurei-shihon-renketsu
fusei-kaikei-chosa-manual
shin-kaikei-zukai-jiten
sukkiri-boki-3kyu
boki-kiso-1-2-gekan
atarashii-boki-3kyu
jissen-zaimu-sosa

合計PDF サイズは約1GB。OCR バッチで md 化したあと、Turso にチャンク分割して投入する流れは前回と同じ。

罠1: ファイル名と Amazon タイトルが食い違う3冊

着手前、amazon_metadata テーブルから PDF パスを引き当てるところで違和感を覚えた。No117 / No240 / No315 の3冊が、ファイル名から想像できるタイトルと Amazon 側のタイトルが噛み合っていない。

そのまま投入すると、別書籍を重複として弾いてしまうか、同じ書籍を二重登録するかのどちらかをやらかす。Claude Code に「PDF の中身(1ページ目)をテキスト抽出して実体タイトルを確認して」と頼んで、3冊それぞれの実物を当てに行ってもらった。

結果、こうだった。

  • No117 = 『スッキリわかる日商簿記3級 第10版』 → sukkiri-boki-3kyu(Amazonと一致)
  • No240 = 『新しい日商簿記3級 テキスト&問題集』 → atarashii-boki-3kyu別書籍。重複ではない
  • No315 = 『簿記基礎 I・II 下巻』 → boki-kiso-1-2-gekan(ファイル名通り)

特に No117 と No240 は両方とも「簿記3級の教科書」というカテゴリで近接していたので、ファイル名の boki-3kyu 部分を見て「これ重複じゃないか?」と一瞬疑った。中身を見たら、章立ても出版社も違う 完全に別の書籍 だった。

ファイル名・Amazon メタデータ・PDF 本文の3点で照合しないと、こういう「似ているが別物」は絶対取りこぼす。今回は3冊とも別物として正しく登録できた。

罠2: OCR 中間 jpg がディスクを食い潰す

前回バッチで disk full を踏んでいた。yomitoku が PDF ページを一旦 jpg に展開してから OCR にかける構造で、4000ページ規模だと中間ファイルが10GB単位で残る。

今回は OCR バッチスクリプトに、1冊終わるたびに中間 jpg を削除する処理 を組み込んだ。方針はシンプルで、こんな雰囲気。

for book_id in "${BOOKS[@]}"; do
  run_yomitoku "$book_id"
  rm -rf "$WORK_DIR/$book_id/jpg/"  # ← これだけ
  echo "[cleanup] $book_id intermediate jpg removed"
done

1時間40分の OCR の間、ディスクは94GB空きで安定し続けた。前回みたいに途中で No space left on device を吐かれて、原因切り分けに30分溶かす展開を避けられた。

OCR 進行とチャンク化の結果

OCRバッチを 06:06 にバックグラウンド起動して、07:46 に全10冊完走。バッチ起動中はずっと別のことができるので、待ち時間の体感はゼロに近い。

完了後のチャンク数を眺めて、面白い偏りに気づいた。

  • 最大: boki-kiso-1-2-gekan 490md → 465 chunks
  • 最小: choukousoku-kaikei-benkyo 175md → 28 chunks(merged 18, skip 11)

choukousoku-kaikei-benkyo は元のページ数も短く、かつ1ページあたりの文字密度も薄いので、/restructure-book のセクション集約が強めにかかった。md 175枚 → チャンク 28個まで圧縮されている。短い本に対しては「むやみに細切れにせず、章単位でまとめる」挙動になっていて、検索体験としても正しい。

逆に簿記基礎の下巻は仕訳例が大量に並ぶ構造で、ページ単位の独立性が高い。結果として md 枚数とチャンク数がほぼ1:1で対応する形に落ち着いた。

バッチ後の状態

DB全体: 268冊 / 39,129 チャンク
今回追加: +10冊 / +3,354 チャンク
所要時間: 約2時間(05:40 → 07:50)

9cdb6c7 でコミットして、会計5thはクローズ。次の候補として残っていた 税務3rd(残15冊) が同じペースで回せそうな分量なので、続けて投げる気でいた。

次は税務3rdじゃなく Kindle に切り替え

終わったあと「次どれ行きます?」と聞いたら、税務3rdじゃなくて Kindle 蔵書の取り込みを進めたい という返事だった。

そっちは PDF 自炊した本ではなく、Kindle Cloud Reader からスクショ経由で取り込む別パイプライン(/yomitoku-kindle)。未OCR は464冊残っていて、ベイズ加重評価の上位から優先取り込みする戦略になっている。

最初に試運転として『会計の世界史』(★4.6・1,517レビュー)を選んで取り込みに入ろうとしたが、Chrome DevTools MCP の接続でつまずいて止まった。そこからは「Kindle 蔵書全体の優先順位付けをどう設計するか」の戦略計画書を書く方向に切り替えて、memo/2026-06-19/kindle-import-priority-plan.md にまとめ直した。

このバッチ運用で固まってきたこと

  • 3点照合は最初にやる: ファイル名・Amazon メタ・PDF 本文。1冊でもズレていたら、その時点で止めて確認する。バッチが2時間走った後に「実は重複でした」が一番つらい
  • 中間ファイルの寿命をスクリプトに織り込む: 「手で消せばいい」は手が回らなくなる。1冊終わるたびに自動で消すフックを入れておく
  • OCR はバックグラウンド前提で組む: 90〜120分かかる処理を待つ時間に他のタスクを進められると、体感の所要時間が半分以下になる

朝一の2時間で10冊片付くと、その日の残り時間の使い方がだいぶ自由になる。