Skip to content

Commit 5e20734

Browse files
fix(agent): prevent AgentLlmNode from overriding default model options (#3986)
* Fixes #3903, prevent AgentLlmNode from overriding default model options * Make sure internalToolExecution(false) is always set for ChatOptions (user might forget to set). Change-Id: I2465cb45bb5fec97d32da8809565efe370b69390 --------- Co-authored-by: chickenlj <ken.lj.hz@gmail.com>
1 parent 4e35fb8 commit 5e20734

File tree

1 file changed

+38
-19
lines changed
  • spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/node

1 file changed

+38
-19
lines changed

spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/node/AgentLlmNode.java

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.alibaba.cloud.ai.graph.agent.interceptor.InterceptorChain;
2828

2929
import org.springframework.ai.chat.client.ChatClient;
30+
import org.springframework.ai.chat.client.DefaultChatClient;
3031
import org.springframework.ai.chat.client.advisor.api.Advisor;
3132
import org.springframework.ai.chat.messages.AssistantMessage;
3233
import org.springframework.ai.chat.messages.Message;
@@ -40,6 +41,7 @@
4041
import org.springframework.ai.model.tool.ToolCallingChatOptions;
4142
import org.springframework.ai.tool.ToolCallback;
4243

44+
import org.springframework.lang.Nullable;
4345
import org.springframework.util.StringUtils;
4446

4547
import org.slf4j.Logger;
@@ -155,7 +157,7 @@ public Map<String, Object> apply(OverAllState state, RunnableConfig config) thro
155157
// Create ModelRequest
156158
ModelRequest.Builder requestBuilder = ModelRequest.builder()
157159
.messages(messages)
158-
.options(chatOptions.copy())
160+
.options(this.chatOptions != null ? this.chatOptions.copy() : null)
159161
.context(config.metadata().orElse(new HashMap<>()));
160162

161163
// Extract tool names and descriptions from toolCallbacks and pass them to ModelRequest
@@ -319,12 +321,10 @@ private List<Message> appendSystemPromptIfNeeded(ModelRequest modelRequest) {
319321
* @param toolCallbacks the tool callbacks to be included
320322
* @return merged ToolCallingChatOptions
321323
*/
324+
@Nullable
322325
private ToolCallingChatOptions buildChatOptions(ChatOptions chatOptions, List<ToolCallback> toolCallbacks) {
323326
if (chatOptions == null) {
324-
return ToolCallingChatOptions.builder()
325-
.toolCallbacks(toolCallbacks)
326-
.internalToolExecutionEnabled(false)
327-
.build();
327+
return null;
328328
}
329329

330330
if (chatOptions instanceof ToolCallingChatOptions builderToolCallingOptions) {
@@ -457,21 +457,40 @@ private ChatClient.ChatClientRequestSpec buildChatClientRequestSpec(ModelRequest
457457
List<ToolCallback> filteredToolCallbacks = filterToolCallbacks(modelRequest);
458458
filteredToolCallbacks.addAll(modelRequest.getDynamicToolCallbacks());
459459

460-
ToolCallingChatOptions chatOptions = modelRequest.getOptions();
461-
if (chatOptions == null) {
462-
chatOptions = ToolCallingChatOptions.builder()
463-
.toolCallbacks(filteredToolCallbacks)
464-
.internalToolExecutionEnabled(false)
465-
.build();
466-
} else {
467-
chatOptions.setToolCallbacks(filteredToolCallbacks);
468-
chatOptions.setInternalToolExecutionEnabled(false);
469-
}
460+
var promptSpec = this.chatClient.prompt()
461+
.messages(messages)
462+
.advisors(this.advisors);
463+
464+
ToolCallingChatOptions requestOptions = modelRequest.getOptions();
465+
466+
if (requestOptions != null) {
467+
requestOptions.setToolCallbacks(filteredToolCallbacks);
468+
// force disable internal tool execution to avoid conflict with Agent framework's tool execution management.
469+
requestOptions.setInternalToolExecutionEnabled(false);
470+
promptSpec.options(requestOptions);
471+
} else {
472+
// Check if user has set default options in ChatModel or ChatClient.
473+
if (promptSpec instanceof DefaultChatClient.DefaultChatClientRequestSpec defaultChatClientRequestSpec) {
474+
ChatOptions options = defaultChatClientRequestSpec.getChatOptions();
475+
// If no default options set, create new ToolCallingChatOptions with filtered tool callbacks and toolExecution disabled.
476+
if (options == null) {
477+
options = ToolCallingChatOptions.builder()
478+
.toolCallbacks(filteredToolCallbacks)
479+
.internalToolExecutionEnabled(false)
480+
.build();
481+
defaultChatClientRequestSpec.options(options);
482+
}
483+
// If options is ToolCallingChatOptions, set filtered tool callbacks and toolExecution disabled.
484+
else if (options instanceof ToolCallingChatOptions toolCallingChatOptions) {
485+
toolCallingChatOptions.setToolCallbacks(filteredToolCallbacks);
486+
toolCallingChatOptions.setInternalToolExecutionEnabled(false);
487+
}
488+
} else if (!filteredToolCallbacks.isEmpty()) {
489+
promptSpec.tools(filteredToolCallbacks);
490+
}
491+
}
470492

471-
return chatClient.prompt()
472-
.options(chatOptions)
473-
.messages(messages)
474-
.advisors(advisors);
493+
return promptSpec;
475494
}
476495

477496
public String getName() {

0 commit comments

Comments
 (0)