はじめに
インティメート・マージャー開発本部の福田です。
世間では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の性格・役割・前提など静的なプロンプト
依存関係の注入
AnalysisDepsとdeps引数
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を使用することで、型安全に出力することができました。
依存関係の注入、動的なシステムプロンプト、ツール関数などを用いることで外部のデータや機能と、アプリケーションを安全かつ柔軟に連携させることができます
おわりに
アドベントカレンダーはまだ続きますので、ぜひ他の記事もご覧ください!
インティメート・マージャーでは、新卒から中途採用まで募集していますので興味があればエントリーしてみてください!