main
liu 10 months ago
parent 71494928f8
commit 3245906812

@ -1,17 +1,25 @@
package com.supervision.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.supervision.dto.roundAsk.SessionParamDTO;
import com.supervision.exception.BusinessException;
import com.supervision.service.AskService;
import com.supervision.vo.*;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static com.supervision.service.impl.AskServiceImpl.SESSION_PARAM;
@Slf4j
@RestController
@RequestMapping("ask")
@ -20,13 +28,26 @@ public class AskController {
private final AskService askService;
private final RedisTemplate<String, Object> redisTemplate;
@ApiOperation("多轮对话")
@PostMapping("roundTalk")
public RoundTalkResVO roundTalk(@RequestBody RoundTalkReqVO roundTalkReqVO) {
if (StrUtil.isBlank(roundTalkReqVO.getSessionId())) {
throw new BusinessException("会话ID不能为空");
}
return askService.roundTalk(roundTalkReqVO);
try {
return askService.roundTalk(roundTalkReqVO);
} catch (Exception e) {
log.info("多轮对话过程中出现了异常,则说明多轮对话走不通,那么就根据sessionId获取Redis中的原始问题,直接走单轮对话");
// 如果多轮对话过程中出现了异常,则说明多轮对话走不通,那么就根据sessionId获取Redis中的原始问题,直接走单轮对话
Object cache = redisTemplate.opsForValue().get(SESSION_PARAM + roundTalkReqVO.getSessionId());
SessionParamDTO sessionParamDTO = BeanUtil.toBean(cache, SessionParamDTO.class);
SingleTalkResVO singleTalkResVO = askService.singleTalk(SingleTalkReqVO.builder().userTalk(sessionParamDTO.getOriginalQuestion()).build());
return RoundTalkResVO.builder().sessionId(roundTalkReqVO.getSessionId())
.answerText(singleTalkResVO.getAnswerText()).build();
}
}
@ApiOperation("单轮对话")

@ -17,50 +17,22 @@ import java.util.Map;
public class AnswerQuestionHandler {
public String answerQuestion(String question, List<String> detailList, Map<String, String> talkRecord) {
List<MessageDTO> messageList = new ArrayList<>();
messageList.add(new MessageDTO("system", "现在你是一个政务事项领域的问答大模型.\n" +
"现在有一个问题,根据这个问题我查到了政策内容,并提供了用户问询过程中的对话记录,可供参考;\n" +
"请你严格根据政策内容回答这个问题,请不要有文件内容之外的内容"));
messageList.add(new MessageDTO("assistant", "好的"));
messageList.add(new MessageDTO("user", StrUtil.format("政务文件内容:[{}]", CollUtil.join(detailList, ";"))));
messageList.add(new MessageDTO("assistant", "继续"));
messageList.add(new MessageDTO("user", StrUtil.format("问题:{}", question)));
messageList.add(new MessageDTO("assistant", "继续"));
if (CollUtil.isNotEmpty(talkRecord)) {
List<String> record = new ArrayList<>();
for (Map.Entry<String, String> entry : talkRecord.entrySet()) {
record.add("询问用户:" + entry.getKey());
record.add("用户回答:" + entry.getValue());
}
messageList.add(new MessageDTO("user", "下面是用户回答过程中的对话记录,可供参考,并提供更精确的回答:{" + CollUtil.join(record, ";") + "}"));
messageList.add(new MessageDTO("assistant", "继续"));
String template = "作为AI助手你的任务是帮助用户查找和理解特定政务的政策内容并给于用户答案。在这个场景中你将使用政策内容来回答用户问题{}。请根据政策内容\n" +
"\"\"\"{}\"\"\"\n" +
"同时,有一个和用户的问答过程的记录供你参考以提供更精确的回答,内容是:" +
"\"\"\"{}\"\"\"\n" +
"请用不超过 100 个词的长度准确和详细的回答用户的问题。";
String askRecordTemplate = "问:{}\n 用户答:{};\n";
StringBuilder askRecord = new StringBuilder();
for (Map.Entry<String, String> entry : talkRecord.entrySet()) {
askRecord.append(StrUtil.format(askRecordTemplate, entry.getKey(), entry.getValue()));
}
messageList.add(new MessageDTO("user", StrUtil.format("现在你可以回答了,如果你从文件内容中,没有提取到回答,你就回复:我暂时还不会这个问题哦!")));
log.info("answerQuestion的prompt是:{}", JSONUtil.toJsonStr(messageList));
String answer = AiUtil.chatByMessage(messageList);
log.info("answerQuestion的答案是:{}", answer);
return answer;
}
/**
*
*
* @return
*/
public String answerSingleQuestion(String question, Map<String, List<String>> detailMap) {
List<MessageDTO> messageList = new ArrayList<>();
messageList.add(new MessageDTO("system", "现在你是一个政务事项领域的问答大模型.\n" +
"现在有一个问题,根据这个问题我查到了一些政策内容\n" +
"请你对该政策内容进行解读后,将这个问题进行回答.但是注意不要有文件内容之外的政策内容解读"));
messageList.add(new MessageDTO("assistant", "好的"));
messageList.add(new MessageDTO("user", StrUtil.format("政务文件内容:[{}]", JSONUtil.toJsonStr(detailMap))));
messageList.add(new MessageDTO("assistant", "继续"));
messageList.add(new MessageDTO("user", StrUtil.format("问题:{}", question)));
messageList.add(new MessageDTO("assistant", "继续"));
messageList.add(new MessageDTO("user", StrUtil.format("现在你可以回答了,请用100字以内进行回答.如果你从文件内容中,没有提取到回答,你就回复:我暂时还不会这个问题哦!")));
log.info("answerQuestion的prompt是:{}", JSONUtil.toJsonStr(messageList));
messageList.add(new MessageDTO("user", StrUtil.format(template, question, JSONUtil.toJsonStr(detailList), askRecord.toString())));
log.info("多轮问答answerQuestion的prompt是:{}", JSONUtil.toJsonStr(messageList));
String answer = AiUtil.chatByMessage(messageList);
log.info("answerQuestion的答案是:{}", answer);
log.info("多轮问答answerQuestion的答案是:{}", answer);
return answer;
}
@ -74,9 +46,9 @@ public class AnswerQuestionHandler {
List<MessageDTO> messageList = new ArrayList<>();
messageList.add(new MessageDTO("user", StrUtil.format(template, question, JSONUtil.toJsonStr(detailMap))));
log.info("answerQuestion的prompt是:{}", JSONUtil.toJsonStr(messageList));
log.info("单轮问答answerQuestion的prompt是:{}", JSONUtil.toJsonStr(messageList));
String answer = AiUtil.chatByMessage(messageList);
log.info("answerQuestion的答案是:{}", answer);
log.info("单轮问答answerQuestion的答案是:{}", answer);
return answer;
}
}

@ -55,9 +55,9 @@ public class AskServiceImpl implements AskService {
private final AnswerQuestionHandler answerQuestionHandler;
private static final String SESSION_PARAM = "KBQA:ASK:SESSION_PARAM:";
public static final String SESSION_PARAM = "KBQA:ASK:SESSION_PARAM:";
private static final String USER_PARAM = "KBQA:ASK:USER_ROLE:";
public static final String USER_PARAM = "KBQA:ASK:USER_ROLE:";
/**
@ -91,13 +91,13 @@ public class AskServiceImpl implements AskService {
// 识别出来意图之后,再去判断是否识别过实体
if (CollUtil.isEmpty(sessionParamDTO.getEntityValueByExtract())) {
// 识别实体(先从图中获取所有的节点名称,然后识别)
// List<String> allItemNode = findItemNodeHandler.findAllItemNode();
//List<String> extractValue = itemExtractHandler.itemExtractByPossibleItem(sessionParamDTO.getOriginalQuestion(), allItemNode);
List<String> allItemNode = findItemNodeHandler.findAllItemNode();
List<String> extractValue = itemExtractHandler.itemExtractByPossibleItemWithExample(sessionParamDTO.getOriginalQuestion(), allItemNode);
// 识别问题中,用户可能问的业务是什么
String extractValue = itemExtractHandler.itemExtractBusiness(sessionParamDTO.getOriginalQuestion());
sessionParamDTO.setEntityValueByExtract(Collections.singletonList(extractValue));
// String extractValue = itemExtractHandler.itemExtractBusiness(sessionParamDTO.getOriginalQuestion());
sessionParamDTO.setEntityValueByExtract(extractValue);
// 根据提取的内容,开始在知识图谱中寻找节点(首先找叶子节点,如果叶子节点有数据,直接返回,如果叶子节点没数据,再去找分支节点)
List<ItemLeaf> allMatchLeafNode = findItemNodeHandler.findAllMatchLeafNode(Collections.singletonList(extractValue));
List<ItemLeaf> allMatchLeafNode = findItemNodeHandler.findAllMatchLeafNode(extractValue);
// 如果找到的节点只有1个,那么说明问的就是这个节点,那么直接缓存起来进行下一步
if (allMatchLeafNode.size() == 1) {
ItemLeaf itemLeaf = allMatchLeafNode.get(0);
@ -194,12 +194,12 @@ public class AskServiceImpl implements AskService {
// 根据意图和节点,找到对应的结果
List<String> itemDetail = findItemDetailHandler.findItemDetail(matchItemLeaf.getVid(), intentEnum.getTagType(), intentEnum.getEdgeType());
if (CollUtil.isEmpty(itemDetail)) {
return RoundTalkResVO.builder().sessionId(sessionParamDTO.getSessionId()).answerText("暂时还不会回答这个问题哦").build();
throw new BusinessException("未找到意图,暂不支持回答");
}
// 提交GPT,问问题的答案
String answer = answerQuestionHandler.answerQuestion(sessionParamDTO.getOriginalQuestion(), itemDetail, sessionParamDTO.getTalkRecord());
if (StrUtil.isBlank(answer)) {
return RoundTalkResVO.builder().sessionId(sessionParamDTO.getSessionId()).answerText("暂时还不会回答这个问题哦!").build();
throw new BusinessException("未找到答案,暂不支持回答");
}
// 清空问话实体
sessionParamDTO.setCurrentEntity(null);

@ -1,8 +1,10 @@
package com.supervision.vo;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class SingleTalkReqVO {

Loading…
Cancel
Save