【LangChain】with_structured_output を活用!PydanticでLLMレスポンスを構造化する方法 🚀

LLM

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システムを構築していきましょう! 🚀

最新情報をチェックしよう!