ChartServiceImpl.java 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. package space.anyi.BI.service.impl;
  2. import cn.hutool.core.util.IdUtil;
  3. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  4. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  5. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  6. import org.slf4j.Logger;
  7. import org.slf4j.LoggerFactory;
  8. import org.springframework.util.StringUtils;
  9. import org.springframework.web.multipart.MultipartFile;
  10. import space.anyi.BI.entity.Chart;
  11. import space.anyi.BI.entity.dto.ChartDTO;
  12. import space.anyi.BI.entity.vo.ChartVO;
  13. import space.anyi.BI.entity.vo.PageVO;
  14. import space.anyi.BI.entity.xinghuo.HttpRequestData;
  15. import space.anyi.BI.entity.xinghuo.HttpResponseData;
  16. import space.anyi.BI.exception.SystemException;
  17. import space.anyi.BI.service.ChartService;
  18. import space.anyi.BI.mapper.ChartMapper;
  19. import org.springframework.stereotype.Service;
  20. import space.anyi.BI.util.AiUtil;
  21. import space.anyi.BI.util.BeanCopyUtil;
  22. import space.anyi.BI.util.ExcelUtils;
  23. import space.anyi.BI.util.SecurityUtils;
  24. import javax.annotation.Resource;
  25. import java.io.IOException;
  26. import java.util.ArrayList;
  27. import java.util.List;
  28. import java.util.concurrent.RejectedExecutionException;
  29. import java.util.concurrent.ThreadPoolExecutor;
  30. /**
  31. * @author 杨逸
  32. * @description 针对表【chart(图标表)】的数据库操作Service实现
  33. * @createDate 2024-11-28 19:51:56
  34. */
  35. @Service
  36. public class ChartServiceImpl extends ServiceImpl<ChartMapper, Chart>
  37. implements ChartService{
  38. private final static Logger log = LoggerFactory.getLogger(ChartServiceImpl.class);
  39. @Resource
  40. private ThreadPoolExecutor threadPoolExecutor;
  41. /**
  42. * 异步使用AI生成图表
  43. * @param chartDTO
  44. * @param file
  45. * @description:
  46. * @author: 杨逸
  47. * @data:2024/12/07 17:43:22
  48. * @since 1.0.0
  49. * @return
  50. */
  51. @Override
  52. public long generateChartByAIAsyn(ChartDTO chartDTO, MultipartFile file) {
  53. Chart chart = BeanCopyUtil.copyBean(chartDTO, Chart.class);
  54. long chartId = IdUtil.getSnowflake(1, 1).nextId();
  55. chart.setId(chartId);
  56. chart.setUserId(SecurityUtils.getUserId());
  57. chart.setState("等待中");
  58. //读数据
  59. String csvData = "";
  60. try {
  61. csvData = ExcelUtils.excel2csv(file.getInputStream());
  62. log.info("上传的数据为:\n{}", csvData);
  63. } catch (IOException e) {
  64. e.printStackTrace();
  65. }
  66. if (csvData.length()>3000){
  67. chart.setChartData("");
  68. chart.setState("失败");
  69. chart.setExecuteMessage("数据量过大,请上传小于3000行的数据");
  70. save(chart);
  71. throw new SystemException(500, "数据量过大,请上传小于3000行的数据");
  72. }
  73. chart.setChartData(csvData);
  74. save(chart);
  75. //使用线程池优化生成图表的逻辑
  76. String finalCsvData = csvData;
  77. try {
  78. threadPoolExecutor.execute(()->{
  79. chart.setState("生成中");
  80. updateById(chart);
  81. StringBuilder message = new StringBuilder("原始数据:\n");
  82. message.append(finalCsvData);
  83. message.append("分析目标:\n");
  84. message.append(chartDTO.getAnalysisTarget());
  85. message.append("\n.使用").append(chartDTO.getChartType()).append("进行可视化分析.\n");
  86. //配置prompt向AI发送请求
  87. HttpRequestData requestData = AiUtil.createDefaultRequestData(message.toString());
  88. HttpResponseData responseData = AiUtil.doChat(requestData);
  89. //解析AI返回的数据
  90. String content = responseData.getChoices().get(0).getMessage().getContent();
  91. log.info("AI返回的数据为:{}", content);
  92. int index = content.indexOf("```");
  93. int endIndex = content.lastIndexOf("```");
  94. if (index == -1 || endIndex == -1){
  95. chart.setState("失败");
  96. chart.setExecuteMessage("AI生成图表失败");
  97. updateById(chart);
  98. throw new SystemException(500, "AI生成图表失败");
  99. }
  100. //数据可视化,Echarts的option代码
  101. chart.setGeneratedChartData(content.substring(index+7, endIndex).trim());
  102. index = endIndex;
  103. //分析结论
  104. chart.setAnalysisConclusion(content.substring(index+3).trim());
  105. //保存到数据库
  106. chart.setState("成功");
  107. chart.setExecuteMessage("AI生成图表成功");
  108. updateById(chart);
  109. });
  110. } catch (RejectedExecutionException e) {
  111. //e.printStackTrace();
  112. log.error("线程池已满,请稍后再试",e);
  113. chart.setState("失败");
  114. chart.setExecuteMessage("系统异常");
  115. updateById(chart);
  116. }
  117. return chartId;
  118. }
  119. @Override
  120. public PageVO getChartPage(Integer pageNum, Integer pageSize, String name, Long userId) {
  121. if (!SecurityUtils.isAdmin()){
  122. userId = SecurityUtils.getUserId();
  123. }
  124. LambdaQueryWrapper<Chart> lambdaQueryWrapper = new LambdaQueryWrapper<Chart>()
  125. .like(StringUtils.hasText(name), Chart::getName, name)
  126. .eq(userId != null, Chart::getUserId, userId);
  127. Page<Chart> page = page(new Page<Chart>(pageNum, pageSize),lambdaQueryWrapper);
  128. List<ChartVO> voList = new ArrayList<>();
  129. for (Chart chart : page.getRecords()) {
  130. ChartVO chartVO = BeanCopyUtil.copyBean(chart, ChartVO.class);
  131. chartVO.setId(chart.getId().toString());
  132. chartVO.setUserId(chart.getUserId().toString());
  133. voList.add(chartVO);
  134. }
  135. PageVO pageVO = new PageVO(voList, page.getTotal());
  136. return pageVO;
  137. }
  138. @Override
  139. public ChartVO generateChartByAI(ChartDTO chartDTO, MultipartFile file) {
  140. //读数据
  141. String csvData = "";
  142. long charId = IdUtil.getSnowflake(1, 1).nextId();
  143. Chart chart = BeanCopyUtil.copyBean(chartDTO, Chart.class);
  144. chart.setId(charId);
  145. chart.setUserId(SecurityUtils.getUserId());
  146. chart.setState("等待中");
  147. try {
  148. csvData = ExcelUtils.excel2csv(file.getInputStream());
  149. log.info("上传的数据为:\n{}", csvData);
  150. } catch (IOException e) {
  151. e.printStackTrace();
  152. }
  153. if (csvData.length()>3000){
  154. chart.setState("失败");
  155. chart.setExecuteMessage("数据量过大,请上传小于3000行的数据");
  156. chart.setChartData("");
  157. save(chart);
  158. throw new SystemException(500, "数据量过大,请上传小于3000行的数据");
  159. }
  160. chart.setChartData(csvData);
  161. save(chart);
  162. StringBuilder message = new StringBuilder("原始数据:\n");
  163. message.append(csvData);
  164. message.append("分析目标:\n");
  165. message.append(chartDTO.getAnalysisTarget());
  166. message.append("\n.使用").append(chartDTO.getChartType()).append("进行可视化分析.\n");
  167. chart.setState("生成中");
  168. chart.setExecuteMessage("AI正在生成图表");
  169. updateById(chart);
  170. //配置prompt向AI发送请求
  171. HttpRequestData requestData = AiUtil.createDefaultRequestData(message.toString());
  172. HttpResponseData responseData = AiUtil.doChat(requestData);
  173. //解析AI返回的数据
  174. //ChartVO chartVO = BeanCopyUtil.copyBean(chartDTO, ChartVO.class);
  175. String content = responseData.getChoices().get(0).getMessage().getContent();
  176. log.info("AI返回的数据为:{}", content);
  177. int index = content.indexOf("```");
  178. int endIndex = content.lastIndexOf("```");
  179. if (index == -1 || endIndex == -1){
  180. chart.setState("失败");
  181. chart.setExecuteMessage("AI生成图表失败");
  182. updateById(chart);
  183. throw new SystemException(500, "AI生成图表失败");
  184. }
  185. //数据可视化,Echarts的option代码
  186. chart.setGeneratedChartData(content.substring(index+7, endIndex).trim());
  187. index = endIndex;
  188. //分析结论
  189. chart.setAnalysisConclusion(content.substring(index+3).trim());
  190. //更新数据库
  191. chart.setState("成功");
  192. chart.setExecuteMessage("图表生成成功");
  193. updateById(chart);
  194. ChartVO chartVO = BeanCopyUtil.copyBean(chart, ChartVO.class);
  195. return chartVO;
  196. }
  197. }