소스 검색

Merge commit '1d982dbd32ac30270709857e46e958dd89fe7dd3'

lihao16 4 달 전
부모
커밋
05087364e9

+ 3 - 1
smsb-admin/src/main/resources/application.yml

@@ -128,7 +128,9 @@ dify:
   # 数促-内容总结公共智能体
   sc_agent:
     apiKey: app-zyDMoN9vjjvfgHompclx3FkW
-
+  sc_dataset:
+    # 诊断评估知识库ID
+    report: e9c7f861-d891-4bff-87d0-3c5bb5fe7a1d
 
 # Sa-Token配置
 sa-token:

+ 199 - 28
smsb-modules/smsb-digital-promotion/src/main/java/com/inspur/digital/service/impl/SmsbAppointmentInfoServiceImpl.java

@@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.github.therapi.runtimejavadoc.repack.com.eclipsesource.json.JsonObject;
+import com.inspur.device.domain.vo.DifyDatasetsFileRspData;
 import com.inspur.device.domain.vo.SmsbDeviceGroupRelVo;
 import com.inspur.device.mapper.SmsbDeviceGroupRelMapper;
 import com.inspur.digital.domain.SmsbAppointmentInfo;
@@ -38,10 +39,17 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Service;
 
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 预约信息Service业务层处理
@@ -73,6 +81,16 @@ public class SmsbAppointmentInfoServiceImpl implements ISmsbAppointmentInfoServi
     private String difyBaseUrl;
     @Value("${dify.sc_agent.apiKey}")
     private String difyScAgentApiKey;
+    @Value("${dify.sc_dataset.report}")
+    private String difyScDatasetReportId;
+    @Value("${server.tempDir}")
+    private String tempDir;
+    @Value("${dify.datasets.apiKey}")
+    private String datasetsApiKey;
+    /**
+     * 知识库API
+     */
+    private final static String API_DATASETS_COMMON = "/v1/datasets";
     /**
      * 默认场景序号 诊断评估
      */
@@ -224,59 +242,68 @@ public class SmsbAppointmentInfoServiceImpl implements ISmsbAppointmentInfoServi
             JSONObject reportContent = reportMapJson.getJSONObject("reportContent");
             // 2-1 评分标准:
             JSONArray standards = reportContent.getJSONArray("standards");
-            StringBuilder standardResult = new StringBuilder();
-            standardResult.append("评分标准:\n");
-            for (int i = 0; i < standards.size(); i++) {
-
-                standardResult.append("等级名称:").append(standards.getJSONObject(i).getStr("levelName")).append("\n");
-                standardResult.append("等级描述:").append(standards.getJSONObject(i).get("levelDesc")).append("\n");
-                standardResult.append("最小分值:").append(standards.getJSONObject(i).get("minScore")).append("\n");
-                standardResult.append("最大分值:").append(standards.getJSONObject(i).get("maxScore")).append("\n");
+            if (null != standards && standards.size() > 0) {
+                StringBuilder standardResult = new StringBuilder();
+                standardResult.append("评分标准:\n");
+                for (int i = 0; i < standards.size(); i++) {
+
+                    standardResult.append("等级名称:").append(standards.getJSONObject(i).getStr("levelName")).append("\n");
+                    standardResult.append("等级描述:").append(standards.getJSONObject(i).get("levelDesc")).append("\n");
+                    standardResult.append("最小分值:").append(standards.getJSONObject(i).get("minScore")).append("\n");
+                    standardResult.append("最大分值:").append(standards.getJSONObject(i).get("maxScore")).append("\n");
+                }
+                result.add(standardResult.toString());
             }
-            result.add(standardResult.toString());
             // 2-2 当前分值
             result.add("当前分值:" + reportContent.get("score"));
             // 2-3 对标情况
             JSONObject benchmarking = reportContent.getJSONObject("benchmarking");
             // 2-3-1 等级情况
             JSONArray rate = benchmarking.getJSONArray("rate");
-            StringBuilder rateResult = new StringBuilder();
-            for (int i = 0; i < rate.size(); i++) {
-                rateResult.append("等级情况:\n");
-                rateResult.append("等级名称:").append(rate.getJSONObject(i).getStr("rate")).append("\n");
-                rateResult.append("等级数量:").append(rate.getJSONObject(i).get("quantity")).append("\n");
-                rateResult.append("平均分值:").append(rate.getJSONObject(i).get("avg")).append("\n");
+            if (null != rate && rate.size() > 0) {
+                StringBuilder rateResult = new StringBuilder();
+                for (int i = 0; i < rate.size(); i++) {
+                    rateResult.append("等级情况:\n");
+                    rateResult.append("等级名称:").append(rate.getJSONObject(i).getStr("rate")).append("\n");
+                    rateResult.append("等级数量:").append(rate.getJSONObject(i).get("quantity")).append("\n");
+                    rateResult.append("平均分值:").append(rate.getJSONObject(i).get("avg")).append("\n");
+                }
+                result.add(rateResult.toString());
             }
-            result.add(rateResult.toString());
             // 2-3-2 得分情况
             JSONObject location = benchmarking.getJSONObject("location");
-            StringBuilder locationResult = new StringBuilder();
-            locationResult.append("得分情况:\n");
-            locationResult.append("自评高于贵公司的数量:").append(location.get("current")).append("\n");
-            locationResult.append("自评等于贵公司的数量:").append(location.get("equalCount")).append("\n");
-            locationResult.append("总数量:").append(location.get("count")).append("\n");
-            result.add(locationResult.toString());
+            if (null != location) {
+                StringBuilder locationResult = new StringBuilder();
+                locationResult.append("得分情况:\n");
+                locationResult.append("自评高于贵公司的数量:").append(location.get("current")).append("\n");
+                locationResult.append("自评等于贵公司的数量:").append(location.get("equalCount")).append("\n");
+                locationResult.append("总数量:").append(location.get("count")).append("\n");
+                result.add(locationResult.toString());
+            }
             // 2-4 分析建议
             JSONObject suggestion = reportContent.getJSONObject("suggestion");
             // 2-4-1 劣势列表
             JSONArray disadvantage = suggestion.getJSONArray("disadvantage");
+            if (null != disadvantage && disadvantage.size() > 0){
             StringBuilder disadvantageResult = new StringBuilder();
             for (int i = 0; i < disadvantage.size(); i++) {
                 disadvantageResult.append("劣势列表:\n");
                 disadvantageResult.append(disadvantage.get(i)).append("\n");
             }
             result.add(disadvantageResult.toString());
+            }
             // 2-4-2 优势列表
             JSONArray advantage = suggestion.getJSONArray("advantage");
-            StringBuilder advantageResult = new StringBuilder();
-            for (int i = 0; i < advantage.size(); i++) {
-                advantageResult.append("优势列表:\n");
-                advantageResult.append(advantage.get(i)).append("\n");
+            if (null != advantage && advantage.size() > 0) {
+                StringBuilder advantageResult = new StringBuilder();
+                for (int i = 0; i < advantage.size(); i++) {
+                    advantageResult.append("优势列表:\n");
+                    advantageResult.append(advantage.get(i)).append("\n");
+                }
+                result.add(advantageResult.toString());
             }
-            result.add(advantageResult.toString());
             // 2-4-3 相关建议列表
             JSONObject content = suggestion.getJSONObject("content");
-
             result.add("相关建议:" + content.toString()
                 .replaceAll("\\{", "").replaceAll("}", "")
                 .replaceAll("\\[", "").replaceAll("]", "").trim());
@@ -393,6 +420,8 @@ public class SmsbAppointmentInfoServiceImpl implements ISmsbAppointmentInfoServi
             return R.ok(result);
         }
         List<SmsbScDeviceStartInfoVo> deviceStartInfoList = new ArrayList<>();
+        // 针对评估所有内容集合
+        List<String> reportContentList = new ArrayList<>();
         for (SmsbDeviceGroupRelVo deviceGroupRel : deviceGroupRelList) {
             SmsbScDeviceStartInfoVo deviceStartInfo = new SmsbScDeviceStartInfoVo();
             deviceStartInfo.setIdentifier(deviceGroupRel.getDeviceIdentifier());
@@ -404,6 +433,12 @@ public class SmsbAppointmentInfoServiceImpl implements ISmsbAppointmentInfoServi
                     .eq(SmsbDeviceChatScReport::getType, 1)
                     .orderByDesc(SmsbDeviceChatScReport::getAppointmentId).last("limit 1"));
                 deviceStartInfo.setHelloWorld(report.getContent());
+                List<SmsbDeviceChatScReportVo> reportVoList = smsbDeviceChatScReportMapper.selectVoList(new LambdaQueryWrapper<SmsbDeviceChatScReport>()
+                    .eq(SmsbDeviceChatScReport::getAppointmentId, appointmentInfo.getId())
+                    .eq(SmsbDeviceChatScReport::getType, 2));
+                if (CollectionUtils.isNotEmpty(reportVoList)) {
+                    reportContentList = reportVoList.stream().map(SmsbDeviceChatScReportVo::getContent).collect(Collectors.toList());
+                }
             } else if (deviceGroupRel.getSceneSort().equals(DEFAULT_SCENE_SORT_2)) {
 
             } else if (deviceGroupRel.getSceneSort().equals(DEFAULT_SCENE_SORT_3)) {
@@ -415,6 +450,142 @@ public class SmsbAppointmentInfoServiceImpl implements ISmsbAppointmentInfoServi
         }
         result.setDeviceStartInfoList(deviceStartInfoList);
         // TODO 异步现场启动 更新知识库
+        // 线程1 更新评估报告知识库
+        syncDatasets(reportContentList, difyScDatasetReportId);
+
         return R.ok(result);
     }
+
+    private void syncDatasets(List<String> contentList, String datasetsId) {
+        Runnable transTask = () -> {
+            try {
+                log.info("syncDatasets thread begin contentList.size(): " + contentList.size() + ",datasetsId : " + datasetsId);
+                // 组装条目
+                StringBuilder allContentStr = new StringBuilder();
+                for (String content : contentList) {
+                    allContentStr.append("###").append("\n");
+                    allContentStr.append(content).append("\n");
+                }
+                String filePath = createTempFile(allContentStr.toString());
+                log.info("syncDatasets thread createTempFile success tempFilePath = " + filePath);
+                boolean uploadResult = uploadDatasetsToDify(datasetsId,filePath);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+            log.info("createReport thread end !");
+        };
+        // 提交Runnable任务到线程池
+        threadPoolTaskExecutor.submit(transTask);
+    }
+
+    private boolean uploadDatasetsToDify(String datasetsId, String filePath) {
+        // 1、 根据知识库ID 获取文件列表
+        List<DifyDatasetsFileRspData> datasetsFiles = getDatasetsFiles(datasetsId);
+        // 2、如果知识库文件不为空,删除知识库内文件
+        if (!CollectionUtils.isEmpty(datasetsFiles)) {
+            for (DifyDatasetsFileRspData datasetsFile : datasetsFiles) {
+                deleteDatasetsFiles(datasetsId,datasetsFile.getId());
+            }
+        }
+        // 3、上传文件
+        boolean uploadResult = uploadDatasetsFiles(datasetsId,filePath);
+        log.info("uploadDatasetsToDify datasetsId is " + datasetsId + ",result = " + uploadResult);
+        return true;
+    }
+
+    private boolean uploadDatasetsFiles(String datasetsId, String filePath) {
+        // 调用dify接口,将文件上传至dify
+        String requestUrl = difyBaseUrl + API_DATASETS_COMMON + "/" + datasetsId + "/document/create-by-file";
+        String requestBody = createAddFileRequestBody();
+
+        // 发送请求
+        HttpResponse response = HttpRequest.post(requestUrl)
+            .header("Authorization", "Bearer " + datasetsApiKey)
+            .header("User-Agent","PostmanRuntime/7.26.8")
+            .form("data", requestBody)
+            .form("file", new File(filePath))
+            .execute();
+        // 处理响应
+        if (!response.isOk()) {
+            return false;
+        }
+        return true;
+    }
+    private String createAddFileRequestBody() {
+        // 构建 JSON 格式的 data 参数
+        JSONObject dataJson = new JSONObject();
+        // 1-索引方式
+        dataJson.put("indexing_technique", "high_quality");
+
+        // 2-处理规则
+        JSONObject processRule = new JSONObject();
+        // 2-1 清洗、分段模式
+        processRule.put("mode", "custom");
+        // 2-2 自定义规则
+        JSONObject rules = new JSONObject();
+        // 2-2-1 预处理规则
+        JSONArray preProcessingRules = new JSONArray();
+        JSONObject rule1 = new JSONObject();
+        rule1.put("id", "remove_extra_spaces");
+        rule1.put("enabled", true);
+        preProcessingRules.add(rule1);
+        JSONObject rule2 = new JSONObject();
+        rule2.put("id", "remove_urls_emails");
+        rule2.put("enabled", true);
+        preProcessingRules.add(rule2);
+        // 2-2-1 分段规则
+        JSONObject segmentation = new JSONObject();
+        segmentation.put("separator", "###");
+        segmentation.put("max_tokens", 800);
+        rules.put("pre_processing_rules", preProcessingRules);
+        rules.put("segmentation", segmentation);
+        processRule.put("rules", rules);
+
+        dataJson.put("process_rule", processRule);
+        return dataJson.toString();
+    }
+
+    private void deleteDatasetsFiles(String datasetsId,String datasetsFileId) {
+        String requestUrl = difyBaseUrl + API_DATASETS_COMMON + "/" + datasetsId + "/documents/" + datasetsFileId;
+        HttpRequest request = HttpRequest.delete(requestUrl)
+            .header("Authorization", "Bearer " + datasetsApiKey)
+            .header("User-Agent","PostmanRuntime/7.26.8");
+        HttpResponse response = request.execute();
+        log.info("delete datasetsId's datasetsFileId is " + response.isOk());
+    }
+
+    private List<DifyDatasetsFileRspData> getDatasetsFiles(String datasetsId) {
+        String requestUrl = difyBaseUrl + API_DATASETS_COMMON + "/" + datasetsId + "/documents?page=1&limit=100";
+        HttpRequest request = HttpRequest.get(requestUrl)
+            .header("Authorization", "Bearer " + datasetsApiKey)
+            .header("User-Agent","PostmanRuntime/7.26.8");
+        HttpResponse response = request.execute();
+        if (!response.isOk()) {
+            return null;
+        }
+        String responseBody = response.body();
+        JSONObject jsonObject = JSONUtil.parseObj(responseBody);
+        // 1 如果结果为0 直接返回
+        Integer total = jsonObject.getInt("total");
+        if (total == 0) {
+            return null;
+        }
+        // data中取出知识库列表
+        List<DifyDatasetsFileRspData> datasetsFiles = jsonObject.getJSONArray("data").toList(DifyDatasetsFileRspData.class);
+        log.info("getDatasetsFiles datasetsId is " + datasetsId + ",total = " + total + ",datasetsFiles size: " + datasetsFiles.size());
+        return datasetsFiles;
+    }
+
+    private String createTempFile(String datasetsContent) throws IOException {
+        // 创建一个临时路径
+        String localPath = tempDir + "/" + System.currentTimeMillis();
+        Path path = Paths.get(localPath);
+        Files.createDirectories(path);
+        // 将datasetsContent保存到临时路径
+        String filePath = localPath + "/" + System.currentTimeMillis() + ".txt";
+        Path filePathObj = Paths.get(filePath);
+        byte[] contentBytes = datasetsContent.getBytes(StandardCharsets.UTF_8);
+        Files.write(filePathObj, contentBytes);
+        return filePath;
+    }
 }