SpringAI 集成 DeepSeek 以及多模型切换功能的demo
1. 需求分析
- 目标:支持动态切换 DeepSeek 的不同模型(如
deepseek-chat
、deepseek-coder
等)。 - 实现方式:通过配置或参数传递模型名称,动态调整 API 请求。
2. 实现步骤
(1) 修改配置文件
在 application.yml
或 application.properties
中定义可切换的模型列表(可选):
deepseek:
api-key: your-deepseek-api-key
base-url: https://api.deepseek.com/v1
# 可选:定义默认模型和可选模型列表
default-model: deepseek-chat
available-models:
- deepseek-chat
- deepseek-coder
- deepseek-math
(2) 修改 DeepSeek 服务类
在 DeepSeekService
中增加模型参数支持,并动态传入 API 请求:
示例代码(WebClient 方式):
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.util.Map;
@Service
public class DeepSeekService {
private final WebClient webClient;
private final String defaultModel; // 默认模型
public DeepSeekService(WebClient.Builder webClientBuilder,
@Value("${deepseek.default-model}") String defaultModel) {
this.webClient = webClientBuilder
.baseUrl("https://api.deepseek.com/v1") // 替换为实际地址
.build();
this.defaultModel = defaultModel;
}
/**
* 生成文本(支持动态模型切换)
* @param prompt 用户输入
* @param modelName 模型名称(如 deepseek-chat)
* @return 生成的文本
*/
public Mono<String> generateText(String prompt, String modelName) {
return webClient.post()
.uri("/chat/completions")
.header("Authorization", "Bearer your-deepseek-api-key") // 替换为实际认证方式
.bodyValue(Map.of(
"model", modelName, // 动态传入模型名称
"messages", List.of(Map.of("role", "user", "content", prompt))
))
.retrieve()
.bodyToMono(Map.class)
.map(response -> (String) response.get("choices").get(0).get("message").get("content"));
}
/**
* 使用默认模型生成文本
* @param prompt 用户输入
* @return 生成的文本
*/
public Mono<String> generateText(String prompt) {
return generateText(prompt, defaultModel); // 调用重载方法,默认模型
}
}
(3) 修改 Controller 接口
提供两种调用方式:
- 显式指定模型:通过 URL 参数传递
modelName
。 - 使用默认模型:不传参数时使用配置的默认模型。
示例代码:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
public class ChatController {
private final DeepSeekService deepSeekService;
public ChatController(DeepSeekService deepSeekService) {
this.deepSeekService = deepSeekService;
}
/**
* 显式指定模型调用
* @param message 用户输入
* @param modelName 模型名称(可选)
* @return 生成的文本
*/
@GetMapping("/chat")
public Mono<String> chat(
@RequestParam String message,
@RequestParam(required = false) String modelName) {
if (modelName != null && !modelName.isEmpty()) {
return deepSeekService.generateText(message, modelName); // 使用指定模型
} else {
return deepSeekService.generateText(message); // 使用默认模型
}
}
}
(4) 测试多模型切换
- 使用默认模型:访问
/chat?message=你好
。 - 显式指定模型:访问
/chat?message=你好&modelName=deepseek-coder
。
3. 高级优化(可选)
(1) 模型配置中心化
将模型列表和默认模型存储在数据库或配置中心(如 Nacos、Apollo),支持动态更新而无需重启服务。
(2) 模型选择策略
- 基于用户权限:不同用户只能使用特定模型(如免费用户仅能用
deepseek-chat
)。 - 基于请求内容:根据输入文本自动选择模型(如代码相关请求用
deepseek-coder
)。
(3) 错误处理与回退
- 如果指定模型不可用(如 API 返回错误),自动回退到默认模型:
public Mono<String> generateText(String prompt, String modelName) {
return webClient.post()
.uri("/chat/completions")
.header("Authorization", "Bearer your-deepseek-api-key")
.bodyValue(Map.of("model", modelName, "messages", List.of(Map.of("role", "user", "content", prompt))))
.retrieve()
.onStatus(HttpStatus::is5xxServerError, response ->
Mono.error(new RuntimeException("模型不可用,尝试回退到默认模型")))
.bodyToMono(Map.class)
.map(response -> (String) response.get("choices").get(0).get("message").get("content"))
.onErrorResume(e -> generateText(prompt, defaultModel)); // 回退逻辑
}
4. 总结
- 核心实现:通过动态传入
modelName
参数到 API 请求,支持多模型切换。 - 调用方式:
- 显式指定模型:
/chat?message=你好&modelName=deepseek-coder
。 - 使用默认模型:
/chat?message=你好
。
- 显式指定模型:
- 扩展性:
- 支持配置中心动态管理模型列表。
- 可结合策略模式实现更复杂的模型选择逻辑(如权限控制、自动回退)。
最终效果:SpringAI 应用可灵活切换 DeepSeek 的不同模型,满足多样化业务需求。