欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > 智能BI项目第二期

智能BI项目第二期

2025/10/2 9:08:49 来源:https://blog.csdn.net/2302_76649176/article/details/142311197  浏览:    关键词:智能BI项目第二期

该项目是全程跟着鱼皮,还未进行功能扩展。为了方便日后复习,打算将一些重要的步骤记录下来。

该笔记着重记录后端代码,前端了解大致方向即可

项目概述

BI:即商业智能:Business Intelligence

过去

       需要手动导入数据、选择要分析的字段和图表,并由专业的数据分析师完成分析,最后得出结论。

现在

       用户只需输入想要分析的目标,并上传原始数据,系统将利用 AI 自动生成可视化图表。这样,会比较方便

端口占用

Windows Hyper-V 虚拟化平台占用了端口

什么是Hyper-V : 

为了使硬件虚拟化,即创建一个没有物理形式的硬件环境,你需要在物理计算机和虚拟机之间有一个中介。这个接口被称为管理程序。物理主机系统可以映射到共享主机硬件(父分区)的多个虚拟客户系统(子分区)。微软已经创建了自己的管理程序 Hyper-V,它包含在 Windows 10、11 或 Windows 8 的专业版本中。该软件也被安装在 Windows Server 中。

第一种方法:

查看被占用的端口,然后选择一个没被占用的端口启动项目。cmd命令打开输入

netsh interface ipv4 show excludedportrange protocol=tcp

 第二种方法:

直接禁用Hyper-V(不推荐)

前端结构介绍

大概了解即可,不用刻意背,用着用着就懂了

检查提交的代码,是否规范(代码校验的小工)

umi 配置,包含由,构路建等配置

整个项目所用的框架,Ant Design Pro 的核心配置

Ant Design Pro 默认设置,可以更改页面样式

一个示例的数据(没用,删掉)

代理,方便本地开发(一般用不到,不用删)

定义网页路由(就是输入哪个网址,跳转到哪个页面)

本地模拟数据(删掉)

icon目录中存放了页面的图标(删掉)

框架自动生成的隐藏文件(不用管)

业务通用组件

国际化资源(删掉)

业务页面入口和常用模板

后台接口服务

可以把自带的删掉,这里先删除 swagger目录,ant-design-pro 先不删,现在项目里很多内容用到它,等后面改完再删。

控制页面访问权限

整个 Ant Design Pro 框架的主要文件

全局样式

全局 JS

开发 app 或 h5 网页指定多种不同的配置。(删掉)例如:生成项目名称、项目图标尺寸等...一般打包的时候用到

控制前端页面发送请求的配置。例如:你向哪个地址发送请求,请求发送错误,怎么处理等.....

h5 网页离线时优化页面的体验

测试工具(删掉)

全是未引用(删掉)

保证前端项目代码规范。在 webstorm 中可以按[Ctrl+Alt+L]格式化代码,可以让代码看起来更美观。

单元测试框架(删掉)

控制语法

整个项目的默认文档

模板优化:

替换logo

public目录下的一些图片是ant design pro自带的图片,我们只要把对应文件后缀和名称的图片覆盖后,就可以更改成我们自己的图片

 替换 Logo 网站、替换 favicon 网站

favicon:网站标签图表、logo:登入页面的图标

美化配置

修改标题

ctrl + shift + f 全局搜索 Ant Design

ctrl + shift + r 全局替换

像网页上的一些东西,都可以用这种类似的方法修改,包括底下的导航栏都行 

开发登入页

在:src/pages/User/Login/index.tsx操作,其他没用的都可以删掉

介绍大致框架

 前端不会,大概知道每个地方干啥的就好了,具体实现以后再说

智能分析业务流程

用户输入

a. 分析目标

b. 上传原始数据(excel)

c. 更精细化地控制图表:比如图表类型、图表名称等

后端校验

a. 校验用户的输入否合法(比如长度)

b. 成本控制(次数统计和校验、鉴权等)

  1. 把处理后的excel数据输入给 AI 模型(调用 Al 接口,星球内部同学可以免费使用 Al 接口),让 AI 模型给我们提供图表信息、结论代码
  2. 图表信息(是一段 json 配置,是一段代码)、结论文本在前端进行展示

代码编写

FileController里有一个uploadFile,用来上传文件,我们可以将他改造成我们需要的上传excel,并对其进行解析。将整个方法复制到ChartController里,并重命名为GenChartByAi

缺失字段如何补充?

红色框框内是我们要补充的字段,填写好后复制

直接粘贴进去

然后在实体类补上缺失的参数,如果我们的model/dto/chart包下的各种请求参数需要的话,也要补上

注意:mapper层里的sql语句也要记得补上

该字段相关的业务逻辑要补上(与名字相关的是模糊查询)

对输入进行简单的判断(不要相信前端的限制,后端也要编写对应代码)

/*** 智能分析** @param multipartFile* @param genChartByAiRequest* @param request* @return*/
@PostMapping("/gen")
public BaseResponse<String> genChartByAi(@RequestPart("file") MultipartFile multipartFile,GenChartByAiRequest genChartByAiRequest, HttpServletRequest request) {String name = genChartByAiRequest.getName();String goal = genChartByAiRequest.getGoal();String chartType = genChartByAiRequest.getChartType();// 校验// 如果分析目标为空,就抛出请求参数错误异常,并给出提示ThrowUtils.throwIf(StringUtils.isBlank(goal), ErrorCode.PARAMS_ERROR, "目标为空");// 如果名称不为空,并且名称长度大于100,就抛出异常,并给出提示ThrowUtils.throwIf(StringUtils.isNotBlank(name) && name.length() > 100, ErrorCode.PARAMS_ERROR, "名称过长");// 读取到用户上传的 excel 文件,进行一个处理User loginUser = userService.getLoginUser(request);// 文件目录:根据业务、用户来划分String uuid = RandomStringUtils.randomAlphanumeric(8);String filename = uuid + "-" + multipartFile.getOriginalFilename();File file = null;try {// 返回可访问地址return ResultUtils.success("");} catch (Exception e) {//            log.error("file upload error, filepath = " + filepath, e);throw new BusinessException(ErrorCode.SYSTEM_ERROR, "上传失败");} finally {if (file != null) {// 删除临时文件boolean delete = file.delete();if (!delete) {//                    log.error("file delete error, filepath = {}", filepath);}}}
}

如何写好一个好的promt

Al提词技巧1:持续输入,持续优化

第一次问: 我给你三行数据,请帮我分析网站的增长趋势,数据如下:

第一行:日期: 1号, 用户数: 10人

第二行:日期: 2号,用户数: 20人

第三行:日期: 3号,用户数: 30人

AI提词技巧2:数据压缩(内容压缩,比如把很长的内容提取关键词,也可以让Al来做)

第二次问:我给你三行数据,请帮我分析网站的增长趋势,数据如下:

表头:日期,用户数

1号,10

2号,20

3号,30

第三次问: 我给你三行数据,请帮我用最少的字数压缩这段数据

第一行:日期: 1号, 用户数: 10人

第二行:日期: 2号,用户数: 20人

第三行:日期: 3号,用户数: 30人

Al回答: 日期1-3号,用户数分别为10/20/30人。


用 chatGPT 也好,还是用鱼聪明,无论使用哪种 AI 模型,输入都是数据而非文件。那怎么输入数据呢?并且输入的字数也会有限制。

所以我们要尽可能地压缩数据,读取excel文件,转化成csv格式

excel转csv格式

基础模板

package com.ptu.api.utils;import cn.hutool.core.collection.CollUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.ResourceUtils;import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;/*** EasyExcel 测试** @author <a href="https://github.com/liyupi">程序员鱼皮</a>* @from <a href="https://yupi.icu">编程导航知识星球</a>*/
@SpringBootTest
public class EasyExcelTest {@Test/*** 该Java代码从类路径加载名为“网站数据.xlsx”的文件,并使用EasyExcel库读取其中的数据。主要功能包括:* 指定Excel类型为XLSX。* 默认读取第一个工作表(sheet)。* 设置表头行号为0,表示第一行是表头。* 同步读取Excel数据到一个包含多行数据的List中,每行数据以Map形式存储,键为列索引,值为单元格内容。*/public void doImport() throws FileNotFoundException {/*** 该Java代码段使用EasyExcel库从上传的多部分文件流中读取Excel数据(格式为XLSX),并执行以下操作:* 读取第一个工作表。* 设置表头行号为0(即第一行为表头)。* 同步执行读取操作,并将结果存储在list变量中。*/List<Map<Integer, String>> list = null;list = EasyExcel.read(ResourceUtils.getFile("classpath:网站数据.xlsx")).excelType(ExcelTypeEnum.XLSX).sheet().headRowNumber(0).doReadSync();//最终的数据StringBuilder sb = new StringBuilder();Map<Integer, String> headerMap = list.get(0);List<String> headList = headerMap.values().stream().filter(ObjectUtils::isNotEmpty).collect(Collectors.toList());/*** 使用 StringUtils.join(headList, ",") 将 headList(第一行的标题)用逗号连接成一个字符串。* 连接结果追加到 sb 对象中。* 在追加的内容后添加换行符。*/sb.append(StringUtils.join(headList,",")).append("\n");for(int i = 1;i < list.size();i++){Map<Integer, String> dataMap = list.get(i);List<String> dataList = dataMap.values().stream().filter(ObjectUtils::isNotEmpty).collect(Collectors.toList());sb.append(StringUtils.join(dataList)).append("\n");}System.out.println(sb.toString());}}

基础模块优化

为了满足业务需求,可以对遍历到的数据进行过滤,这里对表格里删除的数据,但是读取过程依然会读出来(这是没有必要的)

package com.yupi.springbootinit.utils;import cn.hutool.core.collection.CollUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.FileNotFoundException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;/*** Excel 相关工具类*/
public class ExcelUtils {public static String excelToCsv(MultipartFile multipartFile) {File file = null;try {file = ResourceUtils.getFile("classpath:网站数据.xlsx");} catch (FileNotFoundException e) {e.printStackTrace();}// 读取数据List<Map<Integer, String>> list = EasyExcel.read(file).excelType(ExcelTypeEnum.XLSX).sheet().headRowNumber(0).doReadSync();// 如果数据为空if (CollUtil.isEmpty(list)) {return "";}// 转换为 csv// 读取表头(第一行)LinkedHashMap<Integer, String> headerMap = (LinkedHashMap) list.get(0);List<String> headerList = headerMap.values().stream().filter(ObjectUtils::isNotEmpty).collect(Collectors.toList());System.out.println(StringUtils.join(headerList,","));// 读取数据(读取完表头之后,从第一行开始读取)for (int i = 1; i < list.size(); i++) {LinkedHashMap<Integer, String> dataMap = (LinkedHashMap) list.get(i);List<String> dataList = dataMap.values().stream().filter(ObjectUtils::isNotEmpty).collect(Collectors.toList());System.out.println(StringUtils.join(dataList,","));}System.out.println(list);return "";}public static void main(String[] args) {excelToCsv(null);}
}

创建工具类

package com.ptu.api.utils;import cn.hutool.core.collection.CollUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;@Slf4j
public class ExcelUtils {public static String excelToCsv(MultipartFile multipartFile){/*** 该Java代码段使用EasyExcel库从上传的多部分文件流中读取Excel数据(格式为XLSX),并执行以下操作:* 读取第一个工作表。* 设置表头行号为0(即第一行为表头)。* 同步执行读取操作,并将结果存储在list变量中。*/List<Map<Integer, String>> list = null;try {list = EasyExcel.read(multipartFile.getInputStream()).excelType(ExcelTypeEnum.XLSX).sheet().headRowNumber(0).doReadSync();} catch (IOException e) {log.error("表格处理错误",e);}if (CollUtil.isEmpty(list)){return "";}//最终的数据StringBuilder sb = new StringBuilder();Map<Integer, String> headerMap = list.get(0);List<String> headList = headerMap.values().stream().filter(ObjectUtils::isNotEmpty).collect(Collectors.toList());sb.append(StringUtils.join(headList,",")).append("\n");for(int i = 1;i < list.size();i++){Map<Integer, String> dataMap =  list.get(i);List<String> dataList = dataMap.values().stream().filter(ObjectUtils::isNotEmpty).collect(Collectors.toList());sb.append(StringUtils.join(dataList)).append("\n");}return sb.toString();}public static void main(String[] args) {excelToCsv(null);}
}

调用AI

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

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

AI提词技巧3:
在系统(模型)层面做预设效果一般来说,蚍直接拼接在用户消息里效果更好一些。

AI提词技巧4:
除了系统预设外,额外关联一问一答两条消息,相当于给Al一个提示。

/*** 智能分析** @param multipartFile* @param genChartByAiRequest* @param request* @return*/@PostMapping("/gen")public BaseResponse<String> genChartByAi(@RequestPart("file") MultipartFile multipartFile,GenChartByAiRequest genChartByAiRequest, HttpServletRequest request) {String name = genChartByAiRequest.getName();String goal = genChartByAiRequest.getGoal();String chartType = genChartByAiRequest.getChartType();// 校验// 如果分析目标为空,就抛出请求参数错误异常,并给出提示ThrowUtils.throwIf(StringUtils.isBlank(goal), ErrorCode.PARAMS_ERROR, "目标为空");// 如果名称不为空,并且名称长度大于100,就抛出异常,并给出提示ThrowUtils.throwIf(StringUtils.isNotBlank(name) && name.length() > 100, ErrorCode.PARAMS_ERROR, "名称过长");// 用户输入StringBuilder userInput = new StringBuilder();userInput.append("你是一个数据分析师,接下来我会给你我的分析目标和原始数据,请告诉我分析结论。").append("\n");userInput.append("分析目标:").append(goal).append("\n");// 压缩后的数据(把multipartFile传进来,其他的东西先注释)String result = ExcelUtils.excelToCsv(multipartFile);userInput.append("数据:").append(result).append("\n");return ResultUtils.success(userInput.toString());
//        // 读取到用户上传的 excel 文件,进行一个处理
//        User loginUser = userService.getLoginUser(request);
//        // 文件目录:根据业务、用户来划分
//        String uuid = RandomStringUtils.randomAlphanumeric(8);
//        String filename = uuid + "-" + multipartFile.getOriginalFilename();
//        File file = null;
//        try {
//
//            // 返回可访问地址
//            return ResultUtils.success("");
//        } catch (Exception e) {log.error("file upload error, filepath = " + filepath, e);
//            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "上传失败");
//        } finally {
//            if (file != null) {
//                // 删除临时文件
//                boolean delete = file.delete();
//                if (!delete) {log.error("file delete error, filepath = {}", filepath);
//                }
//            }
//        }}

系统预设最好是放在模型里,效果更好

这一期就到这里了,具体如何调用AI下期再来,拜拜溜~

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词