SpringAI中的ChatModel是啥

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()
相关推荐
颜酱6 分钟前
# 02 | 搭骨架:用 LangGraph 编排 12 步工作流(思路)
前端·人工智能·后端
颜酱7 分钟前
02 | 搭骨架:用 LangGraph 编排 12 步工作流
前端·人工智能·后端
嘉伟桑1 小时前
Python调用电价API返回JSON示例:分时电价、现货电价和字段解析
后端
武子康1 小时前
Shippy:确定性工具、会话级 Sandbox 与 Live-Data Eval(4 类收敛 + 7 步实现方案 + 6 类评测指标)
前端·人工智能·后端
我叫黑大帅2 小时前
我为什么单一消费者的场景下,要用 Redis List 当消息队列?
redis·后端·面试
AskHarries2 小时前
文件上传系统
后端
止语Lab3 小时前
好的 DX 不等于少写代码——三种语言的摩擦力设计课
后端
吃饱了得干活3 小时前
别再手动解析 LLM 输出了!LangChain 四种结构化输出方案对比
后端·python·langchain
程序员天天困3 小时前
Arthas trace 命令怎么用?一行定位最慢那行代码
jvm·后端
Huiturn3 小时前
GPT 5.6 连续编码 10 小时,纯 Python 啃下 Word 二进制格式——doc2docx 实现拆解
后端