Преглед изворни кода

1、首次病程录使用算法解析

louhr пре 5 година
родитељ
комит
abc2ba16f0

+ 2 - 63
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/BeHospitalizedAI.java

@@ -29,7 +29,7 @@ import java.util.List;
  * @Date: 2020-03-03 18:58
  */
 @Component
-public class BeHospitalizedAI {
+public class BeHospitalizedAI extends ModelAI {
     /**
      * FirstCourseRecord_cx[病历首程]
      * PastFamily_cx[既往史家族史]
@@ -104,12 +104,7 @@ public class BeHospitalizedAI {
                 //补充诊断
                 putContent(crfContent, medicalTextType.get(6), supple_diag_text, Content.supple_diag);
             }
-            //存储CRF完整所需结构数据
-            CRFVo crfVo = new CRFVo();
-            crfVo.setData(crfContent);
-            //获取CRF模型返回数据
-            JSONArray data = getAnnotation(crfServiceClient, crfVo).getData();
-            JSONObject midData = getOutputs(data);
+            JSONObject midData = loadAI(crfContent, crfServiceClient);
             //处理主诉
             putChiefCrfData(midData.getJSONObject(Content.chief), inputInfo);
             //处理现病史
@@ -400,60 +395,4 @@ public class BeHospitalizedAI {
         List<Vital> vitals = entityProcessVital.extractEntity(aiOut);
         return vitals;
     }
-
-    public void putContent(JSONArray crfContent, String medicalTextType, String text, String sign) {
-        String move_text = CatalogueUtil.removeSpecialChar(text);
-        if (StringUtil.isEmpty(move_text)) {
-            return;
-        }
-        JSONObject detailContent = new JSONObject();
-        detailContent.put("medical_text_type", medicalTextType);
-        detailContent.put("content", move_text);
-        detailContent.put("detail_title", sign);
-        crfContent.add(detailContent);
-    }
-
-    public void putContent(JSONArray crfContent, String medicalTextType, String firstText, String secondText, String sign) {
-        String firstMoveText = CatalogueUtil.removeSpecialChar(firstText);
-        String secondMoveText = CatalogueUtil.removeSpecialChar(secondText);
-        if (StringUtil.isEmpty(firstMoveText) && StringUtil.isEmpty(secondMoveText)) {
-            return;
-        }
-        JSONObject detailContent = new JSONObject();
-        detailContent.put("medical_text_type", medicalTextType);
-        detailContent.put("content", firstMoveText + "\n" + secondMoveText);
-        detailContent.put("detail_title", sign);
-        crfContent.add(detailContent);
-    }
-
-    private Annotation getAnnotation(CRFServiceClient crfServiceClient, CRFVo crfVo) {
-
-        Annotation annotation = new Annotation();
-        try {
-            String annotation_str = crfServiceClient.getAnnotation(crfVo);
-            annotation = JSON.parseObject(annotation_str, Annotation.class);
-        } catch (Exception ex) {
-            ex.printStackTrace();
-        } finally {
-            return annotation;
-        }
-    }
-
-    /**
-     * 获取CRF模型输出并处理
-     *
-     * @param data
-     * @return
-     */
-    public JSONObject getOutputs(JSONArray data) {
-        JSONObject midData = new JSONObject();
-        for (int i = 0; i < data.size(); i++) {
-            JSONObject detailContent = data.getJSONObject(i);
-            String detail_title = detailContent.getString("detail_title");
-            if (StringUtil.isNotEmpty(detail_title) && midData.get(detail_title) == null) {
-                midData.put(detail_title, detailContent);
-            }
-        }
-        return midData;
-    }
 }

+ 124 - 0
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/FirstCourseRecordAI.java

@@ -0,0 +1,124 @@
+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.structure.ai.process.EntityProcessClinic;
+import com.lantone.qc.kernel.structure.ai.process.EntityProcessDiag;
+import com.lantone.qc.kernel.structure.ai.process.EntityProcessTreatPlan;
+import com.lantone.qc.pub.Content;
+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 org.apache.commons.lang3.StringUtils;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @ClassName : FirstCourseRecordAI
+ * @Description :
+ * @Author : 楼辉荣
+ * @Date: 2020-03-19 14:52
+ */
+public class FirstCourseRecordAI extends ModelAI {
+    /**
+     *
+     */
+    public static List<String> medicalTextType = Arrays.asList("FirstCoursera_cx", "Diagnoses_cx");
+    public static String entityRelationObject = "entity_relation_object";
+    public static String outputs = "outputs";
+
+    public void medrec(InputInfo inputInfo, CRFServiceClient crfServiceClient) {
+        JSONArray crfContent = new JSONArray();
+        FirstCourseRecordDoc firstCourseRecordDoc = inputInfo.getFirstCourseRecordDoc();
+        if (firstCourseRecordDoc != null && StringUtils.isNotEmpty(firstCourseRecordDoc.getText())) {
+            //病历特点
+            putContent(crfContent, medicalTextType.get(0), firstCourseRecordDoc.getCaseCharacteristicLabel().getText(), Content.case_feature);
+            //初步诊断
+            putContent(crfContent, medicalTextType.get(1), firstCourseRecordDoc.getInitialDiagLabel().getText(), Content.initial_diag);
+            //诊断依据
+            putContent(crfContent, medicalTextType.get(0), firstCourseRecordDoc.getDiagnosisLabel().getText(), Content.diag_basis);
+            //鉴别诊断
+            putContent(crfContent, medicalTextType.get(1), firstCourseRecordDoc.getDifferentialDiagLabel().getText(), Content.differential_diag_basis);
+            //诊疗计划
+            putContent(crfContent, medicalTextType.get(0), firstCourseRecordDoc.getTreatPlanLabel().getText(), Content.treat_plan);
+
+            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);//处理诊疗计划
+        }
+    }
+
+    /**
+     * 病历特点
+     * @param jsonObject
+     * @param inputInfo
+     */
+    public void putCaseCharacteristicCrfData(JSONObject jsonObject, InputInfo inputInfo) {
+        JSONObject aiOut = loadEntity(jsonObject, entityRelationObject, outputs);
+        //使用现病史结构来处理病历特点
+        EntityProcessClinic entityProcessClinic = new EntityProcessClinic();
+        PresentLabel presentLabel = entityProcessClinic.extractEntity(aiOut);
+        //临床表现
+        inputInfo.getFirstCourseRecordDoc().getCaseCharacteristicLabel().setClinicals(presentLabel.getClinicals());
+    }
+
+    /**
+     * 初步诊断
+     * @param jsonObject
+     * @param inputInfo
+     */
+    public void putInitialDiagCrfData(JSONObject jsonObject, InputInfo inputInfo) {
+        JSONObject aiOut = loadEntity(jsonObject, entityRelationObject, outputs);
+        //诊断信息
+        EntityProcessDiag entityProcessDiag = new EntityProcessDiag();
+        List<Diag> diags = entityProcessDiag.extractEntity(aiOut);
+        inputInfo.getFirstCourseRecordDoc().getInitialDiagLabel().setDiags(diags);
+    }
+
+    /**
+     * 诊断依据
+     * @param jsonObject
+     * @param inputInfo
+     */
+    public void putDiagnosisCrfData(JSONObject jsonObject, InputInfo inputInfo) {
+        JSONObject aiOut = loadEntity(jsonObject, entityRelationObject, outputs);
+        //使用现病史结构来处理诊断依据
+        EntityProcessClinic entityProcessClinic = new EntityProcessClinic();
+        PresentLabel presentLabel = entityProcessClinic.extractEntity(aiOut);
+        //临床表现
+        inputInfo.getFirstCourseRecordDoc().getDiagnosisLabel().setClinicals(presentLabel.getClinicals());
+    }
+
+    /**
+     * 鉴别诊断
+     * @param jsonObject
+     * @param inputInfo
+     */
+    public void putDifferentialDiagCrfData(JSONObject jsonObject, InputInfo inputInfo) {
+        JSONObject aiOut = loadEntity(jsonObject, entityRelationObject, outputs);
+        //诊断信息
+        EntityProcessDiag entityProcessDiag = new EntityProcessDiag();
+        List<Diag> diags = entityProcessDiag.extractEntity(aiOut);
+        inputInfo.getFirstCourseRecordDoc().getDifferentialDiagLabel().setDiags(diags);
+    }
+
+    /**
+     * 诊疗计划
+     * @param jsonObject
+     * @param inputInfo
+     */
+    public void putTreatPlanCrfData(JSONObject jsonObject, InputInfo inputInfo) {
+        JSONObject aiOut = loadEntity(jsonObject, entityRelationObject, outputs);
+        //诊疗计划
+        EntityProcessTreatPlan entityProcessTreatPlan = new EntityProcessTreatPlan();
+        TreatPlanLabel treatPlanLabel = entityProcessTreatPlan.extractEntity(aiOut);
+        treatPlanLabel.setText(inputInfo.getFirstCourseRecordDoc().getTreatPlanLabel().getText());
+        inputInfo.getFirstCourseRecordDoc().setTreatPlanLabel(treatPlanLabel);
+    }
+}

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

@@ -0,0 +1,98 @@
+package com.lantone.qc.kernel.structure.ai;
+
+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.util.CatalogueUtil;
+import com.lantone.qc.pub.model.entity.Annotation;
+import com.lantone.qc.pub.model.vo.CRFVo;
+import com.lantone.qc.pub.util.StringUtil;
+
+/**
+ * @ClassName : ModelAI
+ * @Description : 算法基类
+ * @Author : 楼辉荣
+ * @Date: 2020-03-19 15:08
+ */
+public class ModelAI {
+    /**
+     * 获取CRF返回数据
+     *
+     * @param crfContent
+     * @param crfServiceClient
+     * @return
+     */
+    protected JSONObject loadAI(JSONArray crfContent, CRFServiceClient crfServiceClient) {
+        //存储CRF完整所需结构数据
+        CRFVo crfVo = new CRFVo();
+        crfVo.setData(crfContent);
+        //获取CRF模型返回数据
+        JSONArray data = getAnnotation(crfServiceClient, crfVo).getData();
+        JSONObject midData = getOutputs(data);
+        return midData;
+    }
+
+    protected JSONObject loadEntity(JSONObject jsonObject, String entityRelationObject, String outputs) {
+        if(jsonObject ==null) {
+            return new JSONObject();
+        }
+        JSONObject aiOut = jsonObject.getJSONObject(entityRelationObject).getJSONObject(outputs);
+        return aiOut;
+    }
+
+    private Annotation getAnnotation(CRFServiceClient crfServiceClient, CRFVo crfVo) {
+        Annotation annotation = new Annotation();
+        try {
+            String annotation_str = crfServiceClient.getAnnotation(crfVo);
+            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)) {
+            return;
+        }
+        JSONObject detailContent = new JSONObject();
+        detailContent.put("medical_text_type", medicalTextType);
+        detailContent.put("content", move_text);
+        detailContent.put("detail_title", sign);
+        crfContent.add(detailContent);
+    }
+
+    protected void putContent(JSONArray crfContent, String medicalTextType, String firstText, String secondText, String sign) {
+        String firstMoveText = CatalogueUtil.removeSpecialChar(firstText);
+        String secondMoveText = CatalogueUtil.removeSpecialChar(secondText);
+        if (StringUtil.isEmpty(firstMoveText) && StringUtil.isEmpty(secondMoveText)) {
+            return;
+        }
+        JSONObject detailContent = new JSONObject();
+        detailContent.put("medical_text_type", medicalTextType);
+        detailContent.put("content", firstMoveText + "\n" + secondMoveText);
+        detailContent.put("detail_title", sign);
+        crfContent.add(detailContent);
+    }
+
+    /**
+     * 获取CRF模型输出并处理
+     *
+     * @param data
+     * @return
+     */
+    public JSONObject getOutputs(JSONArray data) {
+        JSONObject midData = new JSONObject();
+        for (int i = 0; i < data.size(); i++) {
+            JSONObject detailContent = data.getJSONObject(i);
+            String detail_title = detailContent.getString("detail_title");
+            if (StringUtil.isNotEmpty(detail_title) && midData.get(detail_title) == null) {
+                midData.put(detail_title, detailContent);
+            }
+        }
+        return midData;
+    }
+}

+ 1 - 1
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/model/EntityEnum.java

@@ -21,7 +21,7 @@ public enum EntityEnum {
     OCCUPATION("职业"), LOCATION("地点"), DEAD("死亡"), DEAD_REASON("死亡原因"),
     SIMILAR_DISEASE_KEYWORD("相似疾病"), GENETIC_DISEASE_KEYWORD("家族遗传病"), EPIDEMIC_AREA_HISTORY("疫区史"), SPECIAL_HOBBY("特殊嗜好"),
     CONTACT_HISTORY("接触史"), MARITAL_HISTORY("冶游史"), MARITAL_STATUS("婚姻情况"), MARRYIAGE("结婚年龄"), NEAR_RELATION("近亲史"),
-    CURE_AIM("治疗目的"), OTHER("其他"),OUTERCOURTYARD("外院");
+    CURE_AIM("治疗目的"), OTHER("其他"),OUTERCOURTYARD("外院"),NURSINGLEVEL("护理级别");
 
     private String value;
 

+ 37 - 0
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/process/EntityProcessTreatPlan.java

@@ -0,0 +1,37 @@
+package com.lantone.qc.kernel.structure.ai.process;
+
+import com.alibaba.fastjson.JSONObject;
+import com.lantone.qc.kernel.structure.ai.model.EntityEnum;
+import com.lantone.qc.kernel.structure.ai.model.Lemma;
+import com.lantone.qc.pub.model.entity.*;
+import com.lantone.qc.pub.model.label.MaritalLabel;
+import com.lantone.qc.pub.model.label.TreatPlanLabel;
+
+import java.util.List;
+
+/**
+ * @ClassName : EntityProcessTreatPlan
+ * @Description : 首次病程录--诊疗计划
+ * @Author : 楼辉荣
+ * @Date: 2020-03-19 15:45
+ */
+public class EntityProcessTreatPlan extends EntityProcess {
+    public TreatPlanLabel extractEntity(JSONObject aiOut) {
+        TreatPlanLabel treatPlanLabel = new TreatPlanLabel();
+        //护理级别
+        List<Lemma> nursingLevelLemmas = createEntityTree(aiOut, EntityEnum.NURSINGLEVEL.toString());
+        for (Lemma lemma :nursingLevelLemmas) {
+            NursingLevel nursingLevel = new NursingLevel();
+            nursingLevel.setName(lemma.getText());
+            treatPlanLabel.setNursingLevel(nursingLevel);
+        }
+        //药品
+        List<Lemma> medicineLemmas = createEntityTree(aiOut, EntityEnum.DRUG.toString());
+        for (Lemma lemma :medicineLemmas) {
+            Medicine medicine = new Medicine();
+            medicine.setName(lemma.getText());
+            treatPlanLabel.setMedicine(medicine);
+        }
+        return treatPlanLabel;
+    }
+}

+ 2 - 0
public/src/main/java/com/lantone/qc/pub/Content.java

@@ -111,6 +111,8 @@ public class Content {
     public static final String case_feature = "一、病例特点";
     public static final String pridiag = "二、初步诊断";
     public static final String diag_basis = "三、诊断依据";
+    public static final String differential_diag_basis = "四、鉴别诊断";
+    public static final String treat_plan = "五、诊疗计划";
 
 
     public static final String name_medical_institution = "医疗机构名称";

+ 11 - 0
public/src/main/java/com/lantone/qc/pub/model/doc/FirstCourseRecordDoc.java

@@ -1,6 +1,9 @@
 package com.lantone.qc.pub.model.doc;
 
+import com.lantone.qc.pub.model.label.CaseCharacteristicLabel;
 import com.lantone.qc.pub.model.label.DiagLabel;
+import com.lantone.qc.pub.model.label.DiagnosisLabel;
+import com.lantone.qc.pub.model.label.TreatPlanLabel;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -15,4 +18,12 @@ import lombok.Setter;
 public class FirstCourseRecordDoc extends ModelDoc {
     //初步诊断
     private DiagLabel initialDiagLabel;
+    //病历特点
+    private CaseCharacteristicLabel caseCharacteristicLabel;
+    //诊断依据
+    private DiagnosisLabel diagnosisLabel;
+    //鉴别诊断
+    private DiagLabel differentialDiagLabel;
+    //诊疗计划
+    private TreatPlanLabel treatPlanLabel;
 }

+ 10 - 0
public/src/main/java/com/lantone/qc/pub/model/entity/NursingLevel.java

@@ -0,0 +1,10 @@
+package com.lantone.qc.pub.model.entity;
+
+/**
+ * @ClassName : NursingLevel
+ * @Description : 护理级别
+ * @Author : 楼辉荣
+ * @Date: 2020-03-19 15:47
+ */
+public class NursingLevel extends General {
+}

+ 24 - 1
public/src/main/java/com/lantone/qc/pub/model/label/CaseCharacteristicLabel.java

@@ -1,10 +1,33 @@
 package com.lantone.qc.pub.model.label;
 
+import com.lantone.qc.pub.model.entity.*;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * @ClassName : CaseCharacteristicLabel
  * @Description : 病历特点
  * @Author : 楼辉荣
  * @Date: 2020-03-03 18:57
  */
-public class CaseCharacteristicLabel {
+@Getter
+@Setter
+public class CaseCharacteristicLabel extends GeneralLabel {
+    //临床表现
+    private List<Clinical> clinicals = new ArrayList<>();
+    //辅助检查
+    private List<Pacs> pacses;
+    //化验
+    private List<Lis> lises;
+    //治疗
+    private List<Treat> treats;
+    //一般情况
+    private List<GeneralDesc> generals;
+    //疾病信息
+    private List<Diag> diags = new ArrayList<>();
+    //入院途径
+    private BeHospitalizedWay beHospitalizedWay;
 }

+ 21 - 0
public/src/main/java/com/lantone/qc/pub/model/label/DiagnosisLabel.java

@@ -0,0 +1,21 @@
+package com.lantone.qc.pub.model.label;
+
+import com.lantone.qc.pub.model.entity.Clinical;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @ClassName : DiagnosisLabel
+ * @Description : 诊断依据
+ * @Author : 楼辉荣
+ * @Date: 2020-03-19 15:02
+ */
+@Setter
+@Getter
+public class DiagnosisLabel extends GeneralLabel {
+    //临床表现
+    private List<Clinical> clinicals = new ArrayList<>();
+}

+ 5 - 0
public/src/main/java/com/lantone/qc/pub/model/label/GeneralLabel.java

@@ -3,6 +3,8 @@ package com.lantone.qc.pub.model.label;
 import lombok.Getter;
 import lombok.Setter;
 
+import java.util.List;
+
 /**
  * @ClassName : GeneralLabel
  * @Description :
@@ -13,4 +15,7 @@ import lombok.Setter;
 @Getter
 public class GeneralLabel {
     private String text;
+    protected  <T> void add(List<T> list, T obj) {
+        list.add(obj);
+    }
 }

+ 19 - 0
public/src/main/java/com/lantone/qc/pub/model/label/TreatPlanLabel.java

@@ -0,0 +1,19 @@
+package com.lantone.qc.pub.model.label;
+
+import com.lantone.qc.pub.model.entity.Medicine;
+import com.lantone.qc.pub.model.entity.NursingLevel;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @ClassName : TreatPlanLabel
+ * @Description : 诊疗计划
+ * @Author : 楼辉荣
+ * @Date: 2020-03-19 15:05
+ */
+@Getter
+@Setter
+public class TreatPlanLabel extends GeneralLabel {
+    private NursingLevel nursingLevel;//护理级别
+    private Medicine medicine;//药品
+}