😽

Googleの新ライブラリ LangExtract をガチで使ってみたら、114ページPDFを10分で解析できた話

に公開

挨拶

はじめまして。株式会社レトリバでAI事業部に所属している森田と申します。
今後、月に数回ペースで、私たちが日々の業務や検証の中で得た知見(趣味も)をZennから発信していきます。第一弾は、Googleの新ライブラリ「LangExtract」を実際に使ってみた体験談です。

🎯 概要

Googleが公開した新ライブラリ LangExtract を使って、114ページの技術系PDFを解析しました。

結論から

  • 無料枠では 429で強制停止
  • Vision APIの トークン消費問題発生
  • それでも工夫して有料枠で回したら 爆速で解析完了
  • 最後はちゃんとデータ取れた

この記事では、

  • LangExtractの特徴(AIが苦手な構造理解をどう補うか)
  • 実際に遭遇した課題(無料枠、Vision API失敗、抽出漏れ)
  • 解決策(有料枠テスト、レート制限対策、フォールバック処理)
  • 実測した処理時間とコスト

をまとめます。

🛠️ 技術スタック

  • OS: Ubuntu 22.04 / macOS Sonoma 14.2
  • 言語: Python 3.11
  • ライブラリ:
    • google-generativeai (Gemini API)
    • LangExtract (Few-shot構造化抽出)
    • pdfplumber, pdf2image
  • インフラ: ローカル実行
  • ツール: VSCode, Poetry, Git

📖 詳細内容

1. 背景

現在私たちは、RAG(Retrieval-Augmented Generation)案件を数多く取り扱っています。
扱うPDF文書の例として、学術論文や研究報告書があります。

例えば論文では:
「実験方法 > 測定手法 > 表3.2 測定結果」
といった情報が階層的に散らばっています。

ところが、文章の階層構造や参照表現を誤って解釈すると、章と節、節と図表が誤った形で結び付いてしまうことがあります。
この誤解をなくすため、LangExtractでの正確な構造化が求められました。

2. LangExtractって何?


LangExtractは「AIに任意の階層構造を守らせる」ための新しいライブラリです。
Few-shotで「論文 > 章 > 節 > 図表」といった構造を定義すると、AIはその枠組みに従って文書を解析してくれます。

人間なら自然にできること

  • 章、節、項の階層構造を理解する
  • インデントや番号付け(2.3.3 (1) ① …)から階層を推測
  • 「この/その/あの」といった指示語を解釈
  • 「〜を参照」「上記の表に示す」といった参照を解決
  • 表が2ページにまたがっても「表3.2(続き)」として結合

AIが苦手なこと

  • ページをまたいだ階層の継承
  • 長距離参照の解決(1ページ目の前提が80ページ後に再利用される)
  • 複雑な照応関係(「前述の方法」=どれ?)
  • 多層構造の混在(章+番号+記号)

LangExtractはこれらを Few-shot学習+コンテキスト継承 によって改善してくれます。

3. Few-shot学習の実例

普通にPDFを投げると、AIは「章」「表」「この表」みたいな構造理解が苦手。
そこでLangExtractでは、Few-shot学習で「こういう文章ならこう抽出して」と例を与えられます。

from langextract import LangExtract

# 定義したい階層
hierarchy = ["章", "節", "図表"]

# Few-shotサンプル(入力と出力の例を与える)
fewshot_examples = [
    {
        "input": "A実験方法 ~(省略)~ B測定手法 表3.2 測定結果...",
        "output": {
            "章": "A実験方法",
            "節": "B測定手法",
            "図表": "表3.2 測定結果"
        }
    },
    {
        "input": "表3.2(続き)",
        "output": {
            "図表": "表3.2 測定結果(続き)"
        }
    }
]

# LangExtract初期化
extractor = LangExtract(
    hierarchy_levels=hierarchy,
    examples=fewshot_examples,
    use_gemini=True
)

results = extractor.process("input.pdf")

Few-shotの効果

  • ルールベースでは難しい構造を柔軟に抽出
  • 指示語(この/その/前述の)を文脈に合わせて解決
  • 誤抽出が減る(章と節を混同しない)

4. 実際にやったこと

114ページの研究論文PDFに対し、以下の流れで処理しました:

  • PDFを1ページごとに画像化(Gemini Vision APIで処理)
  • テキストも抽出(pdfplumberでフォールバック用に)
  • LangExtractで「章 > 節 > 図表」の階層を維持
  • 「この表」「上記の図」などの参照解決を実行

結果、あるページで検出した章の情報が、数ページ先の表にも継承されました。

{
  "hierarchy": {
    "章": "A実験方法",
    "節": "B測定手法",
    "図表": "表3.2 測定結果"
  },
  "continuation_analysis": {
    "is_continuation": true,
    "inherited_from_page": 83
  }
}

「この表はさっきの節の続きだな」と人間なら直感的に理解しますよね。LangExtractを使うと、まさにそのレベルでPDFを読み解けるようになります。AIが人間と遜色ない構造化をしてくれる、というわけです。ただ、課題もありました。

5. 課題

(1) 無料枠の壁

❌ Error 429: Too Many Requests
114ページを投げたら途中で強制終了。詰みました。

(2) Vision APIトークン量問題 → レート制限

全ページを画像モードで処理すると、トークン消費が爆発。

(3) 抽出漏れ

「測定値(Data1, Data2…)」が取れない。
ログを見ると combined_text が空のまま:

2025-08-20 10:08:45 - WARNING - page 83: combined_text is empty

無料枠は詰み、トークン消費は爆発、抽出は抜け落ちる。
この三重苦のままではとても本番で回せない。
そこで、有料枠+レート制御+フォールバックという現実解を選びました。

6. 解決策

(1)無料枠の壁:有料枠APIキーを使用

→ 無料枠では実用不可。課金を有効化したら安定しました。

(2)トークンレート制限対策

  • バッチサイズ: 5 → 3 ページに縮小
  • ページごとに 2秒待機
  • バッチごとに 10秒休憩
  • 最大3回リトライ
window_size = 3
batch_size = 3
api_wait_time = 2
batch_wait_time = 10
max_retries = 3

(3)フォールバック処理

Vision APIが失敗したページはテキスト抽出モードに切替。

def _analyze_page_text_fallback(page_num, text):
    data_pattern = r'(Data\d+)\s+([\d\.]+)'
    matches = re.findall(data_pattern, text)
    return {"page": page_num, "measurements": matches}

これで「測定値」の抽出が復活しました。

7. 実測値

実際に114ページを処理したときの数字です:

  • 処理時間: 8〜12分
  • API呼び出し: 約145回
    • Vision API: 114回
    • Text API: 31回
  • コスト: 約87円(Gemini Pro Visionが大半)
  • 最適化すれば 約45円 まで削減可能

1ページあたりにすると約0.8円・5秒程度。
こう聞くと「ちょっとランチ代を削れば数百ページ処理できるじゃん」と思えてきませんか?

🎉 成果・学んだこと

  • LangExtractは「AIが苦手な構造理解」を補う強力な武器
  • 無料枠では 使用は厳しい
  • Vision APIはトークン爆発
  • レート制御+フォールバックで 爆速解析 に到達

技術仕様書や学術論文を対象とした解析には十分実用レベル。

最後に

114ページPDFを10分で解析できると分かったのは大きな収穫でした。
株式会社レトリバからは、これからも「現場で本当に役立つ検証記事」、または最新情報やマニアックな技術関連記事(趣味に走る人もいるかも)を続々公開していきます。
次は別のメンバーがまた違った視点で記事を書く予定ですので、ぜひフォローしてチェックしてみてください!


🔗 参考リンク

Discussion