Merge remote-tracking branch 'origin/dev_3.0.0' into dev_3.0.0

pull/1/head
xueqingkun 11 months ago
commit f8e59d11a8

@ -0,0 +1,60 @@
-- 创建详细问表
create table vp_ask_template_question_similarity
(
id varchar(64) not null comment '主键'
primary key,
library_id varchar(64) not null comment '标准问题ID',
similarity_question varchar(255) not null comment '相似问题',
create_user_id varchar(64) null comment '创建人ID',
create_time datetime default CURRENT_TIMESTAMP null comment '创建时间',
update_user_id varchar(64) null comment '更新人ID',
update_time datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间'
) comment '相似问问题库';
-- 修改标准问表,移除默认回复
alter table vp_ask_template_question_library drop column default_answer_code;
alter table vp_ask_template_question_library drop column default_answer;
alter table vp_ask_template_question_library drop column default_answer_resource_id;
-- 修改问题记录表结构
alter table vp_diagnosis_qa_record
add match_type int not null default 1 comment '匹配类型 1相似度匹配 2大模型回答' after process_id;
alter table vp_diagnosis_qa_record modify question_library_id varchar (64) null comment '问题ID(如果走了相似问,则记录匹配到的问题ID)';
alter table vp_diagnosis_qa_record drop column question_wav_id;
alter table vp_diagnosis_qa_record drop column answer_type;
alter table vp_diagnosis_qa_record drop column answer_wav_id;
create table vp_ask_circulation_detail
(
id varchar(64) not null comment '主键'
primary key,
process_id varchar(64) null comment '诊断进程ID',
circulation_id varchar(64) null comment '对话流转ID',
circulation_no int null comment '流转序号,消息每经过一次处理,就+1',
question varchar(255) null comment '问题内容',
answer varchar(255) null comment '回答内容',
success_info varchar(255) null comment '成功的记录信息',
success_type int null comment '成功回答的类型 1相似度 2大模型',
fail_info text null comment '失败记录信息',
similarity_info text null comment '相似度匹配信息的JSON',
match_item varchar(64) null comment '匹配到的类目名称',
match_question varchar(255) null comment '相似度匹配 匹配到的问题',
match_score double null comment '如走相似度匹配,记录得分',
match_library_id varchar(64) null comment '如相似度匹配的是标准问ID,则保存',
match_similarity_id varchar(64) null comment '如果匹配到详细问ID则记录',
ai_medical_context text null comment '走大模型时,大模型的病例内容',
remark varchar(255) null comment '备注',
create_user_id varchar(64) null comment '创建人ID',
create_time datetime default CURRENT_TIMESTAMP null comment '创建时间',
update_user_id varchar(64) null comment '更新人ID',
update_time datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新人时间'
) comment '问诊流程详细流转记录表';

@ -29,11 +29,11 @@ public class VectorSimilarityConfiguration {
// 定义搜索过滤器使用的元数据字段(!!!!!!!!千万重要,数据类型一定要用字符串,否则会导致查询不到!!!!!!!!)
.withMetadataFields(
// 问题的ID
RedisVectorStore.MetadataField.tag("questionId"),
RedisVectorStore.MetadataField.tag("matchQuestionId"),
//关联字典ID
RedisVectorStore.MetadataField.tag("dictId"),
// 标准问ID
RedisVectorStore.MetadataField.tag("standardQuestionId"),
RedisVectorStore.MetadataField.tag("libraryQuestionId"),
// 类型 1标准问 2相似问 3自定义
RedisVectorStore.MetadataField.tag("type"))
.build();

@ -13,7 +13,12 @@ public class QaSimilarityQuestionAnswer {
/**
* ID
*/
private String matchQuestionCode;
private String matchQuestionId;
/**
* ID
*/
private String libraryQuestionId;
/**
* ID

@ -44,7 +44,7 @@ public class SimilarityUtil {
QaSimilarityQuestionAnswer qaSimilarityQuestionAnswer = new QaSimilarityQuestionAnswer();
qaSimilarityQuestionAnswer.setMatchQuestion(document.getContent());
qaSimilarityQuestionAnswer.setDictId(String.valueOf(document.getMetadata().get("dictId")));
qaSimilarityQuestionAnswer.setMatchQuestionCode(String.valueOf(document.getMetadata().get("standardQuestionId")));
qaSimilarityQuestionAnswer.setLibraryQuestionId(String.valueOf(document.getMetadata().get("standardQuestionId")));
// 1- 可以使数据进行排序,相似度越高,数值越大(redis相似度给的数据是越小相似度越高)
// -0.25目的是使数据趋近于中间,相似度不要太大(太大也不好调整),以使我们数据和张总之前提供的方法相似度差异稍小一点,但是不能小于0,如果小于0,取一个较大的值
double score = Math.max(0, 1 - Double.parseDouble(String.valueOf(document.getMetadata().get("vector_score"))) - 0.25);

@ -0,0 +1,18 @@
package com.supervision.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.supervision.model.AskCirculationDetail;
/**
* @author flevance
* @description vp_ask_circulation_detail()Mapper
* @createDate 2024-06-06 17:08:59
* @Entity com.supervision.model.AskCirculationDetail
*/
public interface AskCirculationDetailMapper extends BaseMapper<AskCirculationDetail> {
}

@ -0,0 +1,112 @@
package com.supervision.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
*
*
* @TableName vp_ask_circulation_detail
*/
@Builder
@TableName(value = "vp_ask_circulation_detail")
@Data
public class AskCirculationDetail implements Serializable {
@TableField(exist = false)
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId
private String id;
/**
* ID
*/
private String processId;
/**
* ID
*/
private String medicalId;
/**
* ID
*/
private String recordId;
/**
* ,,+1
*/
private Integer circulationNo;
/**
*
*/
private String question;
/**
*
*/
private String answer;
/**
*
*/
private String successInfo;
/**
* 1 2
*/
private Integer successType;
/**
*
*/
private String failInfo;
/**
* JSON
*/
private String similarityInfo;
/**
*
*/
private String matchItem;
/**
*
*/
private String matchQuestion;
/**
* ,
*/
private Double matchScore;
/**
* ,ID
*/
private String matchLibraryId;
/**
* ,ID
*/
private String matchSimilarityId;
/**
* ,
*/
private String aiMedicalContext;
/**
*
*/
private String remark;
/**
* ID
*/
private String createUserId;
/**
*
*/
private LocalDateTime createTime;
/**
* ID
*/
private String updateUserId;
/**
*
*/
private LocalDateTime updateTime;
}

@ -33,14 +33,8 @@ public class DiagnosisQaRecord extends Model<DiagnosisQaRecord> implements Seria
@Schema(description = "诊断进程ID")
private String processId;
@Schema(description = "问答类型:default,patient,如果patient,说明是病历配置的回答,打勾")
private String answerType;
/**
* ID
*/
@Schema(description = "问题答案表ID,default:vp_ask_template_question_library的主键,patient:vp_ask_patient_answer主键")
private String answerId;
@Schema(description = "匹配类型 1相似度匹配 2大模型回答")
private Integer matchType;
/**
*
@ -54,23 +48,15 @@ public class DiagnosisQaRecord extends Model<DiagnosisQaRecord> implements Seria
@Schema(description = "问题ID")
private String questionLibraryId;
/**
* ID
*/
@Schema(description = "问题语音文件ID")
private String questionWavId;
/**
*
*/
@Schema(description = "回答")
private String answer;
/**
* ID
*/
@Schema(description = "回答语音文件ID")
private String answerWavId;
@Schema(description = "回答来源的ID")
private String answerId;
@Schema(description = "是否是证实诊断依据(0否1是)")
private Integer basisConfirmFlag;

@ -0,0 +1,13 @@
package com.supervision.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.supervision.model.AskCirculationDetail;
/**
* @author flevance
* @description vp_ask_circulation_detail()Service
* @createDate 2024-06-06 17:08:59
*/
public interface AskCirculationDetailService extends IService<AskCirculationDetail> {
}

@ -0,0 +1,22 @@
package com.supervision.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.supervision.mapper.AskCirculationDetailMapper;
import com.supervision.model.AskCirculationDetail;
import com.supervision.service.AskCirculationDetailService;
import org.springframework.stereotype.Service;
/**
* @author flevance
* @description vp_ask_circulation_detail()Service
* @createDate 2024-06-06 17:08:59
*/
@Service
public class AskCirculationDetailServiceImpl extends ServiceImpl<AskCirculationDetailMapper, AskCirculationDetail>
implements AskCirculationDetailService {
}

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.supervision.mapper.AskCirculationDetailMapper">
<resultMap id="BaseResultMap" type="com.supervision.model.AskCirculationDetail">
<id property="id" column="id" jdbcType="VARCHAR"/>
<result property="processId" column="process_id" jdbcType="VARCHAR"/>
<result property="medicalId" column="medical_id" jdbcType="VARCHAR"/>
<result property="recordId" column="record_id" jdbcType="VARCHAR"/>
<result property="circulationNo" column="circulation_no" jdbcType="INTEGER"/>
<result property="question" column="question" jdbcType="VARCHAR"/>
<result property="answer" column="answer" jdbcType="VARCHAR"/>
<result property="successInfo" column="success_info" jdbcType="VARCHAR"/>
<result property="successType" column="success_type" jdbcType="INTEGER"/>
<result property="failInfo" column="fail_info" jdbcType="VARCHAR"/>
<result property="similarityInfo" column="similarity_info" jdbcType="VARCHAR"/>
<result property="matchItem" column="match_item" jdbcType="VARCHAR"/>
<result property="matchQuestion" column="match_question" jdbcType="VARCHAR"/>
<result property="matchScore" column="match_score" jdbcType="DOUBLE"/>
<result property="matchLibraryId" column="match_library_id" jdbcType="VARCHAR"/>
<result property="matchSimilarityId" column="match_similarity_id" jdbcType="VARCHAR"/>
<result property="aiMedicalContext" column="ai_medical_context" jdbcType="VARCHAR"/>
<result property="remark" column="remark" jdbcType="VARCHAR"/>
<result property="createUserId" column="create_user_id" jdbcType="VARCHAR"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="updateUserId" column="update_user_id" jdbcType="VARCHAR"/>
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id
,process_id,medical_id,
record_id,circulation_no,question,
answer,success_info,success_type,
fail_info,similarity_info,match_item,
match_question,match_score,match_library_id,
match_similarity_id,ai_medical_context,remark,
create_user_id,create_time,update_user_id,
update_time
</sql>
</mapper>

@ -170,7 +170,7 @@ public class AskDiagnosisResultServiceImpl implements AskDiagnosisResultService
// 初步诊断依据 vp_medical_rec的primarily_diagnosis_criteria
basisPrimaryResultResVO.setPreliminaryDiagnosis(medicalRec.getPrimarilyDiagnosisCriteria());
// 根据record记录寻找符合初步诊断依据的项目
// 2.1 首先获取对话
// 2.1 首先获取对话记录
List<DiagnosisQaRecord> qaRecordList = diagnosisQaRecordService.lambdaQuery().eq(DiagnosisQaRecord::getProcessId, process.getId()).list();
List<AskPatientAnswer> list = askPatientAnswerService.lambdaQuery()
.eq(AskPatientAnswer::getMedicalId, medicalRec.getId()).list();
@ -187,69 +187,70 @@ public class AskDiagnosisResultServiceImpl implements AskDiagnosisResultService
List<AncillaryRecordByResultDTO> ancillaryRecordList = diagnosisAncillaryRecordService.queryAncillaryResultByProcessId(process.getId());
List<DiseaseAncillaryResVo> diseaseAncillaryResVos = diseaseAncillaryService.queryListByDiseaseId(medicalRec.getDiseaseId());
basisDiagnosisNodeResVOS.addAll(ancillaryRecordMergeListsBasisPrimary(ancillaryRecordList,diseaseAncillaryResVos));
basisDiagnosisNodeResVOS.addAll(ancillaryRecordMergeListsBasisPrimary(ancillaryRecordList, diseaseAncillaryResVos));
basisPrimaryResultResVO.setNodeList(basisDiagnosisNodeResVOS);
return basisPrimaryResultResVO;
}
private List<BasisDiagnosisNodeResVO> qaRecordMergeListsBasisPrimary(List<DiagnosisQaRecord> qaRecordList, List<AskPatientAnswer> list){
private List<BasisDiagnosisNodeResVO> qaRecordMergeListsBasisPrimary(List<DiagnosisQaRecord> qaRecordList, List<AskPatientAnswer> list) {
BiFunction<DiagnosisQaRecord,AskPatientAnswer,Boolean> biFunction = (qaRecord, qa) -> qa.getLibraryQuestionId().equals(qaRecord.getQuestionLibraryId());
BiFunction<DiagnosisQaRecord, AskPatientAnswer, Boolean> biFunction = (qaRecord, qa) -> qa.getLibraryQuestionId().equals(qaRecord.getQuestionLibraryId());
list = list.stream().filter(item -> !Integer.valueOf("0").equals(item.getAnswerType())).collect(Collectors.toList());
Set<String> requireCheckIdSet = list.stream().map(AskPatientAnswer::getId).collect(Collectors.toSet());
Function<DiagnosisQaRecord,BasisDiagnosisNodeResVO> t1 = r -> new BasisDiagnosisNodeResVO(0,r.getQuestion(),r.getId(),
Function<DiagnosisQaRecord, BasisDiagnosisNodeResVO> t1 = r -> new BasisDiagnosisNodeResVO(0, r.getQuestion(), r.getId(),
requireCheckIdSet.contains(r.getAnswerId()) ? 1 : 0);
Function<AskPatientAnswer,BasisDiagnosisNodeResVO> t2 = item -> new BasisDiagnosisNodeResVO(0, item.getQuestion(), item.getId(), 0);
Function<AskPatientAnswer, BasisDiagnosisNodeResVO> t2 = item -> new BasisDiagnosisNodeResVO(0, item.getQuestion(), item.getId(), 0);
return mergeListsBasedOnCondition(qaRecordList, list, biFunction, t1, t2);
}
private List<BasisDiagnosisNodeResVO> physicalRecordMergeLists(List<PhysicalRecordByResultDTO> physicalRecordList,
List<DiseasePhysicalResVo> diseasePhysicalResVos,
Function<PhysicalRecordByResultDTO,Integer> functionCorrect){
List<DiseasePhysicalResVo> diseasePhysicalResVos,
Function<PhysicalRecordByResultDTO, Integer> functionCorrect) {
physicalRecordList = physicalRecordList.stream()
.filter(distinctPredicateNotNull(PhysicalRecordByResultDTO::getToolLocationName)).collect(Collectors.toList());
// 工具id相等且 位置为空或者位置id相等
BiFunction<PhysicalRecordByResultDTO,DiseasePhysicalResVo,Boolean> biFunction = (r, diseasePhysical) -> StrUtil.equals(diseasePhysical.getToolId(),r.getToolId())
&& ((StrUtil.isEmpty(diseasePhysical.getLocationId()) && StrUtil.isEmpty(diseasePhysical.getLocationId()))
|| StrUtil.equals(diseasePhysical.getLocationId(),(r.getLocationId())));
BiFunction<PhysicalRecordByResultDTO, DiseasePhysicalResVo, Boolean> biFunction = (r, diseasePhysical) -> StrUtil.equals(diseasePhysical.getToolId(), r.getToolId())
&& ((StrUtil.isEmpty(diseasePhysical.getLocationId()) && StrUtil.isEmpty(diseasePhysical.getLocationId()))
|| StrUtil.equals(diseasePhysical.getLocationId(), (r.getLocationId())));
Function<PhysicalRecordByResultDTO,BasisDiagnosisNodeResVO> t1 = r -> new BasisDiagnosisNodeResVO(1, r.getToolLocationName(),
Function<PhysicalRecordByResultDTO, BasisDiagnosisNodeResVO> t1 = r -> new BasisDiagnosisNodeResVO(1, r.getToolLocationName(),
r.getRecordId(), functionCorrect.apply(r));
// 这里的recordId只为了展示用diseasePhysical.getId()代替。只是为展示使用correct的值固定为不正确
Function<DiseasePhysicalResVo,BasisDiagnosisNodeResVO> t2 = diseasePhysical -> new BasisDiagnosisNodeResVO(1,
diseasePhysical.getToolName() + (StrUtil.isEmpty(diseasePhysical.getLocationName())? "" : "|"+ diseasePhysical.getLocationName()),
Function<DiseasePhysicalResVo, BasisDiagnosisNodeResVO> t2 = diseasePhysical -> new BasisDiagnosisNodeResVO(1,
diseasePhysical.getToolName() + (StrUtil.isEmpty(diseasePhysical.getLocationName()) ? "" : "|" + diseasePhysical.getLocationName()),
diseasePhysical.getId(), 0);
return mergeListsBasedOnCondition(physicalRecordList, diseasePhysicalResVos,biFunction, t1, t2);
return mergeListsBasedOnCondition(physicalRecordList, diseasePhysicalResVos, biFunction, t1, t2);
}
private List<BasisDiagnosisNodeResVO> ancillaryRecordMergeLists(List<AncillaryRecordByResultDTO> ancillaryRecordList,
List<DiseaseAncillaryResVo> diseaseAncillaryResVos,
Function<AncillaryRecordByResultDTO,Integer> functionCorrect){
Function<AncillaryRecordByResultDTO, Integer> functionCorrect) {
ancillaryRecordList = ancillaryRecordList.stream()
.filter(distinctPredicateNotNull(AncillaryRecordByResultDTO::getItemName)).collect(Collectors.toList());
BiFunction<AncillaryRecordByResultDTO,DiseaseAncillaryResVo,Boolean> biFunction =(r, diseaseAncillary) -> StrUtil.equals(diseaseAncillary.getItemId(),r.getItemId());
BiFunction<AncillaryRecordByResultDTO, DiseaseAncillaryResVo, Boolean> biFunction = (r, diseaseAncillary) -> StrUtil.equals(diseaseAncillary.getItemId(), r.getItemId());
Function<AncillaryRecordByResultDTO,BasisDiagnosisNodeResVO> t1 = record -> new BasisDiagnosisNodeResVO(2, record.getItemName(), record.getRecordId(),
Function<AncillaryRecordByResultDTO, BasisDiagnosisNodeResVO> t1 = record -> new BasisDiagnosisNodeResVO(2, record.getItemName(), record.getRecordId(),
functionCorrect.apply(record));
// 这里的recordId只为了展示用diseaseAncillary.getId()代替。只是为展示使用correct的值固定为不正确
Function<DiseaseAncillaryResVo,BasisDiagnosisNodeResVO> t2 = diseaseAncillary -> new BasisDiagnosisNodeResVO(2, diseaseAncillary.getItemName(),
Function<DiseaseAncillaryResVo, BasisDiagnosisNodeResVO> t2 = diseaseAncillary -> new BasisDiagnosisNodeResVO(2, diseaseAncillary.getItemName(),
diseaseAncillary.getId(), 0);
return mergeListsBasedOnCondition(ancillaryRecordList, diseaseAncillaryResVos,biFunction, t1, t2);
return mergeListsBasedOnCondition(ancillaryRecordList, diseaseAncillaryResVos, biFunction, t1, t2);
}
private List<BasisDiagnosisNodeResVO> physicalRecordMergeListsBasisPrimary(List<PhysicalRecordByResultDTO> physicalRecordList,
List<DiseasePhysicalResVo> diseasePhysicalResVos){
List<DiseasePhysicalResVo> diseasePhysicalResVos) {
diseasePhysicalResVos = diseasePhysicalResVos.stream()
.filter(diseasePhysicalResVo -> Integer.valueOf(1).equals(diseasePhysicalResVo.getPrimarilyDiagnosisCriteriaFlag())).collect(Collectors.toList());
@ -257,9 +258,9 @@ public class AskDiagnosisResultServiceImpl implements AskDiagnosisResultService
}
private List<BasisDiagnosisNodeResVO> physicalRecordMergeListsConfirm(List<PhysicalRecordByResultDTO> physicalRecordList,
List<DiseasePhysicalResVo> diseasePhysicalResVos){
List<DiseasePhysicalResVo> diseasePhysicalResVos) {
Function<PhysicalRecordByResultDTO,Integer> functionCorrect = record -> (ObjectUtil.isNotNull(record.getBasisConfirm()) && 1 == record.getBasisConfirm()
Function<PhysicalRecordByResultDTO, Integer> functionCorrect = record -> (ObjectUtil.isNotNull(record.getBasisConfirm()) && 1 == record.getBasisConfirm()
&& Objects.equals(record.getBasisConfirm(), record.getRecordBasisConfirmFlag())) ? 1 : 0;
diseasePhysicalResVos = diseasePhysicalResVos.stream()
@ -268,9 +269,9 @@ public class AskDiagnosisResultServiceImpl implements AskDiagnosisResultService
}
private List<BasisDiagnosisNodeResVO> physicalRecordMergeListsIdentification(List<PhysicalRecordByResultDTO> physicalRecordList,
List<DiseasePhysicalResVo> diseasePhysicalResVos){
List<DiseasePhysicalResVo> diseasePhysicalResVos) {
Function<PhysicalRecordByResultDTO,Integer> functionCorrect = record -> (Integer.valueOf(1).equals(record.getBasisIdentification())
Function<PhysicalRecordByResultDTO, Integer> functionCorrect = record -> (Integer.valueOf(1).equals(record.getBasisIdentification())
&& Objects.equals(record.getBasisIdentification(), record.getRecordBasisIdentificationFlag())) ? 1 : 0;
diseasePhysicalResVos = diseasePhysicalResVos.stream()
@ -279,7 +280,7 @@ public class AskDiagnosisResultServiceImpl implements AskDiagnosisResultService
}
private List<BasisDiagnosisNodeResVO> ancillaryRecordMergeListsBasisPrimary(List<AncillaryRecordByResultDTO> ancillaryRecordList,
List<DiseaseAncillaryResVo> diseaseAncillaryResVos){
List<DiseaseAncillaryResVo> diseaseAncillaryResVos) {
diseaseAncillaryResVos = diseaseAncillaryResVos.stream()
.filter(diseaseAncillaryResVo -> Integer.valueOf(1).equals(diseaseAncillaryResVo.getPrimarilyDiagnosisCriteriaFlag())).collect(Collectors.toList());
@ -290,35 +291,35 @@ public class AskDiagnosisResultServiceImpl implements AskDiagnosisResultService
private List<BasisDiagnosisNodeResVO> ancillaryRecordMergeListsConfirm(List<AncillaryRecordByResultDTO> ancillaryRecordList,
List<DiseaseAncillaryResVo> diseaseAncillaryResVos){
List<DiseaseAncillaryResVo> diseaseAncillaryResVos) {
Function<AncillaryRecordByResultDTO,Integer> functionCorrect = record -> ObjectUtil.isNotNull(record.getBasisConfirm()) && 1 == record.getBasisConfirm()
&& Objects.equals(record.getBasisConfirm(), record.getRecordBasisConfirmFlag()) ? 1 : 0 ;
Function<AncillaryRecordByResultDTO, Integer> functionCorrect = record -> ObjectUtil.isNotNull(record.getBasisConfirm()) && 1 == record.getBasisConfirm()
&& Objects.equals(record.getBasisConfirm(), record.getRecordBasisConfirmFlag()) ? 1 : 0;
diseaseAncillaryResVos = diseaseAncillaryResVos.stream()
.filter(diseaseAncillaryResVo -> Integer.valueOf(1).equals(diseaseAncillaryResVo.getBasisConfirmFlag())).collect(Collectors.toList());
return ancillaryRecordMergeLists(ancillaryRecordList, diseaseAncillaryResVos,functionCorrect);
return ancillaryRecordMergeLists(ancillaryRecordList, diseaseAncillaryResVos, functionCorrect);
}
private List<BasisDiagnosisNodeResVO> ancillaryRecordMergeListsIdentification(List<AncillaryRecordByResultDTO> ancillaryRecordList,
List<DiseaseAncillaryResVo> diseaseAncillaryResVos){
List<DiseaseAncillaryResVo> diseaseAncillaryResVos) {
Function<AncillaryRecordByResultDTO,Integer> functionCorrect = record -> (Integer.valueOf(1).equals(record.getBasisIdentification())
Function<AncillaryRecordByResultDTO, Integer> functionCorrect = record -> (Integer.valueOf(1).equals(record.getBasisIdentification())
&& Objects.equals(record.getBasisIdentification(), record.getRecordBasisIdentificationFlag())) ? 1 : 0;
diseaseAncillaryResVos = diseaseAncillaryResVos.stream()
.filter(diseaseAncillaryResVo -> Integer.valueOf(1).equals(diseaseAncillaryResVo.getBasisIdentificationFlag())).collect(Collectors.toList());
return ancillaryRecordMergeLists(ancillaryRecordList, diseaseAncillaryResVos,functionCorrect);
return ancillaryRecordMergeLists(ancillaryRecordList, diseaseAncillaryResVos, functionCorrect);
}
/**
*
*
* @param simpleList
* @param poolList
* @param poolList
* @param biFunction
* @param t1
* @param t2
* @param t1
* @param t2
* @return
*/
private <T, M, R> List<R> mergeListsBasedOnCondition(List<T> simpleList, List<M> poolList,
@ -346,7 +347,7 @@ public class AskDiagnosisResultServiceImpl implements AskDiagnosisResultService
break;
}
}
if (!find){
if (!find) {
rs.add(t2.apply(m));
}
}

@ -2,6 +2,7 @@ package com.supervision.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.supervision.domain.QaSimilarityQuestionAnswer;
import com.supervision.exception.BusinessException;
import com.supervision.model.Process;
@ -15,12 +16,14 @@ import com.supervision.util.TtsUtil;
import com.supervision.util.UserUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.vectorstore.RedisVectorStore;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
@Service
@ -37,9 +40,10 @@ public class AskServiceImpl implements AskService {
private final MedicalRecService medicalRecService;
private final DiagnosisAiRecordService diagnosisAiRecordService;
private final AskCirculationDetailService askCirculationDetailService;
private final CommonDicService commonDicService;
private final RedisVectorStore redisVectorStore;
@Value("${threshold:0.7}")
private String threshold;
@ -61,21 +65,6 @@ public class AskServiceImpl implements AskService {
return text;
}
private void saveQaRecord(String processId, String answerType, String answerId, String question, AskTemplateQuestionLibrary library, String resText) {
DiagnosisQaRecord record = new DiagnosisQaRecord();
record.setProcessId(processId);
record.setAnswerType(answerType);
record.setAnswerId(answerId);
if (ObjectUtil.isNotEmpty(library)) {
record.setQuestionLibraryId(library.getId());
}
record.setQuestion(question);
record.setAnswer(resText);
record.setCreateUserId(UserUtil.getUser().getId());
record.insert();
}
/**
* 使+
*
@ -84,69 +73,127 @@ public class AskServiceImpl implements AskService {
*/
@Override
public TalkVideoTtsResultResVO talkByVideoAndTts(TalkVideoReqVO talkReqVO) {
String answer = talkByVideoAndTts(talkReqVO.getProcessId(), talkReqVO.getText());
TalkVideoTtsResultResVO talkVideoTtsResultResVO = new TalkVideoTtsResultResVO();
talkVideoTtsResultResVO.setVoiceBase64(TtsUtil.ttsTransform(answer));
talkVideoTtsResultResVO.setAnswerMessage(answer);
return talkVideoTtsResultResVO;
}
private String talkByVideoAndTts(String processId, String question) {
// 流转记录表
List<AskCirculationDetail> circulationList = new ArrayList<>();
// 根据processId找到对应的病人
Process process = Optional.ofNullable(processService.getById(talkReqVO.getProcessId())).orElseThrow(() -> new BusinessException("未找到诊疗进程"));
Process process = Optional.ofNullable(processService.getById(processId)).orElseThrow(() -> new BusinessException("未找到诊疗进程"));
MedicalRec medicalRec = medicalRecService.getById(process.getMedicalRecId());
Optional<QaSimilarityQuestionAnswer> qaSimilarityQuestionAnswerOptional = SimilarityUtil.talkRedisVectorWithScoreByFirst(talkReqVO.getText());
TalkVideoTtsResultResVO talkVideoTtsResultResVO = new TalkVideoTtsResultResVO();
// 如果匹配度没有匹配到任何数据,则走大模型
if (qaSimilarityQuestionAnswerOptional.isEmpty()) {
String talk = aiService.talk(talkReqVO.getText(), medicalRec.getMedicalRecordAi());
talkVideoTtsResultResVO.setAnswerMessage(talk);
saveAiRecord(process.getId(), talkReqVO.getText(), talkVideoTtsResultResVO.getAnswerMessage());
} else {
QaSimilarityQuestionAnswer qaSimilarityQuestionAnswer = qaSimilarityQuestionAnswerOptional.get();
// 如果阈值过低,也走大模型
double thresholdValue = Double.parseDouble(threshold);
if (qaSimilarityQuestionAnswer.getMatchScore() < thresholdValue) {
log.info("{}:匹配到的结果阈值过低,走大模型回答", qaSimilarityQuestionAnswer);
String talk = aiService.talk(talkReqVO.getText(), medicalRec.getMedicalRecordAi());
talkVideoTtsResultResVO.setAnswerMessage(talk);
saveAiRecord(process.getId(), talkReqVO.getText(), talkVideoTtsResultResVO.getAnswerMessage());
} else {
// 如果查到的问题不在问题库中,走大模型回答
AskTemplateQuestionLibrary library = askTemplateQuestionLibraryService.getById(qaSimilarityQuestionAnswer.getMatchQuestionCode());
if (ObjectUtil.isEmpty(library)) {
log.info("{}:未从问题库中找到,走大模型回答", qaSimilarityQuestionAnswer);
String talk = aiService.talk(talkReqVO.getText(), medicalRec.getMedicalRecordAi());
talkVideoTtsResultResVO.setAnswerMessage(talk);
saveAiRecord(process.getId(), talkReqVO.getText(), talkVideoTtsResultResVO.getAnswerMessage());
} else {
// 根据问题找这个病历配置的答案
AskPatientAnswer askPatientAnswer = askPatientAnswerService.lambdaQuery().eq(AskPatientAnswer::getMedicalId, process.getMedicalRecId())
.eq(AskPatientAnswer::getLibraryQuestionId, library.getId()).last("limit 1").one();
// 如果找到了,就走病历配置的内容回答
if (ObjectUtil.isNotEmpty(askPatientAnswer)) {
String resText = askPatientAnswer.getAnswer();
log.info("{}:找到了病历配置的回答语句:{},回答内容:{},走病历回答", qaSimilarityQuestionAnswer.getMatchQuestionCode(), askPatientAnswer.getId(), resText);
talkVideoTtsResultResVO.setAnswerMessage(resText);
// 保存记录到问答记录表
saveQaRecord(talkReqVO.getProcessId(), "patient", askPatientAnswer.getId(), talkReqVO.getText(), library, resText);
} else {
// 如果问题的答案没有配置,还是走大模型的回答
log.info("{}:病历配置,从AskPatientAnswer中未找到回答结果,走大模型", qaSimilarityQuestionAnswer.getMatchQuestionCode());
String talk = aiService.talk(talkReqVO.getText(), medicalRec.getMedicalRecordAi());
talkVideoTtsResultResVO.setAnswerMessage(talk);
saveAiRecord(process.getId(), talkReqVO.getText(), talkVideoTtsResultResVO.getAnswerMessage());
}
}
}
// 进行相似度匹配
List<QaSimilarityQuestionAnswer> similarityAnswerList = SimilarityUtil.talkRedisVectorWithScore(question);
Optional<QaSimilarityQuestionAnswer> first = similarityAnswerList.stream().findFirst();
// 如果匹配度没有匹配到任何数据
if (first.isEmpty()) {
// 记录流转信息
circulationList.add(AskCirculationDetail.builder().failInfo("相似度返回内容为空,走大模型").build());
// 如果没有匹配到,就走大模型
String answer = aiService.talk(question, medicalRec.getMedicalRecordAi());
// 记录大模型的流转记录
buildAiCirculationDetail(circulationList, answer, medicalRec);
// 保存消息到记录表
saveQaRecord(process.getId(), 2, question, null, answer, circulationList);
return answer;
}
talkVideoTtsResultResVO.setVoiceBase64(TtsUtil.ttsTransform(talkVideoTtsResultResVO.getAnswerMessage()));
return talkVideoTtsResultResVO;
QaSimilarityQuestionAnswer similarityResult = first.get();
// 如果阈值过低,也走大模型
double thresholdValue = Double.parseDouble(threshold);
if (similarityResult.getMatchScore() < thresholdValue) {
log.info("{}:匹配到的结果阈值过低,走大模型回答", similarityResult);
circulationList.add(AskCirculationDetail.builder()
.failInfo("相似度为:" + similarityResult.getMatchScore() + ",低于配置的阈值:" + threshold + ",走大模型")
.similarityInfo(JSONUtil.toJsonStr(similarityAnswerList))
.build());
String answer = aiService.talk(question, medicalRec.getMedicalRecordAi());
// 记录流转记录
buildAiCirculationDetail(circulationList, answer, medicalRec);
saveQaRecord(process.getId(), 2, question, null, answer, circulationList);
return answer;
}
// 根据对应的标准问题,从标准问题表中找到标准问题
AskTemplateQuestionLibrary library = askTemplateQuestionLibraryService.getById(similarityResult.getLibraryQuestionId());
if (ObjectUtil.isEmpty(library)) {
log.info("{}:未从问题库中找到答案,走大模型回答", similarityResult);
circulationList.add(AskCirculationDetail.builder()
// 问题库中未找到该问题
.failInfo("问题库中匹配到的问题为:" + similarityResult.getMatchQuestion() + ",但未找到该标准问题:" + similarityResult.getLibraryQuestionId() + ",走大模型")
.similarityInfo(JSONUtil.toJsonStr(similarityAnswerList))
.build());
String answer = aiService.talk(question, medicalRec.getMedicalRecordAi());
// 记录流转记录
buildAiCirculationDetail(circulationList, answer, medicalRec);
saveQaRecord(process.getId(), 2, question, null, answer, circulationList);
return answer;
}
// 根据问题找这个病历配置的答案
AskPatientAnswer askPatientAnswer = askPatientAnswerService.lambdaQuery().eq(AskPatientAnswer::getMedicalId, process.getMedicalRecId())
.eq(AskPatientAnswer::getLibraryQuestionId, library.getId()).last("limit 1").one();
// 如果问题的答案没有配置,还是走大模型的回答
if (ObjectUtil.isEmpty(askPatientAnswer)) {
circulationList.add(AskCirculationDetail.builder()
.failInfo("相似问匹配到了,但未找到对应的病历配置的回答,匹配到的标准问ID为:" + similarityResult.getLibraryQuestionId())
.similarityInfo(JSONUtil.toJsonStr(similarityAnswerList))
.build());
log.info("{}:病历配置,从AskPatientAnswer中未找到回答结果,走大模型", similarityResult.getLibraryQuestionId());
String answer = aiService.talk(question, medicalRec.getMedicalRecordAi());
// 记录流转记录
buildAiCirculationDetail(circulationList, answer, medicalRec);
saveQaRecord(process.getId(), 2, question, null, answer, circulationList);
return answer;
}
// 如果找到了,就走病历配置的内容回答
String patientAnswer = askPatientAnswer.getAnswer();
log.info("{}:找到了病历配置的回答语句:{},回答内容:{},走病历回答", similarityResult.getMatchQuestion(), askPatientAnswer.getId(), patientAnswer);
circulationList.add(AskCirculationDetail.builder()
.answer(patientAnswer)
// 问题库中未找到该问题
.successInfo("相似问匹配到了,走相似问")
.similarityInfo(JSONUtil.toJsonStr(similarityAnswerList))
.matchScore(similarityResult.getMatchScore())
.matchItem(Optional.ofNullable(commonDicService.getById(Long.parseLong(similarityResult.getDictId()))).orElse(new CommonDic()).getNameZhPath())
.matchSimilarityId(similarityResult.getMatchQuestionId())
.matchLibraryId(similarityResult.getLibraryQuestionId())
.matchQuestion(similarityResult.getMatchQuestion())
.successType(1)
.build());
saveQaRecord(process.getId(), 1, question, similarityResult.getLibraryQuestionId(), patientAnswer, circulationList);
return patientAnswer;
}
private void buildAiCirculationDetail(List<AskCirculationDetail> detailList, String answer, MedicalRec medicalRec) {
AskCirculationDetail newDetail = AskCirculationDetail.builder().answer(answer)
.successInfo("走大模型进行匹配,获得答案,回复用户").aiMedicalContext(medicalRec.getMedicalRecordAi())
.successType(2).build();
detailList.add(newDetail);
}
/**
* AI,便AI
*/
private void saveAiRecord(String processId, String question, String answer) {
DiagnosisAiRecord diagnosisAiRecord = new DiagnosisAiRecord();
diagnosisAiRecord.setProcessId(processId);
diagnosisAiRecord.setQuestion(question);
diagnosisAiRecord.setAnswer(answer);
diagnosisAiRecord.setCreateUserId(UserUtil.getUser().getId());
diagnosisAiRecord.setUpdateUserId(UserUtil.getUser().getId());
diagnosisAiRecordService.save(diagnosisAiRecord);
private void saveQaRecord(String processId, Integer matchType, String question, String libraryId, String answer, List<AskCirculationDetail> circulationList) {
DiagnosisQaRecord record = new DiagnosisQaRecord();
record.setProcessId(processId);
record.setMatchType(matchType);
record.setQuestionLibraryId(libraryId);
record.setQuestion(question);
record.setAnswer(answer);
record.setCreateUserId(UserUtil.getUser().getId());
record.insert();
AtomicInteger atomicInteger = new AtomicInteger(0);
circulationList.forEach(e -> {
e.setRecordId(record.getId());
e.setCirculationNo(atomicInteger.incrementAndGet());
e.setQuestion(question);
}
);
askCirculationDetailService.saveBatch(circulationList);
}
}

Loading…
Cancel
Save