Lesson CH06-L02
PDF解析
PDFドキュメントをそのまま入力し、構造化抽出を行う。
- 読了目安
- 10 min
- Colab目安
- 16 min
- 合計
- 26 min
- 前提
- 画像入力
関連: 公式ドキュメント
一行サマリ
DocumentUrl(url='https://.../doc.pdf') または BinaryContent(data=pdf_bytes, media_type='application/pdf') を agent.run_sync のリストに含めるだけで、Gemini に PDF を直接渡してテキスト + レイアウト + 表 + 図 を理解させられる。OCR / 前処理パイプラインを組まずに、構造化抽出までワンショット。
ヒーロー: PDF も「メディア要素」の 1 つ
画像 (Ch6-L01) と同じく、PDF も agent.run_sync([prompt, DocumentUrl(...)]) のリストに混ぜる だけで Gemini に渡せます。Gemini は内部で PDF をページ単位の画像 + テキストに分解し、レイアウトと表構造を保持したまま 解析します。
概念: 画像入力との違いは media_type だけ
| 渡し方 | 型 / media_type |
|---|---|
| URL 参照 | DocumentUrl(url='https://.../file.pdf') |
| バイナリ直接 | BinaryContent(data=bytes, media_type='application/pdf') |
「PDF 用の特別な API」ではなく、Document または media_type='application/pdf' を選ぶだけ。複数 PDF も、PDF + 画像も、PDF + テキスト指示も、リストに積めば自由に組み合わせられます。
Gemini の PDF サイズ上限は概ね 50 MB / リクエスト、ページ数も 数百ページまで 受け付けます (モデルやコンテキスト長による)。本番では事前に分割するのが安全。
コード: 3 つのパターン
パターン 1: 公開 PDF を URL で渡して要約
from pydantic_ai import Agent, DocumentUrl
from pydantic_ai.models.google import GoogleModel
agent = Agent(
GoogleModel('gemini-3-flash-preview'),
instructions='PDF の内容を日本語で 5 行以内に要約してください。',
)
result = agent.run_sync([
'この資料の要点を教えてください。',
DocumentUrl(url='https://arxiv.org/pdf/2305.13245.pdf'),
])
print(result.output)ポイント:
DocumentUrlはpydantic_aiから直接 import- 公開 URL から Gemini 側がダウンロード
- 中身が PDF か HTML かは 拡張子ではなく Content-Type で判定される (PDF を返さないとエラー)
パターン 2: ローカル PDF を BinaryContent で渡す
from pathlib import Path
from pydantic_ai import Agent, BinaryContent
from pydantic_ai.models.google import GoogleModel
agent = Agent(GoogleModel('gemini-3-flash-preview'))
pdf_bytes = Path('./report.pdf').read_bytes()
result = agent.run_sync([
'この PDF の Executive Summary 部分を抜粋してください。',
BinaryContent(data=pdf_bytes, media_type='application/pdf'),
])
print(result.output)media_type を 'application/pdf' にするのが唯一のポイント。社内文書や認証付きストレージから取得した PDF はこのパターン。
パターン 3: PDF から構造化データを抽出 (Ch4 の合わせ技)
from pydantic import BaseModel, Field
from pydantic_ai import Agent, DocumentUrl
from pydantic_ai.models.google import GoogleModel
class PaperMeta(BaseModel):
title: str = Field(description='論文タイトル')
authors: list[str] = Field(description='著者名のリスト')
abstract_ja: str = Field(description='アブストラクトの日本語要約 (200 字以内)')
key_findings: list[str] = Field(description='主要な発見を 3 つ', max_length=3)
agent = Agent(
GoogleModel('gemini-3-flash-preview'),
output_type=PaperMeta,
instructions='論文 PDF から構造化メタ情報を抽出してください。',
)
paper = agent.run_sync([
'この論文のメタ情報を抽出してください。',
DocumentUrl(url='https://arxiv.org/pdf/2305.13245.pdf'),
]).output
print(paper)
# PaperMeta(title='...', authors=['...'], abstract_ja='...', key_findings=['...', '...', '...'])研究論文のサーベイ、見積書のフィールド抽出、契約書からの条項抽出、医療レポートの定型化 ── 「PDF → JSON」のユースケースは無限 にあります。
観察: トークン消費は「ページ数 × 解像度」
PDF は内部で画像 + テキストに分解されるため、ページ数が増えるほど input_tokens が線形以上に伸びる ことがあります。
result = agent.run_sync([
'この PDF を要約',
DocumentUrl(url='https://arxiv.org/pdf/2305.13245.pdf'),
])
print(result.usage())
# RunUsage(requests=1, input_tokens=8500, output_tokens=300, ...)
# ^^^^^ ページ数次第で 1 万超もある長大な PDF は 章ごとに分割して並列処理 したほうが速度・コスト両面で有利。
まとめ
DocumentUrl(url=...)で公開 PDF、BinaryContent(data=bytes, media_type='application/pdf')でローカル PDF- 画像入力と同じくリストに混ぜるだけ
output_type=BaseModelと組み合わせれば「PDF → JSON」を 1 ステップで実現- ページ数 × 解像度で input_tokens が伸びるため、大きい PDF は事前分割
次レッスンでは YouTube URL 直接入力 — Gemini 固有の VideoUrl で動画をそのまま理解させるパターンを扱います。
Colab で実際に動かす
本レッスンの内容を Google Colab 上で実行できるノートブックを用意しています。下のボタンから自分のColab環境に開けます (要 Google アカウント / GOOGLE_API_KEY)。
notebooks/ch06/02-pdf-parsing.ipynb