package space.anyi.BI.service.impl; import cn.hutool.core.util.IdUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import space.anyi.BI.entity.Chart; import space.anyi.BI.entity.dto.ChartDTO; import space.anyi.BI.entity.vo.ChartVO; import space.anyi.BI.entity.vo.PageVO; import space.anyi.BI.entity.xinghuo.HttpRequestData; import space.anyi.BI.entity.xinghuo.HttpResponseData; import space.anyi.BI.exception.SystemException; import space.anyi.BI.service.ChartService; import space.anyi.BI.mapper.ChartMapper; import org.springframework.stereotype.Service; import space.anyi.BI.util.AiUtil; import space.anyi.BI.util.BeanCopyUtil; import space.anyi.BI.util.ExcelUtils; import space.anyi.BI.util.SecurityUtils; import javax.annotation.Resource; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadPoolExecutor; /** * @author 杨逸 * @description 针对表【chart(图标表)】的数据库操作Service实现 * @createDate 2024-11-28 19:51:56 */ @Service public class ChartServiceImpl extends ServiceImpl implements ChartService{ private final static Logger log = LoggerFactory.getLogger(ChartServiceImpl.class); @Resource private ThreadPoolExecutor threadPoolExecutor; /** * 异步使用AI生成图表 * @param chartDTO * @param file * @description: * @author: 杨逸 * @data:2024/12/07 17:43:22 * @since 1.0.0 * @return */ @Override public long generateChartByAIAsyn(ChartDTO chartDTO, MultipartFile file) { Chart chart = BeanCopyUtil.copyBean(chartDTO, Chart.class); long chartId = IdUtil.getSnowflake(1, 1).nextId(); chart.setId(chartId); chart.setUserId(SecurityUtils.getUserId()); chart.setState("等待中"); //读数据 String csvData = ""; try { csvData = ExcelUtils.excel2csv(file.getInputStream()); log.info("上传的数据为:\n{}", csvData); } catch (IOException e) { e.printStackTrace(); } if (csvData.length()>3000){ chart.setChartData(""); chart.setState("失败"); chart.setExecuteMessage("数据量过大,请上传小于3000行的数据"); save(chart); throw new SystemException(500, "数据量过大,请上传小于3000行的数据"); } chart.setChartData(csvData); save(chart); //使用线程池优化生成图表的逻辑 String finalCsvData = csvData; try { threadPoolExecutor.execute(()->{ chart.setState("生成中"); updateById(chart); StringBuilder message = new StringBuilder("原始数据:\n"); message.append(finalCsvData); message.append("分析目标:\n"); message.append(chartDTO.getAnalysisTarget()); message.append("\n.使用").append(chartDTO.getChartType()).append("进行可视化分析.\n"); //配置prompt向AI发送请求 HttpRequestData requestData = AiUtil.createDefaultRequestData(message.toString()); HttpResponseData responseData = AiUtil.doChat(requestData); //解析AI返回的数据 String content = responseData.getChoices().get(0).getMessage().getContent(); log.info("AI返回的数据为:{}", content); int index = content.indexOf("```"); int endIndex = content.lastIndexOf("```"); if (index == -1 || endIndex == -1){ chart.setState("失败"); chart.setExecuteMessage("AI生成图表失败"); updateById(chart); throw new SystemException(500, "AI生成图表失败"); } //数据可视化,Echarts的option代码 chart.setGeneratedChartData(content.substring(index+7, endIndex).trim()); index = endIndex; //分析结论 chart.setAnalysisConclusion(content.substring(index+3).trim()); //保存到数据库 chart.setState("成功"); chart.setExecuteMessage("AI生成图表成功"); updateById(chart); }); } catch (RejectedExecutionException e) { //e.printStackTrace(); log.error("线程池已满,请稍后再试",e); chart.setState("失败"); chart.setExecuteMessage("系统异常"); updateById(chart); } return chartId; } @Override public PageVO getChartPage(Integer pageNum, Integer pageSize, String name, Long userId) { if (!SecurityUtils.isAdmin()){ userId = SecurityUtils.getUserId(); } LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper() .like(StringUtils.hasText(name), Chart::getName, name) .eq(userId != null, Chart::getUserId, userId); Page page = page(new Page(pageNum, pageSize),lambdaQueryWrapper); List voList = new ArrayList<>(); for (Chart chart : page.getRecords()) { ChartVO chartVO = BeanCopyUtil.copyBean(chart, ChartVO.class); chartVO.setId(chart.getId().toString()); chartVO.setUserId(chart.getUserId().toString()); voList.add(chartVO); } PageVO pageVO = new PageVO(voList, page.getTotal()); return pageVO; } @Override public ChartVO generateChartByAI(ChartDTO chartDTO, MultipartFile file) { //读数据 String csvData = ""; long charId = IdUtil.getSnowflake(1, 1).nextId(); Chart chart = BeanCopyUtil.copyBean(chartDTO, Chart.class); chart.setId(charId); chart.setUserId(SecurityUtils.getUserId()); chart.setState("等待中"); try { csvData = ExcelUtils.excel2csv(file.getInputStream()); log.info("上传的数据为:\n{}", csvData); } catch (IOException e) { e.printStackTrace(); } if (csvData.length()>3000){ chart.setState("失败"); chart.setExecuteMessage("数据量过大,请上传小于3000行的数据"); chart.setChartData(""); save(chart); throw new SystemException(500, "数据量过大,请上传小于3000行的数据"); } chart.setChartData(csvData); save(chart); StringBuilder message = new StringBuilder("原始数据:\n"); message.append(csvData); message.append("分析目标:\n"); message.append(chartDTO.getAnalysisTarget()); message.append("\n.使用").append(chartDTO.getChartType()).append("进行可视化分析.\n"); chart.setState("生成中"); chart.setExecuteMessage("AI正在生成图表"); updateById(chart); //配置prompt向AI发送请求 HttpRequestData requestData = AiUtil.createDefaultRequestData(message.toString()); HttpResponseData responseData = AiUtil.doChat(requestData); //解析AI返回的数据 //ChartVO chartVO = BeanCopyUtil.copyBean(chartDTO, ChartVO.class); String content = responseData.getChoices().get(0).getMessage().getContent(); log.info("AI返回的数据为:{}", content); int index = content.indexOf("```"); int endIndex = content.lastIndexOf("```"); if (index == -1 || endIndex == -1){ chart.setState("失败"); chart.setExecuteMessage("AI生成图表失败"); updateById(chart); throw new SystemException(500, "AI生成图表失败"); } //数据可视化,Echarts的option代码 chart.setGeneratedChartData(content.substring(index+7, endIndex).trim()); index = endIndex; //分析结论 chart.setAnalysisConclusion(content.substring(index+3).trim()); //更新数据库 chart.setState("成功"); chart.setExecuteMessage("图表生成成功"); updateById(chart); ChartVO chartVO = BeanCopyUtil.copyBean(chart, ChartVO.class); return chartVO; } }