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

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

  1. 登录阿里云百炼页面,开通“百炼大模型推理”服务。
  1. 创建新的API Key并记录下来。
  1. 将API Key作为环境变量导出:
export AI_DASHSCOPE_API_KEY=这里替换为你的实际API Key
  1. 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 调用国产大模型通义千问的具体例子&#xff0c;按照这个做能够快速的搞定Java应用的调用。 然后就可以把这类应用泛化到所有的涉及到非结构化数据结构化的场景中。 Spring AI&#xff1a;简化Java中大模型调用的框…...

MySQL【二】

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

SQL 常用语句

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

前端埋点系统之如何用heatmap.js画网页热力图

Hello&#xff0c;大家好。在当今数字化时代&#xff0c;理解用户行为成为了企业成功的关键之一。随着互联网的发展&#xff0c;用户与网站、应用和产品的互动变得愈发复杂而多样化。在这样的背景下&#xff0c;埋点系统成为了洞察用户行为的重要工具之一。而其中的热力图分析&…...

CentOS 7系统下Redis Cluster集群一键部署脚本发布

引言 在大数据和云计算时代,Redis作为一款高性能的键值存储数据库,广泛应用于各种场景。然而,手动搭建Redis Cluster集群过程繁琐且容易出错。为了简化这一过程,本文提供了一个在CentOS 7系统下Redis Cluster集群的一键部署脚本,帮助开发者快速搭建Redis Cluster集群。 …...

自编以e为底的对数函数ln,性能接近标准库函数

算法描述&#xff1a; (1). 先做自变量x的范围检查&#xff0c;不能出现负数和0. 自己使用时&#xff0c;如果能通过其它途径保证自变量为正&#xff0c;那么可以省略这两个判断&#xff0c;提高速度。 (2). 根据IEEE 754浮点数的格式&#xff0c;&#xff0c;则 ln(x)kln(2)ln…...

Java中的日期时间

JDK8之前常用的日期时间类 System.currentTimeMillis()&#xff1a;获取当前毫秒数&#xff08;long类型&#xff09; java.util.Date&#xff1a;通用Date类 import java.util.Date;Date date new Date(); // 空参构造器 System.out.println(date.getTime()); // 获取当前时…...

位置编码的表示

位置编码的表示位置编码的表示位置编码的表示位置编码的表示位置编码的表示...

0,国产FPGA(紫光同创)-新建PDS工程

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

c++联合

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

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 及其列已完全初始化时&#xff0c;才使用以下方法。如果需要在表单仍…...

Java 文件操作与IO流

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

探索开源MiniMind项目:让大语言模型不再神秘(1)

简介&#xff1a; 声明&#xff1a;本人非此项目作者&#xff0c;仅仅是探索项目&#xff0c;分享项目。如有不妥&#xff0c;请联系我删除&#xff01; 原项目地址&#xff1a;GitHub - jingyaogong/minimind: 「大模型」3小时完全从0训练26M的小参数GPT&#xff0c;个人显卡即…...

Android 大疆面经

Android 大疆面经 文章目录 Android 大疆面经一面 一面 自我介绍问项目聊了10分钟View的绘制流程MVC&#xff0c;MVP&#xff0c;MVVM的区别view和viewmodel的通信&#xff0c;除了databing还有其他的方式面向对象和面向过程的区别工厂模式和策略模式&#xff0c;哪些框架使用…...

【2024-10-31-2024-11-03】LeetCode刷题——python语法基础题

&#x1f4dd;前言说明&#xff1a; ●本专栏主要记录本人的基础算法学习以及LeetCode刷题记录&#xff0c;主要跟随B站作者灵茶山的视频进行学习&#xff0c;专栏中一篇文章为B站对应的一个视频 题目主要为B站视频内涉及的题目以及B站视频中提到的“课后作业”。 ●文章中的理…...

【算法】二分查找

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

第十五章 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 是一跨平台的开源的可视化分析工具&#xff0c;是目前网络架构和应用分析中最流行的时序数据展示工具&#xff0c;主要用于大规模指标数据的可视化展示。 它是用Go语言开发&#xff0c;可以做数据监控和数据统计&#xff0c;带有告警功能…...

如何获取页面上所有input框

要获取页面上所有的<input>框&#xff0c;你可以使用JavaScript。这通常可以通过查询DOM&#xff08;文档对象模型&#xff09;来实现&#xff0c;有几种方法可以做到这一点&#xff0c;包括使用document.querySelectorAll、document.getElementsByTagName或document.get…...

0-ARM Linux驱动开发-字符设备

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

别再手动调色了!用Matlab bar3函数一键生成论文级渐变三维柱状图(附完整代码)

别再手动调色了&#xff01;用Matlab bar3函数一键生成论文级渐变三维柱状图&#xff08;附完整代码&#xff09; 科研图表的美观程度直接影响论文的第一印象&#xff0c;而三维柱状图在展示多维度数据时尤为常见。传统手动调整每个柱体的颜色、透明度、光照效果不仅耗时&#…...

如何在Windows 11上让经典游戏重获新生:DDrawCompat兼容性解决方案详解

如何在Windows 11上让经典游戏重获新生&#xff1a;DDrawCompat兼容性解决方案详解 【免费下载链接】DDrawCompat DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11 项目地址: https://gitcode.com/gh_m…...

Akebi-GC游戏辅助工具:免费开源的游戏体验增强终极指南

Akebi-GC游戏辅助工具&#xff1a;免费开源的游戏体验增强终极指南 【免费下载链接】Akebi-GC (Fork) The great software for some game that exploiting anime girls (and boys). 项目地址: https://gitcode.com/gh_mirrors/ak/Akebi-GC Akebi-GC是一款开源免费的游戏…...

SoC片上系统:从架构原理到选型实战的深度解析

1. 项目概述&#xff1a;从“黑盒子”到“智慧核心”的认知跃迁在电子产品的世界里&#xff0c;我们常常惊叹于一部智能手机的纤薄与强大&#xff0c;它既能流畅播放高清视频&#xff0c;又能处理复杂的游戏画面&#xff0c;还能实时连接网络、定位导航。这一切的背后&#xff…...

PaperDebugger:用代码调试思维提升学术论文可复现性的工具实践

1. 项目概述&#xff1a;一个为学术论文“排雷”的智能调试器如果你和我一样&#xff0c;常年混迹在学术圈或者技术研发一线&#xff0c;肯定对下面这个场景深恶痛绝&#xff1a;好不容易读完一篇几十页的论文&#xff0c;满心欢喜地准备复现其中的算法或实验&#xff0c;结果发…...

CFETR重载机械臂精确运动控制验证【附仿真】

✨ 长期致力于中国聚变工程实验堆、遥操作、多功能重载机械臂、路径规划、精确控制、数据融合控制研究工作&#xff0c;擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流&#xff0c;点击《获取方式》 &#xff08;1&#xff09;刚柔…...

影刀RPA跨境店群运营架构:基于Python的高并发环境隔离与自动化调度系统设计实战

关于我一个曾经死磕底层算法、痴迷于压榨软硬件性能的资深架构师&#xff0c;最后跑去给跨境工作室写店群底层自动化调度系统这件事。 很多以前在技术圈里混的同行&#xff0c;或者是看着我一路从后端重构做到 ImageTransPro 图像处理软件 5.0.3 这种复杂版本迭代的极客朋友们…...

从零开始通过Taotoken平台文档快速完成首个大模型API调用

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 从零开始通过Taotoken平台文档快速完成首个大模型API调用 对于初次接触大模型API的开发者而言&#xff0c;面对众多模型厂商、复杂…...

从理论到ONNX:手把手带你拆解pytorch_quantization量化YOLOv7的每一个Tensor变化

从理论到ONNX&#xff1a;手把手拆解YOLOv7量化中的Tensor演变 量化技术正在重塑计算机视觉模型的部署格局。当我们将YOLOv7这样的复杂检测模型从FP32压缩到INT8时&#xff0c;每一个卷积核、每一层激活值的细微变化都可能影响最终检测框的坐标精度。本文将以手术刀般的精确度&…...

从网卡硬件到Linux内核:深入理解RSS多队列如何避免你的数据包‘堵车’

从网卡硬件到Linux内核&#xff1a;深入理解RSS多队列如何避免你的数据包‘堵车’ 想象一下早高峰时段的城市主干道&#xff1a;如果只有一条车道&#xff0c;所有车辆不得不排队缓行&#xff0c;而增加车道数量后车流立刻变得顺畅。网络数据包的处理同样遵循这一逻辑——当单队…...