package cc.mrbird.febs.ai.service.impl;
|
|
import cc.mrbird.febs.ai.controller.enumerates.AiTypeEnum;
|
import cc.mrbird.febs.ai.entity.AiMemberTalk;
|
import cc.mrbird.febs.ai.entity.AiMemberTalkItem;
|
import cc.mrbird.febs.ai.entity.AiProductRoleLink;
|
import cc.mrbird.febs.ai.mapper.AiMemberTalkMapper;
|
import cc.mrbird.febs.ai.req.ai.AiMessage;
|
import cc.mrbird.febs.ai.req.ai.AiRequest;
|
import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkAnswerDto;
|
import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkDto;
|
import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkItemPageDto;
|
import cc.mrbird.febs.ai.res.ai.AiResponse;
|
import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkVo;
|
import cc.mrbird.febs.ai.service.AiMemberTalkItemService;
|
import cc.mrbird.febs.ai.service.AiMemberTalkService;
|
import cc.mrbird.febs.ai.service.AiProductRoleLinkService;
|
import cc.mrbird.febs.ai.service.AiService;
|
import cc.mrbird.febs.ai.utils.UUID;
|
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.util.ObjectUtil;
|
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.json.JSONUtil;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import lombok.RequiredArgsConstructor;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.util.Date;
|
import java.util.List;
|
import java.util.function.Consumer;
|
|
/**
|
* AI用户对话训练记录 Service实现类
|
*
|
* @author yourname
|
* @date 2025-07-29
|
*/
|
@Slf4j
|
@Service
|
@RequiredArgsConstructor
|
public class AiMemberTalkServiceImpl extends ServiceImpl<AiMemberTalkMapper, AiMemberTalk> implements AiMemberTalkService {
|
|
private final AiMemberTalkMapper aiMemberTalkMapper;
|
private final AiProductRoleLinkService aiProductRoleLinkService;
|
private final AiMemberTalkItemService aiMemberTalkItemService;
|
private final AiService aiService;
|
|
|
@Override
|
public AiMemberTalk getById(String id) {
|
return aiMemberTalkMapper.selectById( id);
|
}
|
|
@Override
|
@Transactional
|
public FebsResponse start(ApiMemberTalkDto dto) {
|
|
String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid();
|
String productId = dto.getId();
|
|
LambdaQueryWrapper<AiProductRoleLink> productLinkQuery = Wrappers.lambdaQuery(AiProductRoleLink.class);
|
productLinkQuery.eq(AiProductRoleLink::getProductId,productId);
|
productLinkQuery.last("limit 1");
|
AiProductRoleLink aiProductRoleLink = aiProductRoleLinkService.getByQuery(productLinkQuery);
|
if(ObjectUtil.isNull(aiProductRoleLink)){
|
throw new FebsException("产品AI陪练不存在");
|
}
|
|
Date nowTime = new Date();
|
LambdaQueryWrapper<AiMemberTalk> query = Wrappers.lambdaQuery(AiMemberTalk.class);
|
query.eq(AiMemberTalk::getMemberId,memberUuid);
|
query.eq(AiMemberTalk::getProductId,productId);
|
query.last("limit 1");
|
AiMemberTalk aiMemberTalk = this.getByQuery(query);
|
if (ObjectUtil.isNull(aiMemberTalk)){
|
aiMemberTalk = this.add(memberUuid,productId,nowTime);
|
}
|
|
List<AiMessage> aiMessageDtoList = aiMemberTalkItemService.getQuestionUpDownContext(aiMemberTalk.getId(),AiTypeEnum.QUESTION.getCode());
|
|
AiResponse aiResponse = aiService.start(aiMessageDtoList,AiTypeEnum.QUESTION.getCode(),aiProductRoleLink.getProductRoleId(),AiTypeEnum.QUESTION.getName(), null);
|
if(aiResponse.getCode().equals("200")){
|
aiMemberTalkItemService.add(memberUuid,aiMemberTalk.getId(),1,aiResponse.getResContext(),nowTime);
|
this.updateTimeUpdate(nowTime,aiMemberTalk.getId());
|
}else{
|
throw new FebsException(aiResponse.getDescription());
|
}
|
ApiMemberTalkVo apiMemberTalkVo = new ApiMemberTalkVo();
|
apiMemberTalkVo.setMemberTalkId(aiMemberTalk.getId());
|
apiMemberTalkVo.setType(1);
|
apiMemberTalkVo.setContext(aiResponse.getResContext());
|
return new FebsResponse().success().data(apiMemberTalkVo);
|
}
|
|
@Override
|
public void startStream(ApiMemberTalkDto dto, Consumer<AiResponse> callback) {
|
try {
|
String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid();
|
String productId = dto.getId();
|
|
LambdaQueryWrapper<AiProductRoleLink> productLinkQuery = Wrappers.lambdaQuery(AiProductRoleLink.class);
|
productLinkQuery.eq(AiProductRoleLink::getProductId, productId);
|
productLinkQuery.last("limit 1");
|
AiProductRoleLink aiProductRoleLink = aiProductRoleLinkService.getByQuery(productLinkQuery);
|
if (ObjectUtil.isNull(aiProductRoleLink)) {
|
AiResponse aiResponse = new AiResponse();
|
aiResponse.setCode("500");
|
aiResponse.setDescription("产品AI陪练不存在");
|
callback.accept(aiResponse);
|
return;
|
}
|
|
// 构造AI请求
|
AiRequest aiRequest = new AiRequest();
|
aiRequest.setLinkId(aiProductRoleLink.getProductRoleId());
|
aiRequest.setPromptTemplate(aiProductRoleLink.getProductRoleId());
|
aiRequest.setContent("<strong>\"生成题目\"</strong>");
|
|
// 定义AI服务回调处理
|
Consumer<AiResponse> aiCallback = aiResponse -> {
|
Date nowTime = new Date();
|
LambdaQueryWrapper<AiMemberTalk> query = Wrappers.lambdaQuery(AiMemberTalk.class);
|
query.eq(AiMemberTalk::getMemberId, memberUuid);
|
query.eq(AiMemberTalk::getProductId, productId);
|
query.last("limit 1");
|
AiMemberTalk aiMemberTalk = this.getByQuery(query);
|
if (ObjectUtil.isNull(aiMemberTalk)) {
|
aiMemberTalk = this.add(memberUuid, productId, nowTime);
|
}
|
try {
|
if (aiResponse.getCode().equals("200")) {
|
// 如果是最终结果(包含报告)
|
if (aiResponse.getReport() != null) {
|
// 保存完整响应到数据库
|
aiMemberTalkItemService.add(memberUuid, aiMemberTalk.getId(), 1, aiResponse.getResContext(), nowTime);
|
this.updateTimeUpdate(nowTime, aiMemberTalk.getId());
|
|
callback.accept(aiResponse);
|
} else {
|
// 流式响应片段
|
callback.accept(aiResponse);
|
}
|
} else {
|
callback.accept(aiResponse);
|
}
|
} catch (Exception e) {
|
log.error("处理AI响应异常", e);
|
callback.accept(aiResponse);
|
}
|
};
|
|
// 调用AI服务的流式接口
|
aiService.streamQuestion(aiRequest, aiCallback);
|
|
} catch (Exception e) {
|
log.error("流式调用start方法异常", e);
|
|
AiResponse aiResponse = new AiResponse();
|
aiResponse.setCode("500");
|
aiResponse.setDescription("流式调用start方法异常");
|
callback.accept(aiResponse);
|
}
|
}
|
|
@Override
|
public AiMemberTalk getByQuery(LambdaQueryWrapper<AiMemberTalk> query) {
|
return aiMemberTalkMapper.selectOne( query);
|
}
|
|
@Override
|
public void updateTimeUpdate(Date nowTime, String id) {
|
aiMemberTalkMapper.update(
|
null,
|
Wrappers.lambdaUpdate(AiMemberTalk.class)
|
.set(AiMemberTalk::getUpdatedTime,nowTime)
|
.eq(AiMemberTalk::getId,id));
|
}
|
|
|
public static final String ANSWER_FORMAT = "###题目:{}###用户回答:{}";
|
@Override
|
@Transactional
|
public FebsResponse answer(ApiMemberTalkAnswerDto dto) {
|
String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid();
|
String memberTalkId = dto.getId();
|
AiMemberTalk aiMemberTalk = this.getById(memberTalkId);
|
if (ObjectUtil.isNull(aiMemberTalk)){
|
throw new FebsException("产品AI陪练对话不存在");
|
}
|
|
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 reqContext = dto.getReqContext();
|
|
LambdaQueryWrapper<AiMemberTalkItem> memberTalkItemQuery = Wrappers.lambdaQuery(AiMemberTalkItem.class);
|
memberTalkItemQuery.eq(AiMemberTalkItem::getMemberId,memberUuid);
|
memberTalkItemQuery.eq(AiMemberTalkItem::getMemberTalkId,memberTalkId);
|
memberTalkItemQuery.eq(AiMemberTalkItem::getType,1);
|
memberTalkItemQuery.orderByDesc(AiMemberTalkItem::getCreatedTime);
|
memberTalkItemQuery.last("limit 1");
|
AiMemberTalkItem aiMemberTalkItem = aiMemberTalkItemService.getByQuery(memberTalkItemQuery);
|
aiMemberTalkItemService.add(memberUuid,aiMemberTalk.getId(),2,reqContext,new Date());
|
|
String format = StrUtil.format(ANSWER_FORMAT, aiMemberTalkItem.getContext(), reqContext);
|
log.info("format:{}",format);
|
// AiResponse aiResponse = aiService.start(aiProductRoleLink.getProductRoleId(), format);
|
|
|
List<AiMessage> aiMessageDtoList = aiMemberTalkItemService.getQuestionUpDownContext(aiMemberTalk.getId(),AiTypeEnum.ANSWER.getCode());
|
AiResponse aiResponse = aiService.start(aiMessageDtoList,AiTypeEnum.ANSWER.getCode(),aiProductRoleLink.getProductRoleId(), reqContext,aiMemberTalkItem.getContext());
|
String context = null;
|
if(aiResponse.getCode().equals("200")){
|
Date nowTime = new Date();
|
context = String.valueOf(JSONUtil.parse(aiResponse.getReport()));
|
if ("null".equals( context)){
|
context = aiResponse.getResContext();
|
}
|
aiMemberTalkItemService.add(memberUuid,aiMemberTalk.getId(),3, context,nowTime);
|
this.updateTimeUpdate(nowTime,aiMemberTalk.getId());
|
}else{
|
throw new FebsException(aiResponse.getDescription());
|
}
|
ApiMemberTalkVo apiMemberTalkVo = new ApiMemberTalkVo();
|
apiMemberTalkVo.setMemberTalkId(aiMemberTalk.getId());
|
apiMemberTalkVo.setType(3);
|
apiMemberTalkVo.setContext(context);
|
return new FebsResponse().success().data(apiMemberTalkVo);
|
}
|
@Override
|
public AiMemberTalk add(String memberUuid, String productId, Date nowTime) {
|
AiMemberTalk aiMemberTalk = new AiMemberTalk();
|
aiMemberTalk.setId(UUID.getSimpleUUIDString());
|
aiMemberTalk.setCreatedTime(nowTime);
|
aiMemberTalk.setMemberId(memberUuid);
|
aiMemberTalk.setProductId(productId);
|
aiMemberTalkMapper.insert(aiMemberTalk);
|
return aiMemberTalk;
|
}
|
|
@Override
|
public FebsResponse historyPage(ApiMemberTalkItemPageDto dto) {
|
|
String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid();
|
dto.setMemberUuid(memberUuid);
|
return aiMemberTalkItemService.historyPage(dto);
|
}
|
}
|