Skip to content

Commit f7d8f0f

Browse files
HyunSangHanilayaperumalg
authored andcommitted
Fix deepseek model auto-configuration
Related to #4494 Signed-off-by: Hyunsang Han <[email protected]>
1 parent b26b2c6 commit f7d8f0f

File tree

7 files changed

+66
-34
lines changed

7 files changed

+66
-34
lines changed

auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/main/java/org/springframework/ai/model/deepseek/autoconfigure/DeepSeekChatAutoConfiguration.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
3232
import org.springframework.beans.factory.ObjectProvider;
3333
import org.springframework.boot.autoconfigure.AutoConfiguration;
34-
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
3534
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
3635
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
3736
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -50,15 +49,14 @@
5049
* {@link AutoConfiguration Auto-configuration} for DeepSeek Chat Model.
5150
*
5251
* @author Geng Rong
52+
* @author Hyunsang Han
5353
*/
5454
@AutoConfiguration(after = { RestClientAutoConfiguration.class, WebClientAutoConfiguration.class,
5555
SpringAiRetryAutoConfiguration.class, ToolCallingAutoConfiguration.class })
5656
@ConditionalOnClass(DeepSeekApi.class)
5757
@EnableConfigurationProperties({ DeepSeekConnectionProperties.class, DeepSeekChatProperties.class })
5858
@ConditionalOnProperty(name = SpringAIModelProperties.CHAT_MODEL, havingValue = SpringAIModels.DEEPSEEK,
5959
matchIfMissing = true)
60-
@ImportAutoConfiguration(classes = { SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class,
61-
WebClientAutoConfiguration.class, ToolCallingAutoConfiguration.class })
6260
public class DeepSeekChatAutoConfiguration {
6361

6462
@Bean
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2025-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.ai.model.deepseek.autoconfigure;
18+
19+
import java.util.Arrays;
20+
import java.util.stream.Stream;
21+
22+
import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration;
23+
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
24+
import org.springframework.boot.autoconfigure.AutoConfigurations;
25+
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
26+
import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
27+
28+
/**
29+
* Base utility class for DeepSeek integration tests.
30+
*
31+
* @author Hyunsang Han
32+
*/
33+
public abstract class BaseDeepSeekIT {
34+
35+
public static AutoConfigurations deepSeekAutoConfig(Class<?>... additional) {
36+
Class<?>[] dependencies = { SpringAiRetryAutoConfiguration.class, ToolCallingAutoConfiguration.class,
37+
RestClientAutoConfiguration.class, WebClientAutoConfiguration.class };
38+
Class<?>[] all = Stream.concat(Arrays.stream(dependencies), Arrays.stream(additional)).toArray(Class<?>[]::new);
39+
return AutoConfigurations.of(all);
40+
}
41+
42+
}

auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/DeepSeekAutoConfigurationIT.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,22 @@
2929
import org.springframework.ai.chat.model.ChatResponse;
3030
import org.springframework.ai.chat.prompt.Prompt;
3131
import org.springframework.ai.deepseek.DeepSeekChatModel;
32-
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
33-
import org.springframework.boot.autoconfigure.AutoConfigurations;
34-
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
3532
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
3633

3734
import static org.assertj.core.api.Assertions.assertThat;
3835

3936
/**
4037
* @author Geng Rong
38+
* @author Hyunsang Han
4139
*/
4240
@EnabledIfEnvironmentVariable(named = "DEEPSEEK_API_KEY", matches = ".*")
43-
public class DeepSeekAutoConfigurationIT {
41+
public class DeepSeekAutoConfigurationIT extends BaseDeepSeekIT {
4442

4543
private static final Log logger = LogFactory.getLog(DeepSeekAutoConfigurationIT.class);
4644

4745
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
4846
.withPropertyValues("spring.ai.deepseek.apiKey=" + System.getenv("DEEPSEEK_API_KEY"))
49-
.withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class,
50-
RestClientAutoConfiguration.class, DeepSeekChatAutoConfiguration.class));
47+
.withConfiguration(BaseDeepSeekIT.deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class));
5148

5249
@Test
5350
void generate() {

auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/DeepSeekPropertiesTests.java

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,15 @@
1919
import org.junit.jupiter.api.Test;
2020

2121
import org.springframework.ai.deepseek.DeepSeekChatModel;
22-
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
23-
import org.springframework.boot.autoconfigure.AutoConfigurations;
24-
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
2522
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
2623

2724
import static org.assertj.core.api.Assertions.assertThat;
2825

2926
/**
3027
* @author Geng Rong
28+
* @author Hyunsang Han
3129
*/
32-
public class DeepSeekPropertiesTests {
30+
public class DeepSeekPropertiesTests extends BaseDeepSeekIT {
3331

3432
@Test
3533
public void chatProperties() {
@@ -41,8 +39,7 @@ public void chatProperties() {
4139
"spring.ai.deepseek.chat.options.model=MODEL_XYZ",
4240
"spring.ai.deepseek.chat.options.temperature=0.55")
4341
// @formatter:on
44-
.withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class,
45-
RestClientAutoConfiguration.class, DeepSeekChatAutoConfiguration.class))
42+
.withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class))
4643
.run(context -> {
4744
var chatProperties = context.getBean(DeepSeekChatProperties.class);
4845
var connectionProperties = context.getBean(DeepSeekConnectionProperties.class);
@@ -70,8 +67,7 @@ public void chatOverrideConnectionProperties() {
7067
"spring.ai.deepseek.chat.options.model=MODEL_XYZ",
7168
"spring.ai.deepseek.chat.options.temperature=0.55")
7269
// @formatter:on
73-
.withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class,
74-
RestClientAutoConfiguration.class, DeepSeekChatAutoConfiguration.class))
70+
.withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class))
7571
.run(context -> {
7672
var chatProperties = context.getBean(DeepSeekChatProperties.class);
7773
var connectionProperties = context.getBean(DeepSeekConnectionProperties.class);
@@ -108,8 +104,7 @@ public void chatOptionsTest() {
108104
"spring.ai.deepseek.chat.options.user=userXYZ"
109105
)
110106
// @formatter:on
111-
.withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class,
112-
RestClientAutoConfiguration.class, DeepSeekChatAutoConfiguration.class))
107+
.withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class))
113108
.run(context -> {
114109
var chatProperties = context.getBean(DeepSeekChatProperties.class);
115110
var connectionProperties = context.getBean(DeepSeekConnectionProperties.class);
@@ -132,15 +127,15 @@ void chatActivation() {
132127
new ApplicationContextRunner()
133128
.withPropertyValues("spring.ai.deepseek.api-key=API_KEY", "spring.ai.deepseek.base-url=TEST_BASE_URL",
134129
"spring.ai.model.chat=none")
135-
.withConfiguration(AutoConfigurations.of(DeepSeekChatAutoConfiguration.class))
130+
.withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class))
136131
.run(context -> {
137132
assertThat(context.getBeansOfType(DeepSeekChatProperties.class)).isEmpty();
138133
assertThat(context.getBeansOfType(DeepSeekChatModel.class)).isEmpty();
139134
});
140135

141136
new ApplicationContextRunner()
142137
.withPropertyValues("spring.ai.deepseek.api-key=API_KEY", "spring.ai.deepseek.base-url=TEST_BASE_URL")
143-
.withConfiguration(AutoConfigurations.of(DeepSeekChatAutoConfiguration.class))
138+
.withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class))
144139
.run(context -> {
145140
assertThat(context.getBeansOfType(DeepSeekChatProperties.class)).isNotEmpty();
146141
assertThat(context.getBeansOfType(DeepSeekChatModel.class)).isNotEmpty();
@@ -149,7 +144,7 @@ void chatActivation() {
149144
new ApplicationContextRunner()
150145
.withPropertyValues("spring.ai.deepseek.api-key=API_KEY", "spring.ai.deepseek.base-url=TEST_BASE_URL",
151146
"spring.ai.model.chat=deepseek")
152-
.withConfiguration(AutoConfigurations.of(DeepSeekChatAutoConfiguration.class))
147+
.withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class))
153148
.run(context -> {
154149
assertThat(context.getBeansOfType(DeepSeekChatProperties.class)).isNotEmpty();
155150
assertThat(context.getBeansOfType(DeepSeekChatModel.class)).isNotEmpty();

auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/tool/DeepSeekFunctionCallbackIT.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,10 @@
3333
import org.springframework.ai.chat.prompt.Prompt;
3434
import org.springframework.ai.deepseek.DeepSeekChatModel;
3535
import org.springframework.ai.deepseek.DeepSeekChatOptions;
36+
import org.springframework.ai.model.deepseek.autoconfigure.BaseDeepSeekIT;
3637
import org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration;
37-
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
3838
import org.springframework.ai.tool.ToolCallback;
3939
import org.springframework.ai.tool.function.FunctionToolCallback;
40-
import org.springframework.boot.autoconfigure.AutoConfigurations;
41-
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
4240
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
4341
import org.springframework.context.annotation.Bean;
4442
import org.springframework.context.annotation.Configuration;
@@ -47,18 +45,18 @@
4745

4846
/**
4947
* @author Geng Rong
48+
* @author Hyunsang Han
5049
*/
5150
// @Disabled("the deepseek-chat model's Function Calling capability is unstable see:
5251
// https://api-docs.deepseek.com/guides/function_calling")
5352
@EnabledIfEnvironmentVariable(named = "DEEPSEEK_API_KEY", matches = ".*")
54-
public class DeepSeekFunctionCallbackIT {
53+
public class DeepSeekFunctionCallbackIT extends BaseDeepSeekIT {
5554

5655
private final Logger logger = LoggerFactory.getLogger(DeepSeekFunctionCallbackIT.class);
5756

5857
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
5958
.withPropertyValues("spring.ai.deepseek.apiKey=" + System.getenv("DEEPSEEK_API_KEY"))
60-
.withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class,
61-
RestClientAutoConfiguration.class, DeepSeekChatAutoConfiguration.class))
59+
.withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class))
6260
.withUserConfiguration(Config.class);
6361

6462
@Test

auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/tool/FunctionCallbackInPromptIT.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,27 @@
3232
import org.springframework.ai.chat.prompt.Prompt;
3333
import org.springframework.ai.deepseek.DeepSeekChatModel;
3434
import org.springframework.ai.deepseek.DeepSeekChatOptions;
35+
import org.springframework.ai.model.deepseek.autoconfigure.BaseDeepSeekIT;
3536
import org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration;
3637
import org.springframework.ai.tool.function.FunctionToolCallback;
37-
import org.springframework.boot.autoconfigure.AutoConfigurations;
3838
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
3939

4040
import static org.assertj.core.api.Assertions.assertThat;
4141

4242
/**
4343
* @author Geng Rong
44+
* @author Hyunsang Han
4445
*/
4546
// @Disabled("the deepseek-chat model's Function Calling capability is unstable see:
4647
// https://api-docs.deepseek.com/guides/function_calling")
4748
@EnabledIfEnvironmentVariable(named = "DEEPSEEK_API_KEY", matches = ".*")
48-
public class FunctionCallbackInPromptIT {
49+
public class FunctionCallbackInPromptIT extends BaseDeepSeekIT {
4950

5051
private final Logger logger = LoggerFactory.getLogger(FunctionCallbackInPromptIT.class);
5152

5253
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
5354
.withPropertyValues("spring.ai.deepseek.apiKey=" + System.getenv("DEEPSEEK_API_KEY"))
54-
.withConfiguration(AutoConfigurations.of(DeepSeekChatAutoConfiguration.class));
55+
.withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class));
5556

5657
@Test
5758
void functionCallTest() {

auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@
3333
import org.springframework.ai.chat.prompt.Prompt;
3434
import org.springframework.ai.deepseek.DeepSeekChatModel;
3535
import org.springframework.ai.deepseek.DeepSeekChatOptions;
36+
import org.springframework.ai.model.deepseek.autoconfigure.BaseDeepSeekIT;
3637
import org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration;
3738
import org.springframework.ai.model.tool.ToolCallingChatOptions;
38-
import org.springframework.boot.autoconfigure.AutoConfigurations;
3939
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
4040
import org.springframework.context.annotation.Bean;
4141
import org.springframework.context.annotation.Configuration;
@@ -45,17 +45,18 @@
4545

4646
/**
4747
* @author Geng Rong
48+
* @author Hyunsang Han
4849
*/
4950
@EnabledIfEnvironmentVariable(named = "DEEPSEEK_API_KEY", matches = ".*")
5051
// @Disabled("the deepseek-chat model's Function Calling capability is unstable see:
5152
// https://api-docs.deepseek.com/guides/function_calling")
52-
class FunctionCallbackWithPlainFunctionBeanIT {
53+
class FunctionCallbackWithPlainFunctionBeanIT extends BaseDeepSeekIT {
5354

5455
private final Logger logger = LoggerFactory.getLogger(FunctionCallbackWithPlainFunctionBeanIT.class);
5556

5657
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
5758
.withPropertyValues("spring.ai.deepseek.apiKey=" + System.getenv("DEEPSEEK_API_KEY"))
58-
.withConfiguration(AutoConfigurations.of(DeepSeekChatAutoConfiguration.class))
59+
.withConfiguration(deepSeekAutoConfig(DeepSeekChatAutoConfiguration.class))
5960
.withUserConfiguration(Config.class);
6061

6162
@Test

0 commit comments

Comments
 (0)