【Spring AI】Spring AI Alibaba的简单使用

提示:文章最后有详细的参考文档。

前提条件

  • SpringBoot版本为3.x以上
  • JDK为17以上
  • 申请api-key,地址:百炼平台

引入依赖

说明:我的springboot版本为3.2.4,spring-ai-alibaba-starter版本为1.0.0-M2.1(对应spring-ai版本为1.0.0-M2),jdk版本为17。

1. pom.xml中引入

<dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter</artifactId>
</dependency>

spring-ai-alibaba 基于 spring-ai 开发,由于 spring-ai 相关依赖包还没有发布到中央仓库,如出现 spring-ai-core 等相关依赖解析问题,请在您项目的 pom.xml 依赖中加入如下仓库配置。

<repositories><repository><id>maven2</id><name>maven2</name><url>https://repo1.maven.org/maven2/</url><snapshots><enabled>false</enabled></snapshots></repository><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></repository>
</repositories>

并且在maven的setting.xml中做出如下更改:

<mirror>  <id>alimaven</id>  <name>aliyun maven</name>  <url>https://maven.aliyun.com/repository/public</url> <!-- 表示除了spring-milestones、maven2其它都走阿里云镜像  --> <mirrorOf>*,!spring-milestones,!maven2</mirrorOf>  
</mirror>

2. application.yml中引入

spring:ai:dashscope:api-key: 申请的api-keychat:client:enabled: true

3. 代码中引入

    @Resourceprivate ChatModel chatModel;

开发示例

1. 简单的对话

@GetMapping("/simple")
public String simpleChat(@RequestBody JSONObject param) {// 接收并校验参数String inputInfo = CommonUtil.getAndCheck(param, "inputInfo", "请输入内容!");// 构建chatClientChatClient.Builder builder = ChatClient.builder(chatModel);ChatClient chatClient = builder.defaultSystem("你是一个精通Java、Python的程序大佬。").build();return chatClient.prompt().user(inputInfo).call().content();
}

2. 流式对话

使用Server Sent Event(SSE)事件返回,对应前端需要处理SSE事件的数据。

@GetMapping("/stream")
public Flux<ServerSentEvent<String>> streamChat(@RequestBody JSONObject param) {// 接收并校验参数String inputInfo = CommonUtil.getAndCheck(param, "inputInfo", "请输入内容!");return chatModel.stream(new Prompt(inputInfo)).map(response -> ServerSentEvent.<String>builder().data(response.getResult().getOutput().getContent()).build()).doOnComplete(() -> log.info("响应完成!")).doOnError(e -> log.error("响应异常:", e));
}

3. 带记忆对话(原生API存储)

使用原生的:MessageChatMemoryAdvisor

private final ChatClient chatClient;
public AIChatController(ChatClient.Builder builder) {this.chatClient = builder.defaultSystem("你是一个精通Java、Python的程序大佬。").defaultAdvisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory())).build();
}@GetMapping("/memoryStreamWithApi")
public Flux<ServerSentEvent<String>> memoryStreamWithApi(@RequestBody JSONObject param) {// 接收并校验参数// 对话记忆ID,我是通过前端传参获取,你可以获取一个UUIDString accessKey = CommonUtil.getAndCheck(param, "accessKey", "您没有改功能访问权限!");String inputInfo = CommonUtil.getAndCheck(param, "inputInfo", "请输入内容!");// 请求数据return chatClient.prompt().user(inputInfo).advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, accessKey).param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 5))    // 从上下文中检索聊天内存响应大小,具体参数定义可参考文章最后的Spring AI API文档.stream().chatResponse().map(response -> {return ServerSentEvent.<String>builder().data(response.getResult().getOutput().getContent()).build();}).doOnComplete(() -> {log.info("响应完成!");}).doOnError((e) -> {log.warn("响应异常:", e);});
}

4. 带记忆对话(Redis存储)

使用redis存储:

@GetMapping("/memoryStreamWithRedis")
public Flux<ServerSentEvent<String>> memoryStreamWithRedis(@RequestBody JSONObject param) {// 接收并校验参数// 对话记忆ID,我是通过前端传参获取,你可以获取一个UUIDString accessKey = CommonUtil.getAndCheck(param, "accessKey", "您没有改功能访问权限!");String inputInfo = CommonUtil.getAndCheck(param, "inputInfo", "请输入内容!");List<Message> messageList = new ArrayList<>();// 拼接redis keyString redisKey = CommonConst.MY_ACCESS_KEY_PREFIX + accessKey;// 判断是否存在聊天记忆,有的话将其带入本次对话中if (redisService.hasKey(redisKey)) {// 从redis中获取聊天记忆数据List<String> strList = redisService.getCacheList(redisKey);List<Message> memoryList = new ArrayList<>();if (!CollectionUtils.isEmpty(strList)) {strList.forEach(s -> memoryList.add(new UserMessage(s)));// 反转聊天记忆数据,我存入List数据时采用头插法,所以这里需要反转list,以保证聊天内容的先后顺序Collections.reverse(memoryList);messageList.addAll(memoryList);}}messageList.add(new UserMessage(inputInfo));StringBuilder resultStr = new StringBuilder();return chatModel.stream(new Prompt(messageList)).map(response -> {resultStr.append(response.getResult().getOutput().getContent());return ServerSentEvent.<String>builder().data(response.getResult().getOutput().getContent()).build();}).doOnComplete(() -> {// 将LLM返回的文本存入redis,存储的数据类型是List,enqueue()方法的定义看下文redisService.enqueue(redisKey, resultStr.toString(), MAX_LENGTH);log.info("响应完成!");}).doOnError(e -> log.warn("响应异常:", e));
}

RedisService中部分代码:

/*** 添加固定长度的队列,左添加** @param key       key* @param value     value* @param maxLength 最大存储的聊天记录长度*/
public void enqueue(String key, String value, int maxLength) {// 使用Redis的LPUSH命令添加元素,然后确保长度不超过最大值redisTemplate.opsForList().leftPush(key, value);// 保持队列长度不超过指定长度,LTRIM会自动删除超出长度的旧元素if (redisTemplate.opsForList().size(key) > maxLength) {redisTemplate.opsForList().trim(key, 0, maxLength - 1);}
}/*** 获得缓存的list对象** @param key 缓存的键值* @return 缓存键值对应的数据*/
public <T> List<T> getCacheList(final String key) {return redisTemplate.opsForList().range(key, 0, -1);
}/*** 判断 key 是否存在** @param key 键* @return true 存在 false不存在*/
public Boolean hasKey(String key) {return redisTemplate.hasKey(key);
}

参考文档

 官方参考文档:Spring AI Alibaba 官方 、Spring AI 官方、Spring AI API 文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/64142.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《Java源力物语》-3.空值猎手

~犬&#x1f4f0;余~ “我欲贱而贵&#xff0c;愚而智&#xff0c;贫而富&#xff0c;可乎&#xff1f; 曰&#xff1a;其唯学乎” \quad 夜色渐深&#xff0c;在一处偏僻小径上&#xff0c;月光透过浓密的源力云层&#xff0c;在地面上投下斑驳的光影。String正独自练习着刚从…

科技云报到:人工智能时代“三大件”:生成式AI、数据、云服务

科技云报到原创。 就像自行车、手表和缝纫机是工业时代的“三大件”。生成式AI、数据、云服务正在成为智能时代的“新三大件”。加之全球人工智能新基建加速建设&#xff0c;成为了人类社会数字化迁徙的助推剂&#xff0c;让新三大件之间的耦合越来越紧密。从物理世界到数字世…

hiprint结合vue2项目实现静默打印详细使用步骤

代码地址是&#xff1a;vue-plugin-hiprint: hiprint for Vue2/Vue3 ⚡打印、打印设计、可视化设计器、报表设计、元素编辑、可视化打印编辑 本地安装包地址&#xff1a;electron-hiprint 发行版 - Gitee.com 1、先安装hipint安装包在本地 2、项目运行npm&#xff08;socket.…

CUDA各种内存和使用方法

文章目录 1、全局内存2、局部内存3、共享内存3.1 静态共享内存3.2 动态共享内存 4、纹理内存5、常量内存6、寄存器内存7、用CUDA运行时API函数查询设备CUDA 错误检测 1、全局内存 特点&#xff1a;容量最大&#xff0c;访问延时最大&#xff0c;所有线程都可以访问。 线性内存…

Chapter 03 复合数据类型-1

1.列表 Python内置的一种有序、可变的序列数据类型&#xff1b; 列表的定义&#xff1a; [ ]括起来的逗号分隔的多个元素组成的序列 列表对象的创建&#xff1a; &#xff08;1&#xff09;直接赋值 >>> list1 []#创建一个空列表赋值给list1 >>> list…

【后端】LNMP环境搭建

长期更新各种好文&#xff0c;建议关注收藏&#xff01; 本文近期更新完毕。 LNMPlinuxnginxmysqlphp 需要的资源 linux服务器 web服务软件nginx 对应的语言编译器代码文件 数据库mysql安装 tar.gz包或者命令行安装 进入root&#xff1a; sodu 或su mkdir path/{server,soft}…

基于PyQt5的UI界面开发——多界面切换

介绍 最初&#xff0c;因为课设的缘故&#xff0c;我只是想做一个通过按键进行切面切换而已&#xff0c;但是我看网上资料里面仅是语焉不详&#xff0c;让我困惑的很&#xff0c;但后面我通过摸索才发现这件事实在是太简单了&#xff0c;因此我想要记录下来。 本博客将介绍如…

操作002:HelloWorld

文章目录 操作002&#xff1a;HelloWorld一、目标二、具体操作1、创建Java工程①消息发送端&#xff08;生产者&#xff09;②消息接收端&#xff08;消费者&#xff09;③添加依赖 2、发送消息①Java代码②查看效果 3、接收消息①Java代码②控制台打印③查看后台管理界面 操作…

机器视觉检测相机基础知识 | 颜色 | 光源 | 镜头 | 分辨率 / 精度 / 公差

注&#xff1a;本文为 “keyence 视觉沙龙中机器视觉检测基础知识” 文章合辑。 机器视觉检测基础知识&#xff08;一&#xff09;颜色篇 视觉检测硬件构成的基本部分包括&#xff1a;处理器、相机、镜头、光源。 其中&#xff0c;和光源相关的最重要的两个参数就是光源颜色和…

【体验官招募】SoFlu - JavaAI 开发助手:开启智能开发新时代

你是否有过这样的经历&#xff1f;在深夜的办公室里&#xff0c;面对紧急的 Java 项目&#xff0c;看着厚厚的需求文档&#xff0c;你是否感到无从下手&#xff1f; 当你尝试理解客户那些复杂又模糊的需求时&#xff0c;是否会因为要和产品经理反复沟通确认每一个细节而感到厌…

自学记录HarmonyOS Next DRM API 13:构建安全的数字内容保护系统

在完成了HarmonyOS Camera API的开发之后&#xff0c;我开始关注更复杂的系统级功能。在浏览HarmonyOS Next文档时&#xff0c;我发现了一个非常有趣的领域&#xff1a;数字版权管理&#xff08;DRM&#xff09;。最新的DRM API 13提供了强大的工具&#xff0c;用于保护数字内容…

【HENU】河南大学计院2024 操作系统 简答题复习

和光同尘_我的个人主页 一直游到海水变蓝。 单项选择 15x2 30 判断 10x1 10 简答 3x10 30 综合 3x10 30 简答题 简述操作系统的四个基本特征。 并发性 共享性 虚拟性 异步性 并发性是最重要特性&#xff0c;其它三种特性以此为前提。 并发 并发(Concurrence)&#…

GEE错误——PCA系数变换的时候出现的错误

目录 错误提示1 错误提示2 原始的教程链接&#xff1a; 错误代码 修正后的代码 结果 错误提示1 这个是因为原始GEE教程中给的让我们填入需要进行计算的波段名称&#xff0c;而且是以list的形式传入。 错误提示2 这里我们虽然传入了正确的波段名称&#xff0c;但是发现要…

C#代码实现把中文录音文件(.mp3 .wav)转为文本文字内容

我们有一个中文录音文件.mp3格式或者是.wav格式&#xff0c;如果我们想要提取录音文件中的文字内容&#xff0c;我们可以采用以下方法&#xff0c;不需要使用Azure Speech API 密钥注册通过离线的方式实现。 1.首先我们先在NuGet中下载两个包 NAudio 2.2.1、Whisper.net 1.7.3…

计算机操作系统与安全复习笔记

1 绪论 操作系统目标: 方便性; 有效性; 可扩充性; 开放性. 作用: 用户与计算机硬件系统之间的接口; 计算机资源的管理者; 实现了对计算机资源的抽象; 计算机工作流程的组织者. 多道程序设计: 内存中同时存放若干个作业, 使其共享系统资源且同时运行; 单处理机环境下宏观上并行…

qt5.12.11+msvc编译器编译qoci驱动

1.之前编译过minGW编译器编译qoci驱动,很顺利就完成了,文章地址:minGW编译qoci驱动详解,今天按照之前的步骤使用msvc编译器进行编译,直接就报错了: 查了些资料,发现两个编译器在编译时,pro文件中引用的库不一样,下面是msvc编译器引用的库,其中编译引用的库我这里安装…

Java爬虫实战:深度解析VIP商品详情获取技术

在数字化时代&#xff0c;数据的价值不言而喻。对于电商平台而言&#xff0c;掌握VIP商品的详细信息是提升服务质量、优化用户体验的关键。然而&#xff0c;这些信息往往被复杂的网页结构和反爬虫策略所保护。本文将带你深入了解如何使用Java编写爬虫&#xff0c;以安全、高效地…

校史馆云展厅适合远程教学吗?

随着信息技术的飞速发展&#xff0c;远程教学已经成为教育领域的一个重要趋势。 校史馆作为学校文化传承的重要场所&#xff0c;承载着丰富的历史信息和教育资源。 那么&#xff0c;将校史馆搬到云端&#xff0c;构建云展厅&#xff0c;是否适合远程教学呢&#xff1f; 下面…

一些elasticsearch重要概念与配置参数

ES 是在 lucene 的基础上进行研发的&#xff0c;隐藏了 lucene 的复杂性&#xff0c;提供简单易用的 RESTful Api接口。ES 的分片相当于 lucene 的索引。 Node 节点的几种部署实例 实例一: 只用于数据存储和数据查询&#xff0c;降低其资源消耗率 node.master: false node.da…

Go Energy 跨平台框架 v2.5.1 发布

Energy 框架 是Go语言基于CEF 和 LCL 开发的跨平台 GUI 框架, 具体丰富的系统原生 UI 控件集, 丰富的 CEF 功能 API&#xff0c;简化且不失功能的 CEF 功能 API 使用。 特性&#xff1f; 特性描述跨平台支持 Windows, macOS, Linux简单Go语言的简单特性&#xff0c;使用简单…