再帰アドバイザー

再帰アドバイザーとは何ですか ?

Advisors Recursive Recursive advisors are a special type of advisor that can loop through the downstream advisor chain multiple times. This pattern is useful when you need to repeatedly call the LLM until a certain condition is met, such as:

  • 呼び出す必要がなくなるまでツール呼び出しをループで実行する

  • 構造化された出力を検証し、検証が失敗した場合は再試行する

  • リクエストを変更して評価ロジックを実装する

  • リクエストを変更して再試行ロジックを実装する

CallAdvisorChain.copy(CallAdvisor after) 法は、再帰アドバイザパターンを可能にする重要なユーティリティです。この手法は、元のチェーンで指定されたアドバイザの後に続くアドバイザのみを含む新しいアドバイザチェーンを作成し、再帰アドバイザが必要に応じてこのサブチェーンを呼び出すことを可能にします。このアプローチにより、以下のことが保証されます。

  • The recursive advisor can loop through the remaining advisors in the chain

  • Other advisors in the chain can observe and intercept each iteration

  • The advisor chain maintains proper ordering and observability

  • The recursive advisor doesn’t re-execute advisors that came before it

Built-in Recursive Advisors

Spring AI provides two built-in recursive advisors that demonstrate this pattern:

ToolCallAdvisor

The ToolCallAdvisor implements the tool calling loop as part of the advisor chain, rather than relying on the model’s internal tool execution. This enables other advisors in the chain to intercept and observe the tool calling process.

主な機能:

  • Disables the model’s internal tool execution by setting setInternalToolExecutionEnabled(false)

  • Loops through the advisor chain until no more tool calls are present

  • Supports "return direct" functionality - when a tool execution has returnDirect=true, it interrupts the tool calling loop and returns the tool execution result directly to the client application instead of sending it back to the LLM

  • Uses callAdvisorChain.copy(this) to create a sub-chain for recursive calls

  • Includes null safety checks to handle cases where the chat response might be null

使用例:

var toolCallAdvisor = ToolCallAdvisor.builder()
    .toolCallingManager(toolCallingManager)
    .advisorOrder(BaseAdvisor.HIGHEST_PRECEDENCE + 300)
    .build();

var chatClient = ChatClient.builder(chatModel)
    .defaultAdvisors(toolCallAdvisor)
    .build();

Return Direct Functionality

The "return direct" feature allows tools to bypass the LLM and return their results directly to the client application. This is useful when:

  • The tool’s output is the final answer and doesn’t need LLM processing

  • You want to reduce latency by avoiding an additional LLM call

  • The tool result should be returned as-is without interpretation

When a tool execution has returnDirect=true, the ToolCallAdvisor will:

  1. Execute the tool call as normal

  2. Detect the returnDirect flag in the ToolExecutionResult

  3. Break out of the tool calling loop

  4. Return the tool execution result directly to the client application as a ChatResponse with the tool’s output as the generation content

StructuredOutputValidationAdvisor

The StructuredOutputValidationAdvisor validates the structured JSON output against a generated JSON schema and retries the call if validation fails, up to a specified number of attempts.

主な機能:

  • Automatically generates a JSON schema from the expected output type

  • Validates the LLM response against the schema

  • Retries the call if validation fails, up to a configurable number of attempts

  • Augments the prompt with validation error messages on retry attempts to help the LLM correct its output

  • Uses callAdvisorChain.copy(this) to create a sub-chain for recursive calls

  • Optionally supports a custom ObjectMapper for JSON processing

使用例:

var validationAdvisor = StructuredOutputValidationAdvisor.builder()
    .outputType(MyResponseType.class)
    .maxRepeatAttempts(3)
    .advisorOrder(BaseAdvisor.HIGHEST_PRECEDENCE + 1000)
    .build();

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