当前位置: 首页 > news >正文

Spring AI 系列之十八 - ChatModel

之前做个几个大模型的应用,都是使用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》

http://www.dtcms.com/a/290996.html

相关文章:

  • 【实战】Dify从0到100进阶--文档解读(10)参数提取HTTP节点
  • MybatisPlus-15.扩展功能-逻辑删除
  • 国产电钢琴核心优缺点是什么?
  • 深度学习 ---神经网络以及数据准备
  • C++基础数据结构
  • Ubuntu 22 安装 ZooKeeper 3.9.3 记录
  • Cookie、Session、Local Storage和Session Storage区别
  • 低代码平台有什么特殊优势
  • 小架构step系列21:参数和返回值的匹配
  • 昇腾310P软件安装说明
  • java和ptyhon对比
  • 网络编程 示例
  • A316-HF-DAC-V1:专业USB HiFi音频解码器评估板技术解析
  • Linux 文件操作详解:结构、系统调用、权限与实践
  • C语言-字符串数组
  • DL00691-基于深度学习的轴承表面缺陷目标检测含源码python
  • 【STM32】485接口原理
  • Jmeter如何做接口测试?
  • soft_err错误
  • 【C语言进阶】结构体练习:通讯录
  • OCR 赋能发票管理系统:守护医疗票据合规,让管理更智能
  • Milvus:开源向量数据库的初识
  • 第17章 基于AB实验的增长实践——沉淀想法:实验记忆
  • 基于deepseek的LORA微调
  • react-window 大数据列表和表格数据渲染组件之虚拟滚动
  • Neo4j graph database
  • 剖析Sully.ai:革新医疗领域的AI助手功能启示
  • 20. TaskExecutor与ResourceManager心跳
  • HTML前端颜色渐变动画完整指南
  • 处理excel/wps表格中数值格式的警告的工具和脚本