SpringAI中的ChatModel是啥
- [1. ChatModel](#1. ChatModel)
- [2. Prompt](#2. Prompt)
-
- [2.1 Message](#2.1 Message)
- [2.2 ChatOptions](#2.2 ChatOptions)
- [3. ChatResponse](#3. ChatResponse)
在 Spring AI 的开发体系中,模型(Model) 是绝对的核心 ------ 因为我们用 Spring AI 的核心目标,就是对接和使用大模型能力。
Spring AI 兼容多种类型的大模型,并且按照功能做了清晰分类,比如常用的 Chat Model(对话模型)、Embedding Model(嵌入模型),还有 Image Model(图像模型)、Audio Model(音频模型)等。
1. ChatModel
- ChatModel 是 Spring AI 给对话模型做的统一对接接口。它把 OpenAI、Azure OpenAI、Hugging Face 等不同厂商的对话模型都抽象成一套用法,咱们开发者不用关心每个厂商的调用细节,用起来都一样。
- 不管你用的是 OpenAI 的 GPT-4、百炼对接的开源模型,还是本地部署的 Ollama,都能通过同一个 ChatModel 接口调用。
java
public interface ChatModel extends Model<Prompt, ChatResponse>, StreamingChatModel {
default String call(String message) {
Prompt prompt = new Prompt(new UserMessage(message));
Generation generation = call(prompt).getResult();
return (generation != null) ? generation.getOutput().getText() : "";
}
default String call(Message... messages) {
Prompt prompt = new Prompt(Arrays.asList(messages));
Generation generation = call(prompt).getResult();
return (generation != null) ? generation.getOutput().getText() : "";
}
@Override
ChatResponse call(Prompt prompt);
default ChatOptions getDefaultOptions() {
return ChatOptions.builder().build();
}
default Flux<ChatResponse> stream(Prompt prompt) {
throw new UnsupportedOperationException("streaming is not supported");
}
}
- 👆 ChatModel 接口其实继承了两个接口:一个是基础的 Model,另一个是 StreamingChatModel。StreamingChatModel 里有个 stream 方法,返回值是 Flux,这个接口就是专门用来调用大模型做流式输出的。
- ChatModel 中还定义了两个核心对象:Prompt 是输入,ChatResponse 是输出。它的工作流程很简单:接收 Prompt 作为输入,发送给后端大模型,模型生成内容后返回 ChatResponse,应用再将结果展示给用户。
- DashscopeChatModel(阿里云百炼)和 OllamaChatModel是ChatModel的两个具体实现
来一个简单的测试:
java
@RestController
@RequestMapping("/test1/chatModel")
public class A4ChatModelController {
@Resource
private DashScopeChatModel chatModel;
@MyQuickTestFlux(uri = "/test1/chatModel/chat/{message}", desc = "使用DashScopeChatModel的ChatModel")
@GetMapping("/test1/{message}")
public String test1(@PathVariable String message) {
ChatResponse response = chatModel.call(new Prompt(message, DashScopeChatOptions.builder().model("qwen-plus").build()));
return response.getResult().getOutput().getText();
}
/**
* 流式输出
*
* @param message 用户提示词
*/
@MyQuickTestFlux(uri = "/test1/chatModel/test2/chat/{message}", desc = "使用DashScopeChatModel的ChatModel")
@RequestMapping("/test2/chat/{message}")
public Flux<String> test2(HttpServletResponse response, @PathVariable String message) {
// 设置响应头
response.setContentType("text/event-stream");
// 设置响应字符编码为UTF-8
response.setCharacterEncoding("UTF-8");
Prompt prompt = new Prompt(message, DashScopeChatOptions.builder().maxToken(100).build());
Flux<ChatResponse> chatResponseFlux = chatModel.stream(prompt);
return chatResponseFlux.mapNotNull(resp -> resp.getResult().getOutput().getText());
}
}


- 👆 这段代码是 ChatModel 的简单使用示例:test1 方法返回 String,是普通阻塞式调用:传入提示词后,等大模型生成完整结果才返回,适合不需要实时输出的场景。
- test2 方法返回
Flux<String>,是流式输出:会逐段返回大模型的生成内容,更贴合对话场景的实时体验。 - 重点注意:test2 必须加 2 个关键配置 ------
① 方法入参要加 HttpServletResponse;
② 方法内设置两行响应头:
response.setContentType("text/event-stream"):告诉浏览器这是流式响应;
response.setCharacterEncoding("UTF-8"):避免页面展示中文乱码。
2. Prompt
- Prompt 就是 Spring AI 给大模型的统一输入载体,不管是 call 阻塞调用,还是 stream 流式调用,入参都得用它。
- 它主要包两部分:一是你要问模型的核心提示词(比如 "解释下 Spring AI"),二是可选的模型配置(比如指定用 qwen-plus 模型、限制生成长度),不用直接传字符串,统一用 Prompt 更规范。
java
public class Prompt implements ModelRequest<List<Message>> {
// 对话历史+本地对话内容
private final List<Message> messages;
// 调用 Chat Model 时的额外参数
@Nullable
private ChatOptions chatOptions;
}
- Prompt 里有两个核心参数:第一个是
List<Message> messages,就是对话的完整上下文 ------ 包含历史聊天记录 + 你这次的提问内容; - 第二个是 ChatOptions chatOptions(可选),就是调用大模型时的额外配置,比如指定用哪个模型、限制生成长度、调整随机性等。这两个参数分别管 "输入内容" 和 "调用规则",是 Prompt 的核心。
2.1 Message
- Message 就是对话内容的载体,它有多个实现类,对应不同的对话角色:
🖊 SYSTEM 是系统设定(比如 "你是 Java 讲师,回答要简洁");
🖊 USER 是用户的输入提问;
🖊 ASSISTANT 是大模型的回复内容;
🖊 ToolResponse 则是工具调用后的返回结果。 - 不同类型的 Message 组合起来,就构成了完整的对话上下文。

2.2 ChatOptions
- ChatOptions 是个可选字段,用于指定调用 Chat Model 时的额外参数
① 温度(temperature)控制回答的 "creativity / 随机性"。
数字越小:回答越稳定、准确、保守
数字越大:回答越脑洞大、多样、天马行空
② 最大生成 token(max token)
限制模型最多能输出多少字。数字设多少,模型就最多生成多长的内容,防止输出太长。
③ Top-k
控制模型选词时,只从概率最高的前 k 个词里选。k 越小,回答越保守;k 越大,选择越多、越随机。
3. ChatResponse
- 不管是用 call 普通调用,还是 stream 流式调用,返回的都是 ChatResponse,代表大模型给我们的响应。
- 区别只在于:
🖊 call 返回单个 ChatResponse
🖊 stream 返回Flux<ChatResponse> - 最后拿到内容,统一用这一行:
resp.getResult().getOutput().getText()