spring-ai 多个同种类型的 chatclient
·
application.yml
----------------------------------------------------
默认的 Spring AI OpenAI 配置 (可选,如果您仍然需要一个默认实例)
Spring Boot 会根据此配置自动创建一个默认的 OpenAiChatModel 和 ChatClient bean
----------------------------------------------------
spring:
ai:
openai:
chat:
options:
model: gpt-4o-mini # 默认模型
api-key: sk-default-openai-key # 默认API Key
base-url: https://api.openai.com/v1 # 默认Base URL
----------------------------------------------------
自定义配置:用于创建多个相同类型(OpenAI)的 AI 模型实例
我们使用 ‘app.ai.openai-configs’ 前缀来定义一个列表,每个元素代表一个模型配置
----------------------------------------------------
app:
ai:
openai-configs:
# 第一个自定义模型配置
- name: my-model-1 # 为这个模型实例指定一个名称
api-key: sk-your-key-for-model1 # 替换为你的第一个API Key
base-url: https://api.openai.com/v1 # 模型的服务地址
options:
model: gpt-3.5-turbo # 使用的模型名称
temperature: 0.7 # 模型温度参数# 第二个自定义模型配置
- name: my-model-2 # 为这个模型实例指定另一个名称
api-key: sk-your-key-for-model2 # 替换为你的第二个API Key
base-url: https://custom-endpoint.openai.com/v1 # 可以是不同的服务地址或代理地址
options:
model: gpt-4o # 使用的不同模型名称
temperature: 0.9 # 不同的温度参数
topP: 0.95 # 其他选项
// MultipleChatModelConfig.java
package com.example.springai.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Qualifier; // 用于注入特定名称的 Bean
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 这是一个 Spring 配置类,用于根据 YAML 配置创建多个 OpenAiChatModel 和 ChatClient 实例。
*/
@Data
@Configuration
public class MultipleChatModelConfig {
/**
* 定义一个内部类,用于映射 YAML 中单个 OpenAI 模型配置的属性。
*/
public static class OpenAiConfigProperties {
private String name; // 模型的唯一名称
private String apiKey; // API Key
private String baseUrl; // Base URL
private Map<String, Object> options; // 模型选项,如 model, temperature 等
}
/**
* 定义一个内部类,用于绑定 `app.ai` 前缀下的所有自定义 AI 配置。
* `openai-configs` 将被映射到一个 `OpenAiConfigProperties` 对象的列表。
*/
@ConfigurationProperties(prefix = "app.ai")
public static class AppAiProperties {
private List<OpenAiConfigProperties> openaiConfigs;
// Getters 和 Setters
public List<OpenAiConfigProperties> getOpenaiConfigs() { return openaiConfigs; }
public void setOpenaiConfigs(List<OpenAiConfigProperties> openaiConfigs) { this.openaiConfigs = openaiConfigs; }
}
/**
* 将 AppAiProperties 注册为 Spring Bean,以便 Spring Boot 可以绑定 YAML 配置。
* @return 绑定了配置的 AppAiProperties 实例
*/
@Bean
public AppAiProperties appAiProperties() {
return new AppAiProperties();
}
/**
* 根据 `AppAiProperties` 中定义的配置列表,动态创建并注册多个 ChatClient Bean。
* 这些 ChatClient 将被存储在一个 Map 中,键是模型名称,值是对应的 ChatClient 实例。
*
* @param appAiProperties 包含所有自定义模型配置的属性对象
* @return 一个 Map,其中包含所有命名 ChatClient 实例
*/
@Bean
public Map<String, ChatClient> namedChatClients(AppAiProperties appAiProperties) {
// 如果没有配置,则返回一个空 Map
if (appAiProperties.getOpenaiConfigs() == null) {
System.out.println("未找到 app.ai.openai-configs 配置。");
return Map.of();
}
System.out.println("正在创建自定义 ChatClient 实例...");
return appAiProperties.getOpenaiConfigs().stream()
.collect(Collectors.toMap(
OpenAiConfigProperties::getName, // 使用配置中定义的 'name' 作为 Map 的键
config -> {
System.out.println(" - 创建模型: " + config.getName() + " (Base URL: " + config.getBaseUrl() + ", Model: " + config.getOptions().get("model") + ")");
// 1. 创建 OpenAiApi 实例
OpenAiApi openAiApi = new OpenAiApi(config.getBaseUrl(), config.getApiKey());
// 2. 创建 OpenAiChatOptions 实例
// 从 Map 中提取选项,并转换为 OpenAiChatOptions 对象
OpenAiChatOptions.Builder optionsBuilder = OpenAiChatOptions.builder();
if (config.getOptions() != null) {
if (config.getOptions().containsKey("model")) {
optionsBuilder.withModel((String) config.getOptions().get("model"));
}
if (config.getOptions().containsKey("temperature")) {
Object temp = config.getOptions().get("temperature");
if (temp instanceof Number) {
optionsBuilder.withTemperature(((Number) temp).floatValue());
}
}
if (config.getOptions().containsKey("topP")) {
Object topP = config.getOptions().get("topP");
if (topP instanceof Number) {
optionsBuilder.withTopP(((Number) topP).floatValue());
}
}
// 如果有其他 ChatOptions,可以在这里继续添加映射
}
OpenAiChatOptions chatOptions = optionsBuilder.build();
// 3. 创建 OpenAiChatModel 实例
OpenAiChatModel chatModel = new OpenAiChatModel(openAiApi, chatOptions);
// 4. 创建并返回 ChatClient 实例
return ChatClient.builder(chatModel)
.defaultSystemPrompt("您是一个由 " + config.getName() + " 提供支持的有用助手。")
.build();
}
));
}
}
```java
// ChatClientService.java
package com.example.springai.service;
import org.springframework.stereotype.Service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; // 虽然这里直接注入 Map,但理解 @Qualifier 对单个命名 Bean 很有用
import java.util.Map;
/**
* 这是一个服务类,演示如何注入和使用多个命名 ChatClient 实例。
*/
@Service
public class ChatClientService {
// 注入由 MultipleChatModelConfig 创建的 Map<String, ChatClient> Bean
private final Map<String, ChatClient> namedChatClients;
@Autowired
public ChatClientService(Map<String, ChatClient> namedChatClients) {
this.namedChatClients = namedChatClients;
System.out.println("ChatClientService 已初始化,可用模型: " + namedChatClients.keySet());
}
/**
* 根据模型名称生成聊天响应。
* @param modelName 要使用的模型名称(例如:"my-model-1", "my-model-2")
* @param userMessage 用户的消息
* @return 模型的响应内容
*/
public String generateResponse(String modelName, String userMessage) {
ChatClient client = namedChatClients.get(modelName); // 从 Map 中获取对应的 ChatClient 实例
if (client == null) {
System.err.println("错误: 未找到名为 '" + modelName + "' 的 Chat 客户端。");
return "错误: 未找到名为 '" + modelName + "' 的 Chat 客户端。请检查配置或模型名称。";
}
System.out.println("使用模型 '" + modelName + "' 生成响应...");
try {
// 使用 ChatClient 发送消息并获取响应
return client.prompt()
.user(userMessage)
.call()
.content();
} catch (Exception e) {
System.err.println("使用模型 '" + modelName + "' 生成响应时发生错误: " + e.getMessage());
return "生成响应时发生错误: " + e.getMessage();
}
}
// ----------------------------------------------------
// 您可以在 Spring Boot 应用的主类或控制器中调用此服务进行测试:
// ----------------------------------------------------
/*
// 假设这是您的 Spring Boot 主应用类
@SpringBootApplication
public class MyApplication implements CommandLineRunner {
@Autowired
private ChatClientService chatClientService;
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
System.out.println("\n--- 测试模型 'my-model-1' ---");
String response1 = chatClientService.generateResponse("my-model-1", "你好,请自我介绍一下。");
System.out.println("Model 1 响应: " + response1);
System.out.println("\n--- 测试模型 'my-model-2' ---");
String response2 = chatClientService.generateResponse("my-model-2", "讲一个关于人工智能的简短笑话。");
System.out.println("Model 2 响应: " + response2);
System.out.println("\n--- 测试不存在的模型 ---");
String response3 = chatClientService.generateResponse("non-existent-model", "这能工作吗?");
System.out.println("不存在的模型响应: " + response3);
}
}
*/
}
// 如果您想快速测试,可以把这个放在一个简单的 Spring Boot 应用主类中
// SpringAiMultipleModelsApplication.java
package com.example.springai;
import com.example.springai.service.ChatClientService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.beans.factory.annotation.Autowired;
@SpringBootApplication
public class SpringAiMultipleModelsApplication implements CommandLineRunner {
@Autowired
private ChatClientService chatClientService;
public static void main(String[] args) {
SpringApplication.run(SpringAiMultipleModelsApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
System.out.println("\n--- 测试模型 'my-model-1' ---");
String response1 = chatClientService.generateResponse("my-model-1", "你好,请自我介绍一下。");
System.out.println("模型 1 响应: " + response1);
System.out.println("\n--- 测试模型 'my-model-2' ---");
String response2 = chatClientService.generateResponse("my-model-2", "讲一个关于人工智能的简短笑话。");
System.out.println("模型 2 响应: " + response2);
System.out.println("\n--- 测试不存在的模型 ---");
String response3 = chatClientService.generateResponse("non-existent-model", "这能工作吗?");
System.out.println("不存在的模型响应: " + response3);
}
}
<!-- pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version> <!-- 使用与 Spring AI 兼容的 Spring Boot 版本 -->
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>spring-ai-multiple-models</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-ai-multiple-models</name>
<description>Demo project for Spring AI multiple models</description>
<properties>
<java.version>17</java.version>
<spring-ai.version>0.8.1</spring-ai.version> <!-- 确保使用与 Spring Boot 3.2.x 兼容的 Spring AI 版本 -->
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring AI OpenAI 依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
更多推荐
所有评论(0)