はじめに:LLMアプリ開発における「出力の不確実性」という課題
大規模言語モデル(LLM)を業務システムや自社プロダクトに組み込む際、最大の障壁となるのが「出力フォーマットの不確実性」です。プロンプトで「JSON形式で返答してください」と指示しても、不正な構文が混ざったり、必要なフィールドが欠損したりして、後続のシステム処理でエラーが発生するケースは少なくありません。
この課題を根本から解決するフレームワークとして急速に支持を集めているのが、Pythonの標準データバリデーションライブラリ開発元が手掛ける「PydanticAI」です。本記事では、2026年現在の最新仕様に基づき、PydanticAIを活用して型安全で信頼性の高いAIエージェントを構築する手順と活用ノウハウを徹底解説します。
PydanticAIとは?従来のフレームワーク(LangChain等)との違い
PydanticAIは、Python業界でデファクトスタンダードとなっているデータ検証ライブラリ「Pydantic」の強力な型チェック機構をベースにしたLLMエージェント開発フレームワークです。
- 徹底した型安全性: Pythonの型ヒント(Type Hints)と完全連動し、LLMの応答を自動的にPythonオブジェクトへ変換・検証します。
- 厳格なバリデーションと自動リトライ: LLMの出力が定義したスキーマに違反した場合、エラー内容をLLMへ自動フィードバックして再生成(リトライ)を促します。
- 直感的でPythonicな設計: 過度な抽象化を避け、通常のPythonコードを書く感覚でエージェントやツール(Tool)を実装できます。
- マルチモデル対応: OpenAI、Anthropic、Gemini、Ollama(ローカルモデル)など、主要なLLMプロバイダーを同一のコード構造でシームレスに切り替え可能です。
PydanticAIの環境構築と基本セットアップ
まずは開発環境のセットアップを行います。Python 3.10以降の環境を用意し、必要なパッケージをインストールします。
pip install pydantic-ai pydantic logfire続いて、利用するLLMのAPIキーを環境変数に設定します。今回はOpenAIを使用する例で進めますが、AnthropicやGeminiを使用する場合も同様に設定可能です。
export OPENAI_API_KEY="your-openai-api-key"実践:PydanticAIを使った構造化データ抽出とエージェント構築手順
ここからは、非構造化テキスト(お問い合わせメールやログデータ)から必要な情報を抽出し、定義した型どおりのデータを生成する実践的なコード例を解説します。
1. 出力データモデル(Pydantic Schema)の定義
まずは、LLMに抽出させたいデータの構造をPydanticモデルとして定義します。
from pydantic import BaseModel, Field
from typing import List, Optional
class CustomerSupportTicket(BaseModel):
ticket_id: str = Field(description="チケット識別ID(例: TCK-12345)")
customer_name: str = Field(description="顧客の氏名")
urgency: str = Field(description="緊急度 ('HIGH', 'MEDIUM', 'LOW')")
category: str = Field(description="問い合わせのカテゴリ(例: 'Billing', 'TechSupport', 'FeatureRequest')")
summary: str = Field(description="問い合わせ内容の簡潔な要約")
action_items: List[str] = Field(description="対応が必要なタスクのリスト")
2. エージェントの初期化とスキーマのバインド
定義したモデルをresult_typeに指定して、PydanticAIのAgentインスタンスを生成します。
from pydantic_ai import Agent
# モデルの指定と出力型の定義
agent = Agent(
'openai:gpt-4o',
result_type=CustomerSupportTicket,
system_prompt=(
"あなたは優秀なカスタマーサポートAIアナリストです。"
"入力されたテキストから情報を正確に抽出し、指定された構造フォーマットで出力してください。"
)
)
3. エージェントの実行と検証
テキストを入力してエージェントを実行すると、LLMからのレスポンスは自動的にCustomerSupportTicketオブジェクトとして型安全に受け取ることができます。
import asyncio
unstructured_text = """
差出人: 山田 太郎
件名: ログイン不可および請求金額の不一致について
本文:
昨日から管理画面にログインできなくなりました。エラーコードはE-501です。
また、先月分の請求書を確認したところ、契約プランより1,000円高く請求されています。
早急にログイン障害の解除と、過剰請求の返金手続きをお願いします。
"""
async def main():
result = await agent.run(unstructured_text)
ticket: CustomerSupportTicket = result.data
print(f"【顧客名】: {ticket.customer_name}")
print(f"【緊急度】: {ticket.urgency}")
print(f"【カテゴリ】: {ticket.category}")
print(f"【要約】: {ticket.summary}")
print(f"【アクションアイテム】: {ticket.action_items}")
if __name__ == "__main__":
asyncio.run(main())
高度な機能:ツール(Tools)の追加とカスタムバリデーション
PydanticAIの真価は、エージェントに自作関数(Tool)を持たせたり、バリデーションロジックを追加して信頼性を飛躍的に高められる点にあります。
カスタムバリデータによる厳格な品質制御
例えば、抽出された「緊急度(urgency)」が特定の文字列以外だった場合に、LLMに自動で修正させたい場合は、@agent.result_validatorを使用します。
from pydantic_ai import ModelRetry
@agent.result_validator
def validate_urgency(data: CustomerSupportTicket) -> CustomerSupportTicket:
valid_levels = {'HIGH', 'MEDIUM', 'LOW'}
if data.urgency not in valid_levels:
# この例外を投げると、PydanticAIがLLMに修正命令を送って自動再生成する
raise ModelRetry(f"urgencyは {valid_levels} のいずれかで指定してください。受け取った値: {data.urgency}")
return data
このように数行のバリデーションを書くだけで、不正な値が検出された際に自動でLLMへとエラーメッセージが返送され、正しい形式になるまでリトライが実行されます。
まとめ:PydanticAIで業務レベルの堅牢なAIプロダクトへ
LLMを活用したシステム開発において、出力を「予測不能なテキスト」から「型安全なオブジェクト」へと変換することは、システム全体の安定性を左右する極めて重要な要素です。
PydanticAIを活用することで、プロンプトの調整に時間を奪われることなく、コードレベルで厳格なデータハンドリングとエラーリトライを実現できます。構造化データの抽出、AIエージェントによる自動ワークフロー、API連携システムの構築において、ぜひPydanticAIを導入してみてください。
関連サイト: https://www.aegis4.net/