LangChainを活用したAIアプリケーションの開発が進み、より効率的にLLM(大規模言語モデル)を活用できる環境が整っています。その中でも with_structured_output
は、Pydanticモデルを使ってLLMのレスポンスを事前に定義した構造で受け取ることができる強力な機能です。
本記事では、with_structured_output
の基本から応用まで詳しく解説し、Pydanticを活用して正確かつ一貫性のあるデータを取得する方法を紹介します。
【本記事のもくじ】
1. with_structured_output
とは? 🤔
LLMレスポンスを構造化する重要性
LLMは非常に柔軟な回答を生成しますが、
- 出力が一定のフォーマットにならない
- 不要な情報が含まれる
- データの整合性が保証されない
といった課題があります。
そこで、LangChainの with_structured_output
を使うことで、あらかじめ定義したスキーマ(Pydanticモデル)に従ったレスポンスを得ることが可能になります。
2. with_structured_output
の基本的な使い方 📝
📌 必要なライブラリのインストール
まずは、LangChainとPydanticをインストールします。
pip install langchain langchain-openai pydantic
📌 シンプルなPydanticモデルを定義
with_structured_output
を利用するためには、まずPydanticのBaseModel
を継承したデータモデルを定義します。
from pydantic import BaseModel, Field
class FoodComponent(BaseModel):
"""食材の栄養情報を表すモデル"""
name: str = Field(..., description="食材の名前")
weight: str = Field(..., description="食材の重さ(g)")
protein: str = Field(..., description="蛋白質量(g)")
fat: str = Field(..., description="脂肪量(g)")
carbohydrate: str = Field(..., description="炭水化物量(g)")
📌 LangChainと組み合わせてLLMから構造化レスポンスを取得
次に、LangChainの ChatOpenAI
を使って、LLMのレスポンスをPydanticモデルに変換します。
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
# プロンプトを作成
prompt = ChatPromptTemplate.from_messages([
("system", "与えられた食材の栄養情報を返してください"),
("user", "{messages}")
])
# LLMのインスタンスを作成し、with_structured_output を適用
chain = prompt | ChatOpenAI(model="gpt-4o", temperature=0).with_structured_output(FoodComponent)
# 実行
response = chain.invoke({"messages": "かぼちゃの栄養成分を教えて?"})
print(response)
📌 実行結果
FoodComponent(name="かぼちゃ", weight="100g", protein="1.5g", fat="0.1g", carbohydrate="20.1g")
このように、LLMの出力がPydanticのモデルに変換され、型安全なデータとして取得できます。
3. with_structured_output
のパラメータ解説 ⚙️
with_structured_output
にはいくつかのオプションがあります。それぞれの役割を見ていきましょう。
パラメータ | 型 | 説明 |
---|---|---|
schema |
BaseModel |
出力データのPydanticモデル(またはTypedDict、JSONスキーマ) |
method |
str |
変換方式(後述する function_calling , json_mode など) |
include_raw |
bool |
元のLLMレスポンス(rawデータ)も含めるか |
strict |
bool または None |
スキーマとの厳密な一致を求めるか |
4. method
の違いと変換方式の比較 🔄
with_structured_output
では、以下の3つの変換方式が利用できます。それぞれの特徴を解説します。
(1) function_calling
(デフォルト)
- OpenAIの Function Calling を活用し、関数を呼び出すようにデータを取得
- descriptionを詳細に記述できるため、出力の精度が高い
変換例(Pydantic → OpenAI Function Call)
{
"name": "FoodComponent",
"description": "食材の栄養情報を表すモデル",
"parameters": {
"properties": {
"name": {"type": "string", "description": "食材の名前"},
"weight": {"type": "string", "description": "食材の重さ"},
"protein": {"type": "string", "description": "蛋白質量"},
"fat": {"type": "string", "description": "脂肪量"},
"carbohydrate": {"type": "string", "description": "炭水化物量"}
},
"required": ["name", "weight", "protein", "fat", "carbohydrate"]
}
}
(2) json_mode
- 2023年に導入された機能で、出力をJSON形式に統一
- 直接
PydanticOutputParser
でデコードするため、変換がシンプル
使い方
chain = prompt | ChatOpenAI(model="gpt-4o", temperature=0).with_structured_output(FoodComponent, method="json_mode")
(3) json_schema
(最新)
- 2024年8月に追加された新機能
- OpenAIの
json_schema
に対応し、型のバリデーションがより厳格 - ただし、“gpt-4o-2024-08-06” 以降のモデルのみ対応
使い方
chain = prompt | ChatOpenAI(model="gpt-4o", temperature=0).with_structured_output(FoodComponent, method="json_schema")
5. 実際の活用シナリオ 💡
① AIによるレシピ生成アプリ
- 食材の栄養成分を取得し、適切なレシピを提案
② 医療・栄養分野のデータ分析
- 患者の食事管理や栄養バランスの分析
③ ECサイトの商品情報管理
- LLMが取得した商品データをPydanticで構造化し、一貫性のあるデータに整える
6. まとめと今後の展望 🏁
✅ with_structured_output
を使うと、LLMのレスポンスをPydanticモデルに変換できる
✅ function_calling
, json_mode
, json_schema
の3つの変換方式を理解して使い分ける
✅ 医療・食品・ECなど、さまざまな分野での活用が期待できる
今後、LangChainとOpenAIの機能はさらに進化するため、最新のアップデートを追いながら、より強力なAIシステムを構築していきましょう! 🚀