From eca86de28864b466de23e6f2287c6844b329935c Mon Sep 17 00:00:00 2001
From: xueqingkun <xueqingkun@126.com>
Date: Wed, 29 May 2024 16:25:05 +0800
Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E6=B5=8B=E8=AF=95=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../test/java/com/supervision/VecTest.java    | 693 ++++++++++++++++++
 1 file changed, 693 insertions(+)
 create mode 100644 virtual-patient-web/src/test/java/com/supervision/VecTest.java

diff --git a/virtual-patient-web/src/test/java/com/supervision/VecTest.java b/virtual-patient-web/src/test/java/com/supervision/VecTest.java
new file mode 100644
index 00000000..1b329f5f
--- /dev/null
+++ b/virtual-patient-web/src/test/java/com/supervision/VecTest.java
@@ -0,0 +1,693 @@
+package com.supervision;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.NumberUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import cn.hutool.poi.excel.ExcelReader;
+import cn.hutool.poi.excel.ExcelUtil;
+import cn.hutool.poi.excel.ExcelWriter;
+import com.supervision.model.AskPatientAnswer;
+import com.supervision.model.AskTemplateQuestionLibrary;
+import com.supervision.model.CommonDic;
+import com.supervision.service.AskPatientAnswerService;
+import com.supervision.service.AskTemplateQuestionLibraryService;
+import com.supervision.service.CommonDicService;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import java.io.Console;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Slf4j
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@RunWith(SpringJUnit4ClassRunner.class)
+public class VecTest {
+
+
+    private static final String BASE_URL = "http://192.168.10.137:8719";
+    @Autowired
+    private AskTemplateQuestionLibraryService askTemplateQuestionLibraryService;
+    @Autowired
+    private CommonDicService commonDicService;
+    @Autowired
+    private AskPatientAnswerService askPatientAnswerService;
+
+    @Test
+    public void questionCompareGenerateTest() {
+        // initVecData first step
+        String filePath = "F:\\tmp\\1\\副本医生临床问诊问题收集v1.xlsx";
+
+        ExcelReader reader = ExcelUtil.getReader(filePath, 1);
+        List<Map<String, Object>> dataList = reader.readAll();
+
+        // 加载数据库中的问题数据
+        List<AskTemplateQuestionLibrary> questionLibraries = askTemplateQuestionLibraryService.list();
+        Map<String, AskTemplateQuestionLibrary> idMapQuestion = questionLibraries.stream().collect(Collectors.toMap(AskTemplateQuestionLibrary::getId, v -> v));
+        List<CommonDic> commonDics = commonDicService.lambdaQuery().eq(CommonDic::getGroupCode, "AQT").list();
+        Map<Long, CommonDic> pathMapDic = commonDics.stream().collect(Collectors.toMap(CommonDic::getId, v -> v));
+
+
+        for (Map<String, Object> map : dataList) {
+            String question = MapUtil.getStr(map, "部分问诊问题(示例)");
+            //String questionCode = askMatch(StrUtil.trim(question));
+            String questionCode = "";
+            String matchQuestion = "";
+            String matchScore = "";
+            List<Map<String, Object>> maps = questionMatch(StrUtil.trim(question));
+            if (CollUtil.isNotEmpty(maps)) {
+                Map<String, Object> matchMap = maps.get(0);
+                questionCode = MapUtil.getStr(matchMap, "matchQuestionCode");
+                matchQuestion = MapUtil.getStr(matchMap, "matchQuestion");
+                matchScore = MapUtil.getStr(matchMap, "matchScore");
+            }
+            if (StrUtil.isEmpty(questionCode)) {
+                continue;
+            }
+            map.put("匹配到的问题Code", questionCode);
+            if (!NumberUtil.isNumber(questionCode)) {
+                log.warn("question:{}的匹配Code不是数字:{}", question, questionCode);
+                continue;
+            }
+            AskTemplateQuestionLibrary library = idMapQuestion.get(questionCode);
+            if (ObjectUtil.isNotEmpty(library)) {
+                map.put("匹配到的问题", matchQuestion);
+                CommonDic commonDic = pathMapDic.get(library.getDictId());
+                if (ObjectUtil.isNotEmpty(commonDic)) {
+                    String nameZhPath = commonDic.getNameZhPath();
+                    List<String> split = StrUtil.split(nameZhPath, "/");
+                    String first = split.get(0);
+                    String second = null;
+                    if (split.size() > 1) {
+                        second = split.get(1);
+                    }
+                    if (StrUtil.equals(MapUtil.getStr(map, "一级问诊类目"), first)
+                            && StrUtil.equals(MapUtil.getStr(map, "二级问诊类目"), second)) {
+                        map.put("匹配结果", "正确");
+                    } else {
+                        map.put("匹配结果", "错误");
+                    }
+                    map.put("匹配到的问题路径", commonDic.getNameZhPath());
+                    map.put("匹配到的字典id", commonDic.getId());
+                    map.put("相似度", matchScore);
+                }
+            }
+        }
+
+        log.info("开始把结果数据写入表格");
+        ExcelUtil.getWriter(filePath, "结果对比-3").write(dataList).flush();
+        log.info("结束把结果数据写入表格");
+    }
+
+    @Test
+    public void questionEqualGenerateTest() {
+
+        List<AskTemplateQuestionLibrary> libraries = askTemplateQuestionLibraryService.list()
+                .stream().peek(library -> library.getQuestion().forEach(StrUtil::trim))
+                .collect(Collectors.toList());
+
+        List<CommonDic> commonDics = commonDicService.lambdaQuery().eq(CommonDic::getGroupCode, "AQT").list();
+        Map<Long, CommonDic> dicMap = commonDics.stream().collect(Collectors.toMap(CommonDic::getId, v -> v));
+
+        // 构建问题map  id -->> question --->> library
+        Map<String, Map<String, AskTemplateQuestionLibrary>> questionMap = new HashMap<>();
+        for (AskTemplateQuestionLibrary library : libraries) {
+            Map<String, AskTemplateQuestionLibrary> map = library.getQuestion().stream().collect(Collectors.toMap(v -> v, v -> library));
+            questionMap.put(library.getId(), map);
+        }
+
+        // 循环处理数据
+        List<Map<String, Object>> result = new ArrayList<>();
+        for (AskTemplateQuestionLibrary library : libraries) {
+            List<String> questionList = library.getQuestion();
+            for (String sourceQuestion : questionList) {
+                //确认同组数据中是否存在相同的问题
+                long count = questionList.stream().filter(v -> StrUtil.equals(sourceQuestion, v)).count();
+                if (count > 1) {
+                    Map<String, Object> map = new HashMap<>();
+                    map.put("sourceId", library.getId());
+                    map.put("sourceDesc", library.getDescription());
+                    map.put("sourceQuestion", sourceQuestion);
+                    map.put("sourceQuestionCode", library.getCode());
+                    map.put("sourceDicPath", dicMap.get(library.getDictId()).getNameZhPath());
+                    map.put("targetId", library.getId());
+                    map.put("targetDesc", library.getDescription());
+                    map.put("targetQuestion", sourceQuestion);
+                    map.put("sameSource", "是");
+                    map.put("targetDicPath", dicMap.get(library.getDictId()).getNameZhPath());
+                    result.add(map);
+                }
+
+                // 确认是否存在重复的问题数据
+                for (Map.Entry<String, Map<String, AskTemplateQuestionLibrary>> firstEntry : questionMap.entrySet()) {
+                    if (StrUtil.equals(library.getId(), firstEntry.getKey())) {
+                        continue;
+                    }
+                    Map<String, AskTemplateQuestionLibrary> questionLibraryMap = firstEntry.getValue();
+                    for (Map.Entry<String, AskTemplateQuestionLibrary> secondEntry : questionLibraryMap.entrySet()) {
+                        String targetQuestion = secondEntry.getKey();
+                        AskTemplateQuestionLibrary targetLibrary = secondEntry.getValue();
+                        if (StrUtil.equals(sourceQuestion, targetQuestion)) {
+                            HashMap<String, Object> map = new HashMap<>();
+                            map.put("sourceId", library.getId());
+                            map.put("sourceDesc", library.getDescription());
+                            map.put("sourceQuestion", sourceQuestion);
+                            map.put("sourceDicPath", dicMap.get(library.getDictId()).getNameZhPath());
+                            map.put("targetId", targetLibrary.getId());
+                            map.put("targetDesc", targetLibrary.getDescription());
+                            map.put("targetQuestion", targetQuestion);
+                            // 如果id相等则是同源数据
+                            map.put("sameSource", "否");
+                            map.put("targetDicPath", dicMap.get(targetLibrary.getDictId()).getNameZhPath());
+                            result.add(map);
+                        }
+                    }
+                }
+            }
+        }
+
+        // 写出数据
+        String filePath = "F:\\tmp\\1\\问题库问题对比.xlsx";
+        ExcelWriter writer = ExcelUtil.getWriter(filePath, "完全相等对比");
+        writer.addHeaderAlias("sourceId", "源问题库id");
+        writer.addHeaderAlias("sourceDesc", "源问题库描述");
+        writer.addHeaderAlias("sourceQuestion", "源问题");
+        writer.addHeaderAlias("sourceDicPath", "源分类");
+        writer.addHeaderAlias("targetId", "目标问题库id");
+        writer.addHeaderAlias("targetDesc", "目标问题库描述");
+        writer.addHeaderAlias("targetQuestion", "目标问题");
+        writer.addHeaderAlias("sameSource", "是否同源");
+        writer.addHeaderAlias("targetDicPath", "目标分类");
+        writer.write(result).flush();
+
+    }
+
+    @Test
+    public void questionSimilarityGenerateTest() {
+
+        List<AskTemplateQuestionLibrary> questionLibraries = askTemplateQuestionLibraryService.list();
+        List<CommonDic> commonDics = commonDicService.lambdaQuery().eq(CommonDic::getGroupCode, "AQT").list();
+        Map<Long, CommonDic> dicMap = commonDics.stream().collect(Collectors.toMap(CommonDic::getId, v -> v));
+
+        Map<String, AskTemplateQuestionLibrary> libraryMap = questionLibraries.stream().collect(Collectors.toMap(AskTemplateQuestionLibrary::getId, library -> library));
+        // compare
+
+        List<Map<String, Object>> result = new ArrayList<>();
+        for (AskTemplateQuestionLibrary questionLibrary : questionLibraries) {
+            List<String> questionList = questionLibrary.getQuestion();
+            for (String question : questionList) {
+                List<Map<String, Object>> maps = questionMatch(question);
+                if (CollUtil.isEmpty(maps)) {
+                    log.warn("questionMatch:问题:{}没有匹配到结果", question);
+                    continue;
+                }
+                for (Map<String, Object> map : maps) {
+                    String targetId = MapUtil.getStr(map, "matchQuestionCode");
+                    if (!StrUtil.equals(questionLibrary.getId(), targetId)) {
+                        HashMap<String, Object> map1 = new HashMap<>();
+                        map1.put("sourceId", questionLibrary.getId());
+                        map1.put("sourceDesc", questionLibrary.getDescription());
+                        map1.put("sourceQuestion", question);
+                        CommonDic commonDic = dicMap.get(questionLibrary.getDictId());
+                        map1.put("sourceDicPath", commonDic.getNameZhPath());
+                        map1.put("targetId", targetId);
+                        AskTemplateQuestionLibrary targetLibrary = libraryMap.get(targetId);
+                        map1.put("targetDesc", targetLibrary.getDescription());
+                        map1.put("targetQuestion", MapUtil.getStr(map, "matchQuestion"));
+                        map1.put("matchScore", MapUtil.getStr(map, "matchScore"));
+                        map1.put("targetDicPath", dicMap.get(targetLibrary.getDictId()).getNameZhPath());
+                        result.add(map1);
+                    }
+                }
+            }
+        }
+
+        String filePath = "F:\\tmp\\1\\问题库问题对比.xlsx";
+        ExcelWriter writer = ExcelUtil.getWriter(filePath, "向量相似度对比");
+        writer.addHeaderAlias("sourceId", "源问题id");
+        writer.addHeaderAlias("sourceDesc", "源问题描述");
+        writer.addHeaderAlias("sourceQuestion", "源问题");
+        writer.addHeaderAlias("sourceDicPath", "源分类");
+        writer.addHeaderAlias("targetId", "目标问题");
+        writer.addHeaderAlias("targetDesc", "目标问题描述");
+        writer.addHeaderAlias("targetQuestion", "目标问题");
+        writer.addHeaderAlias("matchScore", "相似度");
+        writer.addHeaderAlias("targetDicPath", "目标分类");
+        writer.write(result, true);
+        writer.close();
+
+    }
+
+    @Test
+    public void questionSimilarityTopGenerateTest() {
+        List<AskTemplateQuestionLibrary> questionLibraries = askTemplateQuestionLibraryService.list();
+        List<CommonDic> commonDics = commonDicService.lambdaQuery().eq(CommonDic::getGroupCode, "AQT").list();
+        Map<Long, CommonDic> dicMap = commonDics.stream().collect(Collectors.toMap(CommonDic::getId, v -> v));
+        Map<String, AskTemplateQuestionLibrary> libraryMap = questionLibraries.stream().collect(Collectors.toMap(AskTemplateQuestionLibrary::getId, library -> library));
+
+        List<Map<String, Object>> result = new ArrayList<>();
+        for (AskTemplateQuestionLibrary questionLibrary : questionLibraries) {
+            for (String question : questionLibrary.getQuestion()) {
+
+                List<Map<String, Object>> maps = questionMatch(question);
+                // 只获取前四条数据
+                if (CollUtil.isEmpty(maps)) {
+                    log.warn("questionMatch:问题:{}没有匹配到结果", question);
+                    continue;
+                }
+
+                if (maps.size() > 3) {
+                    // 截取前四条数据
+                    maps = maps.subList(0, 4);
+                }
+
+                int groupRank = 1;
+                for (Map<String, Object> matchMap : maps) {
+                    Map<String, Object> map = new HashMap<>();
+                    String targetId = MapUtil.getStr(matchMap, "matchQuestionCode");
+                    String matchQuestion = MapUtil.getStr(matchMap, "matchQuestion");
+                    String matchScore = MapUtil.getStr(matchMap, "matchScore");
+                    map.put("sourceId", questionLibrary.getId());
+                    map.put("sourceDesc", questionLibrary.getDescription());
+                    map.put("sourceQuestion", question);
+                    String sourceNamePath = dicMap.get(questionLibrary.getDictId()).getNameZhPath();
+                    map.put("sourceDicPath", sourceNamePath);
+
+                    map.put("targetId", targetId);
+                    AskTemplateQuestionLibrary targetLibrary = libraryMap.get(targetId);
+                    map.put("targetDesc", targetLibrary.getDescription());
+                    map.put("targetQuestion", matchQuestion);
+                    String targetNamePath = dicMap.get(targetLibrary.getDictId()).getNameZhPath();
+                    map.put("targetDicPath", targetNamePath);
+                    map.put("matchScore", matchScore);
+
+                    // 问题是否相等
+                    map.put("questionEq", StrUtil.equals(question, matchQuestion) ? "是" : "否");
+                    // 分类是否相等
+                    map.put("questionDicEq", StrUtil.equals(sourceNamePath, targetNamePath) ? "是" : "否");
+
+                    map.put("groupRank", groupRank);
+                    groupRank++;
+                    result.add(map);
+                }
+
+            }
+            String filePath = "F:\\tmp\\1\\问题库问题对比.xlsx";
+            ExcelWriter writer = ExcelUtil.getWriter(filePath, "多维度向量相似度对比");
+            writer.addHeaderAlias("sourceId", "源问题id");
+            writer.addHeaderAlias("sourceDesc", "源问题描述");
+            writer.addHeaderAlias("sourceQuestion", "源问题");
+            writer.addHeaderAlias("sourceDicPath", "源分类");
+            writer.addHeaderAlias("targetId", "目标问题");
+            writer.addHeaderAlias("targetDesc", "目标问题描述");
+            writer.addHeaderAlias("targetQuestion", "目标问题");
+            writer.addHeaderAlias("matchScore", "相似度");
+            writer.addHeaderAlias("targetDicPath", "目标分类");
+            writer.addHeaderAlias("questionEq", "同一语句");
+            writer.addHeaderAlias("questionDicEq", "同一分类");
+            writer.addHeaderAlias("groupRank", "排序");
+            writer.write(result, true);
+            writer.close();
+        }
+    }
+
+    @Test
+    public void questionCaseGenerateTest() {
+
+
+        List<AskTemplateQuestionLibrary> questionLibraries = askTemplateQuestionLibraryService.list();
+        List<CommonDic> commonDics = commonDicService.lambdaQuery().eq(CommonDic::getGroupCode, "AQT").list();
+        Map<Long, CommonDic> dicMap = commonDics.stream().collect(Collectors.toMap(CommonDic::getId, v -> v));
+        Map<String, AskTemplateQuestionLibrary> libraryMap = questionLibraries.stream().collect(Collectors.toMap(AskTemplateQuestionLibrary::getId, library -> library));
+
+        String path = "F:\\tmp\\1\\门诊收集0524.xlsx";
+
+        ExcelReader reader = ExcelUtil.getReader(path);
+        List<Map<String, Object>> maps = reader.readAll();
+
+        for (Map<String, Object> map : maps) {
+            String question = MapUtil.getStr(map, "日常问诊");
+            List<Map<String, Object>> matchMapList = questionMatch(question);
+            if (CollUtil.isEmpty(matchMapList)) {
+                log.warn("questionMatch:问题:{}没有匹配到结果", question);
+                continue;
+            }
+            Map<String, Object> first = CollUtil.getFirst(matchMapList);
+            String matchQuestion = MapUtil.getStr(first, "matchQuestion");
+            String score = MapUtil.getStr(first, "matchScore");
+            String targetId = MapUtil.getStr(first, "matchQuestionCode");
+            map.put("targetId", targetId);
+            map.put("targetQuestion", matchQuestion);
+            AskTemplateQuestionLibrary targetLibrary = libraryMap.get(targetId);
+            map.put("targetDesc", targetLibrary.getDescription());
+            Long dictId = targetLibrary.getDictId();
+            map.put("targetDicPath", dicMap.get(dictId).getNameZhPath());
+            map.put("matchScore", score);
+        }
+
+        ExcelWriter writer = ExcelUtil.getWriter(path, "问询结果-1");
+        writer.addHeaderAlias("病例", "病例");
+        writer.addHeaderAlias("日常问诊", "日常问诊");
+        writer.addHeaderAlias("targetId", "目标问题");
+        writer.addHeaderAlias("targetDesc", "目标问题描述");
+        writer.addHeaderAlias("targetQuestion", "目标问题");
+        writer.addHeaderAlias("matchScore", "相似度");
+        writer.addHeaderAlias("targetDicPath", "目标分类");
+        writer.write(maps, true);
+        writer.close();
+    }
+
+    private List<Map<String, Object>> questionMatch(String question) {
+        Assert.notEmpty(question, "问题不能为空");
+
+        Map<String, Object> params = new HashMap<>();
+        params.put("question", question);
+        HttpRequest request = HttpRequest.post(BASE_URL + "/matchQuestion")
+                .body(JSONUtil.toJsonStr(params));
+        log.info("askMatch:question:{}", question);
+        try (HttpResponse response = request.execute()) {
+            String body = response.body();
+            log.info("askMatch:响应结果:{}", body);
+            JSONObject entries = JSONUtil.parseObj(body);
+            if (entries.get("code", Integer.class) != 200) {
+                log.warn("askMatch:匹配失败");
+                return null;
+            }
+            JSONArray jsonArray = JSONUtil.parseArray(entries.get("data"));
+            if (CollUtil.isNotEmpty(jsonArray)) {
+                ArrayList<Map<String, Object>> maps = new ArrayList<>();
+                for (Object o : jsonArray) {
+                    maps.add(JSONUtil.toBean(JSONUtil.toJsonStr(o), Map.class));
+                }
+                return maps;
+            }
+        } catch (Exception e) {
+            log.error("chat:请求失败", e);
+        }
+
+        log.warn("askMatch:匹配失败");
+        return null;
+    }
+
+    @Test
+    public void initVecData() {
+        List<AskTemplateQuestionLibrary> questionLibraries = askTemplateQuestionLibraryService.list();
+
+        // load vec data
+        List<Map<String, Object>> vecData = questionLibraries.stream().map(library -> {
+            Map<String, Object> map = new HashMap<>();
+            map.put("questionCode", library.getId());
+            map.put("questionList", library.getQuestion());
+            return map;
+        }).collect(Collectors.toList());
+        saveVec(vecData);
+    }
+
+    @Test
+    public void initDescVecData() {
+        List<AskTemplateQuestionLibrary> questionLibraries = askTemplateQuestionLibraryService.list();
+        // load vec data
+        List<Map<String, Object>> vecData = questionLibraries.stream().map(library -> {
+            Map<String, Object> map = new HashMap<>();
+            map.put("questionCode", library.getId());
+            map.put("questionList", CollUtil.newArrayList(library.getDescription()));
+            return map;
+        }).collect(Collectors.toList());
+        saveVec(vecData);
+    }
+
+    @Test
+    public void initQuestionJoinVecData() {
+        List<AskTemplateQuestionLibrary> questionLibraries = askTemplateQuestionLibraryService.list();
+        // load vec data
+        List<Map<String, Object>> vecData = questionLibraries.stream().map(library -> {
+            Map<String, Object> map = new HashMap<>();
+            map.put("questionCode", library.getId());
+            if (StrUtil.isEmpty(library.getDefaultAnswer())) {
+                log.warn("defaultAnswer is empty . libraryId is :{}", library.getId());
+            }
+            List<String> joinList = library.getQuestion().stream()
+                    .map(question -> question + " " + library.getDefaultAnswer()).collect(Collectors.toList());
+            map.put("questionList", joinList);
+            return map;
+        }).collect(Collectors.toList());
+        saveVec(vecData);
+    }
+
+    @Test
+    public void initMedicalVecData() {
+        String medicalId = "1";
+
+        List<AskPatientAnswer> answerList = askPatientAnswerService.lambdaQuery().eq(AskPatientAnswer::getMedicalId, medicalId).list();
+        Map<String, AskPatientAnswer> answerMap = answerList.stream().collect(Collectors.toMap(AskPatientAnswer::getLibraryQuestionId, v -> v));
+        List<AskTemplateQuestionLibrary> questionLibraries = askTemplateQuestionLibraryService.list();
+        List<Map<String, Object>> result = new ArrayList<>();
+        for (AskTemplateQuestionLibrary questionLibrary : questionLibraries) {
+            if (!questionLibrary.getDescription().contains(questionLibrary.getDescription())) {
+                questionLibrary.getQuestion().add(questionLibrary.getDescription());
+            }
+
+            AskPatientAnswer askPatientAnswer = answerMap.get(questionLibrary.getId());
+            if (ObjectUtil.isEmpty(askPatientAnswer)) {
+                log.info("问题:id:{} desc:{},未设置回复答案,跳过", questionLibrary.getId(), questionLibrary.getDescription());
+                continue;
+            }
+            Map<String, Object> map = new HashMap<>();
+            map.put("questionCode", questionLibrary.getId());
+            map.put("questionList", questionLibrary.getQuestion());
+            result.add(map);
+        }
+        saveVec(result);
+    }
+
+    private void saveVec(List<Map<String, Object>> List) {
+
+        HttpRequest request = HttpRequest.post(BASE_URL + "/updateDatabase")
+                .body(JSONUtil.toJsonStr(List));
+
+        log.info("saveVec:请求参数:{}", JSONUtil.toJsonStr(List));
+
+        try (HttpResponse response = request.execute()) {
+            String body = response.body();
+            log.info("saveVec:响应结果:{}", body);
+            JSONObject entries = JSONUtil.parseObj(body);
+            if (!"success".equals(entries.get("status", String.class))) {
+                log.warn("saveVec:保存失败");
+                throw new RuntimeException("saveVec:保存失败");
+            }
+        } catch (Exception e) {
+            log.error("saveVec:保存失败", e);
+            throw new RuntimeException("saveVec:保存失败");
+        }
+    }
+
+    // todo: 找出相似度大于0.5的标准问的数据
+
+    private String askMatch(String question) {
+
+        Assert.notEmpty(question, "问题不能为空");
+        Map<String, Object> params = new HashMap<>();
+        params.put("question", question);
+        HttpRequest request = HttpRequest.post(BASE_URL + "/matchQuestion")
+                .body(JSONUtil.toJsonStr(params));
+        log.info("askMatch:question:{}", question);
+        try (HttpResponse response = request.execute()) {
+            String body = response.body();
+            log.info("askMatch:响应结果:{}", body);
+            JSONObject entries = JSONUtil.parseObj(body);
+            if (entries.get("code", Integer.class) != 200) {
+                log.warn("askMatch:匹配失败");
+                return null;
+            }
+            JSONArray jsonArray = JSONUtil.parseArray(entries.get("data"));
+            if (CollUtil.isNotEmpty(jsonArray)) {
+                return JSONUtil.parseObj(jsonArray.get(0)).get("matchQuestionCode", String.class);
+            }
+        } catch (Exception e) {
+            log.error("chat:请求失败", e);
+        }
+
+        log.warn("askMatch:匹配失败");
+        return null;
+    }
+
+    @Test
+    public void standardQuestionMatch() {
+        // initDescVecData() first step
+        List<AskTemplateQuestionLibrary> questionLibraries = askTemplateQuestionLibraryService.list();
+        List<CommonDic> commonDics = commonDicService.lambdaQuery().eq(CommonDic::getGroupCode, "AQT").list();
+        Map<Long, CommonDic> dicMap = commonDics.stream().collect(Collectors.toMap(CommonDic::getId, v -> v));
+        Map<String, AskTemplateQuestionLibrary> libraryMap = questionLibraries.stream().collect(Collectors.toMap(AskTemplateQuestionLibrary::getId, library -> library));
+
+        List<Map<String, Object>> result = new ArrayList<>();
+
+        for (AskTemplateQuestionLibrary questionLibrary : questionLibraries) {
+            String description = questionLibrary.getDescription();
+            List<Map<String, Object>> maps = questionMatch(description);
+            // 只获取前四条数据
+            if (CollUtil.isEmpty(maps)) {
+                log.warn("questionMatch:问题:{}没有匹配到结果", description);
+                continue;
+            }
+
+            if (maps.size() > 3) {
+                // 截取前四条数据
+                maps = maps.subList(0, 4);
+            }
+            for (Map<String, Object> matchMap : maps) {
+                String targetId = MapUtil.getStr(matchMap, "matchQuestionCode");
+                String matchQuestion = MapUtil.getStr(matchMap, "matchQuestion");
+                String matchScore = MapUtil.getStr(matchMap, "matchScore");
+
+                if (StrUtil.equals(targetId, questionLibrary.getId())) {
+                    log.info("匹配到自己,跳过该条数据,id:{}", targetId);
+                    continue;
+                }
+                Map<String, Object> tmp = new HashMap<>();
+                tmp.put("sourceId", questionLibrary.getId());
+                tmp.put("sourceDesc", description);
+                String sourceNamePath = dicMap.get(questionLibrary.getDictId()).getNameZhPath();
+                tmp.put("sourceDicPath", sourceNamePath);
+                tmp.put("targetId", targetId);
+                tmp.put("targetDesc", matchQuestion);
+                tmp.put("matchScore", matchScore);
+                AskTemplateQuestionLibrary library = libraryMap.get(targetId);
+                tmp.put("targetDicPath", dicMap.get(library.getDictId()).getNameZhPath());
+                result.add(tmp);
+            }
+
+        }
+        String filePath = "F:\\tmp\\1\\问题库问题对比-标准问.xlsx";
+        ExcelWriter writer = ExcelUtil.getWriter(filePath, "标准问匹配");
+        writer.setDefaultRowHeight(18);
+        writer.addHeaderAlias("sourceId", "源问题id");
+        writer.addHeaderAlias("sourceDesc", "源问题");
+        writer.addHeaderAlias("sourceDicPath", "源分类");
+        writer.addHeaderAlias("targetId", "目标问题");
+        writer.addHeaderAlias("targetDesc", "目标问题");
+        writer.addHeaderAlias("targetDicPath", "目标分类");
+        writer.addHeaderAlias("matchScore", "相似度");
+        writer.write(result, true);
+        writer.close();
+    }
+
+    @Test
+    public void medicalQA() {
+        String medicalId = "1";
+
+        List<AskPatientAnswer> answerList = askPatientAnswerService.lambdaQuery().eq(AskPatientAnswer::getMedicalId, medicalId).list();
+        Map<String, AskPatientAnswer> answerMap = answerList.stream().collect(Collectors.toMap(AskPatientAnswer::getLibraryQuestionId, v -> v));
+
+        List<AskTemplateQuestionLibrary> questionLibraries = askTemplateQuestionLibraryService.list();
+
+        List<Map<String, Object>> result = new ArrayList<>();
+        for (AskTemplateQuestionLibrary questionLibrary : questionLibraries) {
+            if (!questionLibrary.getDescription().contains(questionLibrary.getDescription())) {
+                questionLibrary.getQuestion().add(questionLibrary.getDescription());
+            }
+
+            AskPatientAnswer askPatientAnswer = answerMap.get(questionLibrary.getId());
+            if (ObjectUtil.isEmpty(askPatientAnswer)) {
+                log.info("问题:id:{} desc:{},未设置回复答案,跳过", questionLibrary.getId(), questionLibrary.getDescription());
+                continue;
+            }
+            for (String question : questionLibrary.getQuestion()) {
+                HashMap<String, Object> map = new HashMap<>();
+                map.put("Q", question);
+                map.put("A", askPatientAnswer.getAnswer());
+                result.add(map);
+            }
+        }
+
+        String filePath = "F:\\tmp\\1\\病历问答.xlsx";
+        ExcelWriter writer = ExcelUtil.getWriter(filePath);
+        writer.addHeaderAlias("Q", "Q");
+        writer.addHeaderAlias("A", "A");
+        writer.write(result, false);
+        writer.close();
+    }
+
+    @Test
+    public void questionListClean() {
+        List<AskTemplateQuestionLibrary> questionLibraries = askTemplateQuestionLibraryService.lambdaQuery().eq(AskTemplateQuestionLibrary::getId, "1761963910199513090").orderByDesc(AskTemplateQuestionLibrary::getId).list();
+
+        Console console = System.console();
+        for (AskTemplateQuestionLibrary questionLibrary : questionLibraries) {
+            String description = questionLibrary.getDescription();
+            List<String> question = questionLibrary.getQuestion();
+
+            List<String> addList = new ArrayList<>();
+
+            for (String single : question) {
+                log.info("description:{}, single:{}", description, single);
+                log.info("remove is Y else is other");
+                String input = console.readLine();
+                if (!"Y".equals(input) && !"y".equals(input)) {
+                    addList.add(single);
+                }
+            }
+            //askTemplateQuestionLibraryService.lambdaUpdate().set(AskTemplateQuestionLibrary::getQuestion,addList).eq(AskTemplateQuestionLibrary::getId,questionLibrary.getId()).update();
+        }
+    }
+
+
+    @Test
+    public void questionJoinAnswerTest() {
+        List<AskTemplateQuestionLibrary> questionLibraries = askTemplateQuestionLibraryService.list();
+        List<CommonDic> commonDics = commonDicService.lambdaQuery().eq(CommonDic::getGroupCode, "AQT").list();
+        Map<Long, CommonDic> dicMap = commonDics.stream().collect(Collectors.toMap(CommonDic::getId, v -> v));
+        Map<String, AskTemplateQuestionLibrary> libraryMap = questionLibraries.stream().collect(Collectors.toMap(AskTemplateQuestionLibrary::getId, library -> library));
+
+        String path = "F:\\tmp\\1\\门诊收集0524.xlsx";
+
+        ExcelReader reader = ExcelUtil.getReader(path);
+        List<Map<String, Object>> maps = reader.readAll();
+
+        for (Map<String, Object> map : maps) {
+            String question = MapUtil.getStr(map, "日常问诊");
+            List<Map<String, Object>> matchMapList = questionMatch(question);
+            if (CollUtil.isEmpty(matchMapList)) {
+                log.warn("questionMatch:问题:{}没有匹配到结果", question);
+                continue;
+            }
+            Map<String, Object> first = CollUtil.getFirst(matchMapList);
+            String matchQuestion = MapUtil.getStr(first, "matchQuestion");
+            String score = MapUtil.getStr(first, "matchScore");
+            String targetId = MapUtil.getStr(first, "matchQuestionCode");
+            map.put("targetId", targetId);
+            map.put("targetQuestion", matchQuestion);
+            AskTemplateQuestionLibrary targetLibrary = libraryMap.get(targetId);
+            map.put("targetDesc", targetLibrary.getDescription());
+            Long dictId = targetLibrary.getDictId();
+            map.put("targetDicPath", dicMap.get(dictId).getNameZhPath());
+            map.put("matchScore", score);
+        }
+
+        ExcelWriter writer = ExcelUtil.getWriter(path, "问询结果-问答拼接");
+        writer.addHeaderAlias("病例", "病例");
+        writer.addHeaderAlias("日常问诊", "日常问诊");
+        writer.addHeaderAlias("targetId", "目标问题");
+        writer.addHeaderAlias("targetDesc", "目标问题描述");
+        writer.addHeaderAlias("targetQuestion", "目标问题");
+        writer.addHeaderAlias("matchScore", "相似度");
+        writer.addHeaderAlias("targetDicPath", "目标分类");
+        writer.write(maps, true);
+        writer.close();
+    }
+
+}