
2026/03/19 0:44
**25 年の卵**
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
概要:
2026年2月に、著者は11,345件のレシート(PDF、メール、画像)をわずか14日間(2月8日〜22日)で処理するエンドツーエンドパイプラインを構築しました。システムは、CodexとClaudeという二つのAIコーディングエージェントと専門化されたOCRモデルを組み合わせています。「白い影」のようなフラットベッドスキャンなどのOCR課題は、高さのあるレシートを動的に切り分けることで対処され、PaddleOCR‑VL(0.9Bパラメータ)がTesseractの代わりに使用されました。GPUを100%利用し夜間に10.8時間実行して全レシートのテキストをきれいに抽出しました。SAM 3による境界検出は、0.92〜0.98の信頼度で約4秒/スキャンを達成しました。構造化抽出は正規表現から完全バッチCodex処理へ移行し、バッチサイズ調整と分離により平均ETAが約12時間から約3時間に短縮されました。
真実データは375件のレシートを手動でラベル付けして作成され、数ショットLLM分類器(20例)により全レシートの卵分類で99%以上の精度が達成されました。最終的なデータ品質評価では、372件のランダムサンプルで96%の正確性が確認され、偶発的なOCR幻覚は反復的なエージェントフィードバックを通じて修正されました。このパイプラインにより589件の卵レシートが確認され、合計1,972ドルの支出と8,604個の卵がカウントされました。人間によるハンズオン時間はわずか15時間(主に短い指示付与のブースト)でした。
主な課題として、フォルダ名のタイプミス(「Reciepts/Recipts」)、鏡像スキャン、およびHTMLから価格行が欠落するメールレシートが挙げられます。著者はSAM 3やPaddleOCR‑VLなどの専門モデルとコーディングエージェントの相乗効果を強調し、効果的な大規模レシート処理におけるこのハイブリッドアプローチが労働負担を劇的に削減でき、高い精度を維持しつつ、小売業や経費追跡などのより広範な応用へスケール可能であると示唆しています。
本文
公開日:2026年2月23日
誰もがやりがいのある趣味を必要としています。2001年以来、私は自分のレシート全てをスキャンしてきました。一度も金額を入力せずに画像だけを保存し続けていました。いつかテクノロジーがそれらを読み取れるようになり、そのデータが面白くなるだろうと考えていたのです。
今年、私は実際に試しました。2つのAIコーディングエージェントと11 345枚のレシート。まずは卵から始めました。25年間にわたる乱れたサーマルプリント、OCR失敗、フォルダ名のタイプミスを通じて1つの商品を追跡できれば、何でも追跡できます。
14日間。16億トークン。589枚の卵レシートが見つかりました。データはこう語っています。
プロジェクト計画(Day 1)
ではプロジェクト計画を立てましょう。
に大量のレシートがあります。多くは PDF / 画像などです。実際にレシートの内容を抽出して、卵にどれだけ費やしたかを見つけたいと思います。レシートは OCR が非常に苦手なので、もっと高度な処理が必要になるかもしれません。~/Records/
Codex はファイルシステムを探索し、忘れていた2つの SQLite データベースを発見、PDF・メール・画像から11 345枚のレシートを抽出し、プロジェクト計画を作成しました。私は「
plan.md に書いてください」と頼むと、1時間以内に完成しました。
全体で14日間かかりました。実際にキーボードを操作した時間は約15時間――短い指示の発信と長時間エージェントが処理を続けるというパターンでした。Codex は 15 回のインタラクティブセッション、Claude は 10 回を担当しました。
白のグラデーション
最古のレシートはフラットベッドスキャンです。1ページに複数枚、ランダムな向き、白い紙と白いスキャナ床。Codex と私はレシート境界を検出するために7つの従来の CV アプローチを試しました:
- エッジ検出
- 適応閾値処理
- 輪郭解析
- モルフォロジー演算
- ウォータッシュ分割
- テンプレートマッチング
- グリッドベース分解(古典的な HackerRank 問題)
どれも機能しませんでした。根本原因はレシートが白く、スキャナ床も同じ色だったことです。「白のグラデーション問題」と呼びました。最も賢い試みは観光客をランドマーク写真から除去する手法に触発され、すべてのスキャンを重ね合わせ、各位置で中央値ピクセルを計算し差分を取ることでエッジを明らかにしました。最高 F1 は 0.302。
macOS Vision OCR(Codex が即席で書いた Swift スクリプト経由)、Tesseract、その他数多くのツールも試しましたが、フラットベッドスキャンは失われる運命だと感じ始めました。そこで Meta の SAM3 を使いました。
text="receipt" という API 呼び出しで、境界ごとに 0.92–0.98 の信頼度を得られ、1 スキャンあたり約4秒でした。760 ページの多レシートから 1 873 枚が抽出されました。数時間かけた7つのアプローチよりも SAM3 は午後に完了しました。
待て ― あなたはすでに答えを知っている
レシートはランダムな角度で落ちるため、OCR はそれらを直立させる必要があります。Tesseract の向き検出、macOS Vision OCR、Moondream 2 と 3 を試しましたが、どれも信頼できるほどではありませんでした。そこで気づいたのは、レシートを Claude 会話に貼り付けてデバッグすると、すでにテキストが完璧に読み取られていることです ― 回転していてもフェードアウトしていても。
なぜ回転パイプラインを構築する必要があるのでしょうか? 既に会話相手のツールがそれを解決してくれるのに。そこで、11 345枚すべてを Sonnet と Codex に送信しました。時には答えが目の前にあるだけでした。
Tesseract を一晩で置き換える
プロジェクト途中で、Tesseract が弱点でした。「OAT MILK」を「OATH ILK」と読み取り、小数点を落とすなどしていました。古いサーマルプリントでは全く文字が出てこなかったです。Codex は最悪の 20 枚を手動で開き、レシートでないもの(家族写真、ポストカード、挨拶状)が「Receipts」として分類されていることに気付きました。
PaddleOCR‑VL を見つけました。0.9 B パラメータのビジョン・ランゲージモデルで Apple Silicon 上でローカル実行できます。銀行取引明細のサンプルテストでは 2.1 秒でクリーンなテキストが取得でき、Tesseract より高速ですがノイズは多いです。Fred Meyer の長いレシートを試すと「TILL YGRT」が無限に繰り返されるという問題が発生しました。
解決策は簡単でした ― 高さのあるレシートをスライスに分割すること。アスペクト比に応じて動的にスライス数を決定:
num_slices = max(2, round(aspect_ratio / 1.5))
5 本の並列シャードが一晩中走りました。GPU は 10.8 時間で 100% を占有しました。朝には 11 345 枚すべてを OCR 成功させ、アーカイブ内のテキストをクリーンにしました。
PaddleOCR‑VL は Codex の代替ではありません ― 構造化抽出や指示追従はできません。ただし、Tesseract より優れたテキスト取得ツールです。実際のパイプラインは
レシート画像 → PaddleOCR‑VL(ローカルでクリーンなテキスト)→ Codex/Claude(構造化抽出) となります。
12 時間から 3 時間へ
レシートが分割・直立・OCR された後、次に必要なのは構造化抽出 ― 卵の項目を見つけ、価格と数量を取り出すことです。最初は正規表現で始めました。モデルは正規表現が好きです。「egg」というキーワード、金額パターンで価格を探しました。ヒューリスティックは 25/25 のポジティブサンプルで偽陽性ゼロでした ― 悪いものはありませんでした。しかし、全体コーパスでは偽陰性が多く、Fred Meyer の略称「STO LRG BRUNN」、Whole Foods の省略形「EDGS」、OCR が「EGGS」を「LG EGO 12 CT」に変えるなどのケースを捕捉できませんでした。
そこで Codex に「無制限トークンを使ってください」と伝え、すべてのレシートを構造化抽出に送ることにしました。Codex はその一文から並列ワーカーアーキテクチャ―シャーディング、ヘルス管理、チェックポイント、リトライロジック――を提案しました。全体ですべてが完成します。途中で Codex のトークンが足りなくなると、自動的に Claude に切り替えて処理を継続してくれました ― それは私の指示ではなく、ログから学んだ結果でした。
実行中にクラッシュが頻発しました。長い CLI ジョブはセッションタイムアウトで終了し、スクリプトは終了時に結果を書き込むため、途中で死ぬと全て失われました。4 回目の試みで「バッチごとに新しいプロセスを起動するべきだ」と言ったら、それが解決策となりました ― 1 バッチあたり新規プロセスを起動し、ハードコール制限で終了、キャッシュから再開。Codex はそれを修正し、tmux セッションで実行し、ETA を 12 時間から 3 時間へ短縮しました。夜中に処理が止まるのを何度も経験した後に得られた、まさに「その場で気付く」解決策でした。
11 345 枚のレシートが処理されました。本来一晩かけて終わるはずだった作業が寝る前に完了しました。
自分自身の基準を上回った分類器
まずは正確なラベル(グランドトゥルース)が必要でした。Claude にキーボード主体のラベリングツールを構築させました ― 左側がレシート画像、右側が分類データ、矢印キーで移動し、1 文字入力で判定。22 分で Flask アプリ全体を作成しました。私は手動で 375 枚のレシートにラベル付けしました。
正規表現は「egg」と言及する 650 枚を見つけました。これら 375 のラベルと比較すると、88 % のリコールでした。欠損は省略コードや OCR の乱れ、短縮説明などのケースでした。「STO LRG BRUNN」はキーワード検索で捕捉できません。
解決策:手動でラベリングしたエッジケースを少数ショット例として LLM 分類器に投入。2003 年のサーマルプリントから 20 個の「卵」の例を与え、10 枚ずつバッチで呼び出し、8 本並列ワーカーで実行。2 時間で 11 345 枚が分類されました。
最終精度は 99 %+。LLM が「見逃した」ものの多くはグランドトゥルース自体に誤り(自転車店レシート、バーコードのみスキャン、卵麺など)でした。さらに QA を行い、弱い画像 497 枚を目視で確認するツール(「Space」で無卵、Xで有卵)、欠損フィールドがある 95 枚のデータ入力ツール(ナンパッド最適化、自動進行)など、4 本のツールを数分で構築しました。
品質
どれほど良いか? 372 個のランダムサンプルを手作業でチェックした結果、96 % 正確でした。主なエラーは古いスキャンの OCR が乱れたものです。1 件は幻覚 ― レシートに卵が存在しないにもかかわらず、パイプラインが偽造データを生成しました。
実際のデータはこんな風に汚れています:
- 何年もまたり続けるフォルダ名タイプミス:「Reciepts」(2016‑2017)と「Recipts」
- レシートが逆さまにスキャンされたケース ― Claude は OCR を文字ごとに鏡映してデコード
- メールレシートは
を優先し、価格行が HTML 部分だけにある場合を落としてしまうtext/plain
品質を高めたのは、何かを検出するときにエージェントにそのパターンを見せ、全てで修正させることです。住所情報が OCR ノイズに埋もれているケース(「915 Ny 45th St」が実際は 915 NW 45th St)を示したら、40 件の欠損ロケーションレシートを回収し、すべて解決しました。
数値で見る
| 指標 | 値 |
|---|---|
| 経過時間(ウォールクロック) | 14 日間 (2026年2月8日〜22日) |
| 実際の作業時間 | 15 時間 |
| トークン消費量 | 16 億 |
| 推定トークンコスト | $1,591 |
| 確認済み卵レシート数 | 589 |
| 合計卵支出額 | $1,972 |
| 卵総数 | 8,604 |
Codex と Claude はツール構築と構造化データ抽出に優れていますが、画像のセグメンテーションや OCR エンジン置き換えはできませんでした。正解は SAM3(セグメンテーション)、PaddleOCR(文字認識)、Codex/Claude(それ以外)という専門モデルのスタックです。最初にシンプルな道を試した結果、こうなるとは思っていましたが、その価値は十分でした。
これらは奇跡と驚きの日々です。30 年分の卵がどうなるか、楽しみにしています。