From a1dcd7572e9e08b9caaf91af65ae0ac6f344c30c Mon Sep 17 00:00:00 2001 From: brian Date: Fri, 14 Jul 2023 16:57:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=95=E5=85=A5AI=E5=88=86=E6=9E=90=20?= =?UTF-8?q?=E7=94=9F=E6=88=90Echarts=E4=BB=A3=E7=A0=81=E5=92=8C=E5=88=86?= =?UTF-8?q?=E6=9E=90=E7=BB=93=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 ++ .../peng/answerbi/constant/BiConstant.java | 21 ++++++ .../answerbi/controller/ChartController.java | 64 +++++++++++-------- .../top/peng/answerbi/manager/AiManager.java | 63 ++++++++++++++++++ .../model/dto/user/UserQueryRequest.java | 9 +-- .../peng/answerbi/model/vo/BiResponse.java | 33 ++++++++++ .../top/peng/answerbi/model/vo/UserVO.java | 5 ++ .../service/impl/UserServiceImpl.java | 12 ++-- src/main/resources/application.yml | 7 +- .../peng/answerbi/manager/AiManagerTest.java | 38 +++++++++++ 10 files changed, 214 insertions(+), 43 deletions(-) create mode 100644 src/main/java/top/peng/answerbi/constant/BiConstant.java create mode 100644 src/main/java/top/peng/answerbi/manager/AiManager.java create mode 100644 src/main/java/top/peng/answerbi/model/vo/BiResponse.java create mode 100644 src/test/java/top/peng/answerbi/manager/AiManagerTest.java diff --git a/pom.xml b/pom.xml index 5d98b49..6c45f46 100644 --- a/pom.xml +++ b/pom.xml @@ -121,6 +121,11 @@ spring-boot-starter-test test + + com.yucongming + yucongming-java-sdk + 0.0.3 + diff --git a/src/main/java/top/peng/answerbi/constant/BiConstant.java b/src/main/java/top/peng/answerbi/constant/BiConstant.java new file mode 100644 index 0000000..a966fbc --- /dev/null +++ b/src/main/java/top/peng/answerbi/constant/BiConstant.java @@ -0,0 +1,21 @@ +/* + * @(#)BiConstant.java + * + * Copyright © 2023 YunPeng Corporation. + */ +package top.peng.answerbi.constant; + +/** + * BiConstant Bi常量 + * + * @author yunpeng + * @version 1.0 2023/7/14 + */ +public interface BiConstant { + /** + * Bi模型id + */ + Long BI_MODEL_ID = 1679729045626982402L; + + String BI_RESULT_SEPARATOR = "【【【【【"; +} diff --git a/src/main/java/top/peng/answerbi/controller/ChartController.java b/src/main/java/top/peng/answerbi/controller/ChartController.java index afaade0..bd97e05 100644 --- a/src/main/java/top/peng/answerbi/controller/ChartController.java +++ b/src/main/java/top/peng/answerbi/controller/ChartController.java @@ -13,10 +13,12 @@ import top.peng.answerbi.common.CommonResponse; import top.peng.answerbi.common.DeleteRequest; import top.peng.answerbi.common.ErrorCode; import top.peng.answerbi.common.ResultUtils; +import top.peng.answerbi.constant.BiConstant; import top.peng.answerbi.constant.FileConstant; import top.peng.answerbi.constant.UserConstant; import top.peng.answerbi.exception.BusinessException; import top.peng.answerbi.exception.ThrowUtils; +import top.peng.answerbi.manager.AiManager; import top.peng.answerbi.model.dto.chart.ChartAddRequest; import top.peng.answerbi.model.dto.chart.ChartEditRequest; import top.peng.answerbi.model.dto.chart.ChartQueryRequest; @@ -26,6 +28,7 @@ import top.peng.answerbi.model.dto.file.UploadFileRequest; import top.peng.answerbi.model.entity.Chart; import top.peng.answerbi.model.entity.User; import top.peng.answerbi.model.enums.FileUploadBizEnum; +import top.peng.answerbi.model.vo.BiResponse; import top.peng.answerbi.service.ChartService; import top.peng.answerbi.service.UserService; import javax.annotation.Resource; @@ -56,6 +59,9 @@ public class ChartController { @Resource private UserService userService; + @Resource + private AiManager aiManager; + private final static Gson GSON = new Gson(); // region 增删改查 @@ -228,7 +234,7 @@ public class ChartController { * @return */ @PostMapping("/gen") - public CommonResponse genChartByAi(@RequestPart("file") MultipartFile multipartFile, + public CommonResponse genChartByAi(@RequestPart("file") MultipartFile multipartFile, GenChartByAiRequest genChartByAiRequest, HttpServletRequest request) { String chartName = genChartByAiRequest.getChartName(); String goal = genChartByAiRequest.getGoal(); @@ -240,36 +246,38 @@ public class ChartController { //如果名称不为空,并且名称长度大于100,就抛出异常,并给出提示 ThrowUtils.throwIf(StringUtils.isNotBlank(chartName) && chartName.length() > 100,ErrorCode.PARAMS_ERROR,"图表名称过长"); + //通过request对象拿到用户id(必须登录才能使用) + User loginUser = userService.getLoginUser(request); + //用户输入 StringBuilder userInput = new StringBuilder(); - userInput.append("你是一个数据分析师,接下来我会给你我的分析目标和原始数据,请告诉我分析结论。").append("\n"); - userInput.append("分析目标:").append(goal).append("\n"); - + userInput.append("分析需求:").append("\n"); + //拼接分析目标 + String userGoal = goal; + if (StringUtils.isNotBlank(chartType)){ + userGoal += ",请使用" + chartType; + } + userInput.append(userGoal).append("\n"); + userInput.append("原始数据:").append("\n"); //压缩后的数据 - 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); - } - } - }*/ + String csvData = ExcelUtils.excelToCsv(multipartFile); + userInput.append(csvData).append("\n"); + + String aiResult = aiManager.doChat(BiConstant.BI_MODEL_ID, userInput.toString()); + BiResponse biResponse = aiManager.aiAnsToBiResp(aiResult); + + //插入数据库 + Chart chart = new Chart(); + BeanUtils.copyProperties(biResponse,chart); + chart.setChartName(chartName); + chart.setGoal(goal); + chart.setChartType(chartType); + chart.setChartData(csvData); + chart.setUserId(loginUser.getId()); + boolean saveResult = chartService.save(chart); + ThrowUtils.throwIf(!saveResult, ErrorCode.SYSTEM_ERROR, "图表保存失败"); + biResponse.setChartId(chart.getId()); + return ResultUtils.success(biResponse); } } diff --git a/src/main/java/top/peng/answerbi/manager/AiManager.java b/src/main/java/top/peng/answerbi/manager/AiManager.java new file mode 100644 index 0000000..d9bc887 --- /dev/null +++ b/src/main/java/top/peng/answerbi/manager/AiManager.java @@ -0,0 +1,63 @@ +/* + * @(#)AiManager.java + * + * Copyright © 2023 YunPeng Corporation. + */ +package top.peng.answerbi.manager; + +import com.yupi.yucongming.dev.client.YuCongMingClient; +import com.yupi.yucongming.dev.common.BaseResponse; +import com.yupi.yucongming.dev.model.DevChatRequest; +import com.yupi.yucongming.dev.model.DevChatResponse; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; +import top.peng.answerbi.common.ErrorCode; +import top.peng.answerbi.constant.BiConstant; +import top.peng.answerbi.exception.ThrowUtils; +import top.peng.answerbi.model.vo.BiResponse; + +/** + * AiManager AI对话 + * + * @author yunpeng + * @version 1.0 2023/7/14 + */ +@Service +public class AiManager { + + @Resource + private YuCongMingClient yuCongMingClient; + + /** + * AI 对话 + * + * @param modelId 模型id + * @param message 提问 + * @return 结果 + */ + public String doChat(long modelId, String message){ + DevChatRequest devChatRequest = new DevChatRequest(); + devChatRequest.setModelId(modelId); + devChatRequest.setMessage(message); + + BaseResponse response = yuCongMingClient.doChat(devChatRequest); + + ThrowUtils.throwIf(response == null, ErrorCode.SYSTEM_ERROR,"AI响应错误"); + + return response.getData().getContent(); + } + + /** + * 将AI生成的结果转换为 BiResponse + * @param aiAnswer AI 对话 结果 + * @return BiResponse对象 + */ + public BiResponse aiAnsToBiResp(String aiAnswer){ + String[] aiResultSplit = aiAnswer.split(BiConstant.BI_RESULT_SEPARATOR); + ThrowUtils.throwIf(aiResultSplit.length < 3,ErrorCode.SYSTEM_ERROR,"AI 生成错误"); + BiResponse biResponse = new BiResponse(); + biResponse.setGenChart(aiResultSplit[1].trim()); + biResponse.setGenResult(aiResultSplit[2].trim()); + return biResponse; + } +} diff --git a/src/main/java/top/peng/answerbi/model/dto/user/UserQueryRequest.java b/src/main/java/top/peng/answerbi/model/dto/user/UserQueryRequest.java index 722a2c8..3388552 100644 --- a/src/main/java/top/peng/answerbi/model/dto/user/UserQueryRequest.java +++ b/src/main/java/top/peng/answerbi/model/dto/user/UserQueryRequest.java @@ -20,14 +20,9 @@ public class UserQueryRequest extends PageRequest implements Serializable { private Long id; /** - * 开放平台id + * 用户账号 */ - private String unionId; - - /** - * 公众号openId - */ - private String mpOpenId; + private String userAccount; /** * 用户昵称 diff --git a/src/main/java/top/peng/answerbi/model/vo/BiResponse.java b/src/main/java/top/peng/answerbi/model/vo/BiResponse.java new file mode 100644 index 0000000..39da24b --- /dev/null +++ b/src/main/java/top/peng/answerbi/model/vo/BiResponse.java @@ -0,0 +1,33 @@ +/* + * @(#)BiResponse.java + * + * Copyright © 2023 YunPeng Corporation. + */ +package top.peng.answerbi.model.vo; + +import lombok.Data; + +/** + * BiResponse Bi 的返回结果 + * + * @author yunpeng + * @version 1.0 2023/7/14 + */ +@Data +public class BiResponse { + + /** + * 生成的图表数据 + */ + private String genChart; + + /** + * 生成的分析结论 + */ + private String genResult; + + /** + * 新生成的图表Id + */ + private Long chartId; +} diff --git a/src/main/java/top/peng/answerbi/model/vo/UserVO.java b/src/main/java/top/peng/answerbi/model/vo/UserVO.java index 47f64d4..23f3788 100644 --- a/src/main/java/top/peng/answerbi/model/vo/UserVO.java +++ b/src/main/java/top/peng/answerbi/model/vo/UserVO.java @@ -23,6 +23,11 @@ public class UserVO implements Serializable { */ private String userName; + /** + * 用户账号 + */ + private String userAccount; + /** * 用户头像 */ diff --git a/src/main/java/top/peng/answerbi/service/impl/UserServiceImpl.java b/src/main/java/top/peng/answerbi/service/impl/UserServiceImpl.java index 756ccd8..60b1cb1 100644 --- a/src/main/java/top/peng/answerbi/service/impl/UserServiceImpl.java +++ b/src/main/java/top/peng/answerbi/service/impl/UserServiceImpl.java @@ -217,20 +217,18 @@ public class UserServiceImpl extends ServiceImpl implements Us throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空"); } Long id = userQueryRequest.getId(); - String unionId = userQueryRequest.getUnionId(); - String mpOpenId = userQueryRequest.getMpOpenId(); String userName = userQueryRequest.getUserName(); + String userAccount = userQueryRequest.getUserAccount(); String userProfile = userQueryRequest.getUserProfile(); String userRole = userQueryRequest.getUserRole(); String sortField = userQueryRequest.getSortField(); String sortOrder = userQueryRequest.getSortOrder(); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(id != null, "id", id); - queryWrapper.eq(StringUtils.isNotBlank(unionId), "unionId", unionId); - queryWrapper.eq(StringUtils.isNotBlank(mpOpenId), "mpOpenId", mpOpenId); - queryWrapper.eq(StringUtils.isNotBlank(userRole), "userRole", userRole); - queryWrapper.like(StringUtils.isNotBlank(userProfile), "userProfile", userProfile); - queryWrapper.like(StringUtils.isNotBlank(userName), "userName", userName); + queryWrapper.eq(StringUtils.isNotBlank(userAccount), "user_account", userAccount); + queryWrapper.eq(StringUtils.isNotBlank(userRole), "user_role", userRole); + queryWrapper.like(StringUtils.isNotBlank(userProfile), "user_profile", userProfile); + queryWrapper.like(StringUtils.isNotBlank(userName), "user_name", userName); queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC), sortField); return queryWrapper; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index fc0fe00..6c32cd0 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -86,4 +86,9 @@ cos: accessKey: xxx secretKey: xxx region: xxx - bucket: xxx \ No newline at end of file + bucket: xxx + +yuapi: + client: + access-key: xyjjaiosvyjxfk4t98g0qlrplfijigrz + secret-key: q6lppq8sdz587jggbttg35nrsj1iyofl \ No newline at end of file diff --git a/src/test/java/top/peng/answerbi/manager/AiManagerTest.java b/src/test/java/top/peng/answerbi/manager/AiManagerTest.java new file mode 100644 index 0000000..6b54874 --- /dev/null +++ b/src/test/java/top/peng/answerbi/manager/AiManagerTest.java @@ -0,0 +1,38 @@ +package top.peng.answerbi.manager; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Arrays; +import javax.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import top.peng.answerbi.constant.BiConstant; + +/** + * AiManagerTest + * + * @author yunpeng + * @version 1.0 2023/7/14 + */ +@SpringBootTest +class AiManagerTest { + + @Resource + private AiManager aiManager; + + @Test + void doChat() { + String answer = aiManager.doChat(1679729045626982402L, "分析需求:\n" + + "分析网站用户的增长情况\n" + + "原始数据:\n" + + "日期,用户数\n" + + "1号,10\n" + + "2号,20\n" + + "3号,30"); + String[] aiResultSplit = answer.split(BiConstant.BI_RESULT_SEPARATOR); + System.out.println(aiResultSplit[0]); + System.out.println(aiResultSplit[1]); + System.out.println(aiResultSplit[2]); + } +} \ No newline at end of file