エージェントで画像やPDFファイルを解析する - Files APIとAgents SDKとResponses API
最近のLLMはマルチモーダルが当たり前になりつつありますが,Agents SDK(というよりは,その裏側のResponses API)もファイルを入力として受け取ることができます。
Agents SDK / Responses APIでファイルを扱う
Responses APIで,プロンプトと一緒に画像ファイルを入力に与えるコード例がこちらのドキュメントにあります: Images and vision
ファイルの与え方には,
- URLで指定する
- base64エンコードした文字列を直接与える
- Files APIでアップロードしたファイルのIDを与える
の3通りがあります。何度も同じファイルを解析したり,大きいファイルを扱う可能性がある場合は,Files APIに事前にファイルをアップロードしておくのが無難かなあ,と思います。
画像ファイルをアップロードしてエージェントで解析する
ファイルは一度に複数個渡せるので,エージェントに2枚の画像を解析させてみます。
cookie1.jpg

cookie2.jpg 
from openai import OpenAI
from agents import Agent, Runner, TResponseInputItem
client = OpenAI()
image_files = [
"./images/cookies1.jpg",
"./images/cookies2.jpg"
]
file_ids = []
for image_file in image_files:
with open(image_file, "rb") as f:
result = client.files.create(
file=f,
purpose="vision",
)
file_ids.append(result.id)
for file_id in file_ids:
result = client.files.retrieve(file_id)
print(f"Retrieved file info: {result}")
agent = Agent(
name="Image Analysis Agent",
instructions="あなたは画像を解析する専門家です。画像についての質問に答えてください。",
model="gpt-5-mini",
)
input_items: list[TResponseInputItem] = [
{
"role": "user",
"content": [
{"type": "input_text", "text": "クッキーは全部で何個写っている?"},
{
"type": "input_image", "file_id": file_ids[0],
"detail": "auto",
},
{
"type": "input_image",
"file_id": file_ids[1],
"detail": "auto",
},
],
"type": "message",
}
]
result = Runner.run_sync(agent, input=input_items)
print(result.final_output)
for file_id in file_ids:
client.files.delete(file_id)
レスポンス
$ uv run python ./05-image-agent.py
Retrieved file info: FileObject(id='file-6fschKQqi1pfjqMQ2VfVeo', bytes=1638461, created_at=1764943216, filename='cookies1.jpg', object='file', purpose='vision', status='processed', expires_at=None, status_details=None)
Retrieved file info: FileObject(id='file-Sr872vwyDyQQ9udhD3HZB8', bytes=3512374, created_at=1764943221, filename='cookies2.jpg', object='file', purpose='vision', status='processed', expires_at=None, status_details=None)
全部で22個です。ジンジャーブレッドが15個、皿のクッキーが7個で合計22個になります。
正解...!
ちなみに,この例ではgpt-5-miniを使いましたが,モデルをgpt-5-nanoに変えると,「32個です。」のように数え間違いをしていました。画像やファイルを正しく扱うにはモデル選択に気をつけるのが良さそう。
PDFファイルをアップロードしてエージェントで解析する
PDFファイルを扱う具体例はドキュメントにはなさそうですが,画像ファイルと同じ要領でいけます。
レーザーテック株式会社の2026年第1四半期の決算短信PDFを解析させてみたコード。
from openai import OpenAI
from agents import Agent, Runner, TResponseInputItem
client = OpenAI()
pdf_file = "./pdf/kessan_tanshin.pdf"
with open(pdf_file, "rb") as f:
result = client.files.create(
file=f,
purpose="user_data",
)
file_id = result.id
result = client.files.retrieve(file_id)
print(f"Retrieved file info: {result}")
agent = Agent(
name="PDF Analysis Agent",
instructions="あなたはPDFを解析する専門家です。PDFについての質問に答えてください。",
model="gpt-5-mini",
)
input_items: list[TResponseInputItem] = [
{
"role": "user",
"content": [
{"type": "input_text", "text": "四半期の売上高と経常利益と前年同四半期からの増減率を抽出して"},
{
"type": "input_file", "file_id": file_id,
},
],
"type": "message",
}
]
result = Runner.run_sync(agent, input=input_items)
print(result.final_output)
client.files.delete(file_id)
レスポンス
$ uv run python ./05-pdf-agent.py
Retrieved file info: FileObject(id='file-9CKDUHEaJe9FPnC1aE1PmM', bytes=238611, created_at=1764944203, filename='kessan_tanshin.pdf', object='file', purpose='user_data', status='processed', expires_at=None, status_details=None)
以下を抽出しました(単位:百万円、増減率は前年同四半期比)。
- 2026年6月期 第1四半期(2025/7/1–2025/9/30)
- 売上高:54,171(前年同四半期比 +47.5%)
- 経常利益:27,141(前年同四半期比 +113.2%)
- 2025年6月期 第1四半期(2024/7/1–2024/9/30)
- 売上高:36,737(前年同四半期比 △22.3%)
- 経常利益:12,728(前年同四半期比 +16.5%)
必要ならCSV形式や差額(百万円・増加倍数)も出力しますか?
PDFのレイアウトや作成方法によると思いますが,フォーマットがほぼ決まっている決算短信のようなファイルからの情報抽出は正確にできるようです。
これは Agents SDK+αのTipsを一人で書いていくアドカレ Advent Calendar 2025の5日目の記事です。