代码改变世界

完整教程:【SpringAI中Chat-Client用法】

2025-10-12 16:31  tlnshuju  阅读(90)  评论(0)    收藏  举报

Hi~!这里是奋斗的明志,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~
个人主页:奋斗的明志
所属专栏:SpringAI

本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为展示我的学习过程及理解。文笔、排版拙劣,望见谅。

在这里插入图片描述

在这里插入图片描述

了解

ChatClient 基于ChatModel进行了封装提供了通用的 API,它适用所有的大模型, 使用ChatClient可以让你面向SpringAi通用的api 而无需面向为每一种不同的模型的api来进行编程,虽然您仍然可以使用 ChatModel 来实现某些模型更加个性化的操作(ChatModel更偏向于底层),但 ChatClient 提供了灵活、更全面的方法来构建您的客户端选项以与模型进行交互: 比如系统提示词、格式式化响应、聊天记忆 、tools 都更加易用和优雅,所以除非ChatClient无法实现,否则我们优先考虑用ChatClient

所以我们后续基于ChatClient来进行学习应用。

基于ChatModel来学习源码,因为ChatClient底层依然还是ChatModel的封装。

创建子工程

在这里插入图片描述

在这里插入图片描述

添加pom依赖(阿里云百炼平台)

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
  <parent>
  <groupId>com.mingzhi.springai</groupId>
  <artifactId>spring-ai-parent</artifactId>
  <version>0.0.1-mz</version>
  </parent>
<artifactId>chat-client</artifactId>
<description>chat-client学习-聊天客户端</description>
  <properties>
  <maven.compiler.source>17</maven.compiler.source>
  <maven.compiler.target>17</maven.compiler.target>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
    <!--接入百炼平台-->
      <dependency>
      <groupId>com.alibaba.cloud.ai</groupId>
      <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
      </dependency>
    </dependencies>
  </project>

添加配置

server:
port: 8081 #端口号
spring:
application:
name: chat-client #服务应用名称
dashscope:
api-key: sk-e9bcb1abcaeb4da89114ef639067097ede
chat:
options:
model: qwen-vl-max-latest # 模型名称
multi-model: true

代码编写

  • 必须通过ChatClient.Builder 来进行构造
@SpringBootTest
public class ChatClientTest {
@Autowired
private ChatClient.Builder builder;
/**
* 同步响应
*/
@Test
public void test() {
ChatClient chatClient = builder.build();
String content = chatClient.prompt()
.user("hello")// 用户输入的提示词
.call()
.content();
System.out.println(content);
}
/**
* 流式响应
*/
@Test
public void test2() {
ChatClient chatClient = builder.build();
Flux<String> stringFlux = chatClient.prompt()
  .user("hello")// 用户输入的提示词
  .stream()
  .content();
  stringFlux.toIterable().forEach(System.out::println);
  }
  }

这种方式会在底层自动注入1个ChatModel , 如果你配置了多个模型依赖, 会无法注入。引入多个大模型的依赖,在进行依赖注入的时候就会报错

在这里插入图片描述

<dependencies>
  <!--接入百炼平台-->
    <dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
    </dependency>
    <!--接入deepseek依赖-->
      <dependency>
      <groupId>org.springframework.ai</groupId>
      <artifactId>spring-ai-starter-model-deepseek</artifactId>
      </dependency>
      <!--        <dependency>-->
      <!--            <groupId>org.springframework.boot</groupId>-->
      <!--            <artifactId>spring-boot-starter-webflux</artifactId>-->
      <!--        </dependency>-->
    </dependencies>

在这里插入图片描述

在这里插入图片描述

Autowired会先根据类型进行匹配,类型匹配不上就会找对应的名称,名称再找不到,就会出现上述错误

如何进行避免呢?

在这里插入图片描述

可以通过这种方式动态选择ChatModel:

@Autowired
private DashScopeChatModel dashScopeChatModel;
@Test
public void test3() {
ChatClient build = ChatClient.builder(dashScopeChatModel).build();
String content = build.prompt()
.user("hello")// 用户输入的提示词
.call()
.content();
System.out.println(content);
}
@Test
public void testChatStream() {
ChatClient chatClient = ChatClient.builder(dashScopeChatModel).build();
Flux<String> content = chatClient.prompt()
  .user("Hello")
  .stream()
  .content();
  // 阻塞输出
  content.toIterable().forEach(System.out::println);
  }

多平台多模型动态配置大模型平台实战

在这里插入图片描述

配置类

MorPlatformAndModelOptions

package com.mingzhi.springai;
public class MorPlatformAndModelOptions {
/**
* 平台
*/
private String platform;
/**
* 模型
*/
private String model;
/**
* 温度
*/
private Double temperature;
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getPlatform() {
return platform;
}
public void setPlatform(String platform) {
this.platform = platform;
}
public Double getTemperature() {
return temperature;
}
public void setTemperature(Double temperature) {
this.temperature = temperature;
}
}

接口

MorPlatformAndModelController

package com.mingzhi.springai.controller;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
import com.mingzhi.springai.MorPlatformAndModelOptions;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.deepseek.DeepSeekChatModel;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import java.util.HashMap;
import java.util.Map;
@RestController
public class MorPlatformAndModelController {
//声明一个map,用来初始化平台
Map<String, ChatModel> platformMap = new HashMap<>();
  //通过构造函数进行自动注入
  public MorPlatformAndModelController(DashScopeChatModel dashScopeChatModel,
  DeepSeekChatModel deepSeekChatModel) {
  platformMap.put("dashscope", dashScopeChatModel);
  platformMap.put("deepseek", deepSeekChatModel);
  }
  /**
  * @param message 消息
  * @param options 选项
  * @return
  */
  @RequestMapping(value = "/chat",produces = "text/stream;charset=UTF-8")
  public Flux<String> chat(
    String message,
    MorPlatformAndModelOptions options) {
    String platform = options.getPlatform();
    System.out.println("当前平台:" + platform);
    ChatModel chatModel = platformMap.get(platform);
    ChatOptions chatOptions = ChatOptions.builder()
    .temperature(options.getTemperature())
    .model(options.getModel())
    .build();
    ChatClient chatClient = ChatClient.builder(chatModel).defaultOptions(chatOptions).build();
    Flux<String> content = chatClient.prompt()
      .user(message)
      .stream()
      .content();
      return content;
      }
      }

展示效果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

定义3个ChatClient的bean

也可以根据请求动态创建, 看需求

@Configuration
public class AiConfig {
@Bean
public ChatClient deepseekR1(DeepSeekChatProperties chatProperties) {
DeepSeekApi deepSeekApi = DeepSeekApi.builder()
.apiKey(System.getenv("DEEP_SEEK_KEY"))
.build();
DeepSeekChatModel deepSeekChatModel = DeepSeekChatModel.builder()
.deepSeekApi(deepSeekApi)
.defaultOptions(DeepSeekChatOptions.builder().model(DeepSeekApi.ChatModel.DEEPSEEK_REASONER).build())
.build();
return ChatClient.builder(deepSeekChatModel).build();
}
@Bean
public ChatClient deepseekV3() {
DeepSeekApi deepSeekApi = DeepSeekApi.builder()
.apiKey(System.getenv("DEEP_SEEK_KEY"))
.build();
DeepSeekChatModel deepSeekChatModel = DeepSeekChatModel.builder()
.deepSeekApi(deepSeekApi)
.defaultOptions(
DeepSeekChatOptions.builder()
.model(DeepSeekApi.ChatModel.DEEPSEEK_CHAT)
.build()
)
.build();
return ChatClient.builder(deepSeekChatModel).build();
}
@Bean
public ChatClient ollama(@Autowired OllamaApi ollamaApi, @Autowired OllamaChatProperties options) {
OllamaChatModel ollamaChatModel = OllamaChatModel.builder()
.ollamaApi(ollamaApi)
.defaultOptions(OllamaOptions.builder().model(options.getModel()).build())
.build();
return ChatClient.builder(ollamaChatModel).build();
}
}

注意点

在单独引入阿里百炼平台时,有一个依赖可能会引入不进来

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述