掘金 人工智能 04月29日 10:27
基于SpringAI实现简易聊天对话
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文详细介绍了Spring AI Alibaba提供的ChatClient组件的学习和实践过程。ChatClient作为Spring AI中与大语言模型交互的高级API,通过流畅的编程接口简化了聊天应用程序的构建。文章从ChatClient的核心概念和优势入手,讲解了如何创建和配置ChatClient实例,以及如何处理不同类型的AI响应,包括文本、完整响应对象、结构化实体和流式响应。此外,还介绍了如何结合Spring Boot快速搭建一个可交互的聊天后端服务,并探讨了Server-Sent Events在流式响应中的应用,旨在帮助读者掌握ChatClient的使用方法。

💡ChatClient是Spring AI Alibaba提供的高级API,旨在简化与AI模型的交互,尤其是在需要组合提示词模板、聊天记忆、模型本身、输出解析器和RAG组件等多个组件时,它通过Fluent API支持同步和反应式编程模型,隐藏了与LLM交互的复杂性,并减少了样板代码。

🛠️创建ChatClient实例有两种主要方式:一是利用Spring Boot自动配置的ChatClient.Builder,只需注入并调用build()方法;二是禁用自动配置后,手动创建ChatClient.Builder并传入自定义的ChatModel实例,以实现更精细的控制。

🔄ChatClient API提供多种方式处理AI模型的响应,包括返回包含详细信息的ChatResponse对象、将AI模型的文本输出自动映射为Java POJO实体类,以及通过.stream()方法实现流式响应,以支持实时显示或处理部分结果的场景。

⚙️可以在创建ChatClient时设置默认行为,如默认系统消息、用户消息、模型选项、函数和头信息等,这些默认值将应用于该ChatClient实例发出的所有请求,除非在单次请求中被覆盖。

🧩Advisors是一种强大的机制,用于向ChatClient的请求/响应流程中添加额外的功能,如检索增强生成(RAG)和聊天记忆等,通过ChatClient.Builder的.defaultAdvisors(...)方法添加,类似于中间件或AOP中的切面。

简介

本文旨在记录学习和实践 Spring AI Alibaba 提供的 ChatClient 组件的过程。ChatClient 是 Spring AI 中用于与大语言模型(LLM)进行交互的高级 API,它通过流畅(Fluent)的编程接口,极大地简化了构建聊天应用程序的复杂度。相比直接使用底层的 ChatModelChatClient 封装了提示词构建、响应处理、结构化输出、流式响应以及与 RAG、聊天记忆等高级功能的集成。

通过本文的学习,我们将掌握:

我们将从官方文档入手,结合代码实践,逐步深入理解 ChatClient 的使用方法。


ChatClient相关原理

Spring AI Alibaba 文档

核心知识点:ChatClient in Spring AI Alibaba

ChatClient 是 Spring AI Alibaba 提供的一个更高级别的 API,用于与 AI 模型进行交互。它旨在简化开发流程,特别是当应用程序需要组合多个组件(如提示词模板、聊天记忆、模型本身、输出解析器、RAG 组件等)时。

1. ChatClient 简介

2. 创建 ChatClient

创建 ChatClient 实例需要使用 ChatClient.Builder 对象。有两种主要方式获取 ChatClient

import org.springframework.ai.chat.client.ChatClient; // 导入 ChatClient 类import org.springframework.web.bind.annotation.GetMapping; // 导入 GetMapping 注解,用于处理 HTTP GET 请求import org.springframework.web.bind.annotation.RequestParam; // 导入 RequestParam 注解,用于获取请求参数import org.springframework.web.bind.annotation.RestController; // 导入 RestController 注解,标识这是一个 RESTful 控制器@RestController // 声明这是一个 Spring MVC 的 REST 控制器,其方法默认返回 JSON 或其他指定格式的数据public class ChatController {    // 声明一个 final 的 ChatClient 成员变量,用于与 AI 模型交互    private final ChatClient chatClient;    // 控制器的构造函数    // Spring Boot 会自动查找并注入一个 ChatClient.Builder 类型的 Bean    public ChatController(ChatClient.Builder builder) {        // 使用注入的 builder 构建 ChatClient 实例,并赋值给成员变量        // builder 会使用自动配置好的底层 ChatModel (例如通义千问模型) 和其他默认设置        this.chatClient = builder.build();    }    @GetMapping("/chat") // 将 HTTP GET 请求映射到 /chat 路径    // @RequestParam("input") String input 表示从请求参数中获取名为 "input" 的值,并赋给 input 变量    public String chat(@RequestParam("input") String input) {        // 使用 chatClient 的 Fluent API 开始构建一个请求        return this.chatClient.prompt() // 1. 调用 prompt() 方法开始构建一个 Prompt (提示)                .user(input)          // 2. 调用 user() 方法设置用户角色的消息内容,内容为传入的 input 字符串                .call()               // 3. 调用 call() 方法,执行与 AI 模型的同步调用 (发送请求并等待响应)                .content();           // 4. 调用 content() 方法,从 AI 模型的响应 (ChatResponse) 中提取文本内容并返回    }}
import org.springframework.ai.chat.client.ChatClient; // 导入 ChatClient 类import org.springframework.ai.chat.model.ChatModel;   // 导入 ChatModel 接口// ... 其他 importpublic class MyService {    private final ChatClient customChatClient;    // 假设 myChatModel 是你通过其他方式配置或注入的特定 ChatModel 实例    public MyService(ChatModel myChatModel) {        // 方法一:使用 ChatClient.builder() 静态方法,并传入 ChatModel 实例        ChatClient.Builder builder = ChatClient.builder(myChatModel);        // 这里可以继续使用 builder 配置其他选项,例如 .defaultOptions(), .defaultSystem(), etc.        this.customChatClient = builder.build(); // 构建 ChatClient 实例        // 方法二:使用 ChatClient.create() 静态方法,这是一个更简洁的方式        // 它会使用传入的 ChatModel 和默认的 Builder 设置来创建 ChatClient        // this.customChatClient = ChatClient.create(myChatModel);    }    public String askSomething(String question) {        // 使用手动创建的 customChatClient 进行交互        return customChatClient.prompt()                .user(question)                .call()                .content();    }}

3. 处理 ChatClient 响应

ChatClient API 提供了多种方式来处理和格式化来自 AI 模型的响应:

import org.springframework.ai.chat.client.ChatClient; // 导入 ChatClient 类import org.springframework.web.bind.annotation.GetMapping; // 导入 GetMapping 注解import org.springframework.web.bind.annotation.RequestParam; // 导入 RequestParam 注解import org.springframework.web.bind.annotation.RestController; // 导入 RestController 注解@RestControllerpublic class StructuredOutputController {    private final ChatClient chatClient;    // 定义一个简单的 POJO 类,用于接收结构化输出    static class ActorFilms {        public String actor; // 演员姓名        public List<String> movies; // 电影列表    }    public StructuredOutputController(ChatClient.Builder builder) {        this.chatClient = builder.build();    }    @GetMapping("/actor-films") // 将 HTTP GET 请求映射到 /actor-films 路径    public ActorFilms getActorFilms(@RequestParam("actor") String actorName) {        // 使用 chatClient 的 Fluent API        return this.chatClient.prompt()                // 设置用户消息,要求模型列出指定演员的电影,并明确要求 JSON 格式                .user("Generate a list of films for the actor " + actorName + ". Respond in JSON format with keys 'actor' and 'movies'.")                .call() // 执行与 AI 模型的同步调用                // 调用 entity() 方法,并传入 ActorFilms.class                // ChatClient 会尝试将 AI 返回的文本内容 (预期是 JSON 字符串)                // 解析并映射到 ActorFilms 类的实例中                .entity(ActorFilms.class);    }}
import org.springframework.ai.chat.client.ChatClient; // 导入 ChatClient 类import org.springframework.http.MediaType; // 导入 MediaType 类import org.springframework.web.bind.annotation.GetMapping; // 导入 GetMapping 注解import org.springframework.web.bind.annotation.RequestParam; // 导入 RequestParam 注解import org.springframework.web.bind.annotation.RestController; // 导入 RestController 注解import reactor.core.publisher.Flux; // 导入 Flux 类 (来自 Project Reactor)import org.springframework.ai.chat.model.ChatResponse; // 导入 ChatResponse 类@RestControllerpublic class StreamingChatController {    private final ChatClient chatClient;    public StreamingChatController(ChatClient.Builder builder) {        this.chatClient = builder.build();    }    // produces = MediaType.TEXT_EVENT_STREAM_VALUE 指定响应类型为 Server-Sent Events (SSE)    @GetMapping(value = "/stream-chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)    public Flux<String> streamChat(@RequestParam("input") String input) {        // 使用 chatClient 的 Fluent API        return this.chatClient.prompt()                .user(input) // 设置用户消息                .stream()    // 1. 调用 stream() 方法,启动与 AI 模型的流式交互,返回 Flux<ChatResponse>                .content();  // 2. 调用 content() 方法 (针对 Flux),将 ChatResponse 流映射为 String 内容流                             //    每次模型生成一部分内容,就会在这个 Flux 中发布一个 String 片段    }    // 如果需要更详细的流信息,可以直接处理 Flux<ChatResponse>    @GetMapping(value = "/stream-chat-response", produces = MediaType.TEXT_EVENT_STREAM_VALUE)    public Flux<ChatResponse> streamChatResponse(@RequestParam("input") String input) {        return this.chatClient.prompt()                .user(input)                .stream() // 直接返回 ChatResponse 的流                .chatResponse(); // 获取原始的 ChatResponse 流    }}

4. 定制 ChatClient 默认值

可以在创建 ChatClient 时设置一些默认行为,这些默认值会应用于该 ChatClient 实例发出的所有请求,除非在单次请求中被覆盖。

ChatClient chatClient = ChatClient.builder(chatModel)        // 设置默认的系统消息,告诉 AI 它是一个乐于助人的 AI 助手        .defaultSystem("You are a helpful AI assistant.")        .build();// 后续使用这个 chatClient 发送请求时,会自动带上这个系统消息chatClient.prompt().user("What is the capital of France?").call().content();

5. Advisors (增强器/顾问)

// 假设 vectorStore 和 chatMemory 是已经配置好的 BeanVectorStore vectorStore = ...;ChatMemory chatMemory = ...;ChatClient chatClient = ChatClient.builder(chatModel)        // 添加一个 RAG Advisor,使用指定的 VectorStore 进行检索        .defaultAdvisors(new QuestionAnswerAdvisor(vectorStore))        // 添加一个聊天记忆 Advisor        .defaultAdvisors(new ChatMemoryAdvisor(chatMemory))        .build();// 现在使用这个 chatClient 时,会自动进行 RAG 检索和聊天记忆管理chatClient.prompt().user("Tell me about Spring AI based on my previous questions.").call().content();

总结:

ChatClient 是 Spring AI Alibaba 中进行 AI 模型交互的核心组件之一。它通过 Fluent API 极大地简化了与 AI 模型的通信,隐藏了底层实现的复杂性,并提供了强大的功能,如结构化输出、流式响应和通过 Advisors 实现的 RAG、聊天记忆等高级特性。掌握 ChatClient 的使用对于在 Spring 应用中高效地集成 AI 功能至关重要。


实践记录

配置项目

<dependency>  <groupId>com.alibaba.cloud.ai</groupId>  <artifactId>spring-ai-alibaba-starter</artifactId>  <version>1.0.0-M6.1</version></dependency>

为了实践ChatClient的使用,我们创建了一个简单的Spring Boot项目,在pom.xml文件中引入spring-ai-alibaba-starter依赖。

server:  port: 10001spring:  application:    name: spring-ai-alibaba-dashscope-chat-example  ai:    dashscope:      api-key: ${AI_DASHSCOPE_API_KEY}

在application.yml文件中,配置spring.ai.dashscope.api-key,用于设置Dashscope的API密钥,使其从环境变量中读取。

调用content方法

这段代码展示了如何使用 Spring AI Alibaba 快速构建一个简单的聊天接口。 通过 Spring Boot 的 @RestController 注解,我们创建了一个 RESTful 控制器 ChatClientController,它依赖于 Spring AI 提供的 ChatClient 组件。 构造函数中,我们利用 ChatClient.Builder 构建了一个 ChatClient 实例,Spring AI 负责自动注入这个 Builder。 核心逻辑在 chat() 方法中,这个方法通过 @GetMapping("/chat") 注解映射到 HTTP GET 请求。 当用户访问 /chat?input=你的消息 时,chat() 方法会被调用,它会接收 URL 中的 input 参数作为用户输入,并使用 ChatClient 向配置好的 AI 模型发送请求,最终将 AI 模型的响应文本内容返回给客户端。 这个简单的接口可以轻松集成到前端应用中,实现基本的对话功能,是快速体验和构建 AI 应用的理想起点。注释后的代码如下所示。

package com.miku.springaialibabalearn.controller;import org.springframework.ai.chat.client.ChatClient; // 导入 Spring AI 提供的 ChatClient 接口import org.springframework.web.bind.annotation.GetMapping; // 导入 Spring MVC 的 GetMapping 注解,用于处理 GET 请求import org.springframework.web.bind.annotation.RestController; // 导入 Spring MVC 的 RestController 注解,表明这是一个 RESTful 控制器/** *  RestController 注解表明这是一个 RESTful 控制器,用于处理 HTTP 请求并返回数据。 *  此类负责处理与 ChatClient 交互的 HTTP 请求。 */@RestControllerpublic class ChatClientController {    private final ChatClient chatClient; // 声明一个私有 final 的 ChatClient 类型的成员变量,用于进行聊天交互    /**     *  构造器注入 ChatClient.Builder,并通过 builder 构建 ChatClient 实例。     *  Spring 会自动解析 ChatClient.Builder 并注入到这里。     *     * @param builder ChatClient 的构建器,由 Spring AI 自动提供。     */    public ChatClientController( ChatClient.Builder builder ) {        // 使用 ChatClient.Builder 构建 ChatClient 实例并赋值给成员变量 chatClient        this.chatClient = builder.build();    }    /**     *  GetMapping 注解将 HTTP GET 请求 "/chat" 映射到 chat() 方法。     *  当接收到 "/chat" 的 GET 请求时,此方法将被调用。     *     * @param input  请求参数 input,从 URL 的 query parameter 中获取,例如 /chat?input=你好。     *               Spring MVC 会自动将 URL 中的 input 参数值绑定到此方法参数。     * @return String  返回 AI 聊天模型的响应内容,以纯文本形式返回。     */    @GetMapping("/chat")    // 将 HTTP GET 请求映射到 /chat 路径    public String chat( @RequestParam("input") String input ) {        // @RequestParam("input") String input 表示从请求参数中获取名为 "input" 的值,并赋给 input 变量        // 使用 chatClient 的 Fluent API 开始构建一个请求        return this.chatClient.prompt()                // 1. 调用 prompt() 方法开始构建一个 Prompt (提示)                .user(input)                // 2. 调用 user() 方法设置用户角色的消息内容,内容为传入的 input 字符串                .call()                // 3. 调用 call() 方法,执行与 AI 模型的同步调用 (发送请求并等待响应)                .content();                // 4. 调用 content() 方法,从 AI 模型的响应 (ChatResponse) 中提取文本内容并返回    }}

启动Application.java

使用Postman发送GET类型的HTTP请求:http://localhost:10001/chat?input=你好,介绍依赖注入的原理。可以看到成功获得了dashscope模型的响应。


调用chatResponse方法

/**AI 模型的响应是一种由ChatResponse类型定义的丰富结构。它包含响应生成相关的元数据,同时它还可以包含多个子响应(称为Generation),每个子响应都有自己的元数据。元数据包括用于创建响应的令牌(token)数量信息(在英文中,每个令牌大约为一个单词的 3/4),了解令牌信息很重要,因为 AI 模型根据每个请求使用的令牌数量收费。 */@GetMapping( "/response" )    public ChatResponse response(String input ) {              return this.chatClient.prompt()                .user(input)                // 设置了用户消息的内容                .call()                // call 方法向 AI 模型发送请求                .chatResponse();                // 调用 chatResponse() 返回 ChatResponse    }

在浏览器使用http://localhost:10001/response?input=你好发起http请求,返回 ChatResponse。


调用entity方法

// 定义一个 HTTP GET 请求处理方法,映射到 "/singer-songs" 路径@GetMapping("/singer-songs")// 返回类型为 SingerSongs,表示该方法会返回一个 SingerSongs 类型的对象,Spring MVC 会自动将其转换为 JSON 格式返回给客户端public SingerSongs chatEntity(@RequestParam("name") String name) {    // 使用 @RequestParam("name") 注解将 HTTP 请求参数 "name" 绑定到方法参数 String name 上    // 使用 chatClient 的 Fluent API 构建 Prompt 并调用 AI 模型    return this.chatClient.prompt()            // 1. 开始构建 Prompt (提示) 对象,prompt() 方法是 Fluent API 的起始点            .user("Generate a list of songs of the singer " + name + ". Respond in JSON format with keys 'singer' and 'songs'. ")            // 2. 设置用户消息 (User Message),作为 Prompt 的内容            //    - user() 方法指定消息的角色为用户 (User)            //    - 消息内容是动态生成的字符串,包含用户输入的歌手名字 (name)            //    - 指示 AI 模型生成指定歌手的歌曲列表,并明确要求以 JSON 格式返回            //    - JSON 格式要求包含 "singer" 和 "songs" 两个键            .call()            // 3. 调用 call() 方法,执行与 AI 模型的同步请求并等待响应            //    - call() 方法会将之前构建的 Prompt 发送给配置好的 AI 模型服务            //    - 它会返回一个 ChatResponse 对象,包含了 AI 模型的响应结果            .entity(SingerSongs.class);            // 4. 调用 entity(SingerSongs.class) 方法,将 AI 模型的响应结果映射为 SingerSongs 类型的对象            //    - entity() 方法假设 AI 模型返回的响应是 JSON 格式的字符串            //    - 它会自动将 JSON 字符串反序列化 (解析) 成 SingerSongs 类的实例            //    - SingerSongs.class 指定了目标实体类的类型,Spring AI 会根据这个类型进行映射    // 整个方法流程:    // 1. 接收 HTTP GET 请求,并从请求参数中获取歌手名字 (name)。    // 2. 构建一个 Prompt,包含指示 AI 模型生成歌手歌曲列表的指令,并要求 JSON 格式输出。    // 3. 使用 ChatClient 调用 AI 模型,发送 Prompt 并获取 ChatResponse。    // 4. 将 ChatResponse 中的 JSON 格式内容映射为 SingerSongs 对象。    // 5. 返回 SingerSongs 对象,Spring MVC 会自动将其转换为 JSON 格式返回给客户端。}

package com.miku.springaialibabalearn.entity;import java.util.List;public class SingerSongs {    private String singer;    // 歌手名字,对应 JSON 中的 "singer" 键    private List<String> songs;    // 歌曲列表,对应 JSON 中的 "songs" 键    // 必须要有默认的无参构造器,以便 Jackson (或其他 JSON 库) 可以进行反序列化    public SingerSongs() {    }    // Getter 和 Setter 方法 (建议添加,虽然在这个例子中可能不是必须的,但良好的 Java 实践)    public String getSinger() {        return singer;    }    public void setSinger(String singer) {        this.singer = singer;    }    public List<String> getSongs() {        return songs;    }    public void setSongs(List<String> songs) {        this.songs = songs;    }}

在浏览器使用http://localhost:10001/singer-songs?name=初音未来发起http请求,返回JSON格式的singersongs的键值对数据。


调用stream方法

@GetMapping( value = "/stream-chat")// 使用 @GetMapping 注解,将 HTTP GET 请求路径 "/stream-chat" 映射到 streamChat 方法// value = "/stream-chat" 指定了请求的 URL 路径public Flux<String> streamChat(@RequestParam("input") String input) {    // 定义名为 streamChat 的方法,处理 "/stream-chat" 的 GET 请求    // 方法的返回类型是 Flux<String>,表示一个包含多个 String 元素的异步数据流 (Reactive Stream)    // 使用 @RequestParam("input") 注解,将 HTTP 请求参数名为 "input" 的值绑定到方法的 input 参数上,类型为 String    return this.chatClient.prompt()            // 1. 使用 chatClient 的 Fluent API 开始构建 Prompt (提示) 对象            // prompt() 方法开始构建一个新的 Prompt,它是与 AI 模型交互的输入            .user(input)            // 2. 设置用户消息 (User Message) 到 Prompt 中            // user(input) 方法指定消息的角色为 "user",消息内容为方法的参数 input (用户输入)            .stream()            // 3. 调用 stream() 方法,执行与 AI 模型的流式交互            // stream() 方法会将构建好的 Prompt 发送给配置的 AI 模型服务,并启动流式响应            // 返回值是一个 Flux<ChatResponse>,表示 ChatResponse 对象的流            .content();            // 4. 调用 content() 方法,从 Flux<ChatResponse> 中提取内容并转换为 Flux<String>            // content() 方法将 Flux<ChatResponse> 转换为 Flux<String>,只保留每个 ChatResponse 中的文本内容 (getContent())            // 最终返回 Flux<String>,每个 String 元素代表模型流式输出的一部分文本    // 整个 streamChat 方法的流程:    // 1.接收用户通过 HTTP GET 请求传递的 "input" 参数作为用户输入    // 2.构建一个 Prompt,包含用户输入的消息    // 3.使用 ChatClient 发起流式聊天请求,将 Prompt 发送给 AI 模型    // 4.从模型返回的流式 ChatResponse 中提取文本内容,并作为 Flux<String> 返回    // 5.Spring WebFlux 会将返回的 Flux<String> 作为 Server-Sent Events (SSE) 流式响应返回给客户端}@GetMapping( value = "/stream-chat-response")// 使用 @GetMapping 注解,将 HTTP GET 请求路径 "/stream-chat-response" 映射到 streamChatResponse 方法// value = "/stream-chat-response" 指定了请求的 URL 路径public Flux<ChatResponse> streamChatResponse(@RequestParam("input") String input) {    // 定义名为 streamChatResponse 的方法,处理 "/stream-chat-response" 的 GET 请求    // 方法的返回类型是 Flux<ChatResponse>,表示一个包含多个 ChatResponse 对象的异步数据流    // 使用 @RequestParam("input") 注解,将 HTTP 请求参数名为 "input" 的值绑定到方法的 input 参数上,类型为 String    return this.chatClient.prompt()            // 1. 使用 chatClient 的 Fluent API 开始构建 Prompt (提示) 对象            // prompt() 方法开始构建一个新的 Prompt,它是与 AI 模型交互的输入            .user(input)            // 2. 设置用户消息 (User Message) 到 Prompt 中            // user(input) 方法指定消息的角色为 "user",消息内容为方法的参数 input (用户输入)            .stream()            // 3. 调用 stream() 方法,执行与 AI 模型的流式交互            // stream() 方法会将构建好的 Prompt 发送给配置的 AI 模型服务,并启动流式响应            // 返回值是一个 Flux<ChatResponse>,表示 ChatResponse 对象的流            .chatResponse();            // 4. 调用 chatResponse() 方法,直接返回 Flux<ChatResponse> 对象流            // chatResponse() 方法直接返回 stream() 方法返回的 Flux<ChatResponse>,不做任何转换            // 最终返回 Flux<ChatResponse>,每个 ChatResponse 对象包含更完整的模型响应信息 (包括文本内容和元数据等)    // 整个 streamChatResponse 方法的流程:    // 1.接收用户通过 HTTP GET 请求传递的 "input" 参数作为用户输入    // 2.构建一个 Prompt,包含用户输入的消息    // 3.使用 ChatClient 发起流式聊天请求,将 Prompt 发送给 AI 模型    // 4.直接将模型返回的流式 ChatResponse 对象作为 Flux<ChatResponse> 返回    // 5.Spring WebFlux 会将返回的 Flux<ChatResponse> 作为 Server-Sent Events (SSE) 流式响应返回给客户端    // 6.客户端可以接收到完整的 ChatResponse 对象,包含更详细的响应信息}

在浏览器使用http://localhost:10001/stream-chat?input=介绍初音未来发起http请求,得到字符串的流式响应。

在浏览器使用http://localhost:10001/stream-chat-response?input=介绍初音未来发起http请求,得到ChatResponse类型的流式响应。


Server-Sent Events (SSE)

在我们的 Spring AI 应用中,为了实现 AI 回复的流式效果(即内容逐步显示而非一次性返回),我们利用了 Server-Sent Events (SSE) 技术。这通过在 Controller 方法上添加特定的 @GetMapping 注解来实现。

让我们深入理解这个关键注解:

@GetMapping( value = "/stream-chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)

解读如下:

    @GetMappingvalue 属性

    produces = MediaType.TEXT_EVENT_STREAM_VALUE 属性

    这是实现流式响应的核心部分。

    什么是 Server-Sent Events (SSE)?

    SSE 是一种允许服务器向客户端单向推送更新的技术。

总结

@GetMapping(value = "/stream-chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE) 注解的整体含义是:

创建一个处理 /stream-chat 路径 GET 请求的端点,该端点将使用 Server-Sent Events (SSE) 技术,以 text/event-stream 格式向客户端持续推送数据流。

在我们的 Spring AI 聊天应用中,这意味着当客户端请求 /stream-chat 时,后端不会一次性返回完整的 AI 回复,而是将 AI 模型逐步生成的文本块作为 SSE 事件流式地发送给客户端,从而在前端实现打字机般的显示效果。

编写前端界面

用Trae辅助简单编写了一个初音未来网页,点击右上角“AI聊天”,进入对话界面。

发送消息,前端向后端的streamChat方法发起请求,可以看到成功实现了流式对话。


总结与展望

前端代码

后端代码

通过本次学习和实践,我们深入了解了 Spring AI Alibaba 中 ChatClient 的核心用法。我们掌握了:

ChatClient 作为 Spring AI 的高级抽象,有效地降低了在 Spring 应用中集成 LLM 的门槛。它不仅简化了基础的对话交互,还为集成 RAG(通过 QuestionAnswerAdvisor)、聊天记忆(通过 ChatMemoryAdvisor)等高级功能提供了便利的扩展点 (Advisors)。

后续可以探索的方向包括:

总而言之,ChatClient 是 Spring AI 生态中一个非常实用的工具,掌握它将为我们构建更智能、更强大的 Java 应用打下坚实的基础。

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Spring AI Alibaba ChatClient 大语言模型 AI交互 流式响应
相关文章