From e2cd97ab844ef42829ab326d8bacceb2933cdc3f Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Tue, 21 Oct 2025 15:28:13 +0800
Subject: [PATCH] fix(ai):修复会员答题记录创建时间字段错误 - 将会员答题记录的创建时间字段从createdTime更正为updatedTim - 确保答题记录时间戳反映最新更新时间而非初始创建时间
---
src/main/java/cc/mrbird/febs/ai/service/impl/AiMemberTalkStreamServiceImpl.java | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 217 insertions(+), 17 deletions(-)
diff --git a/src/main/java/cc/mrbird/febs/ai/service/impl/AiMemberTalkStreamServiceImpl.java b/src/main/java/cc/mrbird/febs/ai/service/impl/AiMemberTalkStreamServiceImpl.java
index 00411bc..779cc73 100644
--- a/src/main/java/cc/mrbird/febs/ai/service/impl/AiMemberTalkStreamServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/ai/service/impl/AiMemberTalkStreamServiceImpl.java
@@ -5,16 +5,24 @@
import cc.mrbird.febs.ai.enumerates.AiTypeEnum;
import cc.mrbird.febs.ai.mapper.AiMemberTalkMapper;
import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkItemPageDto;
+import cc.mrbird.febs.ai.req.memberTalk.ApiTalkMemberListDto;
+import cc.mrbird.febs.ai.req.memberTalk.ApiTalkReportListDto;
import cc.mrbird.febs.ai.req.memberTalkStream.*;
+import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkListDto;
+import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkMemberAnswerSavaVo;
+import cc.mrbird.febs.ai.res.memberTalk.ApiTalkReportListVo;
import cc.mrbird.febs.ai.res.memberTalkStream.ApiMemberTalkReloadStreamVo;
import cc.mrbird.febs.ai.res.memberTalkStream.ApiMemberTalkStreamVo;
+import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkListVo;
import cc.mrbird.febs.ai.service.*;
import cc.mrbird.febs.ai.strategy.LlmStrategyFactory;
+import cc.mrbird.febs.ai.strategy.enumerates.LlmApplicationAppIdEnum;
import cc.mrbird.febs.ai.strategy.enumerates.LlmStrategyEnum;
import cc.mrbird.febs.ai.strategy.param.LlmStrategyDto;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.exception.FebsException;
import cc.mrbird.febs.common.utils.LoginUserUtil;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
@@ -25,12 +33,10 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
+import java.util.*;
/**
* AI用户对话训练记录 Service实现类
@@ -44,6 +50,7 @@
public class AiMemberTalkStreamServiceImpl extends ServiceImpl<AiMemberTalkMapper, AiMemberTalk> implements AiMemberTalkStreamService {
private final AiMemberTalkMapper aiMemberTalkMapper;
+ private final AiProductService aiProductService;
private final AiProductRoleLinkService aiProductRoleLinkService;
private final AiProductRoleService aiProductRoleService;
private final AiMemberTalkService aiMemberTalkService;
@@ -51,9 +58,11 @@
private final AiProductQuestionService aiProductQuestionService;
private final LlmStrategyFactory llmStrategyFactory;
private final AiService aiService;
+ private final AiCompanyWorkflowService aiCompanyWorkflowService;
@Override
+ @Transactional
public FebsResponse start(ApiMemberTalkStreamDto dto) {
String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid();
@@ -66,16 +75,21 @@
throw new FebsException("产品AI陪练不存在");
}
+ AiProduct aiProduct = aiProductService.getById(productId);
+ Integer questionCount = aiProduct.getQuestionCount();
+
String companyId = aiProductRoleLink.getCompanyId();
Date nowTime = new Date();
LambdaQueryWrapper<AiMemberTalk> query = Wrappers.lambdaQuery(AiMemberTalk.class);
query.eq(AiMemberTalk::getMemberId,memberUuid);
query.eq(AiMemberTalk::getProductId,productId);
+ query.eq(AiMemberTalk::getState,AiTypeEnum.AI_MEMBER_TALK_STATE_ING.getCode());
+ query.orderByDesc(AiMemberTalk::getCreatedTime);
query.last("limit 1");
AiMemberTalk aiMemberTalk = aiMemberTalkService.getByQuery(query);
if (ObjectUtil.isNull(aiMemberTalk)){
- aiMemberTalk = aiMemberTalkService.add(memberUuid,companyId,productId,nowTime);
+ aiMemberTalk = aiMemberTalkService.add(memberUuid,companyId,productId,nowTime,questionCount);
}
ApiMemberTalkStreamVo apiMemberTalkVo = new ApiMemberTalkStreamVo();
@@ -90,8 +104,64 @@
apiMemberTalkVo.setMemberTalkId(aiMemberTalk.getId());
apiMemberTalkVo.setType(1);
apiMemberTalkVo.setContext(title);
+ apiMemberTalkVo.setQuestionCnt(aiMemberTalk.getQuestionCnt());
+ apiMemberTalkVo.setDoneCnt(aiMemberTalk.getDoneCnt() + 1);
return new FebsResponse().success().data(apiMemberTalkVo);
}
+
+ @Override
+ public FebsResponse talkList(ApiMemberTalkListDto dto) {
+
+ return new FebsResponse().success().data(aiMemberTalkService.getPageByDto(dto));
+ }
+
+ @Override
+ public FebsResponse talkMemberList(ApiTalkMemberListDto dto) {
+
+ return new FebsResponse().success().data(aiMemberTalkItemService.getPageByDto(dto));
+ }
+
+ @Override
+ public Flux<FebsResponse> talkReportList(ApiTalkReportListDto dto) {
+ String memberTalkId = dto.getMemberTalkId();
+ AiMemberTalk byId = aiMemberTalkService.getById(memberTalkId);
+ String analysis = byId.getAnalysis();
+
+ if (StrUtil.isEmpty(analysis)) {
+ return Flux.just(new FebsResponse().success().data(""));
+ }
+
+ // 将分析报告分块,每块100个字符
+ return Flux.generate(
+ () -> 0, // 初始状态
+ (index, sink) -> {
+ int endIndex = Math.min(index + 100, analysis.length());
+ String chunk = analysis.substring(index, endIndex);
+
+ Map<String, Object> responseData = new HashMap<>();
+ responseData.put("chunk", chunk);
+ responseData.put("isLast", endIndex >= analysis.length());
+ responseData.put("progress", Math.min(100, (endIndex * 100) / analysis.length()));
+
+ sink.next(new FebsResponse().success().data(responseData));
+
+ if (endIndex >= analysis.length()) {
+ sink.complete();
+ return index; // 结束状态
+ }
+
+ return endIndex; // 下一次的起始索引
+ }
+ );
+ }
+
+ @Override
+ public FebsResponse talkReportListV2(ApiTalkReportListDto dto) {
+ String memberTalkId = dto.getMemberTalkId();
+ AiMemberTalk byId = aiMemberTalkService.getById(memberTalkId);
+ return new FebsResponse().success().data(byId.getAnalysis());
+ }
+
@Override
public FebsResponse reload(ApiMemberTalkReloadStreamDto dto) {
@@ -104,7 +174,7 @@
queryWrapper.eq(AiMemberTalkItem::getType,AiTypeEnum.QUESTION_ANSWER.getCode());
queryWrapper.orderByDesc(AiMemberTalkItem::getCreatedTime);
queryWrapper.last("limit 1");
- AiMemberTalkItem byQuery = aiMemberTalkItemService.getByQuery(queryWrapper);
+ AiMemberTalkItem byQuery = aiMemberTalkItemService.getOneByQuery(queryWrapper);
if (ObjectUtil.isNotNull(byQuery)){
apiMemberTalkReloadVo.setContext(byQuery.getContext());
apiMemberTalkReloadVo.setMemberTalkId(memberTalkId);
@@ -121,6 +191,7 @@
}
@Override
+ @Transactional
public FebsResponse saveMemberAnswer(ApiMemberTalkMemberAnswerSavaDto dto) {
String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid();
String memberTalkId = dto.getMemberTalkId();
@@ -130,11 +201,21 @@
if (ObjectUtil.isNull(aiMemberTalk)){
throw new FebsException("对话不存在");
}
- this.updateMemberTalkUpdateTime(aiMemberTalk.getId(), new Date());
+ int doneCnt = aiMemberTalk.getDoneCnt() + 1;
+ Integer state = aiMemberTalk.getState();
+ Integer questionCnt = aiMemberTalk.getQuestionCnt();
+ if (doneCnt >= questionCnt){
+ state = AiTypeEnum.AI_MEMBER_TALK_STATE_DONE.getCode();
+ }
+ this.updateMemberTalkUpdateTime(state,doneCnt,aiMemberTalk.getId(), new Date());
String companyId = aiMemberTalk.getCompanyId();
aiMemberTalkItemService.add(memberUuid,aiMemberTalk.getId(),companyId,2,content,new Date());
- return new FebsResponse().success();
+
+ ApiMemberTalkMemberAnswerSavaVo apiMemberTalkMemberAnswerSavaVo = new ApiMemberTalkMemberAnswerSavaVo();
+ apiMemberTalkMemberAnswerSavaVo.setQuestionCnt(questionCnt);
+ apiMemberTalkMemberAnswerSavaVo.setDoneCnt(doneCnt);
+ return new FebsResponse().success().data(apiMemberTalkMemberAnswerSavaVo);
}
@Override
@@ -169,7 +250,7 @@
memberTalkItemQuery.eq(AiMemberTalkItem::getType,1);
memberTalkItemQuery.orderByDesc(AiMemberTalkItem::getCreatedTime);
memberTalkItemQuery.last("limit 1");
- AiMemberTalkItem aiMemberTalkItem = aiMemberTalkItemService.getByQuery(memberTalkItemQuery);
+ AiMemberTalkItem aiMemberTalkItem = aiMemberTalkItemService.getOneByQuery(memberTalkItemQuery);
String question = aiMemberTalkItem.getContext();
String prompt = this.buildPrompt(question,reqContext,aiProductRole.getPromptHead(), aiProductRole.getPromptTemplate(), type);
@@ -194,6 +275,7 @@
String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid();
Integer type = dto.getType();
String memberTalkId = dto.getId();
+ Integer state = ObjectUtil.defaultIfNull(dto.getState(),0);
AiMemberTalk aiMemberTalk = this.getById(memberTalkId);
if (ObjectUtil.isNull(aiMemberTalk)){
throw new FebsException("对话不存在");
@@ -218,7 +300,7 @@
memberTalkItemQuery.eq(AiMemberTalkItem::getType,1);
memberTalkItemQuery.orderByDesc(AiMemberTalkItem::getCreatedTime);
memberTalkItemQuery.last("limit 1");
- AiMemberTalkItem aiMemberTalkItem = aiMemberTalkItemService.getByQuery(memberTalkItemQuery);
+ AiMemberTalkItem aiMemberTalkItem = aiMemberTalkItemService.getOneByQuery(memberTalkItemQuery);
String question = aiMemberTalkItem.getContext();
String promptHead = aiProductRole.getPromptHead();
@@ -231,11 +313,48 @@
llmStrategyDtoList.add(llmStrategyDto);
llmStrategyDto = this.buildLlmStrategyDtoList(answer, 2);
llmStrategyDtoList.add(llmStrategyDto);
- llmStrategyDto = this.buildLlmStrategyDtoList(String.valueOf(type), 4);
- llmStrategyDtoList.add(llmStrategyDto);
- String modelName = LlmStrategyEnum.getName(aiService.getSystemSetAiType());
+ AiCompanyWorkflow aiCompanyWorkflow = aiCompanyWorkflowService.getByTypeAndCompanyId(type,aiMemberTalk.getCompanyId());
+ if (ObjectUtil.isNull(aiCompanyWorkflow)){
+ throw new FebsException("工作流配置异常,请联系管理员");
+ }
+ llmStrategyDto = this.buildLlmStrategyDtoList(aiCompanyWorkflow.getCode(), 4);
+ llmStrategyDtoList.add(llmStrategyDto);
+
+ String modelName = LlmStrategyEnum.getName(aiService.getSystemSetAiType());
return llmStrategyFactory.getCalculationStrategyMap().get(modelName).llmInvokeStreamingNoThink(llmStrategyDtoList);
+ }
+
+ private LlmStrategyDto buildMessages(String memberTalkId) {
+
+ LlmStrategyDto message = new LlmStrategyDto();
+ LambdaQueryWrapper<AiMemberTalkItem> memberTalkItemQuery = Wrappers.lambdaQuery(AiMemberTalkItem.class);
+ memberTalkItemQuery.eq(AiMemberTalkItem::getMemberTalkId,memberTalkId);
+ memberTalkItemQuery.in(AiMemberTalkItem::getType,Arrays.asList(1, 2));
+ memberTalkItemQuery.orderByAsc(AiMemberTalkItem::getCreatedTime);
+ List<AiMemberTalkItem> aiMemberTalkItems = aiMemberTalkItemService.getListByQuery(memberTalkItemQuery);
+ if (CollUtil.isEmpty(aiMemberTalkItems)){
+ return message;
+ }
+
+ List<LlmStrategyDto> messages = new ArrayList<>();
+ for (AiMemberTalkItem aiMemberTalkItem : aiMemberTalkItems){
+ LlmStrategyDto llmStrategyDto = new LlmStrategyDto();
+ if (aiMemberTalkItem.getType() == 1){
+ llmStrategyDto.setRole(Role.ASSISTANT.getValue());
+ }
+ if (aiMemberTalkItem.getType() == 2){
+ llmStrategyDto.setRole(Role.USER.getValue());
+ }
+ llmStrategyDto.setContent(aiMemberTalkItem.getContext());
+ messages.add(llmStrategyDto);
+ }
+
+ message.setRole(AiTypeEnum.MESSAGES.getName());
+ message.setContent(AiTypeEnum.MESSAGES.getName());
+ message.setMessages(messages);
+
+ return message;
}
private String buildPrompt(String question,String answer,String promptHead, String promptTemplate,Integer type){
@@ -280,7 +399,7 @@
throw new FebsException("对话不存在");
}
- this.updateMemberTalkUpdateTime(aiMemberTalk.getId(), new Date());
+ this.updateMemberTalkUpdateTime(aiMemberTalk.getState(),aiMemberTalk.getDoneCnt(),aiMemberTalk.getId(), new Date());
String companyId = aiMemberTalk.getCompanyId();
Integer type = dto.getType();
@@ -312,12 +431,93 @@
}
@Override
- public void updateMemberTalkUpdateTime(String memberTalkId, Date updateTime) {
+ public void updateMemberTalkUpdateTime(Integer state,Integer doneCnt,String memberTalkId, Date updateTime) {
aiMemberTalkMapper.update(null,
Wrappers.lambdaUpdate(AiMemberTalk.class)
- .set(AiMemberTalk::getUpdatedTime,updateTime)
- .eq(AiMemberTalk::getId,memberTalkId)
+ .set(AiMemberTalk::getUpdatedTime,updateTime)
+ .set(AiMemberTalk::getDoneCnt,doneCnt)
+ .set(AiMemberTalk::getState,state)
+ .eq(AiMemberTalk::getId,memberTalkId)
);
}
+ @Override
+ public FebsResponse saveReport(ApiMemberTalkReportSavaDto dto) {
+ String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid();
+ String memberTalkId = dto.getMemberTalkId();
+ String content = dto.getContent();
+
+ AiMemberTalk aiMemberTalk = this.getById(memberTalkId);
+ if (ObjectUtil.isNull(aiMemberTalk)){
+ throw new FebsException("对话不存在");
+ }
+
+ this.updateMemberTalkUpdateTime(AiTypeEnum.AI_MEMBER_TALK_STATE_DONE.getCode(), aiMemberTalk.getDoneCnt(),aiMemberTalk.getId(), new Date());
+
+// Integer type = dto.getType();
+// String contentByCode = AiTalkOutputEnum.HIGH_LIGHT.getCodeByType(type);
+// String analysis = aiMemberTalk.getAnalysis();
+// HashMap<String, String> stringStringHashMap = new HashMap<>();
+// if(StrUtil.isEmpty(analysis)){
+// stringStringHashMap.put(contentByCode,content);
+// }else{
+// stringStringHashMap = JSONUtil.toBean(analysis, HashMap.class);
+// stringStringHashMap.put(contentByCode,content);
+// }
+
+ aiMemberTalkMapper.update(
+ null,
+ Wrappers.lambdaUpdate(AiMemberTalk.class)
+ .set(AiMemberTalk::getAnalysis,content)
+ .eq(AiMemberTalk::getId,aiMemberTalk.getId())
+ );
+
+ return new FebsResponse().success();
+ }
+
+ @Override
+ public Flux<FebsResponse> answerV3(AiTalkAnswerStreamDto dto) {
+ String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid();
+ String memberTalkId = dto.getId();
+ AiMemberTalk aiMemberTalk = this.getById(memberTalkId);
+ if (ObjectUtil.isNull(aiMemberTalk)){
+ throw new FebsException("对话不存在");
+ }
+
+ LambdaQueryWrapper<AiProductRoleLink> productLinkQuery = Wrappers.lambdaQuery(AiProductRoleLink.class);
+ productLinkQuery.eq(AiProductRoleLink::getProductId,aiMemberTalk.getProductId());
+ productLinkQuery.last("limit 1");
+ AiProductRoleLink aiProductRoleLink = aiProductRoleLinkService.getByQuery(productLinkQuery);
+ if(ObjectUtil.isNull(aiProductRoleLink)){
+ throw new FebsException("产品没有关联AI陪练");
+ }
+
+ String productRoleId = aiProductRoleLink.getProductRoleId();
+ AiProductRole aiProductRole = aiProductRoleService.getById(productRoleId);
+ if (ObjectUtil.isNull(aiProductRole)){
+ throw new FebsException("产品AI陪练不存在");
+ }
+
+ String promptHead = aiProductRole.getPromptHead();
+
+ List<LlmStrategyDto> llmStrategyDtoList = new ArrayList<>();
+ LlmStrategyDto llmStrategyDto = this.buildLlmStrategyDtoList(promptHead, 1);
+ llmStrategyDtoList.add(llmStrategyDto);
+ llmStrategyDto = this.buildLlmStrategyDtoList("请按照要求生成报告", 2);
+ llmStrategyDtoList.add(llmStrategyDto);
+
+ AiCompanyWorkflow aiCompanyWorkflow = aiCompanyWorkflowService.getByTypeAndCompanyId(LlmApplicationAppIdEnum.REPORT.getCode(),aiMemberTalk.getCompanyId());
+ if (ObjectUtil.isNull(aiCompanyWorkflow)){
+ throw new FebsException("工作流配置异常,请联系管理员");
+ }
+ llmStrategyDto = this.buildLlmStrategyDtoList(aiCompanyWorkflow.getCode(), 4);
+ llmStrategyDtoList.add(llmStrategyDto);
+
+ LlmStrategyDto llmStrategyDtoMessage = buildMessages(memberTalkId);
+ llmStrategyDtoList.add(llmStrategyDtoMessage);
+ String modelName = LlmStrategyEnum.getName(aiService.getSystemSetAiType());
+
+ return llmStrategyFactory.getCalculationStrategyMap().get(modelName).llmInvokeStreamingNoThink(llmStrategyDtoList);
+ }
+
}
--
Gitblit v1.9.1