3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LLMエージェントフレームワーク Pydantic AI を使ってみる

Last updated at Posted at 2025-12-02

はじめに

インティメート・マージャー開発本部の福田です。

世間ではAIを使った業務支援やアプリケーションがどんどん増えてきています。
AIを組み込んだアプリケーションを開発する際、悩ましいのはAIの出力が一定でないことです。

ここで役立つのがPydanticAIということを知ったので使ってみました。
社員の日報をもとに、モチベーションや感情を分析する簡単なアプリケーションを作成しながらPydanticAIについて紹介します。

PydanticAIとは

Pythonの型定義ライブラリPydanticと大規模言語モデル(LLM)を組み合わせ、AIの出力を型安全に扱うためのライブラリです。
出力形式が型で指定できるためAIを安全にアプリケーションへ組み込むことが可能です。また、依存関係の注入やツール関数を使えば、AIにDBデータなどの外部リソースへ安全にアクセスさせることも可能です。

環境設定

インストール

uv add pydantic-ai

APIキーの設定

無料で試したかったのでGeminiを使用することにしました。Google AI Studio にアクセスしてAPIキーを発行してください。

発行したキーを.envに記載してください

GOOGLE_API_KEY=XXXXXXX

簡単な日報分析アプリの例

下記は全コードです

import asyncio
from dataclasses import dataclass

from dotenv import load_dotenv
from pydantic_ai import Agent, RunContext
from pydantic import BaseModel, Field

load_dotenv()

# DataBaseのモック
@dataclass
class EmployeeRecord:
    id: int
    name: str
    content: str


EMPLOYEE_DB = [
    EmployeeRecord(id=1, name="山田太郎", content="タスクは順調で気分がいい。"),
    EmployeeRecord(id=2, name="鈴木一郎", content="タスクが詰まってストレス気味。"),
    EmployeeRecord(id=3, name="佐藤花子", content="新しいタスクで少し不安だが、やる気はある。"),
]


class EmployeeService:
    """DBデータを扱うためのサービスクラス"""
    def get_employee(self, employee_id: int) -> EmployeeRecord | None:
        for employee in EMPLOYEE_DB:
            if employee.id == employee_id:
                return employee
        return None

    def get_content(self, employee_id: int) -> str | None:
        employee = self.get_employee(employee_id)
        if employee:
            return employee.content
        return None

    def get_name(self, employee_id: int) -> str | None:
        employee = self.get_employee(employee_id)
        if employee:
            return employee.name
        return None


class MotivationAnalysis(BaseModel):
    employee_name: str
    motivation_level: int = Field(..., ge=0, le=10)  # モチベーションを0~10で評価
    emotion: str
    advice: str


@dataclass
class AnalysisDeps:
    employee_id: int
    service: EmployeeService


agent = Agent(
    "gemini-2.5-pro",
    output_type=MotivationAnalysis,
    system_prompt="あなたはメンターです。社員の日報からモチベーション・感情を分析し、適切なアドバイスを提供してください。",
)


@agent.system_prompt
def add_employee_content(ctx: RunContext[AnalysisDeps]) -> str:
    """Agentのシステムプロンプトに社員の日報内容を追加する"""
    content = ctx.deps.service.get_content(ctx.deps.employee_id)
    return f"日報内容: {content}."


@agent.tool
def get_employee_name(ctx: RunContext[AnalysisDeps]) -> str:
    """Agentが必要とする場合に、社員の名前を取得するツール"""
    return ctx.deps.service.get_name(ctx.deps.employee_id)


async def main(employee_id: int):
    service = EmployeeService()
    deps = AnalysisDeps(employee_id=employee_id, service=service)
    result = await agent.run(
        "今日のモチベーションを分析してください。",
        deps=deps
    )
    print(result.output)


if __name__ == "__main__":
    asyncio.run(main(employee_id=3))

出力例

employee_name='佐藤花子' motivation_level=8 emotion='ポジティブ' advice='新しいタスクに不安を感じるのは自然なことです。しかし、やる気があるとのこと、素晴らしいですね!不安な点は、一人で抱え込まずに、ぜひ相談してください。新しい挑戦は、あなたの成長の大きなチャンスです。応援しています!'

主要機能の解説

型安全な出力

MotivationAnalysisクラス

PydanticのBaseModelを使用してAIの出力形式を定義

class MotivationAnalysis(BaseModel):
    employee_name: str
    motivation_level: int = Field(..., ge=0, le=10)  # モチベーションを0~10で評価
    emotion: str
    advice: str

AIはこの定義に従ったデータを出力します。
これによりAIの出力が不安定である問題を解消してくれます。

Agentの定義

agentインスタンス

agent = Agent(
    'gemini-2.5-pro',
    output_type=MotivationAnalysis,
    system_prompt="あなたはメンターです。社員の日報からモチベーション・感情を分析し、適切なアドバイスを提供してください。",
)

Agentクラスをインスタンス化します。

  • output_type: 引数AIの出力定義モデル(MotivationAnalysis)
  • system_prompt: Agentの性格・役割・前提など静的なプロンプト

依存関係の注入

AnalysisDepsdeps引数

RunContextを通じて、社員情報サービス(DBアクセスなど)といった外部の依存関係を実行時にAIへ渡します。これにより、AIはアプリケーションの他の部分(データ層)と連携できるようになります。

@dataclass
class AnalysisDeps:
    employee_id: int
    service: EmployeeService

# 省略

result = await agent.run(
    "今日のモチベーションを分析してください。",
    deps=deps
)

動的なシステムプロンプトの追加

@agent.system_promptデコレータ

@agent.system_prompt
def add_employee_content(ctx: RunContext[AnalysisDeps]):
    content = ctx.deps.service.get_content(ctx.deps.employee_id)
    return f"日報内容: {content}."

実行時までわからない動的なプロンプトを生成する役割です。
agent.runが実行される直前にこの関数が呼びだし、依存関係 (ctx.deps) から取得した特定の日報内容がAIへのプロンプトに組み込まれます。

ツール関数

@agent.toolデコレータ

@agent.tool
def get_employee_name(ctx: RunContext[AnalysisDeps]) -> str:
    """Agentが必要とする場合に、社員の名前を取得するツール"""
    return ctx.deps.service.get_name(ctx.deps.employee_id)

Python関数をAgentが自律的に呼び出せる機能として登録します。
Agentが必要に応じて実行し社員名を取得します。

本当にAgentが必要に応じて実行しているのか確かめます。この関数をコメントアウトして実行してみると、下記の結果が返ってきてemployee_nameに適切な名前が入っていないことがわかります。

employee_name='社員' motivation_level=7 emotion='不安とやる気が混在' advice='新しいタスクに取り組む際は、完璧を目指すのではなく、まずは小さなステップから始めてみましょう。不安な点は、先輩や上司に相談することで、解決の糸口が見つかるはずです。'
7

まとめ

大規模言語モデル(LLM)をアプリケーションに組み込むためにPydanticAIを使って実装しました。

Pydantic AIを使用することで、型安全に出力することができました。
依存関係の注入、動的なシステムプロンプト、ツール関数などを用いることで外部のデータや機能と、アプリケーションを安全かつ柔軟に連携させることができます

おわりに

アドベントカレンダーはまだ続きますので、ぜひ他の記事もご覧ください!

インティメート・マージャーでは、新卒から中途採用まで募集していますので興味があればエントリーしてみてください!

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?