Procházet zdrojové kódy

1.首次病程录添加规则
2.文本相似度模型接入

hujing před 5 roky
rodič
revize
3abafb9961

+ 5 - 1
kernel/src/main/java/com/lantone/qc/kernel/analysis/QCAnalysis.java

@@ -1,6 +1,7 @@
 package com.lantone.qc.kernel.analysis;
 
 import com.lantone.qc.kernel.client.CRFServiceClient;
+import com.lantone.qc.kernel.client.SimilarityServiceClient;
 import com.lantone.qc.kernel.structure.ai.AIAnalyze;
 import com.lantone.qc.kernel.util.CatalogueUtil;
 import com.lantone.qc.kernel.util.RedisUtil;
@@ -25,6 +26,9 @@ public class QCAnalysis {
     @Autowired
     CRFServiceClient crfServiceClient;
 
+    @Autowired
+    SimilarityServiceClient similarityServiceClient;
+
     @Autowired
     private RedisUtil redisUtil;
 
@@ -32,7 +36,7 @@ public class QCAnalysis {
         OutputInfo outputInfo = new OutputInfo();
         InputInfo inputInfo = TransDispatch.trans(queryVo);
         inputInfo.setInputCatalogueMap(queryVo.getInputCatalogueMap());
-        AIAnalyze AIAnalyze = new AIAnalyze(crfServiceClient);
+        AIAnalyze AIAnalyze = new AIAnalyze(crfServiceClient, similarityServiceClient);
         AIAnalyze.AIprocess(inputInfo);
         for (Map.Entry<String, Map<String, String>> entry : inputInfo.getInputCatalogueMap().entrySet()) {
             if (CatalogueUtil.qcCatalogueMap.get(entry.getKey()) == null) {

+ 12 - 2
kernel/src/main/java/com/lantone/qc/kernel/catalogue/firstcourserecord/FIRC0083.java

@@ -3,18 +3,28 @@ package com.lantone.qc.kernel.catalogue.firstcourserecord;
 import com.lantone.qc.kernel.catalogue.QCCatalogue;
 import com.lantone.qc.pub.model.InputInfo;
 import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.FirstCourseRecordDoc;
 import org.springframework.stereotype.Component;
 
 import java.util.Map;
 
 /**
- * @ClassName : CLI0001
- * @Description : 无输血/血制品病程记录
+ * @ClassName : FIRC0083
+ * @Description : 病例特点与现病史内容雷同
  * @Author : 楼辉荣
  * @Date: 2020-03-06 17:28
  */
 @Component
 public class FIRC0083 extends QCCatalogue {
     public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status = "0";
+        FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+        if (firstCourseRecordDoc == null || firstCourseRecordDoc.getCaseCharacteristicLabel() == null) {
+            return;
+        }
+        double likeRate = firstCourseRecordDoc.getCaseCharacteristicLabel().getLikeRate();
+        if (likeRate > 0.8d) {
+            status = "-1";
+        }
     }
 }

+ 0 - 1
kernel/src/main/java/com/lantone/qc/kernel/client/CRFServiceClient.java

@@ -1,7 +1,6 @@
 package com.lantone.qc.kernel.client;
 
 
-import com.lantone.qc.kernel.client.hystrix.CRFServiceHystrix;
 import com.lantone.qc.pub.model.vo.CRFVo;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.PostMapping;

+ 24 - 0
kernel/src/main/java/com/lantone/qc/kernel/client/SimilarityServiceClient.java

@@ -0,0 +1,24 @@
+package com.lantone.qc.kernel.client;
+
+
+import com.lantone.qc.pub.model.vo.CRFVo;
+import com.lantone.qc.pub.model.vo.SimilarityVo;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+
+/**
+ * @Description: 调用文本相似度服务
+ * @author: 胡敬
+ * @time: 2020/03/24 16:40
+ */
+@FeignClient(value = "Similarity-service", url="${Similarity.url}")
+public interface SimilarityServiceClient {
+
+    @PostMapping(value = "")
+    String getAnnotation(@RequestBody SimilarityVo similarityVo);
+}
+
+
+

+ 5 - 2
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/AIAnalyze.java

@@ -1,6 +1,7 @@
 package com.lantone.qc.kernel.structure.ai;
 
 import com.lantone.qc.kernel.client.CRFServiceClient;
+import com.lantone.qc.kernel.client.SimilarityServiceClient;
 import com.lantone.qc.kernel.structure.ai.model.CrfOut;
 import com.lantone.qc.pub.model.InputInfo;
 
@@ -11,19 +12,21 @@ import java.util.Map;
 public class AIAnalyze {
 
     private CRFServiceClient crfServiceClient;
+    private SimilarityServiceClient similarityServiceClient;
     BeHospitalizedAI beHospitalizedAI = new BeHospitalizedAI();
     FirstCourseRecordAI firstCourseRecordAI = new FirstCourseRecordAI();
     LeaveHospitalAI leaveHospitalAI = new LeaveHospitalAI();
     ThreeLevelWardAI threeLevelWardAI = new ThreeLevelWardAI();
     OperationAI operationAI = new OperationAI();
 
-    public AIAnalyze(CRFServiceClient crfService) {
+    public AIAnalyze(CRFServiceClient crfService, SimilarityServiceClient similarityServiceClient) {
         this.crfServiceClient = crfService;
+        this.similarityServiceClient = similarityServiceClient;
     }
 
     public void AIprocess(InputInfo inputInfo) {
         beHospitalizedAI.medrec(inputInfo, crfServiceClient);
-        firstCourseRecordAI.medrec(inputInfo, crfServiceClient);
+        firstCourseRecordAI.medrec(inputInfo, crfServiceClient, similarityServiceClient);
         leaveHospitalAI.medrec(inputInfo, crfServiceClient);
         threeLevelWardAI.medrec(inputInfo, crfServiceClient);
         operationAI.medrec(inputInfo, crfServiceClient);

+ 24 - 2
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/FirstCourseRecordAI.java

@@ -3,6 +3,7 @@ package com.lantone.qc.kernel.structure.ai;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.lantone.qc.kernel.client.CRFServiceClient;
+import com.lantone.qc.kernel.client.SimilarityServiceClient;
 import com.lantone.qc.kernel.structure.ai.process.EntityProcessClinic;
 import com.lantone.qc.kernel.structure.ai.process.EntityProcessDiag;
 import com.lantone.qc.kernel.structure.ai.process.EntityProcessTreatPlan;
@@ -11,6 +12,7 @@ import com.lantone.qc.pub.model.InputInfo;
 import com.lantone.qc.pub.model.doc.FirstCourseRecordDoc;
 import com.lantone.qc.pub.model.entity.Diag;
 import com.lantone.qc.pub.model.label.*;
+import com.lantone.qc.pub.util.StringUtil;
 import org.apache.commons.lang3.StringUtils;
 
 import java.util.Arrays;
@@ -26,13 +28,14 @@ public class FirstCourseRecordAI extends ModelAI {
     /**
      *
      */
-    public static List<String> medicalTextType = Arrays.asList("FirstCoursera_cx", "Diagnoses_cx","FirstCourseTreatment_cx");
+    public static List<String> medicalTextType = Arrays.asList("FirstCoursera_cx", "Diagnoses_cx", "FirstCourseTreatment_cx");
     public static String entityRelationObject = "entity_relation_object";
     public static String outputs = "outputs";
     public static String content = "content";
 
-    public void medrec(InputInfo inputInfo, CRFServiceClient crfServiceClient) {
+    public void medrec(InputInfo inputInfo, CRFServiceClient crfServiceClient, SimilarityServiceClient similarityServiceClient) {
         JSONArray crfContent = new JSONArray();
+        JSONArray similarContent = new JSONArray();
         FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
         if (firstCourseRecordDoc != null && StringUtils.isNotEmpty(firstCourseRecordDoc.getText())) {
             //病历特点
@@ -46,12 +49,20 @@ public class FirstCourseRecordAI extends ModelAI {
             //诊疗计划
             putContent(crfContent, medicalTextType.get(2), firstCourseRecordDoc.getTreatPlanLabel().getText(), Content.treat_plan);
 
+            //病历特点与现病史比较相似度
+            if (inputInfo.getBeHospitalizedDoc() != null && StringUtil.isNotBlank(inputInfo.getBeHospitalizedDoc().getPresentLabel().getText())) {
+                putContent(similarContent, firstCourseRecordDoc.getCaseCharacteristicLabel().getText(),inputInfo.getBeHospitalizedDoc().getPresentLabel().getText());
+            }
+
             JSONObject midData = loadAI(crfContent, crfServiceClient);//crf返回数据
             putCaseCharacteristicCrfData(midData.getJSONObject(Content.case_feature), inputInfo);//处理病历特点
             putInitialDiagCrfData(midData.getJSONObject(Content.initial_diag), inputInfo);//处理初步诊断
             putDiagnosisCrfData(midData.getJSONObject(Content.diag_basis), inputInfo);//处理诊断依据
             putDifferentialDiagCrfData(midData.getJSONObject(Content.differential_diag_basis), inputInfo);//处理鉴别诊断
             putTreatPlanCrfData(midData.getJSONObject(Content.treat_plan), inputInfo);//处理诊疗计划
+
+            double likeRate = loadSimilarAI(similarContent, similarityServiceClient);
+            putCaseCharacteristicSimilarData(likeRate,inputInfo);//存放与现病史文本相似度
         }
     }
 
@@ -70,6 +81,17 @@ public class FirstCourseRecordAI extends ModelAI {
         inputInfo.getFirstCourseRecordDoc().getCaseCharacteristicLabel().setClinicals(presentLabel.getClinicals());
     }
 
+    /**
+     * 病历特点与现病史相似度
+     *
+     * @param likeRate
+     * @param inputInfo
+     */
+    public void putCaseCharacteristicSimilarData(double likeRate, InputInfo inputInfo) {
+        //存放与现病史文本相似度
+        inputInfo.getFirstCourseRecordDoc().getCaseCharacteristicLabel().setLikeRate(likeRate);
+    }
+
     /**
      * 初步诊断
      *

+ 64 - 0
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/ModelAI.java

@@ -4,9 +4,11 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.lantone.qc.kernel.client.CRFServiceClient;
+import com.lantone.qc.kernel.client.SimilarityServiceClient;
 import com.lantone.qc.kernel.util.CatalogueUtil;
 import com.lantone.qc.pub.model.entity.Annotation;
 import com.lantone.qc.pub.model.vo.CRFVo;
+import com.lantone.qc.pub.model.vo.SimilarityVo;
 import com.lantone.qc.pub.util.StringUtil;
 
 /**
@@ -33,6 +35,22 @@ public class ModelAI {
         return midData;
     }
 
+    /**
+     * 获取文本相似度返回数据
+     *
+     * @param similarContent
+     * @param similarityServiceClient
+     * @return
+     */
+    protected double loadSimilarAI(JSONArray similarContent, SimilarityServiceClient similarityServiceClient) {
+        //存储CRF完整所需结构数据
+        SimilarityVo similarityVo = new SimilarityVo();
+        similarityVo.setData(similarContent);
+        //获取CRF模型返回数据
+        JSONArray data = getAnnotation(similarityServiceClient, similarityVo).getData();
+        return getSimilarOutputs(data);
+    }
+
     protected JSONObject loadEntity(JSONObject jsonObject, String entityRelationObject, String outputs, String content) {
         if (jsonObject == null) {
             return new JSONObject();
@@ -54,6 +72,18 @@ public class ModelAI {
         }
     }
 
+    private Annotation getAnnotation(SimilarityServiceClient similarityServiceClient, SimilarityVo similarityVo) {
+        Annotation annotation = new Annotation();
+        try {
+            String annotation_str = similarityServiceClient.getAnnotation(similarityVo);
+            annotation = JSON.parseObject(annotation_str, Annotation.class);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        } finally {
+            return annotation;
+        }
+    }
+
     protected void putContent(JSONArray crfContent, String medicalTextType, String text, String sign) {
         String move_text = CatalogueUtil.removeSpecialChar(text);
         if (StringUtil.isEmpty(move_text)) {
@@ -79,6 +109,25 @@ public class ModelAI {
         crfContent.add(detailContent);
     }
 
+    /**
+     * 存放文本相似度入参内容
+     *
+     * @param similarContent
+     * @param firstText
+     * @param secondText
+     */
+    protected void putContent(JSONArray similarContent, String firstText, String secondText) {
+        String moveFirstText = CatalogueUtil.removeSpecialChar(firstText);
+        String moveSecondText = CatalogueUtil.removeSpecialChar(secondText);
+        if (StringUtil.isEmpty(moveFirstText) || StringUtil.isEmpty(moveSecondText)) {
+            return;
+        }
+        JSONObject detailContent = new JSONObject();
+        detailContent.put("text_1", moveFirstText);
+        detailContent.put("text_2", moveSecondText);
+        similarContent.add(detailContent);
+    }
+
     /**
      * 获取CRF模型输出并处理
      *
@@ -96,4 +145,19 @@ public class ModelAI {
         }
         return midData;
     }
+
+    /**
+     * 获取文本相似度模型输出并处理
+     *
+     * @param data 数组里只有一个对象
+     * @return
+     */
+    public double getSimilarOutputs(JSONArray data) {
+        double likeRate = 0d;
+        if (data.size() > 0) {
+            JSONObject dataContent = data.getJSONObject(0);
+            likeRate = dataContent.getDoubleValue("like_rate");
+        }
+        return likeRate;
+    }
 }

+ 4 - 0
kernel/src/main/resources/application.yml

@@ -27,5 +27,9 @@ spring:
 CRF:
   url: http://192.168.3.150:3456/api/mr_info_ex/entity_predict
 
+Similarity:
+  url:http://192.168.3.150:3456/api/mr_info_ex/similarity
+
+
 logging:          # 日志
   config: classpath:logback-spring.xml

+ 2 - 0
public/src/main/java/com/lantone/qc/pub/model/label/CaseCharacteristicLabel.java

@@ -30,4 +30,6 @@ public class CaseCharacteristicLabel extends GeneralLabel {
     private List<Diag> diags = new ArrayList<>();
     //入院途径
     private BeHospitalizedWay beHospitalizedWay;
+    //与现病史相似度
+    private double likeRate;
 }

+ 11 - 0
public/src/main/java/com/lantone/qc/pub/model/vo/SimilarityVo.java

@@ -0,0 +1,11 @@
+package com.lantone.qc.pub.model.vo;
+
+import com.alibaba.fastjson.JSONArray;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class SimilarityVo {
+    private JSONArray data = new JSONArray();
+}