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

基于Spring Boot的智能分析平台

项目介绍:

智能分析平台实现了用户导入需要分析的原始数据集后,利用AI自动生成可视化图表和分析结论,改善了传统BI系统需要用户具备相关数据分析技能的问题。该项目使用到的技术是SSM+Spring Boot、redis、rabbitMq、mysql等。在项目中,使用第三方AI助手平台编写一段系统预设prompt来生成指定的json,全局指定助手的职责、输入内容和回复格式。在项目中,由于AIGC是一个消耗资源和成本的重操作,所以使用了redisson提供的rateLimiter实现对单用户使用AI生成图表功能的限流,以保护系统。在AI生成内容时,处于服务能力的考虑,可能会出现第三方接口处理和返回时长较长,就引入异步化来提高用户体验,使用自定义线程池(JUC并发包中的ThreadPoolExcutor)+任务队列来管理线程、协调任务的执行。最后本项目使用RabbitMq把任务提交改为向消息队列发送消息来解决异步化是通过本地线程池实现带来的限制,实现应用解耦。测试得出,若应用程序中断,消息未确认,还会重发消息用以消费。

界面展示:

需求分析:

1.智能分析:用户输入目标和原始数据,自动生成图表和结论

2.图表管理

3.图表生成的异步化(消息队列)

4.对接AI能力

技术栈:

Spring Boot+Mysql+Mybatis Plus+消息队列(RabbitMQ)+AI能力

数据库表设计

1.用户表

-- 用户表
create table if not exists user
(id           bigint auto_increment comment 'id' primary key,userAccount  varchar(256)                           not null comment '账号',userPassword varchar(512)                           not null comment '密码',userName     varchar(256)                           null comment '用户昵称',userAvatar   varchar(1024)                          null comment '用户头像',userRole     varchar(256) default 'user'            not null comment '用户角色:user/admin',createTime   datetime     default CURRENT_TIMESTAMP not null comment '创建时间',updateTime   datetime     default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',isDelete     tinyint      default 0                 not null comment '是否删除',index idx_userAccount (userAccount)
) comment '用户' collate = utf8mb4_unicode_ci;

2.图表信息表

-- 图表表
create table if not exists chart
(id           bigint auto_increment comment 'id' primary key,goal				 text  null comment '分析目标','name'          varchar(128) null comment '图表名称',chartData    text  null comment '图表数据',chartType	   varchar(128) null comment '图表类型',genChart		 text	 null comment '生成的图表数据',genResult		 text	 null comment '生成的分析结论',status       varchar(128) not null default 'wait' comment 'wait,running,succeed,failed',execMessage  text   null comment '执行信息',userId       bigint null comment '创建用户 id',createTime   datetime     default CURRENT_TIMESTAMP not null comment '创建时间',updateTime   datetime     default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',isDelete     tinyint      default 0                 not null comment '是否删除'
) comment '图表信息表' collate = utf8mb4_unicode_ci;

调用AI:

系统预设(提前告诉他职责、功能、回复格式要求)+分析目标+压缩后的数据

系统预设例子:你是一个数据分析师,接下来我会告诉你我的分析目标和原始数据,请帮我分析并告诉我结论。

Prompt 预设:

你是一个数据分析师和前端开发专家,接下来我会按照以下固定格式给你提供内容:
分析需求:
{数据分析的需求或者目标}
原始数据:
{csv格式的原始数据,用,作为分隔符}
请根据这两部分内容,按照以下指定格式生成内容(此外不要输出任何多余的开头、结尾、注释)
【【【【【
{前端 Echarts V5 的 option 配置对象js代码,合理地将数据进行可视化,不要生成任何多余的内容,比如注释}
【【【【【
{明确的数据分析结论、越详细越好,不要生成多余的注释}

业务流程开发:

生成图表:AI无法直接生成现成的图表、但是AI可以生成图标代码--->可以把代码利用前端的组件库(Echarts)在网页展示

后端接口开发:

根据用户的输入,最后返回图表信息和结论文本

1.构造用户请求:用户消息、csv数据、图表类型

2.调用SDK,得到AI响应结果

3.从AI响应结果中,取出需要的信息

4.保存图表到数据库

项目优化:

1.校验文件传入:解决用户上传一个超大的文件

2.限流:解决用户频繁点击提交,导致服务器资源被占满,其他用户无法使用,控制成本,限制用户调用总次数

限流的相关知识点-CSDN博客

3.异步化:解决调用的服务处理能力有限,或者接口的处理时间较长。当用户要进行耗时很长的操作时,点击提交后,不需要在界面等待,而是把这个任务保存到数据库中记录下来。当任务提交成功时,如果我们的程序还有多余的线程空闲,可以立刻执行这个任务,若没有空闲的,则放入到等待队列中。当任务提交失败时,若没有空闲线程,任务队列满了的情况下,会拒绝这个任务或者保存到数据库中记录失败的任务,并且在程序空闲的时候,可以把这个任务拉出来在执行。

4.自定义线程池:解决线程管理复杂、任务存取复杂问题。使用线程池帮助轻松管理线程、协助调取任务的执行过程。

(1).自定义线程池:

@Configuration
public class ThreadPoolExecutorConfig {@Beanpublic ThreadPoolExecutor threadPoolExecutor() {ThreadFactory threadFactory = new ThreadFactory() {private int count = 1;@Overridepublic Thread newThread(@NotNull Runnable r) {Thread thread = new Thread(r);thread.setName("线程" + count);count++;return thread;}};ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 4, 100, TimeUnit.SECONDS,new ArrayBlockingQueue<>(4), threadFactory);return threadPoolExecutor;}
}

(2).提交任务到线程池:

CompletableFuture.runAsync(() -> {System.out.println("任务执行中:" + name + ",执行人:" + Thread.currentThread().getName());try {Thread.sleep(60000);} catch (InterruptedException e) {e.printStackTrace();}
}, threadPoolExecutor);

5.消息队列:本项目的异步通过本地的线程池实现,可能会出现数据持久化、可扩展行、应用耦合较高情况,使用分布式消息队列可以解决上述问题。使用消息队列后,如果程序中断了,消息没有确认,还会重发

本项目使用的是RabbitMQ

实现步骤:

  1. 创建交换机和队列

  2. 将线程池中的执行代码移到消费者类中

  3. 根据消费者的需求来确认消息的格式(chartId)

  4. 将提交线程池改造为发送消息到队列

(1).引入依赖:使用的版本需要和自己的springboot版本一致

 <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-amqp --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId><version>2.7.2</version></dependency>

(2).在yml中引入配置

spring:rabbitmq:host: localhostport: 5672password: guestusername: guest

(3).创建交换机和队列

public class BiInitMain {public static void main(String[] args) {try {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");Connection connection = factory.newConnection();Channel channel = connection.createChannel();//交换机名称String EXCHANGE_NAME=BiMqConstant.BI_EXCHANGE_NAME;channel.exchangeDeclare(EXCHANGE_NAME, "direct");// 创建队列,随机分配一个队列名称String queueName = BiMqConstant.BI_QUEUE_NAME;channel.queueDeclare(queueName, true, false, false, null);channel.queueBind(queueName, EXCHANGE_NAME, BiMqConstant.BI_ROUTING_KEY);}catch(Exception e){}}
}

(4).生产者代码

@Component
public class BiMessageProducer {/*** 发送消息*/@Resourcepublic RabbitTemplate rabbitTemplate;public void sendMessage(String message){rabbitTemplate.convertAndSend(BiMqConstant.BI_EXCHANGE_NAME,BiMqConstant.BI_ROUTING_KEY,message);}
}

(5).消费者代码:


@Component
@Slf4j
public class BiMessageConsumer {@Resourceprivate ChartService chartService;@Resourceprivate AiManager aiManager;//指定程序监听的消息队列和确认机制@SneakyThrows@RabbitListener(queues = {BiMqConstant.BI_QUEUE_NAME},ackMode = "MANUAL")public void receiveMessage(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) Long deliverTag){if(StringUtils.isBlank(message)){//如果失败,消息拒接channel.basicNack(deliverTag,false,false);throw new BusinessException(ErrorCode.SYSTEM_ERROR,"消息为空");}long chartId=Long.parseLong(message);Chart chart=chartService.getById(chartId);if(chart==null){channel.basicNack(deliverTag,false,false);throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"图表为空");}// 先修改图表任务状态为 “执行中”。等执行成功后,修改为 “已完成”、保存执行结果;执行失败后,状态修改为 “失败”,记录任务失败信息。Chart updateChart = new Chart();updateChart.setId(chart.getId());updateChart.setStatus("running");boolean b = chartService.updateById(updateChart);if (!b) {channel.basicNack(deliverTag,false,false);handleChartUpdateError(chart.getId(), "更新图表执行中状态失败");return;}// 调用 AIString result = aiManager.doChat(CommonConstant.BI_MODEL_ID, buildUserInput(chart));String[] splits = result.split("【【【【【");if (splits.length < 3) {channel.basicNack(deliverTag,false,false);handleChartUpdateError(chart.getId(), "AI 生成错误");return;}String genChart = splits[1].trim();String genResult = splits[2].trim();Chart updateChartResult = new Chart();updateChartResult.setId(chart.getId());updateChartResult.setGenChart(genChart);updateChartResult.setGenResult(genResult);// todo 建议定义状态为枚举值updateChartResult.setStatus("succeed");boolean updateResult = chartService.updateById(updateChartResult);if (!updateResult) {channel.basicNack(deliverTag,false,false);handleChartUpdateError(chart.getId(), "更新图表成功状态失败");}//消息确认channel.basicAck(deliverTag,false);}/*** 构造用户输入* @param chart* @return*/private String buildUserInput(Chart chart){String goal=chart.getGoal();String chartType= chart.getChartType();String csvData=chart.getChartData();//构造用户输入StringBuilder userInput = new StringBuilder();userInput.append("分析需求:").append("\n");//拼接分析目标String userGoal=goal;if(StringUtils.isNotBlank(chartType)){userGoal+=",请使用"+chartType;}userInput.append(userGoal).append("\n");userInput.append("原始数据:").append("\n");userInput.append(csvData).append("\n");return userInput.toString();}private void handleChartUpdateError(long chartId,String execMessage){Chart updateChartResult=new Chart();updateChartResult.setId(chartId);updateChartResult.setStatus("failed");updateChartResult.setExecMessage("execMessage");boolean updateResult = chartService.updateById(updateChartResult);if(!updateResult){log.error("更新图表失败状态失败" + chartId + "," + execMessage);}}}

相关文章:

基于Spring Boot的智能分析平台

项目介绍&#xff1a; 智能分析平台实现了用户导入需要分析的原始数据集后&#xff0c;利用AI自动生成可视化图表和分析结论&#xff0c;改善了传统BI系统需要用户具备相关数据分析技能的问题。该项目使用到的技术是SSMSpring Boot、redis、rabbitMq、mysql等。在项目中&#…...

HTML(13)——显示模式

目录 显示模式 块级元素 行内元素 行内块元素 转换显示模式 显示模式&#xff1a;标签的显示方式 作用&#xff1a;布局网页时&#xff0c;根据标签的显示模式选择合适的标签摆放内容 显示模式 块级元素 独占一行宽度默认为父级的100%添加宽高属性生效 行内元素 …...

【Spring】Spring Boot 快速入门

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 |《MySQL探索之旅》 |《Web世界探险家》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更…...

Go自定义数据的序列化流程

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…...

贪心算法练习题(2024/6/18)

什么是贪心 贪心的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。 贪心算法一般分为如下四步&#xff1a; 将问题分解为若干个子问题找出适合的贪心策略求解每一个子问题的最优解将局部最优解堆叠成全局最优解 1分发饼干 假设你是一位很棒的家长&#xff0c…...

4.1 四个子空间的正交性

一、四个子空间的正交性 如果两个向量的点积为零&#xff0c;则两个向量正交&#xff1a; v ⋅ w v T w 0 \boldsymbol v\cdot\boldsymbol w\boldsymbol v^T\boldsymbol w0 v⋅wvTw0。本章着眼于正交子空间、正交基和正交矩阵。两个子空间的中的向量&#xff0c;一组基中的向…...

RabbitMQ实践——使用WebFlux响应式方式实时返回队列中消息

大纲 Pom.xml监听队列实时返回消息测试完整代码工程代码 在之前的案例中&#xff0c;我们在管理后台收发消息都是通过短连接的形式。本文我们将探索对队列中消息的实时读取&#xff0c;并通过流式数据返回给客户端。 webflux是反应式Web框架&#xff0c;客户端可以通过一个长连…...

SpringBoot前后端传递数据时常用的JSON格式数据是什么?【讲解JSON概念、语法、以及Java对象互转】

SpringBoot前后端传递数据时常用的JSON格式数据是什么&#xff1f; JSON概念JSON语法JSON的两种结构&#xff1a;JSON字符串和Java对象互转&#xff1a;objectMapper.writeValueAsString(person);objectMapper.readValue(jsonStr,Person.class); 在SpringMVC框架中&#xff0c;…...

mysql学习——SQL中的DQL和DCL

SQL中的DQL和DCL DQL基本查询条件查询聚合函数分组查询排序查询分页查询 DCL管理用户权限控制 学习黑马MySQL课程&#xff0c;记录笔记&#xff0c;用于复习。 DQL DQL英文全称是Data Query Language(数据查询语言)&#xff0c;数据查询语言&#xff0c;用来查询数据库中表的记…...

windows系统上nginx搭建文件共享

1、下载windows版nginx 下载地址 2、配置nginx 编辑nginx.conf配置文件 在http模块下添加这个参数 underscores_in_headers on;#修改location内容&#xff0c;共享哪个文件夹&#xff0c;就写哪个文件夹&#xff0c;最后一定要跟上/&#xff0c;否则无法访问 location / {…...

星闪指向遥控,做家电交互的破壁人

“面壁者罗辑&#xff0c;我是你的破壁人。” 科幻小说《三体》中&#xff0c;当人类的基础科学被三体人封锁&#xff0c;变得停步不前&#xff0c;人类启动了自救的面壁计划&#xff0c;通过一次又一次破壁&#xff0c;找到战胜三体人的办法。 现实中&#xff0c;有一点已经成…...

SpringBoot使用AutoConfigure实现依赖库自动导入配置

我们知道导入配置有两种&#xff0c;一种是Value&#xff0c;一种是ConfigurationProperties&#xff0c;将对应的类标记为Component即可导入。但是被注解标识的类创建Bean有一个前提&#xff0c;只对启动类所在的包路径下的所有带有Component等注解的类才会创建Bean。如果我们…...

QT中利用动画弄一个侧边栏窗口,以及贴条效果

1、效果 2、关键代码 void Widget::on_sliderBtn_clicked() {m_sliderWidget->show();QPropertyAnimation* animation = new QPropertyAnimation(m...

win10免安装配置MySQL8.4.0

注&#xff1a;此教程基于win10 22H2 版本 1、下载最新版本MySQL压缩包 下载链接&#xff1a;MySQL官网下载地址 点击第二行的 ZIP Archive 后面的Download&#xff08;当前时间2024-06-19最新版本是8.4.0&#xff09; 2、解压并添加配置文件 下载完毕后&#xff0c;解压缩…...

VS Code安装及环境配置(超详细)

VS Code简介 Visual Studio Code&#xff08;简称 VS Code &#xff09;是 Microsoft 于2015年4月发布的一款代码编辑器&#xff0c;以界面简洁、轻量著称。 它是一款免费开源的现代化轻量级代码编辑器&#xff0c;支持几乎所有主流开发语言的语法高亮、智能代码补全、自定义…...

shell脚本通过解析日志使用串口开关屏知识点整理

#!/bin/bash #logPath 写日志的存放路径 #logPath/home/workspace/tvs/trainborne logPath/home/firefly tmpFile$$ function getLogName() { #echo "$logPath/LCDController_"date "%Y%m%d000000.log" echo "LCDController_20240424000000.log&quo…...

速盾:视频cdn和网站cdn的相同点与不同点

CDN&#xff08;Content Delivery Network&#xff09;是一种分布式网络架构&#xff0c;旨在为用户提供高效、高质量的内容传送服务。CDN主要通过将内容分发到全球各地的边缘节点&#xff0c;并根据用户的地理位置选择最近的节点来提供内容&#xff0c;从而加速内容的传输并降…...

37.自定义协议

自定义协议要素 1.魔数:用来第一时间判定是否是无效数据包。 2.版本号:主持协议升级。 3.序列化算法:消息正文到底采用那种序列化方式,可以由此扩展,例如:json,protobuf(google的序列化算法,基于二进制,虽然可读性不好,但是字节数占用更少),hessian(基于二进制)…...

【React Native】measureInWindow在安卓上无法正确获取View在屏幕上的布局信息

问题描述&#xff1a; 在React Native中&#xff0c;我们可以使用measureInWindow的方式去获取一个View在屏幕中的位置信息&#xff1a; 下面这个Demo中&#xff0c;我们写了一个页面HomePage和一个列表项组件ListItemA&#xff0c;我们期望每过5s监测一次列表中每一项在屏幕中…...

C++ 教程 - 04 类的使用

文章目录 类的定义类定义案例构造函数 类的定义 C 在 C 语言的基础上增加面向对象编程&#xff0c;类是用于指定对象的形式&#xff0c;是一种用户自定义的数据类型&#xff0c;封装了数据和函数。类可以被看作是一种模板&#xff0c;可以用来创建具有相同属性和行为的多个对象…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案

目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后&#xff0c;迭代器会失效&#xff0c;因为顺序迭代器在内存中是连续存储的&#xff0c;元素删除后&#xff0c;后续元素会前移。 但一些场景中&#xff0c;我们又需要在执行删除操作…...

Axure 下拉框联动

实现选省、选完省之后选对应省份下的市区...

JDK 17 序列化是怎么回事

如何序列化&#xff1f;其实很简单&#xff0c;就是根据每个类型&#xff0c;用工厂类调用。逐个完成。 没什么漂亮的代码&#xff0c;只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...