diff --git a/docker/v3.0.0/step1.sql b/docker/v3.0.0/step1.sql
new file mode 100644
index 00000000..98213da1
--- /dev/null
+++ b/docker/v3.0.0/step1.sql
@@ -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 '问诊流程详细流转记录表';
+
+
diff --git a/virtual-patient-common/src/main/java/com/supervision/config/VectorSimilarityConfiguration.java b/virtual-patient-common/src/main/java/com/supervision/config/VectorSimilarityConfiguration.java
index beffc151..1e3463ce 100644
--- a/virtual-patient-common/src/main/java/com/supervision/config/VectorSimilarityConfiguration.java
+++ b/virtual-patient-common/src/main/java/com/supervision/config/VectorSimilarityConfiguration.java
@@ -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();
diff --git a/virtual-patient-common/src/main/java/com/supervision/domain/QaSimilarityQuestionAnswer.java b/virtual-patient-common/src/main/java/com/supervision/domain/QaSimilarityQuestionAnswer.java
index b1592634..c6651ee1 100644
--- a/virtual-patient-common/src/main/java/com/supervision/domain/QaSimilarityQuestionAnswer.java
+++ b/virtual-patient-common/src/main/java/com/supervision/domain/QaSimilarityQuestionAnswer.java
@@ -13,7 +13,12 @@ public class QaSimilarityQuestionAnswer {
     /**
      * 匹配到的问题ID
      */
-    private String matchQuestionCode;
+    private String matchQuestionId;
+
+    /**
+     * 对应的标准问ID
+     */
+    private String libraryQuestionId;
 
     /**
      * 关联的字典ID
diff --git a/virtual-patient-common/src/main/java/com/supervision/util/SimilarityUtil.java b/virtual-patient-common/src/main/java/com/supervision/util/SimilarityUtil.java
index d9515107..41107161 100644
--- a/virtual-patient-common/src/main/java/com/supervision/util/SimilarityUtil.java
+++ b/virtual-patient-common/src/main/java/com/supervision/util/SimilarityUtil.java
@@ -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);
diff --git a/virtual-patient-model/src/main/java/com/supervision/mapper/AskCirculationDetailMapper.java b/virtual-patient-model/src/main/java/com/supervision/mapper/AskCirculationDetailMapper.java
new file mode 100644
index 00000000..9404571c
--- /dev/null
+++ b/virtual-patient-model/src/main/java/com/supervision/mapper/AskCirculationDetailMapper.java
@@ -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> {
+
+}
+
+
+
+
diff --git a/virtual-patient-model/src/main/java/com/supervision/model/AskCirculationDetail.java b/virtual-patient-model/src/main/java/com/supervision/model/AskCirculationDetail.java
new file mode 100644
index 00000000..7ba00e75
--- /dev/null
+++ b/virtual-patient-model/src/main/java/com/supervision/model/AskCirculationDetail.java
@@ -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;
+}
\ No newline at end of file
diff --git a/virtual-patient-model/src/main/java/com/supervision/model/DiagnosisQaRecord.java b/virtual-patient-model/src/main/java/com/supervision/model/DiagnosisQaRecord.java
index 72055581..2ad67019 100644
--- a/virtual-patient-model/src/main/java/com/supervision/model/DiagnosisQaRecord.java
+++ b/virtual-patient-model/src/main/java/com/supervision/model/DiagnosisQaRecord.java
@@ -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;
diff --git a/virtual-patient-model/src/main/java/com/supervision/service/AskCirculationDetailService.java b/virtual-patient-model/src/main/java/com/supervision/service/AskCirculationDetailService.java
new file mode 100644
index 00000000..33b0f419
--- /dev/null
+++ b/virtual-patient-model/src/main/java/com/supervision/service/AskCirculationDetailService.java
@@ -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> {
+
+}
diff --git a/virtual-patient-model/src/main/java/com/supervision/service/impl/AskCirculationDetailServiceImpl.java b/virtual-patient-model/src/main/java/com/supervision/service/impl/AskCirculationDetailServiceImpl.java
new file mode 100644
index 00000000..6dd918e0
--- /dev/null
+++ b/virtual-patient-model/src/main/java/com/supervision/service/impl/AskCirculationDetailServiceImpl.java
@@ -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 {
+
+}
+
+
+
+
diff --git a/virtual-patient-model/src/main/resources/mapper/AskCirculationDetailMapper.xml b/virtual-patient-model/src/main/resources/mapper/AskCirculationDetailMapper.xml
new file mode 100644
index 00000000..8311c43e
--- /dev/null
+++ b/virtual-patient-model/src/main/resources/mapper/AskCirculationDetailMapper.xml
@@ -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>
diff --git a/virtual-patient-web/src/main/java/com/supervision/service/impl/AskDiagnosisResultServiceImpl.java b/virtual-patient-web/src/main/java/com/supervision/service/impl/AskDiagnosisResultServiceImpl.java
index 08c5108c..eeec68c4 100644
--- a/virtual-patient-web/src/main/java/com/supervision/service/impl/AskDiagnosisResultServiceImpl.java
+++ b/virtual-patient-web/src/main/java/com/supervision/service/impl/AskDiagnosisResultServiceImpl.java
@@ -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));
             }
         }
diff --git a/virtual-patient-web/src/main/java/com/supervision/service/impl/AskServiceImpl.java b/virtual-patient-web/src/main/java/com/supervision/service/impl/AskServiceImpl.java
index 2ce52d8a..422a1c69 100644
--- a/virtual-patient-web/src/main/java/com/supervision/service/impl/AskServiceImpl.java
+++ b/virtual-patient-web/src/main/java/com/supervision/service/impl/AskServiceImpl.java
@@ -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);
     }
 }