LangGraph × Pydantic × SubGraph の落とし穴と解決策 🚀

LLM

~PythonでのLangGraph活用時にハマるポイントを徹底解説~

LangGraphは、LangChainのワークフロー管理を強化するためのフレームワークです。特に SubGraph(ネストされたグラフ構造)を活用すると、複雑な処理の分割や管理がしやすくなります。しかし、 Pydantic を組み合わせた場合、意外な落とし穴にハマることがあります。

本記事では、実際に遭遇したエラーを事例として紹介し、その原因と解決策を詳しく解説します。


🔹 この記事で解説すること

SubGraph の基本概念と Pydantic との組み合わせ方
SubGraphStatePydantic を使った際の問題点
✅ 実際のエラー事例とその解決策
LangGraph の最新バージョンでの修正点

これを読めば、 LangGraphPydantic を適用する際の注意点がクリアになります!


1️⃣ LangGraphのSubGraphとは?

まずは SubGraph について簡単に整理しておきましょう。

▶ SubGraph の基本概念

LangGraph は、ノード(Node)とエッジ(Edge)を定義することで、処理のフローを構築するフレームワークです。通常のグラフ構造に加えて、あるグラフの中に別のグラフを組み込む「ネスト構造」を作成できます。これを SubGraph と呼びます。

例えば、以下のような構造を考えてみましょう。

from typing import TypedDict

class GraphState(TypedDict):
    key: str
    count: int

しかし、 TypedDict には以下のような制約があります。

🔴 型チェックが緩い(値のバリデーションがない)
🔴 デフォルト値を定義しにくい
🔴 データの変換がしづらい

そこで、 Pydantic を使うと、型チェックやデフォルト値の管理がしやすくなります。

from pydantic import BaseModel, Field

class GraphState(BaseModel):
    key: str
    count: int = Field(default=0)  # デフォルト値を指定

これにより、State のデータ構造をより厳密に管理できるようになります。

しかし、 Pydantic を使った場合に特有の問題が発生します。次のセクションで具体的な事例を見ていきましょう。


3️⃣ エラー事例①:SubGraphのStateのデフォルト値が適用されない

▶ 発生したエラー

PydanticBaseModelSubGraphState に使ったとき、本来ならデフォルト値が適用されるはずの valueNone が入ってしまい、 ValidationError が発生しました。

from pydantic import BaseModel, Field

class ChildState(BaseModel):
    path: list[str]
    value: str = Field(default="default value")

# グラフを実行
graph.invoke({"path": []})

# エラー発生
# ValidationError: none is not an allowed value (type=type_error.none.not_allowed)

▶ 原因

LangGraph の State は、内部的に Pydantic の通常の初期化とは異なる方法でインスタンスを生成しているため、 Field(default=...) が適用されません。

▶ 解決策

デフォルト値を明示的に __init__ で設定することで回避できます。

class ChildState(BaseModel):
    def __init__(self, **input):
        input["value"] = input.get("value") or "default value"
        super().__init__(**input)

    path: list[str]
    value: str

この方法なら、 invoke 実行時に value のデフォルト値が正しく設定されるようになります。


4️⃣ エラー事例②:親のStateが子のStateのフィールドを持っていないとエラーが発生する

▶ 発生したエラー

親の StateSubGraphState のフィールドを含めていないと、以下のような InvalidUpdateError が発生します。

graph.invoke({'path': []}, debug=True)

# エラー発生
# InvalidUpdateError: Expected dict, got 

▶ 原因

LangGraph の state.py では dict を前提にキーの存在確認を行っています。しかし、 PydanticBaseModel は辞書型ではないため、期待される処理の分岐に入らずエラーが発生します。

▶ 解決策

親の StateSubGraphState のフィールドをすべて含めることで回避できます。

class ParentState(BaseModel):
    path: list[str]
    value: str  # 子のStateのフィールドを追加

5️⃣ 最新バージョン(0.1.15 以降)での改善点

LangGraph の 0.1.15 以降では、この State の取り扱いが改善されました。

BaseModelState に使っても InvalidUpdateError が発生しないよう修正
SubGraphState のデフォルト値が正しく適用されるよう修正


6️⃣ まとめ|LangGraph × Pydantic の正しい使い方

問題点 原因 解決策
SubGraphState のデフォルト値が適用されない LangGraph の State の初期化処理が Pydantic と異なる __init__ でデフォルト値を明示的に設定する
親の State に子の State のフィールドがないとエラー BaseModel が辞書型ではないため、LangGraphState チェックでエラーが発生 親の State に子の State のフィールドを含める
0.1.14 以前のバージョンでは BaseModelState でエラーが発生 LangGraphState 管理が TypedDict を前提に設計されていた 0.1.15 以降にアップデートする

💡 LangGraph を Pydantic と組み合わせる場合は、常に最新バージョンを確認しましょう! 🚀

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