Java SpringBoot调用大模型AI构建AI应用
本文是一个用springboot 结合spring mvc 和spring ai alibaba 调用国产大模型通义千问的具体例子,按照这个做能够快速的搞定Java应用的调用。
然后就可以把这类应用泛化到所有的涉及到非结构化数据结构化的场景中。
Spring AI:简化Java中大模型调用的框架
当前,在Java springboot 中调用大模型时,缺乏优秀的AI应用框架是一个常见问题。
作为老牌的Java应用框架提供商,Spring 在springboot之外提出了解决方案—Spring AI,它借鉴了langchain的核心理念,并结合了Java面向对象编程的特点。
Spring AI最核心的优势在于提供了统一接口,使得开发者能够编写一次代码后仅通过更改配置即可轻松切换不同的AI实现。
此外,得益于专门团队的支持与维护,Spring AI保证了稳定性和持续更新。以本次样例中的Spring AI Alibaba接入阿里云通义大模型为例,用户在完成初步集成后,同样可以方便地更换为自己所需的其他大模型实现。
这种设计极大简化了开发流程,提高了效率,让Java开发者能更专注于业务逻辑本身而非复杂的AI集成工作。
Spring AI Alibaba功能介绍及应用示例
Spring AI Alibaba是Spring AI的一个实现,它基于Spring AI的API完成了阿里云百炼系列云产品的大模型接入。
与Spring Cloud Alibaba一样,Spring AI Alibaba整合了阿里巴巴的最佳实践,是国内最好的Spring AI实现之一。
Spring AI Alibaba提供了一系列强大的功能和能力,包括但不限于模型调用、Prompt模板、RAG(检索增强生成)、文生图以及图像识别等。
通过使用Spring AI Alibaba,开发者可以轻松地开发基于阿里云通义提供的聊天、图片或语音生成AI应用。
框架还提供了诸如OutputParser、Prompt Template、Stuff等实用工具,帮助简化开发流程。本文将以Prompt模板和模型调用两个能力为例,展示如何接入Spring AI Alibaba,以便为项目增添更多AI功能。
通义千问Qwen在MMLU等测试中超越Llama 3 70B,登顶Hugging Face开源模型榜
通义千问Qwen在MMLU、TheoremQA、GPQA等基准测评中表现出色,超越了Llama 3 70B ,在85+分数,与gpt和claude等同属 第一梯队 ,并在Hugging Face开源大模型排行榜Open LLM Leaderboard上荣登榜首。
MMLU 和 GPQA都是 目前客观评分中最公认的两个评测标准,客观评分来说这俩是最好的。
另外,在真人参与评测的arena里面,它不仅在思南平台 上仅次于国际知名的GPT和Claude系列,还在 Hugging Face的视觉模型竞技场 中稳居中国首位。
基于SpringBoot集成Spring AI Alibaba构建对话模型
为了基于SpringBoot集成Spring AI Alibaba完成一个简单的对话模型,并构建一个支持prompt的流返回接口的项目,我们需要按照以下步骤进行操作。首先,确保您的环境满足前置条件,然后通过阿里云申请必要的API Key,接着在项目中添加相应的依赖和配置,最后实现Controller层逻辑以提供所需功能。
前置要求
- 确保您的JDK版本不低于17。
- 使用Spring Boot 3.3.x或以上版本。
- 已经从阿里云申请到了通义千问(Qwen)的API Key。
步骤一:获取并配置API Key
- 登录阿里云百炼页面,开通“百炼大模型推理”服务。
- 创建新的API Key并记录下来。
- 将API Key作为环境变量导出:
export AI_DASHSCOPE_API_KEY=这里替换为你的实际API Key
- 在
application.properties
文件中设置API Key:
spring.ai.dashscope.api-key=${AI_DASHSCOPE_API_KEY}
步骤二:添加Spring仓库及项目依赖
由于Spring AI Alibaba目前尚未发布到Maven中央仓库,您需要手动添加Spring的仓库配置来获取相关依赖。请在pom.xml
文件中的<repositories>
标签下加入以下内容:
<repositories><repository><id>sonatype-snapshots</id><url>https://oss.sonatype.org/content/repositories/snapshots</url><snapshots><enabled>true</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><repository><id>spring-snapshots</id><name>Spring Snapshots</name><url>https://repo.spring.io/snapshot</url><releases><enabled>false</enabled></releases></repository></repositories>
接着,在<dependencies>
部分增加对spring-ai-alibaba-starter
的引用:
<dependencies><!-- 其他已存在的依赖项 --><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter</artifactId><version>1.0.0-M2</version></dependency><!-- Spring Boot Starter Web 用于HTTP请求处理 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot Starter Test 测试库 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>
步骤三:创建Chat Controller
在您的Spring Boot应用中,创建一个新的Controller类,该类将负责处理来自客户端的GET请求,利用ChatClient
实例发送prompt给AI模型,并返回一个Flux<String>
类型的响应。这允许数据以流的形式异步地发送回客户端。
下面是一个示例代码:
@RestController
@RequestMapping("/ai")
@CrossOrigin(origins = "*") // 启用CORS跨域支持
public class ChatController {private final ChatClient chatClient;public ChatController(ChatClient.Builder builder) {this.chatClient = builder.build();}@GetMapping("/steamChat")public Flux<String> steamChat(@RequestParam String input) {return this.chatClient.prompt().user(input).stream().content();}
}
解释
@RestController
注解表明这是一个RESTful风格的控制器。
@RequestMapping("/ai")
定义了所有映射到此类的方法都将使用/ai
作为其URL路径前缀。
@CrossOrigin(origins = "*")
启用跨源资源共享(CORS),允许任何源访问此端点。
ChatController
构造函数接收一个ChatClient.Builder
实例,用来初始化ChatClient
。
@GetMapping("/steamChat")
指定了一个GET请求映射至/steamChat
路径,并接受名为input
的查询参数。
- 方法
steamChat
利用chatClient
向AI发送用户提供的文本(即input
),并通过stream()
方法以Flux<String>
形式输出AI生成的内容流。
这样,我们就成功搭建了一个基于Spring Boot的应用程序,它能够与阿里云通义千问大模型交互,并通过HTTP GET请求提供一个支持prompt能力的聊天接口。当用户访问http://localhost:8080/ai/steamChat?input=…
时,他们将收到由AI模型生成的回答流。
创建React前端应用以支持流式数据输出
构建前端
要基于React构建一个支持流式数据输出的简单项目,你可以按照以下步骤进行。此项目将能够从前端向后端发送消息,并实时显示从后端接收的流式响应。这里假设你的后端已经准备好了一个URL地址http://localhost:8080/ai/steamChat?input=...
用于处理请求并返回flux<String>
格式的数据。
创建新的React应用
首先,你需要创建一个新的React应用并通过npm安装必要的依赖包。打开终端,运行以下命令:
npx create-react-app frontend
cd frontend
npm install
这将为你设置好一个基础的React项目结构。
修改基本文件配置
接下来,我们只需要对默认生成的一些文件做少量修改或添加自定义组件来实现我们的功能需求。
public/index.html
确保该文件内容如下,它定义了HTML文档的基本结构:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Stream Chat App</title></head><body><div id="root"></div></body></html>
src/index.js
保持默认即可,这是React应用的入口点:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';ReactDOM.render(<React.StrictMode><App /></React.StrictMode>,document.getElementById('root')
);
src/App.js
在这个文件中,我们将导入并渲染ChatComponent
组件,它是实际负责与用户交互的部分:
import React from 'react';
import ChatComponent from './components/ChatComponent';function App() {return (<div className="App"><ChatComponent /></div>);
}export default App;
src/components/ChatComponent.js
这是最关键的部分,在这里实现了输入框、发送按钮以及用来展示来自服务器的消息流的功能。请注意替换其中的URL以匹配你实际使用的后端服务地址:
import React, { useState } from 'react';function ChatComponent() {const [input, setInput] = useState('');const [messages, setMessages] = useState('');const handleInputChange = (event) => {setInput(event.target.value);};const handleSendMessage = async () => {try {const response = await fetch(`http://localhost:8080/ai/steamChat?input=${input}`);const reader = response.body.getReader();const decoder = new TextDecoder('utf-8');let done = false;while (!done) {const { value, done: readerDone } = await reader.read();done = readerDone;const chunk = decoder.decode(value, { stream: true });setMessages((prevMessages) => prevMessages + chunk);}// 在每次请求完成后添加换行符setMessages((prevMessages) => prevMessages + '\n\n=============================\n\n');} catch (error) {console.error('Failed to fetch', error);}};const handleClearMessages = () => {setMessages('');};return (<div><inputtype="text"value={input}onChange={handleInputChange}placeholder="Enter your message"/><button onClick={handleSendMessage}>Send</button><button onClick={handleClearMessages}>Clear</button><div><h3>Messages:</h3><pre>{messages}</pre></div></div>);
}export default ChatComponent;
以上代码片段提供了一个完整的聊天界面示例,用户可以输入文本然后点击“Send”按钮发送给服务器。收到的流式响应会被逐段追加到页面上显示出来。
启动应用程序
完成所有这些设置之后,现在可以启动你的React应用了。在项目根目录下执行:
npm start
这会开启开发服务器,默认情况下可以在浏览器访问http://localhost:3000
查看效果。确保你的后端服务也已正确配置并且处于运行状态,这样前端就可以成功与其通信了。
通过上述步骤,你就建立了一个简单的基于React的支持流式数据传输的应用程序。
相关文章:

Java SpringBoot调用大模型AI构建AI应用
本文是一个用springboot 结合spring mvc 和spring ai alibaba 调用国产大模型通义千问的具体例子,按照这个做能够快速的搞定Java应用的调用。 然后就可以把这类应用泛化到所有的涉及到非结构化数据结构化的场景中。 Spring AI:简化Java中大模型调用的框…...

MySQL【二】
查询列 SELECT [ALL | DISTINCT ] * | 列名1[,……列名n] FROM 表名; 查询所有选课学生的学号,结果去除重复值 select distinct sno from sc; 选择行 查询满足条件的数据集 SELECT 字段列表 FROM 表名 WHERE 查询条件 查询不属于数学系或外国语系的学生全部信息 …...

SQL 常用语句
目录 我的测试环境 学习文档 进入数据库 基础通关测验 语句-- 查 展示数据库; 进入某个数据库; 展示表: 展示某个表 desc 查询整个表: 查询特定列: 范围查询 等于特定值 不等于 介于 特定字符查询 Li…...

前端埋点系统之如何用heatmap.js画网页热力图
Hello,大家好。在当今数字化时代,理解用户行为成为了企业成功的关键之一。随着互联网的发展,用户与网站、应用和产品的互动变得愈发复杂而多样化。在这样的背景下,埋点系统成为了洞察用户行为的重要工具之一。而其中的热力图分析&…...
CentOS 7系统下Redis Cluster集群一键部署脚本发布
引言 在大数据和云计算时代,Redis作为一款高性能的键值存储数据库,广泛应用于各种场景。然而,手动搭建Redis Cluster集群过程繁琐且容易出错。为了简化这一过程,本文提供了一个在CentOS 7系统下Redis Cluster集群的一键部署脚本,帮助开发者快速搭建Redis Cluster集群。 …...

自编以e为底的对数函数ln,性能接近标准库函数
算法描述: (1). 先做自变量x的范围检查,不能出现负数和0. 自己使用时,如果能通过其它途径保证自变量为正,那么可以省略这两个判断,提高速度。 (2). 根据IEEE 754浮点数的格式,,则 ln(x)kln(2)ln…...
Java中的日期时间
JDK8之前常用的日期时间类 System.currentTimeMillis():获取当前毫秒数(long类型) java.util.Date:通用Date类 import java.util.Date;Date date new Date(); // 空参构造器 System.out.println(date.getTime()); // 获取当前时…...
位置编码的表示
位置编码的表示位置编码的表示位置编码的表示位置编码的表示位置编码的表示...

0,国产FPGA(紫光同创)-新建PDS工程
国产FPGA正在蓬勃发展,紫光同创FPGA是大家竞赛时经常遇到的一款国产FPGA,本专栏从IP核开始一直到后续图像处理等。 开发板:盘古50K标准板 1,新建PDS工程 点击File(1),然后是New Projects&#…...

c++联合
结构体与联合体的区别 结构体(struct)中所有变量是“共存”的——优点是“有容乃大”,全面;缺点是struct内存空间的分配是粗放的,不管用不用,全分配。 而联合体(union)中是各变量是“互斥”的——缺点就是不够“包容”ÿ…...

Edit Data. Create Cell Editors. Validate User Input 编辑数据。创建 Cell Editors。验证用户输入
Goto Data Grid 数据网格 Edit Data. Create Cell Editors. Validate User Input 编辑数据。创建 Cell Editors。验证用户输入 Get and Modify Cell Values in Code 在代码中获取和修改单元格值 仅当 Grid 及其列已完全初始化时,才使用以下方法。如果需要在表单仍…...

Java 文件操作与IO流
文件 文件有两个概念,在广义来看就是操作系统上对硬件和软件资源抽象为文件。 在侠义上来看,就是我们保存在硬盘上的文件 在这里我们讨论的是狭义的文件,在外面的硬盘上的文件细分又可以分为二进制文件和文本文件,文本文件可以通…...

探索开源MiniMind项目:让大语言模型不再神秘(1)
简介: 声明:本人非此项目作者,仅仅是探索项目,分享项目。如有不妥,请联系我删除! 原项目地址:GitHub - jingyaogong/minimind: 「大模型」3小时完全从0训练26M的小参数GPT,个人显卡即…...
Android 大疆面经
Android 大疆面经 文章目录 Android 大疆面经一面 一面 自我介绍问项目聊了10分钟View的绘制流程MVC,MVP,MVVM的区别view和viewmodel的通信,除了databing还有其他的方式面向对象和面向过程的区别工厂模式和策略模式,哪些框架使用…...

【2024-10-31-2024-11-03】LeetCode刷题——python语法基础题
📝前言说明: ●本专栏主要记录本人的基础算法学习以及LeetCode刷题记录,主要跟随B站作者灵茶山的视频进行学习,专栏中一篇文章为B站对应的一个视频 题目主要为B站视频内涉及的题目以及B站视频中提到的“课后作业”。 ●文章中的理…...

【算法】二分查找
目录 一、概念 二、思路 三、边界问题 一、概念 在一本书中查找某一页,我们总是倾向于先翻到整本书的中间,然后根据当前页数判断我们想要找的页在当前页的左半本中还是右半本中,接着继续翻到剩下半本书的中间...... 这就是二分查找思想在…...

第十五章 Vue工程化开发及Vue CLI脚手架
目录 一、引言 二、Vue CLI 基本介绍 三、安装Vue CLI 3.1. 安装npm和yarn 3.2. 安装Vue CLI 3.3. 查看 Vue 版本 四、创建启动工程 4.1. 创建项目架子 4.2. 启动工程 五、脚手架目录文件介绍 六、核心文件讲解 6.1. index.html 6.2. main.js 6.3. App.vue 一、…...
【Grafana】Grafana 基础入门
Grafana 简介 什么是Grafana Grafana 是一跨平台的开源的可视化分析工具,是目前网络架构和应用分析中最流行的时序数据展示工具,主要用于大规模指标数据的可视化展示。 它是用Go语言开发,可以做数据监控和数据统计,带有告警功能…...
如何获取页面上所有input框
要获取页面上所有的<input>框,你可以使用JavaScript。这通常可以通过查询DOM(文档对象模型)来实现,有几种方法可以做到这一点,包括使用document.querySelectorAll、document.getElementsByTagName或document.get…...

0-ARM Linux驱动开发-字符设备
一、字符设备概述 Linux 系统中,设备被分为字符设备、块设备和网络设备等。字符设备以字节流的方式进行数据传输,数据的访问是按顺序的,一个字节一个字节地进行读取和写入操作,没有缓冲区。例如,终端(/dev…...

【BUG解决】关于BigDecimal与0的比较问题
这是一个很细小的知识点,但是很容易被忽略掉,导致系统问题,因此记录下来 问题背景 明明逻辑上看a和b都不为0才会调用除法,但是系统会报错:java.lang.ArithmeticException异常: if (!a.equals(BigDecimal…...

MySQL指令个人笔记
MySQL学习,SQL语言笔记 一、MySQL 1.1 启动、停止 启动 net start mysql83停止 net stop mysql831.2 连接、断开 连接 mysql -h localhost -P 3306 -u root -p断开 exit或者ctrlc 二、DDL 2.1 库管理 2.1.1 直接创建库 使用默认字符集和排序方式…...

Windows安装docker desktop
Windows 版本: Windows 10/11(64位)专业版、企业版或教育版(家庭版需手动配置)。 版本号需 ≥ 1909(建议更新到最新系统) 打开程序 启动服务后点点点 重启生效(没有的话 安装WSL…...

阿里云无影云桌面深度测评
阿里云无影桌面深度测评:解锁云端工作“新范式”的“未来之钥”! 在数字化浪潮席卷全球的2025年,远程办公与混合办公已不再是权宜之计,而是职场不可逆转的新常态。然而,如何确保员工无论身在何处,都能拥有…...

Java面试八股--07-项目篇
致谢:2025年 Java 面试八股文(20w字)_java面试八股文-CSDN博客 目录 1、介绍一下最近做的项目 1.1 项目背景: 1.2 项目功能 1.3 技术栈 1.4自己负责的功能模块 1.5项目介绍参考: 1.6整体业务介绍: 1.8后台管理系统功能: 1.8.1后台主页: 1.8.2 商品模块: 1.8…...
Ubuntu挂起和休眠
Ubuntu挂起和休眠 1. 挂起(Suspend)2. 休眠(Hibernate)3. 混合挂起(Hybrid-Sleep)注意事项图形界面操作 在 Ubuntu 系统中,挂起(Suspend)和休眠(Hibernate&am…...

Android12 Launcher3显示所有应用列表
Android12 Launcher3显示所有应用列表 1.前言: 最近在Android12Rom定制时需要显示所有桌面应用的图标,并且不能去掉抽屉,在手机上面抽屉和所有应该列表是两种不同模式,用户基可以自行选择,但是在自定义的launcher中这…...
[Java 基础]运算符,将盒子套起来
在 Java 中,运算符(Operator)用于执行特定的操作,例如数学计算、赋值、比较等。运算符是 Java 语言的重要组成部分,能够帮助我们高效地操作数据。 1. 算术运算符 运算符说明示例结果加法5 38-减法5 - 32*乘法5 * 31…...
SpringBoot3.2新特性:JdbcClient
文章目录 一、简介二、使用1、支持隐式位置参数2、通过索引设置位置参数3、支持 Name / Value 对命名参数4、通过 Map 设置命名参数5、使用 JdbClient 执行更新操作6、使用示例 参考资料 一、简介 Spring 6.1 中新添加了 JdbcClient 接口,它提供了 Fluent 风格的 A…...
事件不触发、交互失效?基于 WebDebugX 的移动端事件调试实战总结
在移动端开发中,“点击没反应”“滑动卡住”“长按无效”等事件类问题时常困扰开发者。这类问题不仅和逻辑代码有关,更常见的是出现在浏览器事件模型与设备行为之间的不一致,特别是在 WebView 环境下尤为显著。 本文结合多个真实案例&#x…...