diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..241a302 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,2 @@ +pom.xml @zcao21 +package.json @zcao21 \ No newline at end of file diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/constant/Constant.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/constant/Constant.java index e256aa2..db15973 100644 --- a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/constant/Constant.java +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/constant/Constant.java @@ -4,6 +4,8 @@ public class Constant { public static final String CHANNEL_DCC = "Channel_Dcc"; + public static final String CHANNEL_4IN1 = "Channel_4in1"; + public static final String DISPLAY_STATUS = "FINISHED"; public static final String INTELLIGENT_CUSTOMER_4IN1 = "INTELLIGENT_CUSTOMER_4IN1"; diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/corpus/ImCurMessageDTO.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/corpus/ImCurMessageDTO.java new file mode 100644 index 0000000..1ab00a6 --- /dev/null +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/corpus/ImCurMessageDTO.java @@ -0,0 +1,38 @@ +package com.volvo.ai.analytic.center.dto.corpus; + +import lombok.Data; + +import java.util.Date; + +/** + * @description IM会话存档消息记录表-湖仓同步表 + * @author jlu + * @date 2025-07-17 + */ +@Data +public class ImCurMessageDTO { + + private static final long serialVersionUID = 1L; + + private Long id; + + private String sessionId; + + /** + * 消息内容文本 + */ + private String msgContent; + + /** + * 客户类型0:用户 1:百度 2:GPT 3:人工 4:唯都Agent + */ + private Integer customerType; + + private Long msgTimestamp; + + private String userDemand; + + public ImCurMessageDTO() { + } + +} \ No newline at end of file diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/ClaimVerificationFileDTO.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/ClaimVerificationFileDTO.java index aa95c33..83019ac 100644 --- a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/ClaimVerificationFileDTO.java +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/ClaimVerificationFileDTO.java @@ -16,7 +16,7 @@ public class ClaimVerificationFileDTO { @NotBlank(message = "售后ID不能为空") private String newBieAfterSalesId; - @NotBlank(message = "业务类型不能为空, 99001:文件分析,99002:审计报告") + @NotBlank(message = "业务类型不能为空, 99001:文件分析,99002:审计报告,99003:文件分类") private String businessType; //文件类型 dtc,诊断报告 @@ -33,4 +33,23 @@ public class ClaimVerificationFileDTO { //诊断报告 private JSONObject diagnosticReport; + + //诊断报告 + private JSONObject warrantyReport; + + //ai分析请求id + private String aiAnalysisRequestId; + + //文件分类列表 + private List claimVerificationFiles; + + @Data + @AllArgsConstructor + @NoArgsConstructor + public static class ClaimVerificationFile { + private String fileBusinessId; + private String fileObsPath; + private String fileType; + } + } diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/ClaimVerificationPartHoursDTO.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/ClaimVerificationPartHoursDTO.java new file mode 100644 index 0000000..9421279 --- /dev/null +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/ClaimVerificationPartHoursDTO.java @@ -0,0 +1,18 @@ +package com.volvo.ai.analytic.center.dto.req; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ClaimVerificationPartHoursDTO { + + //主零件id + private String partId; + + //主零件工时id + private String hoursId; + +} diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/CommunityTargetDTO.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/CommunityTargetDTO.java index 2fa70d6..3a4c34d 100644 --- a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/CommunityTargetDTO.java +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/CommunityTargetDTO.java @@ -12,6 +12,7 @@ public class CommunityTargetDTO { private String targetType; private String targetId; private String communityRequestId; + private String communityType; private List content; @Setter diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/ConsultingRequestDTO.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/ConsultingRequestDTO.java new file mode 100644 index 0000000..df660e8 --- /dev/null +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/ConsultingRequestDTO.java @@ -0,0 +1,18 @@ +package com.volvo.ai.analytic.center.dto.req; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.util.Date; + +@Data +public class ConsultingRequestDTO { + private String businessType; // 新增字段 + private String text; + private String sourceCorpusId; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date sourceCorpusTime; + + +} diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/SpokesManDTO.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/SpokesManDTO.java new file mode 100644 index 0000000..04a82a8 --- /dev/null +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/SpokesManDTO.java @@ -0,0 +1,27 @@ +package com.volvo.ai.analytic.center.dto.req; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class SpokesManDTO { + + private List files; + + private String platform; + + private String theme; + + private String communityRequestId; + + private String redNoteType; + + private String userId; + + private String postUrl; +} diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/SummaryQuestionRequestDTO.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/SummaryQuestionRequestDTO.java new file mode 100644 index 0000000..0fe2a34 --- /dev/null +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/dto/req/SummaryQuestionRequestDTO.java @@ -0,0 +1,13 @@ +package com.volvo.ai.analytic.center.dto.req; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class SummaryQuestionRequestDTO { + + private String summaryReportId; + + private String preliminarySummaryResults; + +} diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/DifySpokesManDTO.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/DifySpokesManDTO.java new file mode 100644 index 0000000..66159b3 --- /dev/null +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/DifySpokesManDTO.java @@ -0,0 +1,13 @@ +package com.volvo.ai.analytic.center.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class DifySpokesManDTO { + + private String channel; +} diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/TmClaimVerificationPartHoursMapping.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/TmClaimVerificationPartHoursMapping.java new file mode 100644 index 0000000..cef50ef --- /dev/null +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/TmClaimVerificationPartHoursMapping.java @@ -0,0 +1,69 @@ +package com.volvo.ai.analytic.center.entity; + + +import com.baomidou.mybatisplus.annotation.*; +import com.volvo.common.core.base.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("tm_claim_verification_part_hours_mapping") +public class TmClaimVerificationPartHoursMapping extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** + * 自增主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 外键part_id + */ + @TableField("part_id") + private String partId; + + /** + * 外键hours_id + */ + @TableField("hours_id") + private String hoursId; + + /** + * 记录版本号,即乐观锁 + */ + @TableField("versions") + private Integer versions; + + /** + * 删除标识(0-未删除,1-已删除) + */ + @TableField("is_deleted") + private Integer isDeleted; + + /** + * 创建人 + */ + @TableField("create_by") + private String createBy; + + /** + * 更新人 + */ + @TableField("update_by") + private String updateBy; + + /** + * 创建sql人 + */ + @TableField("create_sqlby") + private String createSqlby; + + /** + * 更新sql人 + */ + @TableField("update_sqlby") + private String updateSqlby; +} diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/TmCorpusQuestionReport.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/TmCorpusQuestionReport.java new file mode 100644 index 0000000..660975c --- /dev/null +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/TmCorpusQuestionReport.java @@ -0,0 +1,125 @@ +package com.volvo.ai.analytic.center.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.util.Date; + +/** + * 单条语料分析结论表 + */ +@Data +@TableName("tm_corpus_question_report") +public class TmCorpusQuestionReport { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + + /** + * 主类别 + */ + @TableField("main_category") + private String mainCategory; + + /** + * 子类别 + */ + @TableField("sub_category") + private String subCategory; + + /** + * 置信度 + */ + @TableField("confidence") + private String confidence; + + /** + * 业务类型 + */ + @TableField("business_type") + private String businessType; + + /** + * 用户需求 + */ + @TableField("user_demand") + private String userDemand; + + /** + * 分析结果 + */ + @TableField("analysis_result_json") + private String analysisResultJson; + + + /** + * 删除标识(0-未删除,1-已删除) + */ + @TableField("is_deleted") + private Integer isDeleted; + + /** + * 记录版本号,即乐观锁 + */ + @TableField("versions") + private Integer versions; + + /** + * 创建人 + */ + @TableField("create_by") + private String createBy; + + /** + * 更新人 + */ + @TableField("update_by") + private String updateBy; + + /** + * 创建sql人 + */ + @TableField("create_sqlby") + private String createSqlby; + + /** + * 更新sql人 + */ + @TableField("update_sqlby") + private String updateSqlby; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新时间 + */ + @TableField("update_time") + private Date updateTime; + + /** + * 原语料外部主键 + */ + @TableField("source_corpus_id") + private String sourceCorpusId; + + /** + * 原语料时间 + */ + @TableField("source_corpus_time") + private Date sourceCorpusTime; + + +} \ No newline at end of file diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/TmCorpusQuestionSummaryReport.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/TmCorpusQuestionSummaryReport.java new file mode 100644 index 0000000..a834906 --- /dev/null +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/TmCorpusQuestionSummaryReport.java @@ -0,0 +1,105 @@ +package com.volvo.ai.analytic.center.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.util.Date; + +/** + * 语料分析初步总结表 + */ +@Data +@TableName("tm_corpus_question_summary_report") +public class TmCorpusQuestionSummaryReport { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 主类别 + */ + @TableField("main_category") + private String mainCategory; + + /** + * 子类别 + */ + @TableField("sub_category") + private String subCategory; + + /** + * 初步结果 + */ + @TableField("preliminary_summary_results") + private String preliminarySummaryResults; + + /** + * 原语料时间 + */ + @TableField("source_time") + private Date sourceTime; + + /** + * 关联id + */ + @TableField("summary_report_id") + private String summaryReportId; + + + /** + * 删除标识(0-未删除,1-已删除) + */ + @TableField("is_deleted") + private Integer isDeleted; + + /** + * 记录版本号,即乐观锁 + */ + @TableField("versions") + private Integer versions; + + /** + * 创建人 + */ + @TableField("create_by") + private String createBy; + + /** + * 更新人 + */ + @TableField("update_by") + private String updateBy; + + /** + * 创建sql人 + */ + @TableField("create_sqlby") + private String createSqlby; + + /** + * 更新sql人 + */ + @TableField("update_sqlby") + private String updateSqlby; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 更新时间 + */ + @TableField("update_time") + private Date updateTime; + +} diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/TmOdsAinpArrivalTestdriveVoiceInfo.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/TmOdsAinpArrivalTestdriveVoiceInfo.java new file mode 100644 index 0000000..007c61d --- /dev/null +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/TmOdsAinpArrivalTestdriveVoiceInfo.java @@ -0,0 +1,232 @@ +package com.volvo.ai.analytic.center.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; + + +/** + * @author Lingma (灵码) + * @description 湖仓同步AI铭牌到店试驾语料信息 (tm_ods_ainp_arrival_testdrive_voice_info) + * @date 2025-07-17 + */ +@Data +@TableName("tm_ods_ainp_arrival_testdrive_voice_info") +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class TmOdsAinpArrivalTestdriveVoiceInfo { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 客流id + */ + @TableField("cust_flow_id") + private Long custFlowId; + + /** + * 商机id + */ + @TableField("biz_opp_id") + private Long bizOppId; + + /** + * 试驾id + */ + @TableField("test_drive_id") + private Long testDriveId; + + /** + * 经销商代码 + */ + @TableField("dealer_code") + private String dealerCode; + + /** + * 线索状态 + */ + @TableField("leads_stat") + private Integer leadsStat; + + /** + * 厅接待意向车型 + */ + @TableField("showroom_reception_intention_veh_model") + private String showroomReceptionIntentionVehModel; + + /** + * 厅接待意向车型燃料类型 + */ + @TableField("showroom_veh_model_fuel_type") + private Integer showroomVehModelFuelType; + + /** + * 商机主意向车型 + */ + @TableField("main_intention_veh_model") + private String mainIntentionVehModel; + + /** + * 商机主意向车型燃料类型 + */ + @TableField("main_intention_veh_model_fuel_type") + private Integer mainIntentionVehModelFuelType; + + /** + * 试驾车型 + */ + @TableField("test_drive_veh_model") + private String testDriveVehModel; + + /** + * 试驾车型燃料类型 + */ + @TableField("test_drive_veh_model_fuel_type") + private Integer testDriveVehModelFuelType; + + /** + * 到店销售顾问id + */ + @TableField("arrival_sales_consultant_id") + private String arrivalSalesConsultantId; + + /** + * 到店销售顾问 + */ + @TableField("arrival_sales_consultant") + private String arrivalSalesConsultant; + + /** + * 到店接待顾问id + */ + @TableField("arrival_reception_consultant_id") + private String arrivalReceptionConsultantId; + + /** + * 到店接待顾问 + */ + @TableField("arrival_reception_consultant") + private String arrivalReceptionConsultant; + + /** + * 试驾销售顾问id + */ + @TableField("test_drive_sales_consultant_id") + private String testDriveSalesConsultantId; + + /** + * 试驾销售顾问 + */ + @TableField("test_drive_sales_consultant") + private String testDriveSalesConsultant; + + /** + * 试驾顾问id + */ + @TableField("test_drive_consultant_id") + private String testDriveConsultantId; + + /** + * 试驾顾问 + */ + @TableField("test_drive_consultant") + private String testDriveConsultant; + + /** + * 试驾开始时间 + */ + @TableField("test_drive_start_time") + private Date testDriveStartTime; + + /** + * 试驾结束时间 + */ + @TableField("test_drive_end_time") + private Date testDriveEndTime; + + /** + * 录音开始时间 + */ + @TableField("voice_start_time") + private String voiceStartTime; + + /** + * 录音结束时间 + */ + @TableField("voice_end_time") + private String voiceEndTime; + + /** + * 录音时长,单位秒 + */ + @TableField("voice_duration") + private Integer voiceDuration; + + /** + * 语料内容 + */ + @TableField("content") + private String content; + + /** + * 声道标识位 + */ + @TableField("is_mix") + private Byte isMix; + + /** + * 语料类型 + */ + @TableField("content_code") + private Byte contentCode; + + /** + * 分区字段 + */ + @TableField("pday") + private String pday; + + /** + * 创建时间 + */ + @TableField("created_time") + private Date createdTime; + + /** + * 创建人 + */ + @TableField("created_by") + private String createdBy; + + /** + * 更新时间 + */ + @TableField("updated_time") + private Date updatedTime; + + /** + * 更新人 + */ + @TableField("updated_by") + private String updatedBy; + + /** + * 删除标志位,0:未删除,1:已删除 + */ + @TableField("is_deleted") + private Byte isDeleted; +} diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/TmOdsImRealtimeMessageCur.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/TmOdsImRealtimeMessageCur.java new file mode 100644 index 0000000..107ec37 --- /dev/null +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/entity/TmOdsImRealtimeMessageCur.java @@ -0,0 +1,171 @@ +package com.volvo.ai.analytic.center.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; + + +/** + * @description 湖仓同步实时IM消息表 (tm_ods_im_realtime_message_cur) + * @date 2025-07-17 + */ +@Data +@TableName("tm_ods_im_realtime_message_cur") +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class TmOdsImRealtimeMessageCur { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 消息唯一标识键 + */ + @TableField("msg_key") + private String msgKey; + + /** + * 会话ID + */ + @TableField("session_id") + private String sessionId; + + /** + * 消息内容 + */ + @TableField("msg_content") + private String msgContent; + + /** + * 消息类型,文本类型:TIMTextElem + */ + @TableField("msg_type") + private String msgType; + + /** + * 消息体 + */ + @TableField("msg_body") + private String msgBody; + + /** + * 客户类型0:用户 1:百度 2:GPT 3:人工 4:唯都Agent + */ + @TableField("customer_type") + private Integer customerType; + + /** + * 云端自定义数据 + */ + @TableField("cloud_custom_data") + private String cloudCustomData; + + /** + * 客服来源 + */ + @TableField("cs_source") + private String csSource; + + /** + * 发送方账号 + */ + @TableField("from_account") + private String fromAccount; + + /** + * 插入时间(原字符串格式转换为datetime) + */ + @TableField("insert_time") + private Date insertTime; + + /** + * 会员ID + */ + @TableField("member_id") + private String memberId; + + /** + * 消息标志位 + */ + @TableField("msg_flag_bits") + private Integer msgFlagBits; + + /** + * 消息随机数 + */ + @TableField("msg_random") + private Long msgRandom; + + /** + * 消息序列号 + */ + @TableField("msg_seq") + private String msgSeq; + + /** + * 消息时间戳(毫秒级) + */ + @TableField("msg_timestamp") + private Long msgTimestamp; + + /** + * 第三方平台OpenID + */ + @TableField("open_id") + private String openId; + + /** + * 来源标识 0:公众号,1:app + */ + @TableField("source_type") + private Integer sourceType; + + /** + * 接收方账号 + */ + @TableField("to_account") + private String toAccount; + + /** + * 创建时间 + */ + @TableField("created_time") + private Date createdTime; + + /** + * 创建人 + */ + @TableField("created_by") + private String createdBy; + + /** + * 更新时间 + */ + @TableField("updated_time") + private Date updatedTime; + + /** + * 更新人 + */ + @TableField("updated_by") + private String updatedBy; + + /** + * 删除标志位,0:未删除,1:已删除 + */ + @TableField("is_deleted") + private Byte isDeleted; +} diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/enums/BusinessTypeEnum.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/enums/BusinessTypeEnum.java index 3507eb2..546e00f 100644 --- a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/enums/BusinessTypeEnum.java +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/enums/BusinessTypeEnum.java @@ -6,16 +6,21 @@ import lombok.Getter; public enum BusinessTypeEnum { COMMUNITYTARGET("CommunityTarget", "社区舆情分析"), + FEEDQUALITY("feedQuality", "Feed流好内容"), + PUBLICOPINIONAUTOMATION("publicOpinionAutomation", "舆情自动化"), + SMART_ASSISTANT("SMART_ASSISTANT", "智能助手-DCC"), SMART_ASSISTANT_QIWEI("SMART_ASSISTANT_QIWEI", "智能助手-企微"), INTELLIGENT_CUSTOMER("INTELLIGENT_CUSTOMER_4IN1", "智能客服-4合一"), - + SMART_ASSISTANT_4IN1("SMART_ASSISTANT_4IN1", "智能客服-4In1"), //索赔检核 CLAIM_VERIFICATION("CLAIM_VERIFICATION", "索赔检核流程"), CLAIM_VERIFICATION_FILE_ANALYSIS("99001", "索赔检核文件分析"), CLAIM_VERIFICATION_AUDIT("99002", "索赔检核审计报告"), CLAIM_VERIFICATION_DTC("DTC", "DTC报告"), CLAIM_VERIFICATION_DIAGNOSTIC("DIAGNOSTIC", "诊断报告"), + CLAIM_VERIFICATION_CLASSIFY("CLAIM_VERIFICATION_CLASSIFY", "索赔检核文件分类"), + CLAIM_VERIFICATION_CLASSIFY_APP("99003", "索赔检核文件分类/应用侧"), //索赔检核配置类型 AUDITRULES("AuditRules", "审计规则配置"), @@ -25,6 +30,18 @@ public enum BusinessTypeEnum { SMART_ASSISTANT_NAMEPLATE("SMART_ASSISTANT_NAMEPLATE", "智能助手-铭牌"), + IM_CORPUS_ANALYSIS("IM_CORPUS_ANALYSIS", "IM语料库"), + SUMMARY_REPORT("SUMMARY_REPORT", "问题总结"), + + + //特邀发言官 + SPOKESMAN("SPOKESMAN", "特邀发言官"), + //特邀发言官敏感词 + SPOKESMAN_SENSITIVE_WORD("SPOKESMAN_SENSITIVE_WORD", "特邀发言官敏感词"), + //特邀发言官审核规则 + SPOKESMAN_AUDIT_RULE("SPOKESMAN_AUDIT_RULE", "特邀发言官审核规则"), + SMART_ASSISTANT_NAMEPLATE("SMART_ASSISTANT_NAMEPLATE", "智能助手-铭牌"), + CORPUS_PORTRAIT_DCC("CORPUS_PORTRAIT_DCC", "智能助手-画像-DCC"), CORPUS_PORTRAIT_QIWEI("CORPUS_PORTRAIT_QIWEI", "智能助手-画像-企微"), CORPUS_PORTRAIT_NAMEPLATE("CORPUS_PORTRAIT_NAMEPLATE", "智能助手-画像-铭牌"), diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/enums/ImCustomTypeEnums.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/enums/ImCustomTypeEnums.java new file mode 100644 index 0000000..5185164 --- /dev/null +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/enums/ImCustomTypeEnums.java @@ -0,0 +1,27 @@ +package com.volvo.ai.analytic.center.enums; + +public enum ImCustomTypeEnums { + + CUSTOMER(0, "用户"), + BAIDU(1, "百度"), + GPT(2, "GPT"), + MANUAL(3, "人工"), + VOLVO_AGENT(4, "唯都Agent"), + ; + + private Integer code; + private String message; + + ImCustomTypeEnums(Integer code, String message) { + this.code = code; + this.message = message; + } + + public Integer getCode() { + return this.code; + } + + public String getMessage() { + return this.message; + } +} diff --git a/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/enums/QuestionMainCategoryEnum.java b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/enums/QuestionMainCategoryEnum.java new file mode 100644 index 0000000..8bed73b --- /dev/null +++ b/ai-analytic-center-api/src/main/java/com/volvo/ai/analytic/center/enums/QuestionMainCategoryEnum.java @@ -0,0 +1,26 @@ +package com.volvo.ai.analytic.center.enums; + +public enum QuestionMainCategoryEnum { + + CAR_PURCHASE_RELATED("CAR_PURCHASE_RELATED", "购车相关"), + AFTER_SALES_SERVICE("AFTER_SALES_SERVICE", "售后服务"), + USER_OPERATION("USER_OPERATION", "用户运营"), + CORPORATE_VALUES("CORPORATE_VALUES", "企业价值观"), + SCENE_NOT_CLEAR("SCENE_NOT_CLEAR", "场景不明确"), + ; + private String code; + private String message; + + QuestionMainCategoryEnum(String code, String message) { + this.code = code; + this.message = message; + } + + public String getCode() { + return this.code; + } + + public String getMessage() { + return this.message; + } +} diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/AiAnalyticCenterServiceApplication.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/AiAnalyticCenterServiceApplication.java index 913f6d4..469bc69 100644 --- a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/AiAnalyticCenterServiceApplication.java +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/AiAnalyticCenterServiceApplication.java @@ -9,6 +9,7 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.context.annotation.Bean; import org.springframework.retry.annotation.EnableRetry; +import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.client.RestTemplate; @@ -18,6 +19,7 @@ import org.springframework.web.client.RestTemplate; @MapperScan("com.volvo.ai.analytic.center.mapper") @EnableDiscoveryClient @EnableRetry +@EnableAsync public class AiAnalyticCenterServiceApplication { public static void main(String[] args) { diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/controller/AiAnalysisDifyController.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/controller/AiAnalysisDifyController.java index 30eceb0..c170448 100644 --- a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/controller/AiAnalysisDifyController.java +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/controller/AiAnalysisDifyController.java @@ -7,20 +7,19 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.volvo.ai.analytic.center.dto.req.AnalysisQueryReq; import com.volvo.ai.analytic.center.dto.req.AnalysisReq; +import com.volvo.ai.analytic.center.dto.req.SummaryQuestionRequestDTO; import com.volvo.ai.analytic.center.dto.resp.AnalysisResp; import com.volvo.ai.analytic.center.service.AiAnalysisDifyService; +import com.volvo.ai.analytic.center.service.UserQuestionSummaryService; import com.volvo.common.core.util.ResultMsg; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; -import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController() @@ -30,13 +29,14 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping("analysis") public class AiAnalysisDifyController { - @Autowired - private RocketMQTemplate rocketMQTemplate; - @Autowired private AiAnalysisDifyService aiAnalysisDifyService; + @Autowired + private UserQuestionSummaryService userQuestionSummaryService; + @Value("${dify.corpusQuestion.appKey:z9B4hg9NFEikyfg81neDd1nl}") + private String corpusQuestionAppKey; @PostMapping("/updateByAiId") @ApiOperation(value = "更新dify结果") @@ -48,32 +48,52 @@ public class AiAnalysisDifyController { @PostMapping("/aiAnalyze") @ApiOperation(value = "Ai解析接口") - public AnalysisResp aiAnalyze(@Validated @RequestBody String message) { - log.info("aiAnalyze data: {}",message); + public AnalysisResp aiAnalyze(@Validated @RequestBody String message) { + log.info("aiAnalyze data: {}", message); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); // 允许未转义的控制字符 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); try { - AnalysisReq analysisReq = objectMapper.readValue(message, AnalysisReq.class); + AnalysisReq analysisReq = objectMapper.readValue(message, AnalysisReq.class); analysisReq.validate(); - return aiAnalysisDifyService.aiAnalyze(analysisReq); + return aiAnalysisDifyService.aiAnalyze(analysisReq); } catch (JsonProcessingException e) { - log.info("aiAnalyze data error: {}",e); + log.info("aiAnalyze data error: {}", e); return AnalysisResp.failed("解析失败"); } } @PostMapping("/query") @ApiOperation(value = "Ai解析结果查询") - public AnalysisResp query(@RequestBody @Validated AnalysisQueryReq analysisQueryReq) { - log.info("aiAnalyze query data: {}",analysisQueryReq); - return aiAnalysisDifyService.query(analysisQueryReq); + public AnalysisResp query(@RequestBody @Validated AnalysisQueryReq analysisQueryReq) { + log.info("aiAnalyze query data: {}", analysisQueryReq); + return aiAnalysisDifyService.query(analysisQueryReq); } + @PostMapping("/callback") @ApiOperation(value = "Ai解析结果查询") public AnalysisResp testCallback(@RequestBody AnalysisResp analysisResp) { - log.info("aiAnalyze testCallback data: {}",analysisResp); - return AnalysisResp.success("ok"); + log.info("aiAnalyze testCallback data: {}", analysisResp); + return AnalysisResp.success("ok"); + } + + + @PostMapping("/corpusSummaryQuestion") + @ApiOperation(value = "单条语料分析结论入库") + public AnalysisResp corpusSummaryQuestion( + @RequestHeader(value = "appKey", required = true) String appKey, + @RequestParam("summaryReportId") String summaryReportId, + @RequestParam("preliminarySummaryResults") String preliminarySummaryResults) { + log.info("aiAnalyze corpusSummaryQuestion appKey={},summaryReportId={},preliminarySummaryResults={}", appKey, summaryReportId, preliminarySummaryResults); + if (!corpusQuestionAppKey.equals(appKey)) { + return AnalysisResp.failed("appKey 不正确 "); + } + // 打印接收到的参数 + SummaryQuestionRequestDTO requestDTO = new SummaryQuestionRequestDTO(); + requestDTO.setSummaryReportId(summaryReportId); + requestDTO.setPreliminarySummaryResults(preliminarySummaryResults); + userQuestionSummaryService.updateSummery(requestDTO); + return AnalysisResp.success("ok"); } diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/controller/EGEventSubscriptionController.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/controller/EGEventSubscriptionController.java index 217343b..e0d124c 100644 --- a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/controller/EGEventSubscriptionController.java +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/controller/EGEventSubscriptionController.java @@ -1,82 +1,47 @@ package com.volvo.ai.analytic.center.controller; -import com.alibaba.fastjson.JSON; import com.huaweicloud.sdk.eg.v1.model.*; import com.volvo.ai.analytic.center.dto.event.ListSubscriptionsRequestDto; +import com.volvo.ai.analytic.center.dto.event.SendEventDto; import com.volvo.ai.analytic.center.dto.event.SubscriptionCreateReqDto; -import com.volvo.ai.analytic.center.dto.resp.CompetingBrrandsDTO; +import com.volvo.ai.analytic.center.dto.event.SubscriptionOperateReqDto; import com.volvo.ai.analytic.center.dto.resp.ResultDTO; -import com.volvo.ai.analytic.center.feign.CompetingBrandsClient; import com.volvo.ai.analytic.center.service.HuaWeiEGService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; -import java.util.List; import java.util.concurrent.ExecutionException; /** * 事件订阅管理 */ +@Tag(name = "/event", description = "事件订阅管理") @RestController -@RequestMapping("/cloudEvents") +@RequestMapping("/event") @Slf4j public class EGEventSubscriptionController { @Resource HuaWeiEGService huaWeiService; - - @Autowired - CompetingBrandsClient CompetingBrandsClient; - @Value("${huawei.cloud.EG.channel.ltoChannelId}") - private String ltoChannelId; - @GetMapping("/getBrand") - public void getBrand(){ - ResultDTO> result = CompetingBrandsClient.getBrand(); - log.info("getBrand", JSON.toJSONString(result)); - } - @GetMapping("/getSeriesByBrandId") - public void getSeriesByBrandId(@RequestParam("brandId") String brandId){ - ResultDTO> result = CompetingBrandsClient.getSeriesByBrandId(brandId); - log.info("getSeriesByBrandId", JSON.toJSONString(result)); - } - /** - * 接收事件 - * @param body - */ - @PostMapping("callback") - public void receiveEvent(@RequestBody String body) { - log.info("receiveEvent, {}", body); - } /** * 发布事件到事件通道 */ + @Operation(summary = "发布事件到事件通道") @PostMapping("/sendEvent") - public ResultDTO sendEvent(@RequestBody CloudEvents req) throws ExecutionException { - return ResultDTO.success(huaWeiService.sendEvent(req,ltoChannelId)); + public ResultDTO sendEvent(@RequestBody CloudEvents req, @RequestParam("channel") String channel) throws ExecutionException { + return ResultDTO.success(huaWeiService.sendEvent(req, "channel")); } - // 创建目标连接 - @PostMapping("/connection") - public ResultDTO createConnection(@RequestBody ConnectionCreateReq req) { - return ResultDTO.success(huaWeiService.createConnection(req)); - } - - @PostMapping("/createAgencies") - public ResultDTO createAgencies(@RequestBody AgencyCreateReq req) { - return ResultDTO.success(huaWeiService.createAgencies(req)); - } - - /** * 创建事件订阅 * * @param req req * @return 事件订阅ID */ + @Operation(summary = "创建事件订阅") @PostMapping("/subscription") public ResultDTO createSubscription(@RequestBody SubscriptionCreateReqDto req) { return ResultDTO.success(huaWeiService.createSubscription(req)); @@ -88,6 +53,7 @@ public class EGEventSubscriptionController { * @param req req * @return 事件订阅目标ID */ + @Operation(summary = "创建事件订阅目标") @PostMapping("/subscriptionTarget") public ResultDTO createSubscriptionTarget(@RequestBody CreateSubscriptionTargetRequest req) { return ResultDTO.success(huaWeiService.createSubscriptionTarget(req)); @@ -99,6 +65,7 @@ public class EGEventSubscriptionController { * @param subscriptionId 事件订阅ID * @return */ + @Operation(summary = "删除事件订阅") @DeleteMapping("/subscription/{subscriptionId}") public ResultDTO deleteSubscription(@PathVariable("subscriptionId") String subscriptionId) { huaWeiService.deleteSubscription(subscriptionId); @@ -112,6 +79,7 @@ public class EGEventSubscriptionController { * @param targetId 事件订阅目标ID * @return */ + @Operation(summary = "删除事件订阅目标") @DeleteMapping("/subscriptionTarget/{subscriptionId}/{targetId}") public ResultDTO deleteSubscriptionTarget(@PathVariable("subscriptionId") String subscriptionId, @PathVariable("targetId") String targetId) { huaWeiService.deleteSubscriptionTarget(subscriptionId, targetId); @@ -124,12 +92,24 @@ public class EGEventSubscriptionController { * @param req req * @return */ + @Operation(summary = "查询事件订阅列表") @PostMapping("/subscription/list") public ResultDTO listSubscriptions(@RequestBody ListSubscriptionsRequestDto req) { return ResultDTO.success(huaWeiService.listSubscriptions(req)); } - + /** + * 启用禁用事件订阅 + * + * @param req req + * @return + */ + @Operation(summary = "启用禁用事件订阅") + @PostMapping("/subscription/enabled") + public ResultDTO operateSubscription(@RequestBody SubscriptionOperateReqDto req) { + huaWeiService.operateSubscription(req); + return ResultDTO.success(); + } /** * 查询事件订阅详情 @@ -137,6 +117,7 @@ public class EGEventSubscriptionController { * @param subscriptionId 事件订阅ID * @return */ + @Operation(summary = "查询事件订阅详情") @GetMapping("/subscription/{subscriptionId}") public ResultDTO showDetailOfSubscription(@PathVariable("subscriptionId") String subscriptionId) { return ResultDTO.success(huaWeiService.showDetailOfSubscription(subscriptionId)); diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/controller/TestController.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/controller/TestController.java index cf3451f..c17306e 100644 --- a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/controller/TestController.java +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/controller/TestController.java @@ -48,6 +48,7 @@ public class TestController { @PostMapping("/mockMq") @ApiOperation(value = "补偿处理消息") public ResultMsg mockMq(@RequestBody String message) { + log.info("mockMq message:{}", message); JSONObject messageJson = JSONObject.parseObject(message); String topic = messageJson.getString("topic"); String tag = messageJson.getString("tag"); diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/job/CorpusFailJob.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/job/CorpusFailJob.java index 3513b7f..02b36bf 100644 --- a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/job/CorpusFailJob.java +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/job/CorpusFailJob.java @@ -3,18 +3,20 @@ package com.volvo.ai.analytic.center.job; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.volvo.ai.analytic.center.dto.PageDto; import com.volvo.ai.analytic.center.dto.corpus.AicorpusTelephoneDTO; import com.volvo.ai.analytic.center.dto.corpus.CorpusReportDTO; import com.volvo.ai.analytic.center.dto.req.DiFyReq; import com.volvo.ai.analytic.center.entity.AiAnalysisErrors; import com.volvo.ai.analytic.center.entity.AiAnalysisRequestLogs; -import com.volvo.ai.analytic.center.entity.TmNameplateCorpus; import com.volvo.ai.analytic.center.enums.BusinessTypeEnum; import com.volvo.ai.analytic.center.enums.CategoryEnum; +import com.volvo.ai.analytic.center.feign.DiFyFeign; import com.volvo.ai.analytic.center.mapper.AiAnalysisRequestLogsMapper; import com.volvo.ai.analytic.center.mapper.TmTelephoneCorpusMapper; import com.volvo.ai.analytic.center.service.*; +import com.volvo.ai.analytic.center.utils.FlowResultSplitUtil; import com.xxl.job.core.handler.annotation.XxlJob; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; @@ -31,9 +33,11 @@ import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; @Slf4j @@ -66,22 +70,16 @@ public class CorpusFailJob { private String dccMqTipic; @Value("${rocketmq.consumer.intelligentCustomer.topic}") private String intelligentCustomerTipic; + + @Value("${rocketmq.producer.intelligentCustomer.topic}") + private String intelligentCustomerProducerTopic; + @Autowired private TmTelephoneCorpusMapper tmTelephoneCorpusMapper; @Autowired - private TmNameplateCorpusService tmNameplateCorpusService; + private DiFyFeign diFyFeign; - @Autowired - private CorpusPortraitService corpusPortraitService; - - @Resource - HuaWeiEGService huaWeiService; - @Value("${huawei.cloud.EG.channel.ltoChannelId}") - private String ltoChannelId; - - @Value("${huawei.cloud.EG.channel.ltoSourceId}") - private String sourceId; /** * 企微语料处理 @@ -91,72 +89,65 @@ public class CorpusFailJob { public void corpusFailTask() { log.info(" corpusFailTask解析失败重试处理"); - Integer total = aiAnalysisErrorsService.queryCountAnalysisErrorList(Arrays.asList(BusinessTypeEnum.SMART_ASSISTANT.getCode(),BusinessTypeEnum.SMART_ASSISTANT_QIWEI.getCode(),BusinessTypeEnum.SMART_ASSISTANT_NAMEPLATE.getCode())); + Integer total = aiAnalysisErrorsService.queryCountAnalysisErrorList(Arrays.asList(BusinessTypeEnum.SMART_ASSISTANT.getCode(),BusinessTypeEnum.SMART_ASSISTANT_QIWEI.getCode())); log.info("corpusFailTask语料解析失败重试处理数据量:{}", total); int totalPages = PageDto.getTotalPages(total, pageSize); log.info("corpusFailTask 语料解析失败重试处理数据量:{},总页数:{}", total, totalPages); for (int i = 1; i <= totalPages; i++) { int offset = (i - 1) * pageSize; - List aiAnalysisErrorsListlist = aiAnalysisErrorsService.queryAnalysisErrorList(Arrays.asList(BusinessTypeEnum.SMART_ASSISTANT.getCode(),BusinessTypeEnum.SMART_ASSISTANT_QIWEI.getCode(),BusinessTypeEnum.SMART_ASSISTANT_NAMEPLATE.getCode()),offset, pageSize); + List aiAnalysisErrorsListlist = aiAnalysisErrorsService.queryAnalysisErrorList(Arrays.asList(BusinessTypeEnum.SMART_ASSISTANT.getCode(),BusinessTypeEnum.SMART_ASSISTANT_QIWEI.getCode()),offset, pageSize); if(CollectionUtils.isNotEmpty(aiAnalysisErrorsListlist)) { log.info("corpusFailTask语料解析失败重试处理 size:{}", aiAnalysisErrorsListlist.size()); - List requestIdList = aiAnalysisErrorsListlist.stream() - .map(AiAnalysisErrors::getAiAnalysisRequestId) - .collect(Collectors.toList()); + aiAnalysisErrorsListlist.stream().forEach(aiAnalysisErrors -> { - List aiAnalysisRequestLogsList = aiAnalysisRequestLogsMapper.queryByAiAnalysisRequestIds(requestIdList); - Map requestLogsMap = aiAnalysisRequestLogsList.stream() - .collect(Collectors.toMap( AiAnalysisRequestLogs::getAiAnalysisRequestId,logs -> logs )); - aiAnalysisErrorsListlist.forEach(aiAnalysisErrors -> { try { - AiAnalysisRequestLogs oldAiAnalysisRequestLogs = requestLogsMap.get(aiAnalysisErrors.getAiAnalysisRequestId()); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(AiAnalysisRequestLogs::getAiAnalysisRequestId, aiAnalysisErrors.getAiAnalysisRequestId()); + AiAnalysisRequestLogs oldAiAnalysisRequestLogs = aiAnalysisRequestLogsMapper.selectOne(queryWrapper); - if (null != oldAiAnalysisRequestLogs && StringUtils.isBlank(oldAiAnalysisRequestLogs.getBusinessResponse())) { + if (null != oldAiAnalysisRequestLogs) { DiFyReq diFyReq = JSONObject.parseObject(oldAiAnalysisRequestLogs.getDifyRequest(), DiFyReq.class); CorpusReportDTO corpusReportDTO = JSONObject.parseObject(oldAiAnalysisRequestLogs.getBusinessRequest(), CorpusReportDTO.class); - + Map ltoMap = new HashMap<>(); + ltoMap.put("analysisRecordId", oldAiAnalysisRequestLogs.getAiAnalysisRequestId()); + ltoMap.put("analysisScene", corpusReportDTO.getAnalysisScene() + ""); String tag = ""; if (null != corpusReportDTO && corpusReportDTO.getAnalysisScene() == 1) { //企微 + ltoMap.put("unionId", corpusReportDTO.getUnionId()); + ltoMap.put("consultantId", corpusReportDTO.getUserId()); tag = CategoryEnum.ENTERPRISE_WECHAT.getCode(); JSONObject execDifyFlow = diFyService.executeDifyFlow(diFyReq); log.info(" corpusFailTask runDify execDifyFlow {}", execDifyFlow); if (null != execDifyFlow && execDifyFlow.get("status").equals("succeeded")) { - JSONObject text = execDifyFlow.getJSONObject("outputs"); - // 发送MQ - log.info("send mq {}", text); - tmTelephoneCorpusService.sendMq(tag, text.toJSONString()); - // 保存报告 - oldAiAnalysisRequestLogs.setBusinessResponse( text.toJSONString()); - - oldAiAnalysisRequestLogs.setDifyResponse(JSON.toJSONString(execDifyFlow)); - updateDiFyRequest(oldAiAnalysisRequestLogs, oldAiAnalysisRequestLogs.getAiAnalysisRequestId()); - aiAnalysisErrors.setAiAnalysisErrorHandlingStatus("1"); - } - aiAnalysisErrors.setRetryCount(aiAnalysisErrors.getRetryCount() + 1); - updateAiAnalysisErrors(aiAnalysisErrors, oldAiAnalysisRequestLogs.getAiAnalysisRequestId()); - } else if(null != corpusReportDTO && corpusReportDTO.getAnalysisScene() == 3){ - log.info(" corpusFailTask 铭牌数据重试:{},aiId:{}", corpusReportDTO.getCustomerFlowId(), oldAiAnalysisRequestLogs.getAiAnalysisRequestId()); - JSONObject execDifyFlow = diFyService.executeDifyFlow(diFyReq, oldAiAnalysisRequestLogs.getAiAnalysisRequestType(), JSONObject.toJSONString(corpusReportDTO),oldAiAnalysisRequestLogs.getAiAnalysisRequestId()); - List nameplateCorpusList = tmNameplateCorpusService.queryTelephoneCorpusByCustomerFlowId( Arrays.asList(corpusReportDTO.getCustomerFlowId())); - if (null != execDifyFlow && execDifyFlow.get("status").equals("succeeded")) { - JSONObject text = execDifyFlow.getJSONObject("outputs"); - if(CollectionUtils.isNotEmpty(nameplateCorpusList)) { - TmNameplateCorpus nameplateCorpus = nameplateCorpusList.get(0); - tmNameplateCorpusService.sendNameplateLto(execDifyFlow,oldAiAnalysisRequestLogs.getAiAnalysisRequestId(), nameplateCorpus); + String text = execDifyFlow.getJSONObject("outputs").getString("text"); + String resultStrOne = FlowResultSplitUtil.flowOutputTextSplit(text, "任务1", "任务2"); + String resultStrTwo = FlowResultSplitUtil.flowOutputTextSplit(text, "任务2", null); + if (StringUtils.isBlank(resultStrOne) || StringUtils.isBlank(resultStrTwo)) { + log.info(" corpusFailTask 企微语料解析为空,text:{}", text); + return; } - oldAiAnalysisRequestLogs.setBusinessResponse( text.toJSONString()); + + + ltoMap.put("communicateDate", corpusReportDTO.getCorpusTime()); + ltoMap.put("analysisResult", resultStrOne.replace("#", "")); + ltoMap.put("analysisDetail", resultStrTwo); + // 发送MQ + log.info("corpusFailTask send mq {}", ltoMap); + tmTelephoneCorpusService.sendMq(tag, JSONObject.toJSONString(ltoMap)); + // 保存报告 + oldAiAnalysisRequestLogs.setBusinessResponse(JSONObject.toJSONString(ltoMap)); oldAiAnalysisRequestLogs.setDifyResponse(JSON.toJSONString(execDifyFlow)); updateDiFyRequest(oldAiAnalysisRequestLogs, oldAiAnalysisRequestLogs.getAiAnalysisRequestId()); + aiAnalysisErrors.setRetryCount(aiAnalysisErrors.getRetryCount() + 1); aiAnalysisErrors.setAiAnalysisErrorHandlingStatus("1"); + updateAiAnalysisErrors(aiAnalysisErrors, oldAiAnalysisRequestLogs.getAiAnalysisRequestId()); + } - aiAnalysisErrors.setRetryCount(aiAnalysisErrors.getRetryCount() + 1); - updateAiAnalysisErrors(aiAnalysisErrors, oldAiAnalysisRequestLogs.getAiAnalysisRequestId()); - }else { - log.info("corpusFailTask Dcc失败重试:{}, {}", corpusReportDTO.getRecordId(), oldAiAnalysisRequestLogs.getAiAnalysisRequestId()); + } else { List dccDtoList = tmTelephoneCorpusMapper.queryTelephoneCorpusBySourceIds( Arrays.asList(corpusReportDTO.getRecordId())); if(CollectionUtils.isNotEmpty(dccDtoList)){ AicorpusTelephoneDTO dccDto = dccDtoList.get(0); @@ -219,16 +210,11 @@ public class CorpusFailJob { List aiAnalysisErrorsListlist = aiAnalysisErrorsService.queryAnalysisErrorList(Arrays.asList(BusinessTypeEnum.INTELLIGENT_CUSTOMER.getCode()),offset, pageSize); if(CollectionUtils.isNotEmpty(aiAnalysisErrorsListlist)) { log.info("intelligentCustomer4in1FailTask语料解析失败重试处理 size:{}", aiAnalysisErrorsListlist.size()); - - List requestIdList = aiAnalysisErrorsListlist.stream() - .map(AiAnalysisErrors::getAiAnalysisRequestId) - .collect(Collectors.toList()); - List aiAnalysisRequestLogsList = aiAnalysisRequestLogsMapper.queryByAiAnalysisRequestIds(requestIdList); - Map requestLogsMap = aiAnalysisRequestLogsList.stream() - .collect(Collectors.toMap( AiAnalysisRequestLogs::getAiAnalysisRequestId,logs -> logs )); - aiAnalysisErrorsListlist.forEach(aiAnalysisErrors -> { + aiAnalysisErrorsListlist.stream().forEach(aiAnalysisErrors -> { try { - AiAnalysisRequestLogs oldAiAnalysisRequestLogs = requestLogsMap.get(aiAnalysisErrors.getAiAnalysisRequestId()); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(AiAnalysisRequestLogs::getAiAnalysisRequestId, aiAnalysisErrors.getAiAnalysisRequestId()); + AiAnalysisRequestLogs oldAiAnalysisRequestLogs = aiAnalysisRequestLogsMapper.selectOne(queryWrapper); if (null != oldAiAnalysisRequestLogs) { JSONObject businessRequest = JSONObject.parseObject(oldAiAnalysisRequestLogs.getBusinessRequest()); @@ -258,66 +244,94 @@ public class CorpusFailJob { } } - - /** - * 画像error补偿 + * 智能客服-电话场景-四合一 一分钟一次 */ - @XxlJob("corpusPortraitFailTask") - public void corpusPortraitFailTask() { + @XxlJob("intelligentCustomer4in1MobileFailTask") + @PostMapping("intelligentCustomer4in1MobileFailTask") + public void intelligentCustomer4in1MobileFailTask() { - log.info(" corpusPortraitFailTask画像解析失败重试处理"); - Integer total = aiAnalysisErrorsService.queryCountAnalysisErrorList(Arrays.asList(BusinessTypeEnum.CORPUS_PORTRAIT_DCC.getCode(),BusinessTypeEnum.CORPUS_PORTRAIT_QIWEI.getCode(),BusinessTypeEnum.CORPUS_PORTRAIT_NAMEPLATE.getCode())); - log.info("corpusPortraitFailTask画像语料解析失败重试处理数据量:{}", total); + log.info(" intelligentCustomer4in1MobileFailTask 解析失败重试处理"); + Integer total = aiAnalysisErrorsService.queryCountAnalysisErrorList(Collections.singletonList(BusinessTypeEnum.SMART_ASSISTANT_4IN1.getCode())); + log.info("intelligentCustomer4in1MobileFailTask 语料解析失败重试处理数据量:{}", total); int totalPages = PageDto.getTotalPages(total, pageSize); - log.info("corpusFailTask 语料解析失败重试处理数据量:{},总页数:{}", total, totalPages); + log.info("intelligentCustomer4in1MobileFailTask 语料解析失败重试处理数据量:{},总页数:{}", total, totalPages); for (int i = 1; i <= totalPages; i++) { int offset = (i - 1) * pageSize; - List aiAnalysisErrorsListlist = aiAnalysisErrorsService.queryAnalysisErrorList(Arrays.asList(BusinessTypeEnum.CORPUS_PORTRAIT_DCC.getCode(),BusinessTypeEnum.CORPUS_PORTRAIT_QIWEI.getCode(),BusinessTypeEnum.CORPUS_PORTRAIT_NAMEPLATE.getCode()),offset, pageSize); - if(CollectionUtils.isNotEmpty(aiAnalysisErrorsListlist)) { - log.info("corpusFailTask语料解析失败重试处理 size:{}", aiAnalysisErrorsListlist.size()); - List requestIdList = aiAnalysisErrorsListlist.stream() - .map(AiAnalysisErrors::getAiAnalysisRequestId) - .collect(Collectors.toList()); - - List aiAnalysisRequestLogsList = aiAnalysisRequestLogsMapper.queryByAiAnalysisRequestIds(requestIdList); - - Map requestLogsMap = aiAnalysisRequestLogsList.stream() - .collect(Collectors.toMap( AiAnalysisRequestLogs::getAiAnalysisRequestId,logs -> logs )); + List aiAnalysisErrorsListlist = aiAnalysisErrorsService.queryAnalysisErrorList( + Collections.singletonList(BusinessTypeEnum.SMART_ASSISTANT_4IN1.getCode()), offset, pageSize); + if (CollectionUtils.isNotEmpty(aiAnalysisErrorsListlist)) { + log.info("intelligentCustomer4in1MobileFailTask语料解析失败重试处理 size:{}", aiAnalysisErrorsListlist.size()); aiAnalysisErrorsListlist.forEach(aiAnalysisErrors -> { - try { - AiAnalysisRequestLogs oldAiAnalysisRequestLogs = requestLogsMap.get(aiAnalysisErrors.getAiAnalysisRequestId()); + log.info("intelligentCustomer4in1MobileFailTask aiAnalysisRequestLogs-id:{}", aiAnalysisErrors.getAiAnalysisRequestId()); + String aiAnalysisRequestId = aiAnalysisErrors.getAiAnalysisRequestId(); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(AiAnalysisRequestLogs::getAiAnalysisRequestId, aiAnalysisRequestId); + AiAnalysisRequestLogs aiAnalysisRequestLogs = aiAnalysisRequestLogsMapper.selectOne(queryWrapper); - if (null != oldAiAnalysisRequestLogs && StringUtils.isBlank(oldAiAnalysisRequestLogs.getBusinessResponse())) { - DiFyReq diFyReq = JSONObject.parseObject(oldAiAnalysisRequestLogs.getDifyRequest(), DiFyReq.class); - log.info(" corpusFailTask runDify req {}", JSON.toJSONString(diFyReq)); - JSONObject execDifyFlow = diFyService.executeDifyFlow(diFyReq); - log.info(" corpusFailTask runDify execDifyFlow {}", execDifyFlow); - if (null != execDifyFlow && execDifyFlow.get("status").equals("succeeded")) { - JSONObject text = execDifyFlow.getJSONObject("outputs"); - // 发送MQ - log.info("sendEvent mq {}", text); - huaWeiService.sendEvent(corpusPortraitService.setCloudEvents(oldAiAnalysisRequestLogs.getAiAnalysisRequestId(), text.toJSONString(), oldAiAnalysisRequestLogs.getAiAnalysisRequestType().substring(oldAiAnalysisRequestLogs.getAiAnalysisRequestType().lastIndexOf("_")+1)), ltoChannelId); + log.info("intelligentCustomer4in1MobileFailTask aiAnalysisRequestLogs:{}", aiAnalysisRequestLogs); - // 保存报告 - oldAiAnalysisRequestLogs.setBusinessResponse( text.toJSONString()); + if (null != aiAnalysisRequestLogs) { + String difyRequest = aiAnalysisRequestLogs.getDifyRequest(); + log.info("intelligentCustomer4in1MobileFailTask aiAnalysisRequestLogs difyRequest:{}", aiAnalysisRequestLogs); + DiFyReq diFyReq = JSON.parseObject(difyRequest, DiFyReq.class); + Map map = new HashMap<>(); + map.put("inputs", diFyReq.getInputs()); + map.put("response_mode", "blocking"); + map.put("user", diFyReq.getUser()); + log.info("intelligentCustomer4in1MobileFailTask execDifyFlow dify request data:{}", map); + JSONObject difyResult = diFyFeign.runWorkflows("Bearer " + diFyReq.getFlowId(), map); + JSONObject data = difyResult.getJSONObject("data"); + log.info("intelligentCustomer4in1MobileFailTask execDifyFlow dify response aiID:{} , data:{}", aiAnalysisRequestId, data); + data.put("aiAnalysisRequestId", aiAnalysisRequestId); - oldAiAnalysisRequestLogs.setDifyResponse(JSON.toJSONString(execDifyFlow)); - updateDiFyRequest(oldAiAnalysisRequestLogs, oldAiAnalysisRequestLogs.getAiAnalysisRequestId()); - aiAnalysisErrors.setAiAnalysisErrorHandlingStatus("1"); + if (data.get("status").equals("succeeded")) { + JSONObject outputsJson = data.getJSONObject("outputs"); + String message = JSONObject.toJSONString(outputsJson); + log.info("intelligentCustomer4in1MobileFailTask send 4IN1mq {}", message); + rocketMqTemplate.asyncSend(intelligentCustomerProducerTopic, MessageBuilder.withPayload(message).build(), new SendCallback() { + @Override + public void onSuccess(SendResult sendResult) { + log.info(" intelligentCustomer4in1MobileFailTask 失败补偿 发送MQ成功 消息体:{}", message); + } + + @Override + public void onException(Throwable e) { + log.error("intelligentCustomer4in1MobileFailTask 失败补偿 送MQ异常 消息体:{}, 异常:", message, e); + } + }, 10000); + AiAnalysisErrors aiAnalysisErrors1 = new AiAnalysisErrors(); + aiAnalysisErrors1.setAiAnalysisRequestId(aiAnalysisRequestId); + aiAnalysisErrors1.setAiAnalysisErrorHandlingStatus("1"); + aiAnalysisErrorsService.updateAiAnalysisErrors(aiAnalysisErrors1); + aiAnalysisRequestLogsService.saveAiAnalysisRequestLogs(AiAnalysisRequestLogs.builder() + .aiAnalysisRequestId(data.getString("aiAnalysisRequestId")) + .businessResponse(message) + .difyResponse(data.toJSONString()) + .build()); + } else { + log.info("intelligentCustomer4in1MobileFailTask execDifyFlow failed, aiAnalysisRequestId:{} , data:{}", aiAnalysisRequestId, + data); + String errorMsg = data.getString("error"); + aiAnalysisErrors.setRetryCount(aiAnalysisErrors.getRetryCount() + 1); + aiAnalysisErrors.setUpdateBy("xxlJob"); + aiAnalysisErrors.setUpdateTime(new Date()); + aiAnalysisErrors.setAiAnalysisErrorMessage(errorMsg.length() > 1000 ? errorMsg.substring(0, 1000) : errorMsg); + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(AiAnalysisErrors::getAiAnalysisRequestId, aiAnalysisRequestId); + aiAnalysisErrorsService.update(aiAnalysisErrors,updateWrapper); } - aiAnalysisErrors.setRetryCount(aiAnalysisErrors.getRetryCount() + 1); - updateAiAnalysisErrors(aiAnalysisErrors, oldAiAnalysisRequestLogs.getAiAnalysisRequestId()); } } catch (Exception e) { - log.info("画像重试异常:{},{}",aiAnalysisErrors.getAiAnalysisRequestId() , e); + log.info("intelligentCustomer4in1MobileFailTask 语料解析失败补偿异常:{}", e); + aiAnalysisErrors.setAiAnalysisErrorHandlingStatus("0"); + aiAnalysisErrors.setRetryCount(aiAnalysisErrors.getRetryCount() + 1); + updateAiAnalysisErrors(aiAnalysisErrors, aiAnalysisErrors.getAiAnalysisRequestId()); } - }); } } } - } diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/job/ImMessageAnalysisJob.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/job/ImMessageAnalysisJob.java new file mode 100644 index 0000000..bb88f38 --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/job/ImMessageAnalysisJob.java @@ -0,0 +1,44 @@ +package com.volvo.ai.analytic.center.job; + +import com.volvo.ai.analytic.center.service.TmOdsImRealtimeMessageCurService; +import com.volvo.common.core.util.ResultMsg; +import com.xxl.job.core.context.XxlJobHelper; +import com.xxl.job.core.handler.annotation.XxlJob; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@Slf4j +@Component +@RestController +public class ImMessageAnalysisJob { + + @Autowired + private TmOdsImRealtimeMessageCurService tmOdsImRealtimeMessageCurService; + + /** + * 企微语料处理 + */ + @XxlJob("imMessageAnalysisTask") + public ResultMsg imMessageAnalysisTask(@RequestBody String paramJson) { + try { + // 获取任务参数 + String param = XxlJobHelper.getJobParam(); + if(StringUtils.isEmpty(param)){ + param = paramJson; + } + // 执行业务逻辑 + XxlJobHelper.log("任务参数: {}", param); + log.info("imMessageAnalysisTask IM语料分析处理:{}",param); + tmOdsImRealtimeMessageCurService.runImCorpusDify(param); + } catch (Exception e) { + log.error("imMessageAnalysisTask 定时任务处理消息异常",e.getMessage()); + throw new RuntimeException(e); + } + return ResultMsg.ok(); + } + +} diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/job/InvitedSpeakerJob.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/job/InvitedSpeakerJob.java new file mode 100644 index 0000000..25afd48 --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/job/InvitedSpeakerJob.java @@ -0,0 +1,33 @@ +package com.volvo.ai.analytic.center.job; + + +import com.volvo.ai.analytic.center.service.SpokesManService; +import com.volvo.common.core.util.ResultMsg; +import com.xxl.job.core.handler.annotation.XxlJob; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class InvitedSpeakerJob { + + @Autowired + private SpokesManService spokesmanService; + + + /** + * 邀约消息推送 + */ + @XxlJob("invitedSpeakerJobTask") + public ResultMsg invitedSpeakerJobTask() { + try { + log.info("invitedSpeakerJobTask 开始执行特邀发言官定时任务补偿处理消息"); + spokesmanService.spokesManTask(); + } catch (Exception e) { + log.error("invitedSpeakerJobTask 定时任务补偿处理消息异常",e.getMessage()); + throw new RuntimeException(e); + } + return ResultMsg.ok(); + } +} diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/job/UserQuestionSummaryJob.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/job/UserQuestionSummaryJob.java new file mode 100644 index 0000000..29fb684 --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/job/UserQuestionSummaryJob.java @@ -0,0 +1,44 @@ +package com.volvo.ai.analytic.center.job; + +import com.volvo.ai.analytic.center.service.UserQuestionSummaryService; +import com.volvo.common.core.util.ResultMsg; +import com.xxl.job.core.context.XxlJobHelper; +import com.xxl.job.core.handler.annotation.XxlJob; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@Slf4j +@Component +@RestController +public class UserQuestionSummaryJob { + + @Autowired + private UserQuestionSummaryService userQuestionSummaryService; + + /** + * 企微语料处理 + */ + @XxlJob("userQuestionSummaryTask") + public ResultMsg userQuestionSummaryTask(@RequestBody String paramJson) { + try { + // 获取任务参数 + String param = XxlJobHelper.getJobParam(); + if(StringUtils.isEmpty(param)){ + param = paramJson; + } + // 执行业务逻辑 + XxlJobHelper.log("任务参数: {}", param); + log.info("userQuestionSummaryTask 用户问题总结处理:{}",param); + userQuestionSummaryService.runUserQuestionSummary(param); + } catch (Exception e) { + log.error("userQuestionSummaryTask 定时任务处理消息异常",e.getMessage()); + throw new RuntimeException(e); + } + return ResultMsg.ok(); + } + +} diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mapper/TmClaimVerificationPartHoursMappingMapper.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mapper/TmClaimVerificationPartHoursMappingMapper.java new file mode 100644 index 0000000..cb14b77 --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mapper/TmClaimVerificationPartHoursMappingMapper.java @@ -0,0 +1,17 @@ +package com.volvo.ai.analytic.center.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.volvo.ai.analytic.center.dto.req.ClaimVerificationPartHoursDTO; +import com.volvo.ai.analytic.center.entity.TmClaimVerificationPartHoursMapping; + +import java.util.List; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +@Mapper +public interface TmClaimVerificationPartHoursMappingMapper extends BaseMapper { + + List queryConfigByPartId(@Param("partIds") List partIds); + +} diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mapper/TmCorpusQuestionReportMapper.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mapper/TmCorpusQuestionReportMapper.java new file mode 100644 index 0000000..6695b99 --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mapper/TmCorpusQuestionReportMapper.java @@ -0,0 +1,21 @@ +package com.volvo.ai.analytic.center.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.volvo.ai.analytic.center.dto.corpus.ImCurMessageDTO; +import com.volvo.ai.analytic.center.entity.TmCorpusQuestionReport; + +import java.util.Date; +import java.util.List; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * 单条语料分析结论 + */ +@Mapper +public interface TmCorpusQuestionReportMapper extends BaseMapper { + + List queryQuestionReportList(@Param("statTime") Date statTime, @Param("endTime") Date endTime, @Param("mainCategory") String mainCategory); + +} \ No newline at end of file diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mapper/TmCorpusQuestionSummaryReportMapper.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mapper/TmCorpusQuestionSummaryReportMapper.java new file mode 100644 index 0000000..3157dc2 --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mapper/TmCorpusQuestionSummaryReportMapper.java @@ -0,0 +1,12 @@ +package com.volvo.ai.analytic.center.mapper; + +import org.apache.ibatis.annotations.Param; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.volvo.ai.analytic.center.entity.TmCorpusQuestionSummaryReport; + +public interface TmCorpusQuestionSummaryReportMapper extends BaseMapper { + + int updateBySummaryReportId(@Param("summaryReportId") String summaryReportId, @Param("preliminarySummaryResults") String preliminarySummaryResults); + +} \ No newline at end of file diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mapper/TmOdsAinpArrivalTestdriveVoiceInfoMapper.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mapper/TmOdsAinpArrivalTestdriveVoiceInfoMapper.java new file mode 100644 index 0000000..9f37e70 --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mapper/TmOdsAinpArrivalTestdriveVoiceInfoMapper.java @@ -0,0 +1,14 @@ +package com.volvo.ai.analytic.center.mapper; + + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.volvo.ai.analytic.center.entity.TmOdsAinpArrivalTestdriveVoiceInfo; +import org.apache.ibatis.annotations.Mapper; + +/** + * @description 湖仓同步AI铭牌到店试驾语料信息- + * @date 2025-07-17 + */ +@Mapper +public interface TmOdsAinpArrivalTestdriveVoiceInfoMapper extends BaseMapper { +} diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mapper/TmOdsImRealtimeMessageCurMapper.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mapper/TmOdsImRealtimeMessageCurMapper.java new file mode 100644 index 0000000..ce70cb4 --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mapper/TmOdsImRealtimeMessageCurMapper.java @@ -0,0 +1,26 @@ +package com.volvo.ai.analytic.center.mapper; + + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.volvo.ai.analytic.center.dto.corpus.ImCurMessageDTO; +import com.volvo.ai.analytic.center.entity.TmOdsImRealtimeMessageCur; + +import java.util.List; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * @description 湖仓同步实时IM消息表-Mapper (tm_ods_im_realtime_message_cur) + * @date 2025-07-17 + */ +@Mapper +public interface TmOdsImRealtimeMessageCurMapper extends BaseMapper { + + // 统计IM消息数据 + int countImRealtimeMessageCurByDate(@Param("statTime") Long statTime, @Param("endTime") Long endTime); + // 分页获取处理数据 + List queryImRealtimeMessageCurByDate(@Param("statTime") Long statTime, @Param("endTime") Long endTime, @Param("offset") int offset, @Param("pageSize") int pageSize); + + List queryImRealtimeMessageCurBySessionId(@Param("statTime") Long statTime, @Param("endTime") Long endTime, @Param("sessionId") String sessionId); +} diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/CorpusDccMqConsumer.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/CorpusDccMqConsumer.java index fa6cddf..d583973 100644 --- a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/CorpusDccMqConsumer.java +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/CorpusDccMqConsumer.java @@ -1,11 +1,11 @@ package com.volvo.ai.analytic.center.mq; +import com.alibaba.fastjson.JSON; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.volvo.ai.analytic.center.constant.Constant; import com.volvo.ai.analytic.center.dto.corpus.AicorpusTelephoneDTO; -import com.volvo.ai.analytic.center.service.AiAnalysisRequestLogsService; -import com.volvo.ai.analytic.center.service.CorpusPortraitService; import com.volvo.ai.analytic.center.service.TmTelephoneCorpusService; import lombok.extern.slf4j.Slf4j; import org.apache.rocketmq.common.message.MessageExt; @@ -13,15 +13,13 @@ import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.core.RocketMQListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RestController; -import javax.annotation.Resource; -import java.util.concurrent.CompletableFuture; +import java.util.Objects; /** - * @ClassName CorpusProcessKafkaConsumer + * @ClassName 湖仓发送过来的kafka消息自己发MQ自己消费 DCC通话记录 (目前接入的需求:4IN1的智能工单-电话场景,LTO跟进记录AI总结) * @Description * @Author renzhen * @Date 2025-03-04 10:18 @@ -42,16 +40,7 @@ public class CorpusDccMqConsumer implements RocketMQListener { @Autowired private TmTelephoneCorpusService tmTelephoneCorpusService; - @Autowired - private AiAnalysisRequestLogsService aiAnalysisRequestLogsService; - private final ObjectMapper objectMapper = new ObjectMapper(); - @Autowired - @Resource(name = "threadPoolTaskExecutor") - private ThreadPoolTaskExecutor executor; - - @Autowired - private CorpusPortraitService corpusPortraitService; @Override public void onMessage(MessageExt messageExt) { @@ -61,15 +50,15 @@ public class CorpusDccMqConsumer implements RocketMQListener { String message = new String(messageExt.getBody()); log.info("dcc_mq message: " + message); AicorpusTelephoneDTO aicorpusTelephone = objectMapper.readValue(message, AicorpusTelephoneDTO.class); - tmTelephoneCorpusService.runTelephoneCorpusDify(aicorpusTelephone); - // 提交异步任务 - CompletableFuture.runAsync(() -> { - try { - corpusPortraitService.portraitDcc(aicorpusTelephone); - } catch (Exception e) { - log.error("ccorpusPortrait画像Dcc异步任务执行失败", e); - } - }, executor); + //DCC场景 + if(Objects.equals(aicorpusTelephone.getCategoryCode(), Constant.CHANNEL_DCC)){ + tmTelephoneCorpusService.runTelephoneCorpusDify(aicorpusTelephone); + } + //channel_4in1场景 + if(Objects.equals(aicorpusTelephone.getCategoryCode(), Constant.CHANNEL_4IN1)){ + log.info("channel_4in1 message: " + JSON.toJSONString(aicorpusTelephone)); + tmTelephoneCorpusService.runTelephoneCorpusDify4in1(aicorpusTelephone); + } log.info("corpusDccMqProducer mq 处理完成: {}", aicorpusTelephone.getSourceId()); log.info("dcc_mq 处理完成,耗时:{}", System.currentTimeMillis() - startTime); } catch (JsonProcessingException e) { diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/CorpusProcessKafkaProducer.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/CorpusProcessKafkaProducer.java index 990aa9d..db43838 100644 --- a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/CorpusProcessKafkaProducer.java +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/CorpusProcessKafkaProducer.java @@ -1,14 +1,15 @@ package com.volvo.ai.analytic.center.mq; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.volvo.ai.analytic.center.constant.Constant; import com.volvo.ai.analytic.center.dto.corpus.AicorpusTelephoneDTO; +import com.volvo.ai.analytic.center.dto.corpus.DisplayDTO; import com.volvo.ai.analytic.center.entity.TmTelephoneCorpus; import com.volvo.ai.analytic.center.service.TmTelephoneCorpusService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; +import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.rocketmq.client.producer.SendCallback; import org.apache.rocketmq.client.producer.SendResult; import org.apache.rocketmq.spring.core.RocketMQTemplate; @@ -17,20 +18,19 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.kafka.annotation.KafkaListener; -import org.springframework.messaging.handler.annotation.Payload; import org.springframework.messaging.support.MessageBuilder; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.List; -import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * @ClassName CorpusProcessKafkaConsumer - * @Description + * @Description 消费湖仓同步的DCC通话记录kafka消息 * @Author renzhen * @Date 2025-03-04 10:18 * @Version 1.0 @@ -53,89 +53,92 @@ public class CorpusProcessKafkaProducer { @Resource private RocketMQTemplate rocketMqTemplate; - @Autowired - @Resource(name = "threadPoolTaskExecutor") - private ThreadPoolTaskExecutor executor; - - - @KafkaListener(topics = "${spring.kafka.topic}", groupId = "${spring.kafka.group}") - public void listen(@Payload List messageList) { +// @KafkaListener( +// topicPartitions = @TopicPartition( +// topic = "${spring.kafka.topic}", +// partitionOffsets = { +// @PartitionOffset(partition = "0", initialOffset = "2792520"), +// @PartitionOffset(partition = "1", initialOffset = "2596153"), +// @PartitionOffset(partition = "2", initialOffset = "2536889"), +// @PartitionOffset(partition = "3", initialOffset = "2782173"), +// @PartitionOffset(partition = "4", initialOffset = "2616677"), +// @PartitionOffset(partition = "5", initialOffset = "2529585"), +// @PartitionOffset(partition = "6", initialOffset = "2761950"), +// @PartitionOffset(partition = "7", initialOffset = "2581957"), +// @PartitionOffset(partition = "8", initialOffset = "2530225"), +// @PartitionOffset(partition = "9", initialOffset = "2803179"), +// @PartitionOffset(partition = "10", initialOffset = "2599129"), +// @PartitionOffset(partition = "11", initialOffset = "2546277") +// } +// ), +// groupId = "${spring.kafka.group}" +// ) + @KafkaListener(topics = "${spring.kafka.topic}", groupId = "${spring.kafka.group}") + public void listen(List> recordMessages) { long startTime = System.currentTimeMillis(); - log.info("corpusProcessKafkaProducerMessageSize:{}", messageList.size()); - if (CollectionUtils.isEmpty(messageList)) { - log.debug("Received empty message batch."); - return; - } + log.info("CorpusProcessKafkaProducer Received message: {}", recordMessages); + // 获取消息列表 + int optimalThreadPoolSize = Runtime.getRuntime().availableProcessors() + 2; + log.info("获取的线程数:{}", optimalThreadPoolSize); + ExecutorService executor = Executors.newFixedThreadPool(optimalThreadPoolSize); try { - for (String message:messageList) { - log.debug("corpusProcessKafkaProducerMessage:{}", message); + if(CollectionUtils.isNotEmpty(recordMessages)){ + log.info("CorpusProcessKafkaProducer List size: {}", recordMessages.size()); + for (ConsumerRecord record : recordMessages) { + log.info("CorpusProcessKafkaProducer message: {}",record); + executor.submit(() -> { + try { + String message = (String) record.value(); + AicorpusTelephoneDTO aicorpusTelephone = objectMapper.readValue(message, AicorpusTelephoneDTO.class); + log.info("aicorpusTelephone categoryCode:{}, display: {}", aicorpusTelephone.getCategoryCode(), aicorpusTelephone.getDisplay()); + DisplayDTO display = objectMapper.readValue(aicorpusTelephone.getDisplay(), DisplayDTO.class); + log.info("aicorpusTelephone display getSegments: {}", display.getSegments()); + TmTelephoneCorpus tmTelephoneCorpus = new TmTelephoneCorpus(); + BeanUtils.copyProperties(aicorpusTelephone, tmTelephoneCorpus); + tmTelephoneCorpus.setCreateBy("kafka"); + tmTelephoneCorpus.setCreateTime(LocalDateTime.now()); + // 条件:只处理dcc的 10s通话时间以上 + log.info("CorpusProcessKafkaProducer getCategoryCode: {},audioFileId:{},sourceId:{}", tmTelephoneCorpus.getCategoryCode(), aicorpusTelephone.getAudioFileId(), aicorpusTelephone.getSourceId()); + if (Constant.CHANNEL_DCC.equals(tmTelephoneCorpus.getCategoryCode())||Constant.CHANNEL_4IN1.equals(tmTelephoneCorpus.getCategoryCode())) { + log.info(" dcc 语料开始处理"); + tmTelephoneCorpusService.saveTelephoneCorpus(tmTelephoneCorpus); + long startTimeDify = System.currentTimeMillis(); - // 提交异步任务 - CompletableFuture.runAsync(() -> { - try { - processSingleRecord(message); - } catch (Exception e) { - log.error("corpusProcessKafkaProducer异步任务执行失败", e); - } - }, executor); + rocketMqTemplate.asyncSend(dccMqTipic, MessageBuilder.withPayload(message).build(), + new SendCallback() { + @Override + public void onSuccess(SendResult sendResult) { + log.info("dcc发送MQ成功 消息体:{}", message); + } + @Override + public void onException(Throwable e) { + log.error("dcc 送MQ异常 消息体:{}, 异常:", message, e); + } + }, 10000); + + log.info(" dify处理耗时:{}", System.currentTimeMillis() - startTimeDify); + } + } catch (Exception e) { + log.error("CorpusProcessKafkaProducer 电话语料 解析JSON出错: {}", e.getMessage()); + }finally { + executor.shutdown(); + } + }); + + } + executor.shutdown(); } + log.info("Kafka 消息处理完成,耗时:{}", System.currentTimeMillis() - startTime); + // 在这里可以添加对解析后的对象的进一步处理逻辑 } catch (Exception e) { - log.error("corpusProcessKafkaProducer Failed to process message batch: {}", e.getMessage(), e); - } finally { - - log.info("corpusProcessKafkaProducer Total processing time: {} ms", System.currentTimeMillis() - startTime); - } - } - - /** - * 单条消息处理逻辑(解耦核心逻辑) - */ - private void processSingleRecord(String record) { - try { - log.info("corpusProcessKafkaProducer processSingleRecord :{}", record); - AicorpusTelephoneDTO aicorpusTelephone = objectMapper. readValue(record, AicorpusTelephoneDTO.class); - TmTelephoneCorpus tmTelephoneCorpus = new TmTelephoneCorpus(); - BeanUtils.copyProperties(aicorpusTelephone, tmTelephoneCorpus); - tmTelephoneCorpus.setCreateBy("kafka"); - tmTelephoneCorpus.setCreateTime(LocalDateTime.now()); - - // 3. 逻辑拆分:处理 DCC 语料 - if (Constant.CHANNEL_DCC.equals(tmTelephoneCorpus.getCategoryCode())) { - handleDccCorpus(tmTelephoneCorpus, record); - } - } catch (JsonProcessingException e) { - log.error("JSON parsing failed for message: {},{}", record, e); - } catch (Exception e) { - log.error("Unexpected error processing message: {}", e); + log.error("CorpusProcessKafkaProducer 电话语料 解析JSON出错: {}" , e.getMessage()); + }finally { + executor.shutdown(); } } - /** - * 处理 DCC 语料逻辑(异步发送 MQ) - */ - private void handleDccCorpus(TmTelephoneCorpus corpus, String rawMessage) { - log.info("corpusProcessKafkaProducerSaveSourceId: {}",corpus.getSourceId()); - // 4. 保存语料 - tmTelephoneCorpusService.saveTelephoneCorpus(corpus); - - // 5. 异步发送 RocketMQ(带超时和异常回调) - long startTimeDify = System.currentTimeMillis(); - rocketMqTemplate.asyncSend(dccMqTipic, MessageBuilder.withPayload(rawMessage).build(), - new SendCallback() { - @Override - public void onSuccess(SendResult sendResult) { - log.debug("DCC MQ sent successfully发送成功: {}", rawMessage); - } - @Override - public void onException(Throwable e) { - log.error("DCC MQ send failed发送失败: {}", rawMessage, e); - } - }, 10000); // 超时时间配置化(建议提取到 @Value) - - log.info("handleDccCorpus: {} ms", System.currentTimeMillis() - startTimeDify); - } } diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/CorpusQuestionConsumer.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/CorpusQuestionConsumer.java new file mode 100644 index 0000000..076fb0f --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/CorpusQuestionConsumer.java @@ -0,0 +1,82 @@ +package com.volvo.ai.analytic.center.mq; + +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.volvo.ai.analytic.center.constant.Constant; +import com.volvo.ai.analytic.center.entity.TmCorpusQuestionReport; +import com.volvo.ai.analytic.center.feign.DiFyFeign; +import com.volvo.ai.analytic.center.mapper.TmCorpusQuestionReportMapper; +import com.volvo.ai.analytic.center.utils.ConstantStr; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@Slf4j +@Component +@RocketMQMessageListener(consumerGroup = "${rocketmq.consumer.corpus.questiongroup}", + topic = "${rocketmq.consumer.corpus.questiontopic}", consumeThreadNumber = 2) +@RefreshScope +public class CorpusQuestionConsumer implements RocketMQListener> { + + + @Value("${dify.corpusQuestion.token:app-erbXevAmaQiyg5QFPn2NpJ7G}") + private String corpusQuestionToken; + + @Autowired + TmCorpusQuestionReportMapper tmCorpusQuestionReportMapper; + @Autowired + private DiFyFeign diFyFeign; + + @Override + public void onMessage(Map inputMap) { + inputMap.put("businessType", Constant.CHANNEL_4IN1); + log.info("corpusQuestionConsumer {}", JSON.toJSONString(inputMap)); + log.info("corpusQuestionToken {}", corpusQuestionToken); + + Map requestMap = new HashMap<>(); + requestMap.put("inputs", inputMap); + requestMap.put("user", ConstantStr.CORPUS_QUESTION_USER); + requestMap.put("response_mode", "blocking"); + + try { + JSONObject difyResult = diFyFeign.runWorkflows("Bearer " + corpusQuestionToken, requestMap); + log.info("dify corpusQuestionResult {}", difyResult.toJSONString()); + JSONObject data = difyResult.getJSONObject("data"); + + if (data.get("status").equals("succeeded")) { + JSONObject outputJson = data.getJSONObject("outputs"); + JSONObject textJsonObject = JSONObject.parseObject(outputJson.getString("text")); + JSONObject consultingScenario = textJsonObject.getJSONObject("consultingScenario"); + String userDemand = textJsonObject.getString("userDemand"); + if (userDemand != null && userDemand.length() > 4000) { + log.warn("userDemand 字段长度超过 4000,已自动截取。原始长度:{}", userDemand.length()); + userDemand = userDemand.substring(0, 4000); + } + TmCorpusQuestionReport tmCorpusQuestionReport = new TmCorpusQuestionReport(); + tmCorpusQuestionReport.setBusinessType(outputJson.getString("businessType")); + tmCorpusQuestionReport.setSourceCorpusId(outputJson.getString("sourceCorpusId")); + tmCorpusQuestionReport.setUserDemand(userDemand); + Date sourceCorpusDate = DateUtil.parse(outputJson.getString("sourceCorpusTime"), "yyyy-MM-dd HH:mm:ss"); + tmCorpusQuestionReport.setAnalysisResultJson(outputJson.toJSONString()); + tmCorpusQuestionReport.setMainCategory(consultingScenario.getString("mainCategory")); + tmCorpusQuestionReport.setSubCategory(consultingScenario.getString("subCategory")); + tmCorpusQuestionReport.setConfidence(consultingScenario.getString("confidence")); + tmCorpusQuestionReport.setSourceCorpusTime(sourceCorpusDate); + tmCorpusQuestionReportMapper.insert(tmCorpusQuestionReport); + } else { + log.info("dify corpusQuestion fail {}", JSON.toJSONString(inputMap)); + } + } catch (Exception e) { + log.info("dify corpusQuestion Exception {}", e.getMessage()); + } + } +} diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/CorpusQuestionProducer.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/CorpusQuestionProducer.java new file mode 100644 index 0000000..ee9e22e --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/CorpusQuestionProducer.java @@ -0,0 +1,29 @@ +package com.volvo.ai.analytic.center.mq; + +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.Map; + +@Component +@Slf4j +public class CorpusQuestionProducer { + + @Value("${rocketmq.producer.corpus.questiontopic}") + private String corpusQuestionTopic; + + + @Resource + private RocketMQTemplate rocketMQTemplate; + + public void sendCorpusQuestion(Map inputMap) { + + rocketMQTemplate.convertAndSend(corpusQuestionTopic, inputMap); + + } + + +} diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/InvitedSpeakerConsumer.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/InvitedSpeakerConsumer.java new file mode 100644 index 0000000..cdf0f3f --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/mq/InvitedSpeakerConsumer.java @@ -0,0 +1,25 @@ +package com.volvo.ai.analytic.center.mq; + +import com.volvo.ai.analytic.center.service.SpokesManService; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +@RocketMQMessageListener(consumerGroup = "${rocketmq.consumer.invitedSpeaker.group}", + topic = "${rocketmq.consumer.invitedSpeaker.topic}", + enableMsgTrace = true) +public class InvitedSpeakerConsumer implements RocketMQListener { + + @Autowired + private SpokesManService spokesmanService; + @Override + public void onMessage(MessageExt messageExt) { + log.info("特邀发言官 message: " + messageExt); + spokesmanService.spokesManCallBack(new String(messageExt.getBody())); + } +} diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/CorpusQuestionService.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/CorpusQuestionService.java new file mode 100644 index 0000000..97fb46a --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/CorpusQuestionService.java @@ -0,0 +1,7 @@ +package com.volvo.ai.analytic.center.service; + +import com.volvo.ai.analytic.center.dto.req.ConsultingRequestDTO; + +public interface CorpusQuestionService { + void runCorpusQuestionDify(ConsultingRequestDTO consultingRequestDTO); +} diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/HuaWeiEGService.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/HuaWeiEGService.java index 0302899..0f5558e 100644 --- a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/HuaWeiEGService.java +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/HuaWeiEGService.java @@ -5,6 +5,7 @@ import com.huaweicloud.sdk.eg.v1.EgClient; import com.huaweicloud.sdk.eg.v1.model.*; import com.volvo.ai.analytic.center.dto.event.ListSubscriptionsRequestDto; import com.volvo.ai.analytic.center.dto.event.SubscriptionCreateReqDto; +import com.volvo.ai.analytic.center.dto.event.SubscriptionOperateReqDto; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Component; @@ -20,26 +21,19 @@ public class HuaWeiEGService { private static final String HA_WEI_REQUEST = "hwReq={}"; private static final String HA_WEI_RESPONSE = "hwRes={}"; - @Resource EgClient egClient; - public CreateAgenciesResponse createAgencies(AgencyCreateReq reqbody) { - CreateAgenciesRequest request = new CreateAgenciesRequest(); - request.setBody(reqbody); - log.info(HA_WEI_REQUEST, JSON.toJSONString(request)); - CreateAgenciesResponse response = egClient.createAgencies(request); - log.info(HA_WEI_RESPONSE, JSON.toJSONString(response)); - return response; - } + /** * 发布事件到事件通道 sdk * * @param event event + * @param channel channel */ - public PutEventsResponse sendEvent(CloudEvents event, String channelId) { + public PutEventsResponse sendEvent(CloudEvents event, String channel) { PutEventsRequest request = new PutEventsRequest(); - request.withChannelId(channelId); + request.withChannelId(channel); List eventsList = new ArrayList<>(); eventsList.add(event); @@ -121,6 +115,24 @@ public class HuaWeiEGService { return response; } + /** + * 操作事件订阅 + */ + public OperateSubscriptionResponse operateSubscription(SubscriptionOperateReqDto req) { + OperateSubscriptionRequest request = new OperateSubscriptionRequest(); + + SubscriptionOperateReq body = new SubscriptionOperateReq(); + List subscriptionIds = new ArrayList<>(); + subscriptionIds.add(req.getSubscriptionId()); + body.setSubscriptionIds(subscriptionIds); + body.setOperation(req.getStatus() == 1 ? SubscriptionOperateReq.OperationEnum.ENABLE : SubscriptionOperateReq.OperationEnum.DISABLE); + request.withBody(body); + + log.info(HA_WEI_REQUEST, JSON.toJSONString(request)); + OperateSubscriptionResponse response = egClient.operateSubscription(request); + log.info(HA_WEI_RESPONSE, JSON.toJSONString(response)); + return response; + } /** * 查询事件订阅详情 @@ -411,6 +423,17 @@ public class HuaWeiEGService { return response; } + /** + * 事件模型自动发现 + */ + public DiscoverEventSchemaFromDataResponse discoverEventSchemaFromData(DiscoverEventSchemaFromDataReq body) { + DiscoverEventSchemaFromDataRequest request = new DiscoverEventSchemaFromDataRequest(); + request.withBody(body); + log.info(HA_WEI_REQUEST, JSON.toJSONString(request)); + DiscoverEventSchemaFromDataResponse response = egClient.discoverEventSchemaFromData(request); + log.info(HA_WEI_RESPONSE, JSON.toJSONString(response)); + return response; + } /** * 查询事件模型列表 diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/SpokesManService.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/SpokesManService.java new file mode 100644 index 0000000..26b3a82 --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/SpokesManService.java @@ -0,0 +1,226 @@ +package com.volvo.ai.analytic.center.service; + +import com.alibaba.cloud.commons.lang.StringUtils; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.volvo.ai.analytic.center.dto.req.*; +import com.volvo.ai.analytic.center.entity.AiAnalysisErrors; +import com.volvo.ai.analytic.center.entity.AiAnalysisRequestLogs; +import com.volvo.ai.analytic.center.entity.AiAnalyticBusinessConfig; +import com.volvo.ai.analytic.center.enums.BusinessTypeEnum; +import com.volvo.ai.analytic.center.mapper.AiAnalysisErrorsMapper; +import com.volvo.ai.analytic.center.mapper.AiAnalysisRequestLogsMapper; +import com.volvo.ai.analytic.center.mapper.AiAnalyticBusinessConfigMapper; +import com.volvo.ai.analytic.center.utils.AiAnalysisUtils; +import com.volvo.ai.analytic.center.utils.PublishedTimeFormatter; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 社区特邀发言官服务 + * 该服务用于处理社区特邀发言官相关的业务逻辑 + */ +@Slf4j +@Service +public class SpokesManService { + + @Autowired + private AiAnalyticBusinessConfigMapper aiAnalyticBusinessConfigMapper; + + @Autowired + private DiFyService diFyService; + + @Autowired + private AiAnalysisRequestLogsMapper aiAnalysisRequestLogsMapper; + + @Autowired + private AiAnalysisErrorsMapper aiAnalysisErrorsMapper; + + @Autowired + private RocketMQTemplate rocketMQTemplate; + + @Value("${dify.spokesMan.token}") + private String spokesManToken; + + @Value("${rocketmq.producer.InvitedSpeaker.topic}") + private String topic; + + /** + * 处理社区特邀发言官回调请求 + * + * @param req SpokesManDTO 请求对象 + */ + public void spokesManCallBack(String req) { + + // 生成ai分析请求id + String aiAnalysisRequestId = AiAnalysisUtils.getAiAnalysisRequestId(BusinessTypeEnum.COMMUNITYTARGET.getCode()); + try { + // 异步保存请求日志 + syncSaveRequestLogs(JSON.toJSONString(req), aiAnalysisRequestId); + //把req转成SpokesManDTO对象 + SpokesManDTO spokesManDTO = JSON.parseObject(req, SpokesManDTO.class); + if (spokesManDTO == null || spokesManDTO.getFiles() == null || spokesManDTO.getFiles().isEmpty() + || spokesManDTO.getPlatform() == null) { + log.error("社区特邀发言官入参错误"); + throw new RuntimeException("社区特邀发言官入参错误"); + } + //获取审核规则配置 + List auditRulesList = aiAnalyticBusinessConfigMapper.selectList( + Wrappers.lambdaQuery() + .eq(AiAnalyticBusinessConfig::getBusinessLine, BusinessTypeEnum.SPOKESMAN.getCode()) + .eq(AiAnalyticBusinessConfig::getConfigType, BusinessTypeEnum.SPOKESMAN_AUDIT_RULE.getCode()) + .eq(AiAnalyticBusinessConfig::getVerificationMethod, spokesManDTO.getPlatform()) + .eq(AiAnalyticBusinessConfig::getIsDeleted, 0) + .eq(AiAnalyticBusinessConfig::getConfigVersion, 1) + ); + log.info("社区特邀发言官审核规则配置:{}", auditRulesList.toArray()); + String auditRules = auditRulesList.stream() + .map(AiAnalyticBusinessConfig::getConfigData) + .collect(Collectors.joining(" ")); + JSONArray imageUrls = new JSONArray(); + + for (String url : spokesManDTO.getFiles()) { + DifyImageWorkFlow diFyImageWorkFlow = new DifyImageWorkFlow(); + diFyImageWorkFlow.setUrl(url); + imageUrls.add(diFyImageWorkFlow); + } + DiFyReq diFyReq = new DiFyReq(); + diFyReq.setUser(BusinessTypeEnum.SPOKESMAN.getCode()); + diFyReq.setFlowId(spokesManToken); + JSONObject inputs = new JSONObject(); + inputs.put("files", imageUrls); + inputs.put("platform", spokesManDTO.getPlatform()); + inputs.put("theme", spokesManDTO.getTheme()); + inputs.put("auditRule", auditRules); + diFyReq.setInputs(inputs); + //异步更新dify请求日志 + syncUpdateDiFyRequest(diFyReq, aiAnalysisRequestId); + //调用workflow + JSONObject difSpokesManResult = (JSONObject) diFyService.getDiFyObject(diFyReq); + difSpokesManResult.put("communityRequestId", spokesManDTO.getCommunityRequestId()); + difSpokesManResult.put("aiAnalysisRequestId", aiAnalysisRequestId); + //处理发布时间 + updatePublishedTime(difSpokesManResult); + //返回结果推送到社区的MQ + rocketMQTemplate.syncSend(topic, difSpokesManResult.toString()); + //异步更新dify响应日志 + syncUpdateDiFyResponse(difSpokesManResult, aiAnalysisRequestId); + } catch (Exception e) { + log.error("特邀发言官异常:{}", e.getMessage()); + //保存错误日志 + aiAnalysisErrorsMapper.insert(AiAnalysisErrors.builder() + .aiAnalysisRequestId(aiAnalysisRequestId) + .aiAnalysisErrorMessage(e.getMessage()) + .aiAnalysisRequestType(BusinessTypeEnum.SPOKESMAN.getCode()) + .build()); + } + } + //特邀发言补偿 + public void spokesManTask() { + try { + //捞取异常表中属于社区的异常数据 + List aiAnalysisErrors = aiAnalysisErrorsMapper.selectList(new LambdaQueryWrapper() + .eq(AiAnalysisErrors::getAiAnalysisRequestType, BusinessTypeEnum.SPOKESMAN.getCode()) + .eq(AiAnalysisErrors::getAiAnalysisErrorHandlingStatus, "0") + .lt(AiAnalysisErrors::getRetryCount, 4)); + if (aiAnalysisErrors != null && aiAnalysisErrors.size() > 0) { + //根据ai_analysis_request_id获取AiAnalysisRequestLogs表中的对应的dify_request字段 + for (AiAnalysisErrors aiAnalysisError : aiAnalysisErrors) { + try { + AiAnalysisRequestLogs aiAnalysisRequestLogs = aiAnalysisRequestLogsMapper.selectOne(new LambdaQueryWrapper() + .eq(AiAnalysisRequestLogs::getAiAnalysisRequestId, aiAnalysisError.getAiAnalysisRequestId())); + if (aiAnalysisRequestLogs != null) { + //获取dify_request字段 + String message = aiAnalysisRequestLogs.getBusinessRequest(); + String difyRequest = aiAnalysisRequestLogs.getDifyRequest(); + if (StringUtils.isNotEmpty(message) || StringUtils.isNotEmpty(difyRequest)) { + SpokesManDTO spokesManDTO = JSON.parseObject(message, SpokesManDTO.class); DiFyReq diFyReq = JSON.parseObject(difyRequest, DiFyReq.class); + //调用workflow + JSONObject difSpokesManResult = (JSONObject) diFyService.getDiFyObject(diFyReq); + difSpokesManResult.put("communityRequestId", spokesManDTO.getCommunityRequestId()); + difSpokesManResult.put("aiAnalysisRequestId", aiAnalysisError.getAiAnalysisRequestId()); + //处理发布时间 + updatePublishedTime(difSpokesManResult); + //返回结果推送到社区的MQ + rocketMQTemplate.syncSend(topic, difSpokesManResult.toString()); + //异步更新dify响应日志 + syncUpdateDiFyResponse(difSpokesManResult, aiAnalysisError.getAiAnalysisRequestId()); + } else { + aiAnalysisErrorsMapper.update(new AiAnalysisErrors(), new LambdaUpdateWrapper() + .eq(AiAnalysisErrors::getAiAnalysisRequestId, aiAnalysisError.getAiAnalysisRequestId()) + .set(AiAnalysisErrors::getAiAnalysisErrorHandlingStatus, "2")); + } + } + } catch (Exception e) { + log.error("补偿社区消息,AIID:{},异常:{}", aiAnalysisError.getAiAnalysisRequestId(), e); + aiAnalysisErrorsMapper.update(new AiAnalysisErrors(), new LambdaUpdateWrapper() + .eq(AiAnalysisErrors::getAiAnalysisRequestId, aiAnalysisError.getAiAnalysisRequestId()) + .set(AiAnalysisErrors::getRetryCount, aiAnalysisError.getRetryCount() + 1)); + } + } + } + } catch (Exception e) { + log.error("处理社区异常消息异常:{}", e); + } + } + public static void updatePublishedTime(JSONObject rootJson) { + String contentAnalysisResultStr = rootJson.getString("ContentAnalysisResult"); + if (contentAnalysisResultStr == null || contentAnalysisResultStr.isEmpty()) return; + + JSONObject contentAnalysisResult = JSON.parseObject(contentAnalysisResultStr); + JSONObject contentAnalysisReport = contentAnalysisResult.getJSONObject("contentAnalysisReport"); + if (contentAnalysisReport == null) return; + + JSONObject publishedContentOuter = contentAnalysisReport.getJSONObject("publishedContent"); + if (publishedContentOuter == null) return; + + JSONObject publishedContentInner = publishedContentOuter.getJSONObject("publishedContent"); + if (publishedContentInner == null) return; + + String publishedTime = publishedContentInner.getString("publishedTime"); + String formattedPublishedTime = PublishedTimeFormatter.parsePublishedTime(publishedTime); + + if (formattedPublishedTime != null) { + publishedContentInner.put("publishedTime", formattedPublishedTime); + publishedContentOuter.put("publishedContent", publishedContentInner); + contentAnalysisReport.put("publishedContent", publishedContentOuter); + contentAnalysisResult.put("contentAnalysisReport", contentAnalysisReport); + rootJson.put("ContentAnalysisResult", contentAnalysisResult.toJSONString()); + } + } + + + @Async + protected void syncSaveRequestLogs(String message, String aiAnalysisRequestId) { + aiAnalysisRequestLogsMapper.insert(AiAnalysisRequestLogs.builder() + .aiAnalysisRequestId(aiAnalysisRequestId) + .businessRequest(message) + .difyAgentKey(spokesManToken) + .aiAnalysisRequestType(BusinessTypeEnum.SPOKESMAN.getCode()) + .build()); + } + @Async + protected void syncUpdateDiFyRequest(Object obj, String aiAnalysisRequestId) { + aiAnalysisRequestLogsMapper.update(new AiAnalysisRequestLogs(), + new UpdateWrapper().set("dify_request", JSON.toJSONString(obj)) + .eq("ai_analysis_request_id", aiAnalysisRequestId)); + } + @Async + protected void syncUpdateDiFyResponse(JSONObject result, String aiAnalysisRequestId) { + aiAnalysisRequestLogsMapper.update(new AiAnalysisRequestLogs(), + new UpdateWrapper().set("dify_response", result.toJSONString()) + .eq("ai_analysis_request_id", aiAnalysisRequestId)); + } +} diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/TmOdsImRealtimeMessageCurService.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/TmOdsImRealtimeMessageCurService.java new file mode 100644 index 0000000..ce2b71f --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/TmOdsImRealtimeMessageCurService.java @@ -0,0 +1,15 @@ +package com.volvo.ai.analytic.center.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.volvo.ai.analytic.center.entity.TmOdsImRealtimeMessageCur; +/** + * @description 电话语料表-同步表 + * @author BEJSON + * @date 2025-03-04 + */ +public interface TmOdsImRealtimeMessageCurService extends IService { + + void runImCorpusDify(String paramJson); + + +} \ No newline at end of file diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/TmTelephoneCorpusService.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/TmTelephoneCorpusService.java index 3babda0..45dea49 100644 --- a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/TmTelephoneCorpusService.java +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/TmTelephoneCorpusService.java @@ -20,6 +20,9 @@ public interface TmTelephoneCorpusService extends IService { void runTelephoneCorpusDify(AicorpusTelephoneDTO aicorpusTelephone); + void runTelephoneCorpusDify4in1(AicorpusTelephoneDTO aicorpusTelephone); + + String getCarModelList(); void sendMq(String tag, String message); diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/UserQuestionSummaryService.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/UserQuestionSummaryService.java new file mode 100644 index 0000000..1f797f8 --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/UserQuestionSummaryService.java @@ -0,0 +1,18 @@ +package com.volvo.ai.analytic.center.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.volvo.ai.analytic.center.dto.req.SummaryQuestionRequestDTO; +import com.volvo.ai.analytic.center.entity.TmCorpusQuestionSummaryReport; +/** + * @description 用户问题总结 + * @author lujie + * @date 2025-07-23 + */ +public interface UserQuestionSummaryService extends IService { + + void runUserQuestionSummary(String paramJson); + + void updateSummery(SummaryQuestionRequestDTO summaryQuestionRequestDTO); + + +} \ No newline at end of file diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/ClaimVerificationServiceImpl.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/ClaimVerificationServiceImpl.java index a0c64d6..c6c45c4 100644 --- a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/ClaimVerificationServiceImpl.java +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/ClaimVerificationServiceImpl.java @@ -9,6 +9,8 @@ import com.obs.services.model.ObsObject; import com.volvo.ai.analytic.center.constant.ClaimVerificationConstant; import com.volvo.ai.analytic.center.constant.Constant; import com.volvo.ai.analytic.center.dto.req.ClaimVerificationFileDTO; +import com.volvo.ai.analytic.center.dto.req.ClaimVerificationFileDTO.ClaimVerificationFile; +import com.volvo.ai.analytic.center.dto.req.ClaimVerificationPartHoursDTO; import com.volvo.ai.analytic.center.dto.req.DiFyReq; import com.volvo.ai.analytic.center.dto.req.RunMaskingRuleInput; import com.volvo.ai.analytic.center.entity.*; @@ -16,6 +18,7 @@ import com.volvo.ai.analytic.center.enums.BusinessTypeEnum; import com.volvo.ai.analytic.center.enums.ClaimVerificationFileTypeEnums; import com.volvo.ai.analytic.center.mapper.AiAnalysisErrorsMapper; import com.volvo.ai.analytic.center.mapper.AiAnalyticWarrantyAuditMapper; +import com.volvo.ai.analytic.center.mapper.TmClaimVerificationPartHoursMappingMapper; import com.volvo.ai.analytic.center.service.DataMaskingRuleService; import org.apache.commons.lang3.StringUtils; import org.apache.commons.text.StringEscapeUtils; @@ -37,7 +40,6 @@ import org.springframework.web.multipart.MultipartFile; import java.io.InputStream; import java.util.*; -import java.util.stream.Collectors; @Slf4j @Service @@ -49,6 +51,9 @@ public class ClaimVerificationServiceImpl implements ClaimVerificationService { @Autowired private AiAnalyticBusinessConfigMapper aiAnalyticBusinessConfigMapper; + @Autowired + private TmClaimVerificationPartHoursMappingMapper tmClaimVerificationPartHoursMappingMapper; + @Autowired private DiFyFeign diFyFeign; @@ -61,6 +66,9 @@ public class ClaimVerificationServiceImpl implements ClaimVerificationService { @Value("${dify.claimVerification.verificationToken}") private String verificationToken; + @Value("${dify.claimVerification.fileClassifyToken}") + private String fileClassifyToken; + @Value("${rocketmq.producer.claimVerification}") private String topic; @@ -89,12 +97,16 @@ public class ClaimVerificationServiceImpl implements ClaimVerificationService { log.info("售后索赔检核MQ message: {}", message); ClaimVerificationFileDTO claimVerificationFileAnalysisDTO = JSON.parseObject(message, ClaimVerificationFileDTO.class); if (claimVerificationFileAnalysisDTO == null) { - log.error("售后索赔检核文件入参为空: {}", claimVerificationFileAnalysisDTO.toString()); + log.error("售后索赔检核文件入参为空"); saveException("售后索赔检核文件分析入参为空", aiAnalysisRequestId, null); + return; } JSONObject diFyObject = new JSONObject(); try { // 异步保存请求日志 + if (StringUtils.isNotEmpty(claimVerificationFileAnalysisDTO.getAiAnalysisRequestId())) { + aiAnalysisRequestId = claimVerificationFileAnalysisDTO.getAiAnalysisRequestId(); + } syncSaveRequestLogs(message, aiAnalysisRequestId); if (claimVerificationFileAnalysisDTO.getBusinessType().equals(BusinessTypeEnum.CLAIM_VERIFICATION_FILE_ANALYSIS.getCode())) { //文件分析 @@ -102,7 +114,7 @@ public class ClaimVerificationServiceImpl implements ClaimVerificationService { List> fileIds = new ArrayList<>(); log.info("文件分析文件ID:{}", fileObsPath); //上传所有文件到dify - uploadFileToObs(fileObsPath, fileIds); + uploadFileToObs(fileObsPath, fileIds, fileToken); //根据业务线标识和文件配置分类查询配置 List aiAnalyticBusinessConfigs = aiAnalyticBusinessConfigMapper.selectList( Wrappers.lambdaQuery() @@ -146,19 +158,8 @@ public class ClaimVerificationServiceImpl implements ClaimVerificationService { syncUpdateDiFyResponse(diFyObject, aiAnalysisRequestId); } else if (claimVerificationFileAnalysisDTO.getBusinessType().equals(BusinessTypeEnum.CLAIM_VERIFICATION_AUDIT.getCode())) { //审计报告 - //加载审计规则配置 - List aiAnalyticBusinessConfigs = aiAnalyticBusinessConfigMapper.selectList( - Wrappers.lambdaQuery() - .eq(AiAnalyticBusinessConfig::getBusinessLine, BusinessTypeEnum.CLAIM_VERIFICATION.getCode()) - .eq(AiAnalyticBusinessConfig::getConfigType, BusinessTypeEnum.AUDITRULES.getCode()) - .eq(AiAnalyticBusinessConfig::getIsDeleted, 0) - .in(AiAnalyticBusinessConfig::getVerificationMethod, methodList) - ); - String configDataString = aiAnalyticBusinessConfigs.stream() - .map(AiAnalyticBusinessConfig::getConfigData) - .collect(Collectors.joining(" ")); //组装审计报告workflow入参 - JSONObject parsedAudit = buildAuditToDify(configDataString, claimVerificationFileAnalysisDTO); + JSONObject parsedAudit = buildAuditToDify(claimVerificationFileAnalysisDTO); //根据aiAnalysisRequestId更新请求日志表的difyRequest字段 syncUpdateDiFyRequest(parsedAudit.toString(), aiAnalysisRequestId); DiFyReq diFyReq = new DiFyReq(); @@ -181,6 +182,70 @@ public class ClaimVerificationServiceImpl implements ClaimVerificationService { //审核次数记录 saveAuditCount(claimVerificationFileAnalysisDTO); } + } else if (claimVerificationFileAnalysisDTO.getBusinessType().equals(BusinessTypeEnum.CLAIM_VERIFICATION_CLASSIFY_APP.getCode())) { + //文件分类 + List claimVerificationFiles = claimVerificationFileAnalysisDTO.getClaimVerificationFiles(); + List resultFiles = new ArrayList<>(); + for (ClaimVerificationFile claimVerificationFile : claimVerificationFiles) { + try { + List fileObsPath = new ArrayList<>(); + fileObsPath.add(claimVerificationFile.getFileObsPath()); + List> fileIds = new ArrayList<>(); + log.info("文件分类文件ID:{}", fileObsPath); + //上传所有文件到dify + uploadFileToObs(fileObsPath, fileIds, fileClassifyToken); + + //组装文件分析workflow入参 + JSONArray files = new JSONArray(); + for (HashMap fileToDifyDTO : fileIds) { + JSONObject object = new JSONObject(); + object.put(ClaimVerificationConstant.UPLOAD_FILE_ID, fileToDifyDTO.get(ClaimVerificationConstant.ID)); + object.put(ClaimVerificationConstant.TYPE, fileToDifyDTO.get(ClaimVerificationConstant.TYPE)); + object.put(ClaimVerificationConstant.TRANSFER_METHOD, ClaimVerificationConstant.LOCAL_FILE); + files.add(object); + } + //构建入参 + JSONObject fileToDifyDTO = new JSONObject(); + fileToDifyDTO.put("files", files); + //根据aiAnalysisRequestId更新请求日志表的difyRequest字段 + syncUpdateDiFyRequest(fileToDifyDTO.toString(), aiAnalysisRequestId); + DiFyReq diFyReq = new DiFyReq(); + diFyReq.setUser(BusinessTypeEnum.CLAIM_VERIFICATION.getCode()); + diFyReq.setFlowId(fileClassifyToken); + diFyReq.setInputs(fileToDifyDTO); + //调用dify 工作流 + JSONObject classifyDiFyObject = (JSONObject) diFyService.getDiFyObject(diFyReq); + + //处理结果 + if (classifyDiFyObject == null) { + log.error(" 售后索赔检核文件分类dify返回结果为空"); + saveException("售后索赔检核文件分类dify返回结果为空", aiAnalysisRequestId, null); + } else { + //解析dify返回结果 + String fileType = classifyDiFyObject.getString("fileBusinessType"); + //判断字符串那个是不为空的然后进行处理 + if (StringUtils.isNotBlank(fileType)) { + claimVerificationFile.setFileType(fileType); + } else { + claimVerificationFile.setFileType("3"); + } + resultFiles.add(claimVerificationFile); + } + } catch (Exception e) { + log.error("文件分类异常:{}", e.getMessage()); + claimVerificationFile.setFileType("3"); + resultFiles.add(claimVerificationFile); + } + } + JSONObject data = new JSONObject(); + data.put("newBieAfterSalesId", claimVerificationFileAnalysisDTO.getNewBieAfterSalesId()); + data.put("businessType", claimVerificationFileAnalysisDTO.getBusinessType()); + data.put("claimVerificationFiles", resultFiles); + data.put("aiAnalysisRequestId", aiAnalysisRequestId); + rocketMQTemplate.syncSend(topic, data); + log.info("索赔检核文件分类发送回调MQ完成: {}", data); + //异步更新请求日志表的difyResponse字段 + syncUpdateDiFyResponse(data, aiAnalysisRequestId); } else { saveException("售后索赔检核业务类型错误", aiAnalysisRequestId, null); } @@ -225,12 +290,12 @@ public class ClaimVerificationServiceImpl implements ClaimVerificationService { .build()); } - private JSONObject buildAuditToDify(String configDataString, ClaimVerificationFileDTO claimVerificationFileAnalysisDTO) { + private JSONObject buildAuditToDify(ClaimVerificationFileDTO claimVerificationFileAnalysisDTO) { JSONObject audit = new JSONObject(); - audit.put("analysisRules", configDataString); audit.put("diagnosticReport", claimVerificationFileAnalysisDTO.getDiagnosticReport() == null ? " " :claimVerificationFileAnalysisDTO.getDiagnosticReport().toString()); audit.put("preCheckReport", claimVerificationFileAnalysisDTO.getPreCheckReport() == null ? " " :claimVerificationFileAnalysisDTO.getPreCheckReport().toString()); audit.put("dtcReport", claimVerificationFileAnalysisDTO.getDtcReport() == null ? " " :claimVerificationFileAnalysisDTO.getDtcReport().toString()); + audit.put("warrantyReport", claimVerificationFileAnalysisDTO.getWarrantyReport() == null ? " " :claimVerificationFileAnalysisDTO.getWarrantyReport().toString()); //脱敏处理 List maskingRuleItems = dataMaskingRuleService.getDataMaskingRuleListByApplicationChannel(Constant.CHANNEL_DCC); @@ -239,21 +304,67 @@ public class ClaimVerificationServiceImpl implements ClaimVerificationService { runMaskingRuleInput.setOldStr(audit.toString()); String corpusChat = dataMaskingRuleService.runMaskingRule(runMaskingRuleInput); JSONObject parsedAudit = JSON.parseObject(corpusChat); + + parsedAudit.put("diagnosticUndesensitized", claimVerificationFileAnalysisDTO.getDiagnosticReport() == null ? " " :claimVerificationFileAnalysisDTO.getDiagnosticReport().toString()); + parsedAudit.put("preCheckUndesensitized", claimVerificationFileAnalysisDTO.getPreCheckReport() == null ? " " :claimVerificationFileAnalysisDTO.getPreCheckReport().toString()); + parsedAudit.put("dtcUndesensitized", claimVerificationFileAnalysisDTO.getDtcReport() == null ? " " :claimVerificationFileAnalysisDTO.getDtcReport().toString()); + parsedAudit.put("warrantyUndesensitized", claimVerificationFileAnalysisDTO.getWarrantyReport() == null ? " " :claimVerificationFileAnalysisDTO.getWarrantyReport().toString()); + parsedAudit.put("partHoursConfig", claimVerificationFileAnalysisDTO.getWarrantyReport() == null ? " " :getPartHoursList(claimVerificationFileAnalysisDTO.getWarrantyReport())); return parsedAudit; } + private String getPartHoursList(JSONObject warrantyJson) { + if (warrantyJson == null || !warrantyJson.containsKey("warrantyReport")) { + return " "; + } + + // 获取warrantyReport对象 + JSONObject warrantyReport = warrantyJson.getJSONObject("warrantyReport"); + + // 检查partItems是否存在且是数组 + if (!warrantyReport.containsKey("partItems")) { + return " "; + } else { + Object value = warrantyReport.get("partItems"); + if (!(value instanceof JSONArray)) { + return " "; + } + } + + // 获取partItems数组 + JSONArray partItems = warrantyReport.getJSONArray("partItems"); + List partNoList = new ArrayList<>(); + + // 遍历数组并提取partNo + for (int i = 0; i < partItems.size(); i++) { + JSONObject partItem = partItems.getJSONObject(i); + if (partItem.containsKey("partNo")) { + if (partItem.containsKey("isMain") && "10041001".equals(partItem.getString("isMain"))) { + partNoList.add(partItem.getString("partNo")); + } + } + } + if (partNoList.isEmpty()) { + return " "; + } + List result = tmClaimVerificationPartHoursMappingMapper.queryConfigByPartId(partNoList); + if (result.isEmpty()) { + return " "; + } + return JSONObject.toJSONString(result); + } + @NotNull private static JSONObject getJsonObjectToNewBie(JSONObject diFyObject, ClaimVerificationFileDTO claimVerificationFileAnalysisDTO, String aiAnalysisRequestId) { - if (diFyObject.containsKey("answer") && !diFyObject.getJSONObject("answer").isEmpty()) { - diFyObject = diFyObject.getJSONObject("answer"); + JSONObject warrantyAuditReport = diFyObject.getJSONObject("warrantyAuditReport"); + if (warrantyAuditReport.containsKey("answer") && !warrantyAuditReport.getJSONObject("answer").isEmpty()) { + warrantyAuditReport = warrantyAuditReport.getJSONObject("answer"); } - String warrantyAuditReport = diFyObject.getString("warrantyAuditReport"); - warrantyAuditReport = StringEscapeUtils.unescapeJava(warrantyAuditReport); - JSONObject audiResToAfter = JSON.parseObject(warrantyAuditReport); + JSONObject data = new JSONObject(); data.put("newBieAfterSalesId", claimVerificationFileAnalysisDTO.getNewBieAfterSalesId()); data.put("businessType", claimVerificationFileAnalysisDTO.getBusinessType()); - data.put("warrantyAuditReport", audiResToAfter); + data.put("warrantyAuditReport", warrantyAuditReport); data.put("aiAnalysisRequestId", aiAnalysisRequestId); return data; } @@ -340,15 +451,15 @@ public class ClaimVerificationServiceImpl implements ClaimVerificationService { } } - private void uploadFileToObs(List fileObsPath, List> fileIds) { + private void uploadFileToObs(List fileObsPath, List> fileIds, String uploadToken) { if (fileObsPath != null && fileObsPath.size() > 0) { for (String filePath : fileObsPath) { HashMap fileToDifyDTO = new HashMap<>(); ObsObject obsObject = ObsUtil.downloadFile(filePath); InputStream inputStream = obsObject.getObjectContent(); MultipartFile file = ObsUtil.getMultipartFile(inputStream, ObsUtil.getFilenameByUrl(filePath)); - log.info("索赔检核文件上传dify请求参数:{},token:{}", file, fileToken); - JSONObject fileUploadRes = diFyFeign.fileUpload("Bearer " + fileToken, file); + log.info("索赔检核文件上传dify请求参数:{},token:{}", file, uploadToken); + JSONObject fileUploadRes = diFyFeign.fileUpload("Bearer " + uploadToken, file); log.info("索赔检核文件上传dify响应结果:{}", fileUploadRes); String uploadFileId = fileUploadRes.getString(ClaimVerificationConstant.ID); String extension = fileUploadRes.getString(ClaimVerificationConstant.EXTENSION); diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/CorpusQuestionServiceImpl.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/CorpusQuestionServiceImpl.java new file mode 100644 index 0000000..4ad6a80 --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/CorpusQuestionServiceImpl.java @@ -0,0 +1,42 @@ +package com.volvo.ai.analytic.center.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.volvo.ai.analytic.center.dto.req.ConsultingRequestDTO; +import com.volvo.ai.analytic.center.entity.TmCorpusQuestionReport; +import com.volvo.ai.analytic.center.mapper.TmCorpusQuestionReportMapper; +import com.volvo.ai.analytic.center.service.CorpusQuestionService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class CorpusQuestionServiceImpl implements CorpusQuestionService { + + @Autowired + TmCorpusQuestionReportMapper tmCorpusQuestionReportMapper; + + @Override + public void runCorpusQuestionDify(ConsultingRequestDTO consultingRequestDTO) { + String text = consultingRequestDTO.getText(); + JSONObject textJsonObject = JSONObject.parseObject(text); + JSONObject consultingScenario = textJsonObject.getJSONObject("consultingScenario"); + String userDemand = textJsonObject.getString("userDemand"); + if (userDemand != null && userDemand.length() > 4000) { + log.warn("userDemand 字段长度超过 4000,已自动截取。原始长度:{}", userDemand.length()); + userDemand = userDemand.substring(0, 4000); + } + TmCorpusQuestionReport tmCorpusQuestionReport = new TmCorpusQuestionReport(); + tmCorpusQuestionReport.setMainCategory(consultingScenario.getString("mainCategory")); + tmCorpusQuestionReport.setSubCategory(consultingScenario.getString("subCategory")); + tmCorpusQuestionReport.setUserDemand(userDemand); + + tmCorpusQuestionReport.setConfidence(consultingScenario.getString("confidence")); + tmCorpusQuestionReport.setBusinessType(consultingRequestDTO.getBusinessType()); + tmCorpusQuestionReport.setSourceCorpusId(consultingRequestDTO.getSourceCorpusId()); + tmCorpusQuestionReport.setSourceCorpusTime(consultingRequestDTO.getSourceCorpusTime()); + tmCorpusQuestionReport.setAnalysisResultJson(text); + tmCorpusQuestionReportMapper.insert(tmCorpusQuestionReport); + + } +} diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/IntelligentCustomerServiceImpl.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/IntelligentCustomerServiceImpl.java index a2c4d7c..14f6969 100644 --- a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/IntelligentCustomerServiceImpl.java +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/IntelligentCustomerServiceImpl.java @@ -54,8 +54,6 @@ public class IntelligentCustomerServiceImpl implements IntelligentCustomerServic private String topic; @Value("${dify.intelligentCustomer.fourInOneToken}") private String fourInOneToken; - @Autowired - private RemoteCarModelClient remoteCarModelClient; @Autowired private DataMaskingRuleService dataMaskingRuleService; @@ -66,13 +64,6 @@ public class IntelligentCustomerServiceImpl implements IntelligentCustomerServic @Autowired private AiAnalysisErrorsService aiAnalysisErrorsService; - @Autowired - private AiAnalysisErrorsMapper aiAnalysisErrorsMapper; - - @Autowired - private TcIntelligentCustomerMapper tcIntelligentCustomerMapper; - - private Map> tcIntelligentCustomer = Collections.EMPTY_MAP; @Override public void fourInOneMqService(FourInOneRequestDTO fourInOneRequestDTO) { @@ -148,39 +139,4 @@ public class IntelligentCustomerServiceImpl implements IntelligentCustomerServic }, 10000); } - // 咨询类【201】/投诉类【202】/投诉类型【203】 过滤 - /** private String fourInOneMqServiceFilter(String customerType,String customerValue){ - if(tcIntelligentCustomer.isEmpty()){ - queryTcIntelligentCustomer(); - } - List typeValues = tcIntelligentCustomer.get(customerType); - if(!typeValues.contains(customerValue)){ - return ""; - } - return customerValue; - } - - - public Map> queryTcIntelligentCustomer() { - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(TcIntelligentCustomer::getIsDeleted, "0"); - List tcIntelligentCustomerList =tcIntelligentCustomerMapper.selectList(queryWrapper); - tcIntelligentCustomer = tcIntelligentCustomerList.stream() - .collect(Collectors.groupingBy( - TcIntelligentCustomer::getIntelligentCustomerType, // 按照 IntelligentCustomerType 分组 - Collectors.mapping( - customer -> { - if (customer.getIntelligentCustomerType().equals(IntelligentCustomerTypeEnum.CONSULT_TYPE.getCode())) { - return customer.getTypeOne(); // 如果是咨询类型,返回 TypeOne - } else { - return customer.getTypeOne().concat("#").concat(customer.getTypeTwo()).concat("#").concat(customer.getTypeThree()); // 其他类型,拼接 TypeOne、TypeTwo、TypeThree - } - }, - Collectors.toList() - ) - )); - return tcIntelligentCustomer; - } -**/ - } \ No newline at end of file diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/MqMessageRecordServiceImpl.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/MqMessageRecordServiceImpl.java index 2c92322..6d11f5e 100644 --- a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/MqMessageRecordServiceImpl.java +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/MqMessageRecordServiceImpl.java @@ -77,6 +77,9 @@ public class MqMessageRecordServiceImpl extends ServiceImpl() + .eq(AiAnalysisRequestLogs::getAiAnalysisRequestId, aiAnalysisRequestId) + .last("for update")); - // 内容主题关键词打标 - JSONObject keywordResult = callCommunityWorkFlow(difyCommunityTargetDTO,user, keywordToken); + if (aiAnalysisRequestLogs == null) { + log.error("未找到对应的 AiAnalysisRequestLogs,请求ID: {}", aiAnalysisRequestId); + throw new RuntimeException("未找到对应的请求日志"); + } - // litecrm线索分析 - JSONObject clueAnalysisResult = callCommunityWorkFlow(difyCommunityTargetDTO,user, clueAnalysisToken); + String difyResponseStr = aiAnalysisRequestLogs.getDifyResponse(); + JSONObject difyResponse = StringUtils.isNotBlank(difyResponseStr) + ? JSONObject.parseObject(difyResponseStr) + : new JSONObject(); - difyResult.add(caseResult); - difyResult.add(keywordResult); - difyResult.add(clueAnalysisResult); - //处理结果 - processingCommunityDifyResponse(caseResult,keywordResult,clueAnalysisResult, aiAnalysisRequestId,difyCommunityTargetDTO.getCommunityRequestId()); + difyResponse.put(businessType, difFeedQualityResult); + + aiAnalysisRequestLogsMapper.update(null, + new UpdateWrapper() + .set("dify_response", difyResponse.toJSONString()) + .eq("ai_analysis_request_id", aiAnalysisRequestId)); + } + + @Async + protected void processPublicOpinionAutomationDify(DifyCommunityTargetDTO difyCommunityTargetDTO, String user, JSONArray difyResult, String aiAnalysisRequestId) { + try { + //舆情案件分析 + JSONObject caseResult = callCaseCommunityWorkFlow(difyCommunityTargetDTO, user, caseToken); + + // 内容主题关键词打标 + JSONObject keywordResult = callCommunityWorkFlow(difyCommunityTargetDTO, user, keywordToken); + + // litecrm线索分析 + JSONObject clueAnalysisResult = callCommunityWorkFlow(difyCommunityTargetDTO, user, clueAnalysisToken); + + difyResult.add(caseResult); + difyResult.add(keywordResult); + difyResult.add(clueAnalysisResult); + //处理结果 + processingCommunityDifyResponse(caseResult, keywordResult, clueAnalysisResult, aiAnalysisRequestId, difyCommunityTargetDTO.getCommunityRequestId()); + } catch (Exception e) { + log.error("舆情自动化异常:{}", e.getMessage()); + saveOrUpdateError(aiAnalysisRequestId, e, BusinessTypeEnum.PUBLICOPINIONAUTOMATION.getCode()); + } + } + + private void saveOrUpdateError(String aiAnalysisRequestId, Exception e, String businnessType) { + //根据aiAnalysisRequestId查询是否存在错误日志,无则新增,有则更新retryCount+1 + AiAnalysisErrors aiAnalysisErrors = aiAnalysisErrorsMapper.selectOne( + new LambdaQueryWrapper() + .eq(AiAnalysisErrors::getAiAnalysisRequestId, aiAnalysisRequestId) + .eq(AiAnalysisErrors::getAiAnalysisRequestType, businnessType) + .last("for update") // 添加悲观锁 + ); + if (aiAnalysisErrors != null) { + aiAnalysisErrors.setRetryCount(aiAnalysisErrors.getRetryCount() + 1); + aiAnalysisErrorsMapper.updateById(aiAnalysisErrors); + log.error("处理错误日志失败:{}", e.getMessage()); + } else { + aiAnalysisErrorsMapper.insert(AiAnalysisErrors.builder() + .aiAnalysisRequestId(aiAnalysisRequestId) + .aiAnalysisErrorMessage(e.getMessage()) + //舆情自动化标识 + .aiAnalysisRequestType(businnessType) + .build()); + } } /** * 调用案件,关键词,线索工作流 */ - private JSONObject callCommunityWorkFlow(DifyCommunityTargetDTO difyCommunityTargetDTO ,String user, String token) { - log.info("开始调用关键词,线索工作流,token: {}",token); + private JSONObject callCommunityWorkFlow(DifyCommunityTargetDTO difyCommunityTargetDTO, String user, String token) { + log.info("开始调用关键词,线索工作流,token: {}", token); DiFyReq diFyReq = new DiFyReq(); diFyReq.setUser(user); diFyReq.setInputs(difyCommunityTargetDTO); @@ -184,7 +261,7 @@ public class MqMessageRecordServiceImpl extends ServiceImpl aiAnalyticBusinessConfigs = aiAnalyticBusinessConfigMapper.selectList( Wrappers.lambdaQuery() .eq(AiAnalyticBusinessConfig::getBusinessLine, BusinessTypeEnum.COMMUNITYTARGET.getCode()) @@ -192,7 +269,7 @@ public class MqMessageRecordServiceImpl extends ServiceImpl().set("dify_response", caseResult.toJSONString()) - .eq("ai_analysis_request_id", aiAnalysisRequestId)); + updaterDifyResponse(aiAnalysisRequestId, caseResult, BusinessTypeEnum.PUBLICOPINIONAUTOMATION.getCode()); } } @@ -290,7 +369,7 @@ public class MqMessageRecordServiceImpl extends ServiceImpl aiAnalysisErrors = aiAnalysisErrorsMapper.selectList(new LambdaQueryWrapper() - .eq(AiAnalysisErrors::getAiAnalysisRequestType, BusinessTypeEnum.COMMUNITYTARGET.getCode()) + .in(AiAnalysisErrors::getAiAnalysisRequestType, BusinessTypeEnum.COMMUNITYTARGET.getCode(), + BusinessTypeEnum.PUBLICOPINIONAUTOMATION.getCode(), BusinessTypeEnum.FEEDQUALITY.getCode()) .eq(AiAnalysisErrors::getAiAnalysisErrorHandlingStatus, "0") .lt(AiAnalysisErrors::getRetryCount, maxRetryCount)); if (aiAnalysisErrors != null && aiAnalysisErrors.size() > 0) { @@ -658,25 +738,34 @@ public class MqMessageRecordServiceImpl extends ServiceImpl() .eq(AiAnalysisErrors::getAiAnalysisRequestId, aiAnalysisError.getAiAnalysisRequestId()) .set(AiAnalysisErrors::getRetryCount, aiAnalysisError.getRetryCount() + 1) .set(AiAnalysisErrors::getAiAnalysisErrorHandlingStatus, "1")); - //根据ai_analysis_request_id更新tt_ai_analysis_request_logs表中的dify_response字段 - aiAnalysisRequestLogsMapper.update(new AiAnalysisRequestLogs(), new LambdaUpdateWrapper() - .eq(AiAnalysisRequestLogs::getAiAnalysisRequestId, aiAnalysisError.getAiAnalysisRequestId()) - .set(AiAnalysisRequestLogs::getDifyResponse, difyResult.toJSONString())); - }else{ + } else { aiAnalysisErrorsMapper.update(new AiAnalysisErrors(), new LambdaUpdateWrapper() .eq(AiAnalysisErrors::getAiAnalysisRequestId, aiAnalysisError.getAiAnalysisRequestId()) .set(AiAnalysisErrors::getAiAnalysisErrorHandlingStatus, "2")); } } } catch (Exception e) { - log.error("补偿社区消息,AIID:{},异常:{}",aiAnalysisError.getAiAnalysisRequestId(), e); + log.error("补偿社区消息,AIID:{},异常:{}", aiAnalysisError.getAiAnalysisRequestId(), e); aiAnalysisErrorsMapper.update(new AiAnalysisErrors(), new LambdaUpdateWrapper() .eq(AiAnalysisErrors::getAiAnalysisRequestId, aiAnalysisError.getAiAnalysisRequestId()) .set(AiAnalysisErrors::getRetryCount, aiAnalysisError.getRetryCount() + 1)); @@ -684,7 +773,7 @@ public class MqMessageRecordServiceImpl extends ServiceImpl implements TmOdsImRealtimeMessageCurService { + + @Autowired + private TmOdsImRealtimeMessageCurMapper tmOdsImRealtimeMessageCurMapper; + + @Autowired + private DiFyService diFyService; + + @Value("${dify.corpus.imCurToken}") + private String imCurToken; + + @Value("${batch.size}") + public int pageSize = 100; + + @Autowired + private DataMaskingRuleService dataMaskingRuleService; + + @Autowired + private CorpusQuestionService corpusQuestionService; + + @Override + public void runImCorpusDify(String paramJson) { + long startTime = System.currentTimeMillis(); + log.info("runImCorpusDify paramJson {}", paramJson); + // 获取当前日期 + LocalDate today = LocalDate.now(); + // 获取前一天日期 + LocalDate yesterday = today.minusDays(1); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + // 格式化输出 + String formattedDate = yesterday.toString(); // 默认格式为 yyyy-MM-dd + String statTimeString = formattedDate.concat(" 00:00:00"); + String endTimeString = formattedDate.concat(" 23:59:59"); + if (StringUtils.isNotBlank(paramJson)) { + JSONObject paramJsonObj = JSONObject.parseObject(paramJson); + if (null != paramJsonObj && paramJsonObj.containsKey("statTime") && paramJsonObj.containsKey("endTime")) { + statTimeString = paramJsonObj.getString("statTime"); + endTimeString = paramJsonObj.getString("endTime"); + } + } + Long finalStatTime = stringTimeToTimeStamp(statTimeString, formatter); + Long finalEndTime = stringTimeToTimeStamp(endTimeString, formatter); + + Long statTime = stringTimeToTimeStamp(statTimeString, formatter); + Long endTime = stringTimeToTimeStamp(endTimeString, formatter); + + Integer total = tmOdsImRealtimeMessageCurMapper.countImRealtimeMessageCurByDate(statTime, endTime); + int totalPages = PageDto.getTotalPages(total, pageSize); + + // 设置脱敏规则 + List maskingRuleItems = dataMaskingRuleService.getDataMaskingRuleListByApplicationChannel(BusinessTypeEnum.SMART_ASSISTANT_QIWEI.getCode()); + RunMaskingRuleInput runMaskingRuleInput = new RunMaskingRuleInput(); + runMaskingRuleInput.setDataMaskingRules(maskingRuleItems); + + // 创建线程池 + int optimalThreadPoolSize = Runtime.getRuntime().availableProcessors() + 1; + log.info("IM处理总数据量:{},总页数:{},获取的线程数:{}",total,totalPages,optimalThreadPoolSize); + ExecutorService executor = Executors.newFixedThreadPool(optimalThreadPoolSize); // 根据需求调整线程池大小 + + try { + for (int i = 1; i <= totalPages; i++) { + int offset = (i - 1) * pageSize; + List messageList = tmOdsImRealtimeMessageCurMapper.queryImRealtimeMessageCurByDate(statTime, endTime, offset, pageSize); + // 处理查询到的数据 + // 使用 CompletableFuture 并行处理 + CompletableFuture[] futures = messageList.stream() + .map(item -> CompletableFuture.runAsync(() -> { + try { + processItem(item, finalStatTime, finalEndTime, runMaskingRuleInput, formatter); + } catch (Exception e) { + log.error("处理IM语料失败: sessionId={}, 异常: {}", + item.getSessionId(), e.getMessage(), e); + } + }, executor)) + .toArray(CompletableFuture[]::new); + // 等待所有任务完成 + CompletableFuture.allOf(futures).join(); + } + // 关闭线程池 + executor.shutdown(); + } catch (Exception e) { + log.error("IM数据跑批异常",e); + } finally { + // 关闭线程池 + executor.shutdown(); + } + log.info("IM数据跑批结束 耗时:{}",System.currentTimeMillis()-startTime); + } + + private void processItem(ImCurMessageDTO item, Long statTime, Long endTime, RunMaskingRuleInput runMaskingRuleInput, DateTimeFormatter formatter) { + log.info("IM语料内容处理:sessionId:{}", item.getSessionId()); + + // 获取语料信息 + List contetnList = tmOdsImRealtimeMessageCurMapper.queryImRealtimeMessageCurBySessionId(statTime, endTime, item.getSessionId()); + + // 组装语料信息 + StringBuffer chatList = new StringBuffer(); + contetnList.forEach(contentItem -> { + if (item.getMsgTimestamp() == null) { + item.setMsgTimestamp(contentItem.getMsgTimestamp()); + } + String title = ""; + if(ImCustomTypeEnums.CUSTOMER.getCode().equals(contentItem.getCustomerType())){ + title="客户:"; + }else{ + title="顾问:"; + } + JSONObject contentJson = JSONObject.parseObject(contentItem.getMsgContent()); + String content = contentJson.getString("text"); + // 拼接 role 和 text + String chat = title.concat(content); + runMaskingRuleInput.setOldStr(chat); + String corpusChat = dataMaskingRuleService.runMaskingRule(runMaskingRuleInput); + chatList.append(corpusChat).append("\n"); + }); + Map inputMap = new HashMap<>(); + inputMap.put("chat", chatList.toString()); + inputMap.put("businessType", BusinessTypeEnum.IM_CORPUS_ANALYSIS.getCode()); + inputMap.put("sourceCorpusId", item.getSessionId()); + inputMap.put("sourceCorpusTime", item.getMsgTimestamp() != null ? timeStampToLocalDateTime(item.getMsgTimestamp(), formatter) : null); + + DiFyReq diFyImageReq = new DiFyReq(); + diFyImageReq.setUser(ConstantStr.corpus_user); + diFyImageReq.setFlowId(imCurToken); + diFyImageReq.setInputs(inputMap); + // 调用dify + JSONObject resultJsonObject = (JSONObject) diFyService.getDiFyObject(diFyImageReq); + log.info("runDify difyflow {}", resultJsonObject); + + // 保存结果 + if (resultJsonObject != null) { + ConsultingRequestDTO corpusQuestion = new ConsultingRequestDTO(); + corpusQuestion.setText(resultJsonObject.getString("text")); + corpusQuestion.setBusinessType(resultJsonObject.getString("businessType")); + corpusQuestion.setSourceCorpusId(resultJsonObject.getString("sourceCorpusId")); + String sourceCorpusTimeStr = resultJsonObject.getString("sourceCorpusTime"); + if (StringUtils.isNotBlank(sourceCorpusTimeStr)) { + try { + corpusQuestion.setSourceCorpusTime(DateUtil.parse(sourceCorpusTimeStr)); + } catch (Exception e) { + log.error("转换 sourceCorpusTime 为 Date 类型失败,时间字符串: {}", sourceCorpusTimeStr, e); + } + } + corpusQuestionService.runCorpusQuestionDify(corpusQuestion); + } + + } + + /** + * 时间字符串转时间戳秒级 + * @param stringTime + * @param formatter + * @return + */ + private Long stringTimeToTimeStamp(String stringTime, DateTimeFormatter formatter) { + if (StringUtils.isBlank(stringTime)) { + return null; + } + LocalDateTime localDateTime = LocalDateTime.parse(stringTime, formatter); + + // 转换为秒级时间戳 + return localDateTime.atZone(ZoneId.systemDefault()).toEpochSecond(); + } + + /** + * 秒级时间戳转时间字符串 + * @param timeStamp + * @param formatter + * @return + */ + private String timeStampToLocalDateTime(Long timeStamp, DateTimeFormatter formatter) { + if (timeStamp == null) { + return null; + } + Instant instant = Instant.ofEpochSecond(timeStamp); + LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); + return localDateTime.format(formatter); + } + +} \ No newline at end of file diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/TmTelephoneCorpusServiceImpl.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/TmTelephoneCorpusServiceImpl.java index b0a4d34..69a0d08 100644 --- a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/TmTelephoneCorpusServiceImpl.java +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/service/impl/TmTelephoneCorpusServiceImpl.java @@ -18,10 +18,12 @@ import com.volvo.ai.analytic.center.enums.BizEnum; import com.volvo.ai.analytic.center.enums.BusinessTypeEnum; import com.volvo.ai.analytic.center.enums.CategoryEnum; import com.volvo.ai.analytic.center.feign.RemoteCarModelClient; -import com.volvo.ai.analytic.center.mapper.AiAnalysisErrorsMapper; import com.volvo.ai.analytic.center.mapper.TmTelephoneCorpusMapper; +import com.volvo.ai.analytic.center.mq.CorpusQuestionProducer; import com.volvo.ai.analytic.center.service.*; +import com.volvo.ai.analytic.center.utils.AiAnalysisUtils; import com.volvo.ai.analytic.center.utils.ConstantStr; +import com.volvo.ai.analytic.center.utils.FlowResultSplitUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -65,6 +67,9 @@ public class TmTelephoneCorpusServiceImpl extends ServiceImpl (JSONObject) segment) + .forEach(segment -> { + JSONObject result = segment.getJSONObject("result"); + String text = result.getString("text"); + JSONObject analysisInfo = result.getJSONObject("analysis_info"); + String role = analysisInfo.getString("role"); + String title=""; + if(role.equals("AGENT")){ + title="顾问"; + }else{ + title="客户"; + } + // 拼接 role 和 text + String chat = title + ": " + text; + runMaskingRuleInput.setOldStr(chat); + String corpusChat = dataMaskingRuleService.runMaskingRule(runMaskingRuleInput); + chatList.append(corpusChat).append("\n"); - ZonedDateTime zonedDateTime = ZonedDateTime.parse(JSONObject.parseObject(aicorpusTelephone.getDisplay()).getString("start_time")); + }); + + ZonedDateTime zonedDateTime = ZonedDateTime.parse(jsonObject.getString("start_time")); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String formattedDateStartTime = zonedDateTime.format(formatter); - String carModel = getCarModelList(); - inputMap.put("chat",chatContent); - inputMap.put("model",carModel); - inputMap.put("analysisScene", "2"); - inputMap.put("recordId", aicorpusTelephone.getSourceId()); - inputMap.put("communicateDate", formattedDateStartTime); - inputMap.put("version",2); + + inputMap.put("chat",chatList.toString()); + inputMap.put("model",getCarModelList()); diFyImageReq.setInputs(inputMap); CorpusReportDTO corpusReportDTO = new CorpusReportDTO(); corpusReportDTO.setCorpusTime(formattedDateStartTime); corpusReportDTO.setRecordId(aicorpusTelephone.getSourceId()); corpusReportDTO.setAnalysisScene(2l); - corpusReportDTO.setCarModel(carModel); // 获取配置 JSONObject execDifyFlow = diFyService.executeDifyFlow(diFyImageReq, BusinessTypeEnum.SMART_ASSISTANT.getCode(), JSONObject.toJSONString(corpusReportDTO), aicorpusTelephone.getAiAnalysisRequestId()); log.info("runDify execDifyFlow {}",execDifyFlow); if(null != execDifyFlow && execDifyFlow.get("status").equals("succeeded")){ - JSONObject text = execDifyFlow.getJSONObject("outputs"); + String text = execDifyFlow.getJSONObject("outputs").getString("text"); + String resultStrOne = FlowResultSplitUtil.flowOutputTextSplit(text, "任务1", "任务2"); + String resultStrTwo =FlowResultSplitUtil.flowOutputTextSplit(text, "任务2", null); + if (StringUtils.isBlank(resultStrOne) || StringUtils.isBlank(resultStrTwo)){ + log.info("电话语料解析为空,text:{}", text); + return; + } String aiAnalysisRequestId = execDifyFlow.getString("aiAnalysisRequestId"); + Map ltoMap = new HashMap(); + ltoMap.put("analysisRecordId", aiAnalysisRequestId); + ltoMap.put("analysisScene", "2"); + ltoMap.put("recordId", aicorpusTelephone.getSourceId()); + ltoMap.put("communicateDate", formattedDateStartTime); + ltoMap.put("analysisResult", resultStrOne); + ltoMap.put("analysisDetail", resultStrTwo); // 发送MQ - log.info("send mq {}",text); - sendMq( CategoryEnum.PHONE_VOICE.getCode(), text.toJSONString()); + + log.info("send mq {}",ltoMap); + sendMq( CategoryEnum.PHONE_VOICE.getCode(), JSONObject.toJSONString(ltoMap)); try { if(StringUtils.isNotEmpty(aicorpusTelephone.getAiAnalysisRequestId())){ AiAnalysisErrors aiAnalysisErrors = new AiAnalysisErrors(); @@ -140,7 +186,7 @@ public class TmTelephoneCorpusServiceImpl extends ServiceImpl maskingRuleItems) { - JSONObject jsonObject = JSONObject.parseObject(display); - JSONArray segments = jsonObject.getJSONArray("segments"); - Long audioDuration = jsonObject.getLong("audio_duration"); // 单位:毫秒 - // 时长小于10秒不处理 - if (audioDuration / 1000 <= 10) { - log.info("电话语料时长小于10秒,不进行dify处理"); - return null; + + /** + * 4in1语料处理 + * @param aicorpusTelephone + */ + @Override + public void runTelephoneCorpusDify4in1(AicorpusTelephoneDTO aicorpusTelephone) { + + if(null != aicorpusTelephone){ + + List maskingRuleItems = dataMaskingRuleService.getDataMaskingRuleListByApplicationChannel(BusinessTypeEnum.SMART_ASSISTANT_4IN1.getCode()); + + RunMaskingRuleInput runMaskingRuleInput = new RunMaskingRuleInput(); + runMaskingRuleInput.setDataMaskingRules(maskingRuleItems); + + Map inputMap = new HashMap(); + DiFyReq diFyImageReq = new DiFyReq(); + diFyImageReq.setUser(ConstantStr.corpus_user); + diFyImageReq.setFlowId(channel4In1Token); + + + JSONObject jsonObject = JSONObject.parseObject( aicorpusTelephone.getDisplay()); + JSONArray segments = jsonObject.getJSONArray("segments"); + // Long audioDuration = jsonObject.getLong("audio_duration"); // 毫秒 + // if(audioDuration/1000 <=10){ + // log.info("电话语料时长小于10秒,不进行dify处理"); + // return; + // } + if (segments == null || segments.isEmpty()) { + log.info("电话语料内容segments为空,不进行dify处理"); + return; + } + // 遍历 segments + StringBuffer chatList = new StringBuffer(); + segments.stream() + .map(segment -> (JSONObject) segment) + .forEach(segment -> { + JSONObject result = segment.getJSONObject("result"); + String text = result.getString("text"); + JSONObject analysisInfo = result.getJSONObject("analysis_info"); + String role = analysisInfo.getString("role"); + String title=""; + if(role.equals("AGENT")){ + title="顾问"; + }else{ + title="客户"; + } + // 拼接 role 和 text + String chat = title + ": " + text; + runMaskingRuleInput.setOldStr(chat); + String corpusChat = dataMaskingRuleService.runMaskingRule(runMaskingRuleInput); + chatList.append(corpusChat).append("\n"); + + }); + inputMap.put("workOrderContent", chatList.toString()); + + Map questionInput = new HashMap(); + questionInput.put("chat", chatList.toString()); + questionInput.put("sourceCorpusId", aicorpusTelephone.getSourceId()); + questionInput.put("sourceCorpusTime", aicorpusTelephone.getTranscribeTime()); + + //发送单个问题消息 + corpusQuestionProducer.sendCorpusQuestion(questionInput); + + inputMap.put("workOrderId",aicorpusTelephone.getSourceId()); + + String oldAiAnalysisRequestId = aicorpusTelephone.getAiAnalysisRequestId(); + String newAiAnalysisRequestId = StringUtils.isEmpty(oldAiAnalysisRequestId)? AiAnalysisUtils.getAiAnalysisRequestId(BusinessTypeEnum.SMART_ASSISTANT_4IN1.getCode()): + oldAiAnalysisRequestId; + + inputMap.put("aiAnalysisRequestId",newAiAnalysisRequestId); + diFyImageReq.setInputs(inputMap); + CorpusReportDTO corpusReportDTO = new CorpusReportDTO(); + corpusReportDTO.setRecordId(aicorpusTelephone.getSourceId()); + + log.info("开始处理智能客服4IN1工作流,{}",diFyImageReq); + + // 获取配置 + JSONObject execDifyFlow = diFyService.executeDifyFlow(diFyImageReq, BusinessTypeEnum.SMART_ASSISTANT_4IN1.getCode(), JSONObject.toJSONString(corpusReportDTO),newAiAnalysisRequestId ); + log.info("runDify智能客服4IN1 {}",execDifyFlow); + String aiAnalysisRequestId = execDifyFlow.getString("aiAnalysisRequestId"); + if(null != execDifyFlow && execDifyFlow.get("status").equals("succeeded")){ + JSONObject outputsJson = execDifyFlow.getJSONObject("outputs"); + String message = JSONObject.toJSONString(outputsJson); + log.info("send 4IN1mq {}",message); + intelligentCustomerService.sendMq(message); + if(StringUtils.isNotEmpty(aicorpusTelephone.getAiAnalysisRequestId())){ + AiAnalysisErrors aiAnalysisErrors = new AiAnalysisErrors(); + aiAnalysisErrors.setAiAnalysisRequestId(aiAnalysisRequestId); + aiAnalysisErrors.setAiAnalysisErrorHandlingStatus("1"); + aiAnalysisErrorsService.updateAiAnalysisErrors(aiAnalysisErrors); + } + aiAnalysisRequestLogsService.saveAiAnalysisRequestLogs(AiAnalysisRequestLogs.builder().aiAnalysisRequestId(execDifyFlow.getString("aiAnalysisRequestId")).businessResponse(message).build()); + + } + } - - // segments 为空不处理 - if (segments == null || segments.isEmpty()) { - log.info("电话语料内容segments为空,不进行dify处理"); - return null; - } - - RunMaskingRuleInput runMaskingRuleInput = new RunMaskingRuleInput(); - runMaskingRuleInput.setDataMaskingRules(maskingRuleItems); - - StringBuffer chatList = new StringBuffer(); - - // 遍历 segments 并拼接内容 - segments.stream() - .map(segment -> (JSONObject) segment) - .forEach(segment -> { - JSONObject result = segment.getJSONObject("result"); - String text = result.getString("text"); - JSONObject analysisInfo = result.getJSONObject("analysis_info"); - String role = analysisInfo.getString("role"); - - String title = "客户"; - if ("AGENT".equals(role)) { - title = "顾问"; - } - - String chat = title + ": " + text; - - // 应用脱敏规则 - runMaskingRuleInput.setOldStr(chat); - String corpusChat = dataMaskingRuleService.runMaskingRule(runMaskingRuleInput); - - chatList.append(corpusChat).append("\n"); - }); - - return chatList.toString(); } public String getCarModelList(){ @@ -224,7 +322,7 @@ public class TmTelephoneCorpusServiceImpl extends ServiceImpl implements UserQuestionSummaryService { + + @Autowired + private TmCorpusQuestionSummaryReportMapper tmCorpusQuestionSummaryReportMapper; + @Autowired + private TmCorpusQuestionReportMapper tmCorpusQuestionReportMapper; + + @Autowired + private DiFyService diFyService; + + @Value("${dify.corpus.reportSummaryToken}") + private String reportSummaryToken; + + @Override + public void runUserQuestionSummary(String paramJson) { + long startTime = System.currentTimeMillis(); + log.info("runUserQuestionSummary paramJson {}", paramJson); + // 获取当前日期 + LocalDate today = LocalDate.now(); + // 获取前一天日期 + LocalDate yesterday = today.minusDays(1); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + // 格式化输出 + String formattedDate = yesterday.toString(); // 默认格式为 yyyy-MM-dd + String statTimeString = formattedDate.concat(" 00:00:00"); + String endTimeString = formattedDate.concat(" 23:59:59"); + if (StringUtils.isNotBlank(paramJson)) { + JSONObject paramJsonObj = JSONObject.parseObject(paramJson); + if (null != paramJsonObj && paramJsonObj.containsKey("statTime") && paramJsonObj.containsKey("endTime")) { + statTimeString = paramJsonObj.getString("statTime"); + endTimeString = paramJsonObj.getString("endTime"); + } + } + + Date statTime = stringTimeToDate(statTimeString, formatter); + Date endTime = stringTimeToDate(endTimeString, formatter); + + for (QuestionMainCategoryEnum enumValue : QuestionMainCategoryEnum.values()) { + String mainCategoryString = enumValue.getMessage(); + try { + processItem(statTime, endTime, mainCategoryString); + } catch (Exception e) { + log.error("处理问题汇总失败: 异常: {}", e.getMessage(), e); + } + } + log.info("处理问题结束 耗时:{}",System.currentTimeMillis()-startTime); + } + + + @Override + public void updateSummery(SummaryQuestionRequestDTO summaryQuestionRequestDTO) { + if (summaryQuestionRequestDTO == null || summaryQuestionRequestDTO.getSummaryReportId() == null || summaryQuestionRequestDTO.getPreliminarySummaryResults() ==null) { + return; + } + tmCorpusQuestionSummaryReportMapper.updateBySummaryReportId(summaryQuestionRequestDTO.getSummaryReportId(), summaryQuestionRequestDTO.getPreliminarySummaryResults().toString()); + } + + private void processItem(Date statTime, Date endTime, String mainCategoryString) { + log.info("用户问题总结处理:mainCategory:{}", mainCategoryString); + + // 获取分析结果信息 + List resultList = tmCorpusQuestionReportMapper.queryQuestionReportList(statTime, endTime, mainCategoryString); + + if (resultList == null || resultList.isEmpty()) { + return; + } + + TmCorpusQuestionSummaryReport summaryReport = new TmCorpusQuestionSummaryReport(); + summaryReport.setMainCategory(mainCategoryString); + summaryReport.setSourceTime(statTime); + String aiAnalysisRequestId = AiAnalysisUtils.getAiAnalysisRequestId(BusinessTypeEnum.SUMMARY_REPORT.getCode()); + summaryReport.setSummaryReportId(aiAnalysisRequestId); + tmCorpusQuestionSummaryReportMapper.insert(summaryReport); + + // 组装语料信息 + StringBuffer demandList = new StringBuffer(); + resultList.forEach(contentItem -> { + if (StringUtils.isNotBlank(contentItem.getUserDemand())) { + demandList.append(contentItem.getUserDemand()).append("\n"); + } + }); + Map inputMap = new HashMap<>(); + inputMap.put("chat", demandList.toString()); + inputMap.put("summaryReportId", aiAnalysisRequestId); + + DiFyReq diFyImageReq = new DiFyReq(); + diFyImageReq.setUser(ConstantStr.corpus_user); + diFyImageReq.setFlowId(reportSummaryToken); + diFyImageReq.setInputs(inputMap); + // 调用dify + JSONObject resultJsonObject = (JSONObject) diFyService.getDiFyObject(diFyImageReq); + log.info("runDify userQuestionSummary difyflow {}", resultJsonObject); + // 保存结果 + if (resultJsonObject != null) { + tmCorpusQuestionSummaryReportMapper.updateBySummaryReportId(aiAnalysisRequestId, resultJsonObject.getString("preliminarySummaryResults")); + } + + } + + /** + * 时间字符串转时间戳秒级 + * @param stringTime + * @param formatter + * @return + */ + private Date stringTimeToDate(String stringTime, DateTimeFormatter formatter) { + if (StringUtils.isBlank(stringTime)) { + return null; + } + LocalDateTime localDateTime = LocalDateTime.parse(stringTime, formatter); + + // 转换为秒级时间戳 + return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); + } + +} \ No newline at end of file diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/utils/ConstantStr.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/utils/ConstantStr.java index 3fcf89d..b5d0f55 100644 --- a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/utils/ConstantStr.java +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/utils/ConstantStr.java @@ -12,6 +12,9 @@ public class ConstantStr { public static final String CHANNEL_DCC = "Channel_Dcc"; public static final String corpus_user = "corpush_user"; + public static final String CORPUS_QUESTION_USER = "corpush_question_user"; + + public static final String CARMODELLIST_CACHEKEY = "ai_carmodellist"; public static final String INTELLIGENT_CUSTOMER_4IN1 = "INTELLIGENT_CUSTOMER_4IN1"; @@ -23,4 +26,4 @@ public class ConstantStr { public static final String aiAnalysisRequestId = "aiAnalysisRequestId"; public static final String DIFY_COUNTERRATELIMIT = "DIFY_COUNTERRATELIMIT"; -} +} \ No newline at end of file diff --git a/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/utils/PublishedTimeFormatter.java b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/utils/PublishedTimeFormatter.java new file mode 100644 index 0000000..397bcab --- /dev/null +++ b/ai-analytic-center-biz/src/main/java/com/volvo/ai/analytic/center/utils/PublishedTimeFormatter.java @@ -0,0 +1,59 @@ +package com.volvo.ai.analytic.center.utils; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; + +@Slf4j +@Component +@SuppressWarnings("squid:S4784") +public class PublishedTimeFormatter { + private static final DateTimeFormatter DATE_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + public static String parsePublishedTime(String publishedTime) { + if (publishedTime == null || publishedTime.isEmpty() || publishedTime.equals("\"\"")) { + return null; // 空值直接返回null或按需处理 + } + + LocalDate now = LocalDate.now(); + + try { + // 处理 "X天前" 格式 + if (publishedTime.endsWith("天前")) { + int daysAgo = Integer.parseInt(publishedTime.replace("天前", "")); + return now.minus(daysAgo, ChronoUnit.DAYS).format(DateTimeFormatter.ISO_DATE); + } + + // 处理 "X月X日" 格式 + if (publishedTime.matches("\\d+月\\d+日")) { + // 提取月份和日期 + int monthStart = 0; + int monthEnd = publishedTime.indexOf("月"); + int dayStart = monthEnd + 1; + int dayEnd = publishedTime.indexOf("日"); + + int monthValue = Integer.parseInt(publishedTime.substring(monthStart, monthEnd)); + int dayValue = Integer.parseInt(publishedTime.substring(dayStart, dayEnd)); + + // 构建当年的 LocalDate 对象 + return LocalDate.of(now.getYear(), monthValue, dayValue) + .format(DateTimeFormatter.ISO_DATE); + } + + // 处理 "2025-05-06 23:00:00" 格式 + if (publishedTime.contains("-")) { + LocalDateTime parsed = LocalDateTime.parse(publishedTime, DATE_TIME_FORMAT); + return parsed.toLocalDate().format(DateTimeFormatter.ISO_DATE); + } + + } catch (Exception e) { + // 可记录异常或忽略错误格式 + log.error("无法解析时间:{} " ,publishedTime); + } + return null; // 未知格式返回null + } +} diff --git a/ai-analytic-center-biz/src/main/resources/mapper/TmClaimVerificationPartHoursMappingMapper.xml b/ai-analytic-center-biz/src/main/resources/mapper/TmClaimVerificationPartHoursMappingMapper.xml new file mode 100644 index 0000000..222df1e --- /dev/null +++ b/ai-analytic-center-biz/src/main/resources/mapper/TmClaimVerificationPartHoursMappingMapper.xml @@ -0,0 +1,18 @@ + + + + + + + \ No newline at end of file diff --git a/ai-analytic-center-biz/src/main/resources/mapper/TmCorpusQuestionReportMapper.xml b/ai-analytic-center-biz/src/main/resources/mapper/TmCorpusQuestionReportMapper.xml new file mode 100644 index 0000000..5955f0f --- /dev/null +++ b/ai-analytic-center-biz/src/main/resources/mapper/TmCorpusQuestionReportMapper.xml @@ -0,0 +1,18 @@ + + + + + + + \ No newline at end of file diff --git a/ai-analytic-center-biz/src/main/resources/mapper/TmCorpusQuestionSummaryReportMapper.xml b/ai-analytic-center-biz/src/main/resources/mapper/TmCorpusQuestionSummaryReportMapper.xml new file mode 100644 index 0000000..94ab11a --- /dev/null +++ b/ai-analytic-center-biz/src/main/resources/mapper/TmCorpusQuestionSummaryReportMapper.xml @@ -0,0 +1,11 @@ + + + + + + update tm_corpus_question_summary_report + set preliminary_summary_results = #{preliminarySummaryResults} + where summary_report_id = #{summaryReportId} + + + \ No newline at end of file diff --git a/ai-analytic-center-biz/src/main/resources/mapper/TmOdsImRealtimeMessageCurMapper.xml b/ai-analytic-center-biz/src/main/resources/mapper/TmOdsImRealtimeMessageCurMapper.xml new file mode 100644 index 0000000..2f8de71 --- /dev/null +++ b/ai-analytic-center-biz/src/main/resources/mapper/TmOdsImRealtimeMessageCurMapper.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/ai-analytic-center-biz/target/classes/mapper/TmClaimVerificationPartHoursMappingMapper.xml b/ai-analytic-center-biz/target/classes/mapper/TmClaimVerificationPartHoursMappingMapper.xml new file mode 100644 index 0000000..222df1e --- /dev/null +++ b/ai-analytic-center-biz/target/classes/mapper/TmClaimVerificationPartHoursMappingMapper.xml @@ -0,0 +1,18 @@ + + + + + + + \ No newline at end of file diff --git a/ai-analytic-center-biz/target/classes/mapper/TmCorpusQuestionReportMapper.xml b/ai-analytic-center-biz/target/classes/mapper/TmCorpusQuestionReportMapper.xml new file mode 100644 index 0000000..5955f0f --- /dev/null +++ b/ai-analytic-center-biz/target/classes/mapper/TmCorpusQuestionReportMapper.xml @@ -0,0 +1,18 @@ + + + + + + + \ No newline at end of file diff --git a/ai-analytic-center-biz/target/classes/mapper/TmCorpusQuestionSummaryReportMapper.xml b/ai-analytic-center-biz/target/classes/mapper/TmCorpusQuestionSummaryReportMapper.xml new file mode 100644 index 0000000..94ab11a --- /dev/null +++ b/ai-analytic-center-biz/target/classes/mapper/TmCorpusQuestionSummaryReportMapper.xml @@ -0,0 +1,11 @@ + + + + + + update tm_corpus_question_summary_report + set preliminary_summary_results = #{preliminarySummaryResults} + where summary_report_id = #{summaryReportId} + + + \ No newline at end of file diff --git a/ai-analytic-center-biz/target/classes/mapper/TmOdsImRealtimeMessageCurMapper.xml b/ai-analytic-center-biz/target/classes/mapper/TmOdsImRealtimeMessageCurMapper.xml new file mode 100644 index 0000000..2f8de71 --- /dev/null +++ b/ai-analytic-center-biz/target/classes/mapper/TmOdsImRealtimeMessageCurMapper.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index a851f07..b5802bd 100644 --- a/pom.xml +++ b/pom.xml @@ -75,17 +75,16 @@ 1.8.0 - com.huaweicloud.sdk huaweicloud-sdk-eg - 3.1.151 + 3.1.36 - + com.huaweicloud.sdk huaweicloud-sdk-core - 3.1.151 + 3.1.36 @@ -256,18 +255,18 @@ ai-analytic-center-api ai-analytic-center-biz - - - - - - - - - - - - - - + + + ronglian-releases + ronglian releases + https://devops.digitalvolvo.com/nexus/repository/newbie-ronglian-maven-releases/ + true + + + ronglian-snapshots + ronglian snapshots + https://devops.digitalvolvo.com/nexus/repository/newbie-ronglian-maven-snapshots/ + true + +