之前做个几个大模型的应用,都是使用Python语言,后来有一个项目使用了Java,并使用了Spring AI框架。随着Spring AI不断地完善,最近它发布了1.0正式版,意味着它已经能很好的作为企业级生产环境的使用。对于Java开发者来说真是一个福音,其功能已经能满足基于大模型开发企业级应用。借着这次机会,给大家分享一下Spring AI框架。
注意:由于框架不同版本改造会有些使用的不同,因此本次系列中使用基本框架是 Spring AI-1.0.0,JDK版本使用的是19。
代码参考: https://github.com/forever1986/springai-study
目录
- 1 ChatModel 源码解析
- 2 示例演示
- 2.1 简单示例
- 2.2 提示词示例
- 2.3 手动配置示例
上一章解析了ChatClient的创建和底层原理,也知道其最终调用了ChatModel。那这一章,来了解Spring AI的ChatModel。
1 ChatModel 源码解析
聊天大模型通常的工作方式是向人工智能模型发送提示或部分对话,然后该模型根据其训练数据和对自然语言模式的理解生成对话的完成部分或延续内容。完成后的响应随后返回给应用程序,应用程序可以将其呈现给用户或用于进一步处理。
而Spring AI 秉承着这个工作方式,ChatModel API 被设计成一个简单且便携的接口,用于与各种 AI 模型进行交互,使开发人员能够在不同模型之间切换时只需进行最少的代码更改。这种设计与 Spring 的模块化和可互换性理念相一致。
下面来看看ChatModel这个接口的源码,代码如下:
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() : "";}// 大模型供应商需要实现真正call方法@OverrideChatResponse call(Prompt prompt);default ChatOptions getDefaultOptions() {return ChatOptions.builder().build();}// 大模型供应商需要实现真正stream方法,继承至StreamingChatModel。流式实现流式方式default Flux<ChatResponse> stream(Prompt prompt) {throw new UnsupportedOperationException("streaming is not supported");}}
说明:从上面代码看,如果一个大模型供应商要集成到Spring AI,就需要实现ChatModel 接口,实现call和stream方法
在Spring AI中已经实现了很多聊天大模型,如下图:
说明:上面对于ChatModel 的源码解析以及Spring AI聊天大模型目前集成的厂商做了一个预览,下面通过使用ChatModel 方式来调用聊天大模型,而非ChatClient。
2 示例演示
以下代码参考lesson15子模块
2.1 简单示例
代码参考lesson15子模块的simple子模块
示例说明:使用ChatModel方式访问聊天大模型
1)在lesson15子模块下,新建simple子模块,其pom引入如下:
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-zhipuai</artifactId></dependency>
</dependencies>
2)配置application.properties文件
# 聊天模型
spring.ai.zhipuai.api-key=你的智谱模型的API KEY
spring.ai.zhipuai.chat.options.model=GLM-4-Flash-250414
spring.ai.zhipuai.chat.options.temperature=0.7
3)新建演示类ChatModelController :
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class ChatModelController {private final ChatModel chatModel;@Autowiredpublic ChatModelController(ChatModel chatModel) {this.chatModel = chatModel;}@GetMapping("/chatmodel/generate")public String generate(@RequestParam(value = "message", defaultValue = "请跟我说个笑话!") String message) {return this.chatModel.call(message);}
}
4)新建启动类Lesson15SimpleApplication :
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class Lesson15SimpleApplication {public static void main(String[] args) {SpringApplication.run(Lesson15SimpleApplication.class, args);}}
5)演示效果:
http://localhost:8080/chatmodel/generate
2.2 提示词示例
代码参考lesson15子模块的simple子模块
示例说明:使用ChatModel方式访问聊天大模型,并为大模型设定角色
1)沿用lesson15子模块的的simple子模块,新建演示类:
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
public class ChatModelRoleController {private final ChatModel chatModel;@Autowiredpublic ChatModelRoleController(ChatModel chatModel) {this.chatModel = chatModel;}@GetMapping(value = "/chatmodel/systemrole", produces = "text/html;charset=UTF-8") //设定返回的字符,不然会出现乱码public String systemrole(@RequestParam(value = "message", defaultValue = "空指针一般有什么问题造成的?") String message) {Message systemMessage = new SystemMessage("你是一个精通Java的工程师,专门解决Java遇到的问题。");Message userMessage = new UserMessage(message);Prompt prompt = new Prompt(List.of(systemMessage,userMessage));return this.chatModel.call(prompt).getResult().getOutput().getText();}
}
2)演示效果
http://localhost:8080/chatmodel/systemrole
说明:从上面可以看到如果不使用ChatClient一样能达到效果,只不过在一些场景下需要自己实现功能,比如聊天记忆、RAG、MCP等。这就说明Spring AI 为了方便用户使用大模型,遵循的简单和便利的原则。
2.3 手动配置示例
代码参考lesson15子模块的manual-demo子模块
示例说明:如果你不是SpringBoot项目或者Web项目,Spring AI一样开发了手动配置ChatModel的包,下面就演示手动配置ChatModel
1)新建lesson16子模块,其pom引入如下:
<dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-zhipuai</artifactId></dependency>
</dependencies>
2)创建演示类ManualChatModelTest:
import org.springframework.ai.zhipuai.ZhiPuAiChatModel;
import org.springframework.ai.zhipuai.ZhiPuAiChatOptions;
import org.springframework.ai.zhipuai.api.ZhiPuAiApi;public class ManualChatModelTest {public static void main(String[] args) {// 设置API KEYvar zhiPuAiApi = new ZhiPuAiApi("你的智谱模型的API KEY");var chatModel = new ZhiPuAiChatModel(zhiPuAiApi, ZhiPuAiChatOptions.builder()// 设置模型.model("GLM-4-Flash-250414")// 设置温度.temperature(0.7).build());System.out.println(chatModel.call("请跟我说个笑话!"));}
}
3)演示效果
说明:可以看到每个厂商的大模型都提供一个通过手动方式创建的模式,这就是Spring AI框架为了用户在不同场景下使用考虑的各方各面。
结语:本章通过解析ChatModel源码,并通过几个示例演示了不通过ChatClient的方式使用ChatModel。虽然一样可以实现,但是如果遇到如RAG、MCP等复杂场景,其使用便捷度就没有ChatClient那么高。ChatModel聊天大模型是比较规范和成熟的模型,因此在Spring AI中有很多不同厂商的实现,下两章将针对聊天大模型比较常用的2种部署模式进行讲解。
Spring AI系列上一章:《Spring AI 系列之十七 - ChatClient源码解析》
Spring AI系列下一章:《Spring AI 系列之十九 - Ollama集成Deepseek》