Skip to content

Commit e7e2e92

Browse files
committed
Fix a FunctionCallback inside a container that pollutes the global model's ChatOptions
> The SpingBoot autoconfiguration class adds the container's FunctionCallback directly to the model's ChatOptions, which results in the FunctionCallback being included in the request each time it is called. > The modification registers the container's FunctionCallback directly to the model's functionCallbackRegister.
1 parent 03d1d50 commit e7e2e92

File tree

7 files changed

+61
-18
lines changed

7 files changed

+61
-18
lines changed

spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/anthropic/AnthropicAutoConfiguration.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
package org.springframework.ai.autoconfigure.anthropic;
1717

1818
import java.util.List;
19+
import java.util.Map;
20+
import java.util.function.Function;
21+
import java.util.stream.Collectors;
1922

2023
import org.springframework.ai.anthropic.AnthropicChatModel;
2124
import org.springframework.ai.anthropic.api.AnthropicApi;
@@ -66,12 +69,15 @@ public AnthropicChatModel anthropicChatModel(AnthropicApi anthropicApi, Anthropi
6669
RetryTemplate retryTemplate, FunctionCallbackContext functionCallbackContext,
6770
List<FunctionCallback> toolFunctionCallbacks) {
6871

72+
AnthropicChatModel chatModel = new AnthropicChatModel(anthropicApi, chatProperties.getOptions(), retryTemplate, functionCallbackContext);
73+
6974
if (!CollectionUtils.isEmpty(toolFunctionCallbacks)) {
70-
chatProperties.getOptions().getFunctionCallbacks().addAll(toolFunctionCallbacks);
75+
Map<String, FunctionCallback> toolFunctionCallbackMap = toolFunctionCallbacks.stream()
76+
.collect(Collectors.toMap(FunctionCallback::getName, Function.identity(), (a, b) -> b));
77+
chatModel.getFunctionCallbackRegister().putAll(toolFunctionCallbackMap);
7178
}
7279

73-
return new AnthropicChatModel(anthropicApi, chatProperties.getOptions(), retryTemplate,
74-
functionCallbackContext);
80+
return chatModel;
7581
}
7682

7783
@Bean

spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/azure/openai/AzureOpenAiAutoConfiguration.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
import org.springframework.util.StringUtils;
4141

4242
import java.util.List;
43+
import java.util.Map;
44+
import java.util.function.Function;
45+
import java.util.stream.Collectors;
4346

4447
/**
4548
* @author Piotr Olaszewski
@@ -101,11 +104,15 @@ public AzureOpenAiChatModel azureOpenAiChatModel(OpenAIClient openAIClient,
101104
AzureOpenAiChatProperties chatProperties, List<FunctionCallback> toolFunctionCallbacks,
102105
FunctionCallbackContext functionCallbackContext) {
103106

107+
AzureOpenAiChatModel chatModel = new AzureOpenAiChatModel(openAIClient, chatProperties.getOptions(), functionCallbackContext);
108+
104109
if (!CollectionUtils.isEmpty(toolFunctionCallbacks)) {
105-
chatProperties.getOptions().getFunctionCallbacks().addAll(toolFunctionCallbacks);
110+
Map<String, FunctionCallback> toolFunctionCallbackMap = toolFunctionCallbacks.stream()
111+
.collect(Collectors.toMap(FunctionCallback::getName, Function.identity(), (a, b) -> b));
112+
chatModel.getFunctionCallbackRegister().putAll(toolFunctionCallbackMap);
106113
}
107114

108-
return new AzureOpenAiChatModel(openAIClient, chatProperties.getOptions(), functionCallbackContext);
115+
return chatModel;
109116
}
110117

111118
@Bean

spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/minimax/MiniMaxAutoConfiguration.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
import org.springframework.web.client.RestClient;
3838

3939
import java.util.List;
40+
import java.util.Map;
41+
import java.util.function.Function;
42+
import java.util.stream.Collectors;
4043

4144
/**
4245
* @author Geng Rong
@@ -59,11 +62,15 @@ public MiniMaxChatModel miniMaxChatModel(MiniMaxConnectionProperties commonPrope
5962
var miniMaxApi = miniMaxApi(chatProperties.getBaseUrl(), commonProperties.getBaseUrl(),
6063
chatProperties.getApiKey(), commonProperties.getApiKey(), restClientBuilder, responseErrorHandler);
6164

65+
MiniMaxChatModel chatModel = new MiniMaxChatModel(miniMaxApi, chatProperties.getOptions(), functionCallbackContext, retryTemplate);
66+
6267
if (!CollectionUtils.isEmpty(toolFunctionCallbacks)) {
63-
chatProperties.getOptions().getFunctionCallbacks().addAll(toolFunctionCallbacks);
68+
Map<String, FunctionCallback> toolFunctionCallbackMap = toolFunctionCallbacks.stream()
69+
.collect(Collectors.toMap(FunctionCallback::getName, Function.identity(), (a, b) -> b));
70+
chatModel.getFunctionCallbackRegister().putAll(toolFunctionCallbackMap);
6471
}
6572

66-
return new MiniMaxChatModel(miniMaxApi, chatProperties.getOptions(), functionCallbackContext, retryTemplate);
73+
return chatModel;
6774
}
6875

6976
@Bean

spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/mistralai/MistralAiAutoConfiguration.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
package org.springframework.ai.autoconfigure.mistralai;
1717

1818
import java.util.List;
19+
import java.util.Map;
20+
import java.util.function.Function;
21+
import java.util.stream.Collectors;
1922

2023
import org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration;
2124
import org.springframework.ai.mistralai.MistralAiChatModel;
@@ -81,12 +84,15 @@ public MistralAiChatModel mistralAiChatModel(MistralAiCommonProperties commonPro
8184
var mistralAiApi = mistralAiApi(chatProperties.getApiKey(), commonProperties.getApiKey(),
8285
chatProperties.getBaseUrl(), commonProperties.getBaseUrl(), restClientBuilder, responseErrorHandler);
8386

87+
MistralAiChatModel chatModel = new MistralAiChatModel(mistralAiApi, chatProperties.getOptions(), functionCallbackContext, retryTemplate);
88+
8489
if (!CollectionUtils.isEmpty(toolFunctionCallbacks)) {
85-
chatProperties.getOptions().getFunctionCallbacks().addAll(toolFunctionCallbacks);
90+
Map<String, FunctionCallback> toolFunctionCallbackMap = toolFunctionCallbacks.stream()
91+
.collect(Collectors.toMap(FunctionCallback::getName, Function.identity(), (a, b) -> b));
92+
chatModel.getFunctionCallbackRegister().putAll(toolFunctionCallbackMap);
8693
}
8794

88-
return new MistralAiChatModel(mistralAiApi, chatProperties.getOptions(), functionCallbackContext,
89-
retryTemplate);
95+
return chatModel;
9096
}
9197

9298
private MistralAiApi mistralAiApi(String apiKey, String commonApiKey, String baseUrl, String commonBaseUrl,

spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/openai/OpenAiAutoConfiguration.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
package org.springframework.ai.autoconfigure.openai;
1717

1818
import java.util.List;
19+
import java.util.Map;
20+
import java.util.function.Function;
21+
import java.util.stream.Collectors;
1922

2023
import org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration;
2124
import org.springframework.ai.model.function.FunctionCallback;
@@ -73,12 +76,13 @@ public OpenAiChatModel openAiChatModel(OpenAiConnectionProperties commonProperti
7376
var openAiApi = openAiApi(chatProperties.getBaseUrl(), commonProperties.getBaseUrl(),
7477
chatProperties.getApiKey(), commonProperties.getApiKey(), restClientBuilder, webClientBuilder,
7578
responseErrorHandler, "chat");
76-
79+
OpenAiChatModel chatModel = new OpenAiChatModel(openAiApi, chatProperties.getOptions(), functionCallbackContext, retryTemplate);
7780
if (!CollectionUtils.isEmpty(toolFunctionCallbacks)) {
78-
chatProperties.getOptions().getFunctionCallbacks().addAll(toolFunctionCallbacks);
81+
Map<String, FunctionCallback> toolFunctionCallbackMap = toolFunctionCallbacks.stream().collect(Collectors.toMap(FunctionCallback::getName, Function.identity(), (a, b) -> b));
82+
chatModel.getFunctionCallbackRegister().putAll(toolFunctionCallbackMap);
7983
}
8084

81-
return new OpenAiChatModel(openAiApi, chatProperties.getOptions(), functionCallbackContext, retryTemplate);
85+
return chatModel;
8286
}
8387

8488
@Bean

spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/gemini/VertexAiGeminiAutoConfiguration.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717

1818
import java.io.IOException;
1919
import java.util.List;
20+
import java.util.Map;
21+
import java.util.function.Function;
22+
import java.util.stream.Collectors;
2023

2124
import com.google.auth.oauth2.GoogleCredentials;
2225
import com.google.cloud.vertexai.VertexAI;
@@ -79,11 +82,15 @@ public VertexAiGeminiChatModel vertexAiGeminiChat(VertexAI vertexAi, VertexAiGem
7982

8083
FunctionCallbackContext functionCallbackContext = springAiFunctionManager(context);
8184

85+
VertexAiGeminiChatModel chatModel = new VertexAiGeminiChatModel(vertexAi, chatProperties.getOptions(), functionCallbackContext);
86+
8287
if (!CollectionUtils.isEmpty(toolFunctionCallbacks)) {
83-
chatProperties.getOptions().getFunctionCallbacks().addAll(toolFunctionCallbacks);
88+
Map<String, FunctionCallback> toolFunctionCallbackMap = toolFunctionCallbacks.stream()
89+
.collect(Collectors.toMap(FunctionCallback::getName, Function.identity(), (a, b) -> b));
90+
chatModel.getFunctionCallbackRegister().putAll(toolFunctionCallbackMap);
8491
}
8592

86-
return new VertexAiGeminiChatModel(vertexAi, chatProperties.getOptions(), functionCallbackContext);
93+
return chatModel;
8794
}
8895

8996
/**

spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/zhipuai/ZhiPuAiAutoConfiguration.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
import org.springframework.web.client.RestClient;
4040

4141
import java.util.List;
42+
import java.util.Map;
43+
import java.util.function.Function;
44+
import java.util.stream.Collectors;
4245

4346
/**
4447
* @author Geng Rong
@@ -61,11 +64,14 @@ public ZhiPuAiChatModel zhiPuAiChatModel(ZhiPuAiConnectionProperties commonPrope
6164
var zhiPuAiApi = zhiPuAiApi(chatProperties.getBaseUrl(), commonProperties.getBaseUrl(),
6265
chatProperties.getApiKey(), commonProperties.getApiKey(), restClientBuilder, responseErrorHandler);
6366

67+
ZhiPuAiChatModel chatModel = new ZhiPuAiChatModel(zhiPuAiApi, chatProperties.getOptions(), functionCallbackContext, retryTemplate);
68+
6469
if (!CollectionUtils.isEmpty(toolFunctionCallbacks)) {
65-
chatProperties.getOptions().getFunctionCallbacks().addAll(toolFunctionCallbacks);
66-
}
70+
Map<String, FunctionCallback> toolFunctionCallbackMap = toolFunctionCallbacks.stream()
71+
.collect(Collectors.toMap(FunctionCallback::getName, Function.identity(), (a, b) -> b));
72+
chatModel.getFunctionCallbackRegister().putAll(toolFunctionCallbackMap); }
6773

68-
return new ZhiPuAiChatModel(zhiPuAiApi, chatProperties.getOptions(), functionCallbackContext, retryTemplate);
74+
return chatModel;
6975
}
7076

7177
@Bean

0 commit comments

Comments
 (0)