このバージョンはまだ開発中であり、まだ安定しているとは見なされていません。最新の安定バージョンについては、Spring AI 2.0.1 を使用してください!

スキーマ検証と自己修正

デフォルトの .entity(…​) 呼び出しでは、モデルにスキーマに一致する JSON を生成するように要求しますが、強制することはできません。モデルが余分なフィールドを返したり、必須フィールドを省略したり、JSON を散文で囲んだりすると、パーサーは例外をスローします。

不正な出力を処理する最も簡単な方法は、それを検出して再試行することです。Spring AI は、EntityParamSpec コンシューマー上の単一のスイッチでこれを自動的に行います。

ActorsFilms films = chatClient.prompt()
    .user("Generate the filmography for a random actor.")
    .call()
    .entity(ActorsFilms.class, spec -> spec.validateSchema());

自己修正ループの仕組み

spec → spec.validateSchema() コンシューマーは、自己修正型の再試行ループを有効にします。

  1. モデルが反応します。

  2. Spring AI は、レスポンスを対象型の JSON スキーマに対して検証します。

  3. 検証に合格すれば、入力したレコードが返されます。

  4. 検証に失敗した場合、検証エラー(たとえば、「必須フィールド actor`", "expected `array がありません。`string` が入力されました」)がユーザープロンプトに追加され、呼び出しが再発行されます(デフォルトでは最大 3 回まで試行されます)。

モデルは再試行のたびに具体的なエラーを認識するため、2 回目の試行は闇クラウドな再試行ではなく、何が間違っていたのかを把握し、それを修正することができます。

Structured Output Self-Correction Loop

これは、validateSchema() を呼び出すと自動的に登録される再帰アドバイザーである StructuredOutputValidationAdvisor によって動作します。接続は一切不要で、スイッチ自体が構成全体となります。

validateSchema() がアクティブな場合、ストリーミングはサポートされません。アドバイザーが検証するには、完全なレスポンスが必要です。

アドバイザーのカスタマイズ

StructuredOutputValidationAdvisor はデフォルトで 3 回再試行し、Spring AI のデフォルトの JsonMapper を使用します。再試行回数を増やしたり、事前に用意されたスキーマを使用したり、別のマッパーを使用したりするなど、カスタマイズするには、独自のインスタンスを構築して ChatClient に登録します。明示的に登録されたアドバイザーは、自動的に登録されたアドバイザーに置き換えられます。

var validationAdvisor = StructuredOutputValidationAdvisor.builder()
    .outputType(ActorsFilms.class)
    .maxRepeatAttempts(5)
    .build();

ChatClient chatClient = ChatClient.builder(chatModel)
    .defaultAdvisors(validationAdvisor)
    .build();

アドバイザーは、outputType (スキーマが自動的に生成される)または outputJsonSchema (事前に指定されたスキーマ文字列を使用する)のいずれかで構成できます。この 2 つのオプションは相互に排他的です。

var validationAdvisor = StructuredOutputValidationAdvisor.builder()
    .outputJsonSchema(myConverter.getJsonSchema())
    .build();

主な行動:

  • 想定される出力型から JSON スキーマを生成するか、事前に指定されたスキーマ文字列を受け入れます。

  • JSON スキーマ DRAFT_2020_12 を使用して、LLM レスポンスをスキーマに対して検証します。

  • 検証が失敗した場合に呼び出しを再試行します(デフォルト: 最大 3 回)。

  • 再試行時に検証エラーメッセージを追加してプロンプトを表示することで、モデルの自己修正を支援します。

  • トークンの使用量は、検証試行ごとに累積されるため、返される ChatResponse は、最終試行だけでなく、すべての再試行の累積使用量を報告します ( 複数ステップのフローにおける累積使用量を参照)。

  • オプションでカスタム JsonMapper をサポートします。

このアドバイザーの背後にある再帰アドバイザーのメカニズムの詳細については、StructuredOutputValidationAdvisor を参照してください。

プロバイダーネイティブ出力との組み合わせ

validateSchema() はレスポンス側のセーフティネットであり、不正な出力をリアクティブ的に検知して再試行します。useProviderStructuredOutput() は補完的なリクエスト側の制約です。この 2 つは自然に組み合わさります。

ActorsFilms films = chatClient.prompt()
    .user("Generate the filmography for a random actor.")
    .call()
    .entity(ActorsFilms.class, spec -> spec
        .useProviderStructuredOutput()
        .validateSchema());

これは、ネイティブの強制が部分的なプロバイダーのエッジケース、たとえば JSON ではなくプレーンテキストの推論トレースを出力する可能性のある Ollama 推論モデルなどに特に役立ちます。既知の制限を参照してください。