1
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?

【LangChain v1】create_agent の response_format を指定するとエージェントが「真面目」になる理由

Last updated at Posted at 2026-01-01

はじめに

LangChain v1でエージェントを構築する際、create_agent 関数の引数で response_format がサポートされました。Pydanticモデルを渡すだけで出力を構造化してくれる便利な機能ですが、「出力の形を整える」以上の影響をエージェントの思考プロセス(ツール呼び出しの挙動)に与えているようです

知らずに、response_format を使ってAIエージェントが思い通りに動作せず解析に苦労したのでココにメモを残しておく。

検証の結果、response_format でエビデンスを回答に含めるように指定すると、エージェントがエビデンスの検証ツールを 「明らかに積極的に」 呼び出すようになることが分かりました。

結論:何が変わるのか?

特定の「エビデンス(根拠)」フィールドを含むスキーマを response_format に設定した場合と、設定せずにプロンプトだけで指示した場合を比較したサマリーがこちらです。

設定 validate ツール呼び出し率
response_format あり(Pydantic等) 100%
response_format なし(プロンプト指示) 40%

※ OpenAIの ProviderStrategyToolStrategy いずれにおいても同様の傾向が見られました。

つまり、response_format を使うとエージェントは「出力を埋めるために必要な情報を集めなければならない」という強い拘束力を受け、結果として 情報の正確性が向上する という副作用(副次的メリット)があるのです。


1. response_format の3つの戦略

まずは内部的な仕組みを整理します。create_agent で使用される response_format には、主に以下の戦略が存在します。

戦略 説明 主なユースケース
None 構造化なし。ReActパターンでループ 自由な探索が必要な場合
ToolStrategy スキーマを「ツール」として登録し、それを呼んだら終了 構造化出力が必要な場合
ProviderStrategy OpenAIのNative Structured Outputs等を使用 精度の高い構造化出力
AutoStrategy モデルに応じて自動選択(gpt-4o系はNative優先) 手軽に実装したい場合

2. なぜ「真面目」にツールを呼ぶようになるのか?

コードを読み解くと、大きな要因が3つあることが分かりました。

2.1 構造化スキーマが「ツール」として定義される

response_format を指定すると、背後ではPydanticモデルがJSON Schemaに変換され、一つの「ツール」としてLLMに渡されます。

langchain/agents/structured_output.py
# Pydanticモデルがツールとして定義されるプロセス
return cls(
    schema=schema_spec.schema,
    tool=StructuredTool(
        args_schema=schema_spec.json_schema,
        name=schema_spec.name,
        description=schema_spec.description,
    ),
)

2.2 tool_choice="required" の強制

ここが重要なポイントです。response_format がある場合、LangChainは内部的に tool_choice="any"(OpenAI APIでは "required")を強制します。

これにより、LLMは 「最終的に必ず構造化出力ツールを呼ばなければならない」 という制約下で推論を開始します。

2.3 終了条件の違い

  • なしの場合: LLMが「もうツールを呼ぶ必要がない」と判断(tool_calls が空)したら終了
  • ありの場合: 「構造化出力ツールを呼び出した」 時点で終了

この「出口戦略」の違いが、ループの執着心に直結するようです


3. LLMの認識はどう変わるのか(比較図)

LLMが受け取る情報の差を可視化してみます

LLMの内部動作は不明であるため挙動からの推測になります

response_format ありの場合

エージェントは「ゴール(必須ツール)」から逆算して行動します。

response_format なしの場合

「できればやってね」というプロンプト指示は、しばしば無視されたり、ツールを使わずに適当な回答(ハルシネーション)で済まされたりします。


4. 検証実験:四則演算エージェントでの実演

この挙動を証明するために、複雑な四則演算をステップ実行し、最後に「検証ツール」を呼ぶかどうかをテストしました

検証内容

  • タスク: 暗算が難しい複雑な計算(10ケース)
  • 指示: 「検証してください」という明示的な言葉は含めない
  • スキーマ: validation_result フィールドを定義

検証結果

設定 validate 呼び出し回数
ProviderStrategy (with_validation) 10回 / 10回
ToolStrategy (with_validation) 10回 / 10回
なし (プロンプトのみ) 4回 / 10回

結果は一目瞭然です。response_format を指定した場合は、100%の確率で検証ツールを実行してから回答を生成しました。

一方、指定しない場合は「計算だけして満足してしまい、検証をスキップする」ケースが目立ちました。


5. 実装のアドバイス

この特性を踏まえると、用途に合わせて以下のように使い分けるのがベストです。

徹底的に情報を収集・検証させたい場合

構造化出力スキーマに、具体的な型と説明(description)を持ったエビデンスフィールドを定義しましょう。

class AnalysisResult(BaseModel):
    is_anomaly: bool
    # 具体的な説明を書くことで、LLMが「ツールを使わなきゃ」と思いやすくなる
    evidence: List[str] = Field(description="ログから引用した具体的な証拠リスト")
    validation_status: str = Field(description="検証ツールの実行結果")

自由な探索(ReAct)を優先したい場合

あえて response_format を指定せず、エージェントに終了タイミングを委ねる方が、余計なツール呼び出し(コストと時間の増大)を抑えられる場合があります。

まとめ

LangChain v1 の response_format は、単なる出力のパース機能ではなく、LLMの推論に「責任」を持たせるための強力な拘束具として機能します。

エージェントがなかなかツールを使ってくれない、あるいは詰めが甘い と感じている場合には response_format で厳格なスキーマを定義するのが良いですが、 毎回検証なんかされたら動作が遅くなってこまる 場合には response_format を使わないほうが良い場合もあるようです。

参考資料

1
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
1
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?