代码提交

main
liu 10 months ago
parent 304bb50f89
commit 2de5a9dea2

@ -41,7 +41,7 @@ public class AskController {
// 如果多轮对话过程中出现了异常,则说明多轮对话走不通,那么就根据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());
SingleTalkResVO singleTalkResVO = askService.singleTalk(SingleTalkReqVO.builder().userTalk(roundTalkReqVO.getUserTalk()).build());
return RoundTalkResVO.builder().sessionId(roundTalkReqVO.getSessionId())
.answerText(singleTalkResVO.getAnswerText()).build();
}

@ -21,7 +21,7 @@ public class AnswerQuestionHandler {
"\"\"\"{}\"\"\"\n" +
"同时,有一个和用户的问答过程的记录供你参考以提供更精确的回答,内容是:" +
"\"\"\"{}\"\"\"\n" +
"请用不超过 100 个词的长度准确和详细的回答用户的问题。请直接给我最终答案,不要反问";
"请用不超过 100 个词的长度准确和详细的回答用户的问题。回答一定要忠于原文,简洁但不丢信息,不要胡乱编造。请直接给我最终答案,不要反问";
String askRecordTemplate = "问:{}\n 用户答:{};\n";
StringBuilder askRecord = new StringBuilder();
for (Map.Entry<String, String> entry : talkRecord.entrySet()) {
@ -42,7 +42,7 @@ public class AnswerQuestionHandler {
public String answerSingleQuestionNew(String question, Map<String, List<String>> detailMap) {
String template = "作为AI助手你的任务是帮助用户查找和理解特定政务的政策内容并给于用户答案。在这个场景中你将使用政策内容来回答用户问题{}。请根据政策内容\n" +
"\"\"\"{}\"\"\"\n" +
"并用不超过 100 个词的长度准确和详细的回答用户的问题。请直接给我最终答案,不要反问";
"并用不超过 100 个词的长度准确和详细的回答用户的问题。回答一定要忠于原文,简洁但不丢信息,不要胡乱编造。请直接给我最终答案,不要反问";
List<MessageDTO> messageList = new ArrayList<>();
messageList.add(new MessageDTO("user", StrUtil.format(template, question, JSONUtil.toJsonStr(detailMap))));

@ -33,10 +33,10 @@ public class ConditionJudgeHandler {
public Set<String> conditionJudgeAll(String question, Collection<String> candidateAnswerList, String userAnswer) {
List<MessageDTO> messageList = new ArrayList<>();
String template = "当我问用户:{},用户给我的回答是:[{}]\n" +
"基于用户的回答,请依次判断以下列表:[{}]中的哪些项满足用户的回答?\n" +
"请从给定列表中找出所有满足的项,并以json数组的格式返回,格式示例[\"xxx\",\"xxx\"]。直接说答案,不需要推理过程。如果列表中项全部不满足,则返回:未找到";
"基于用户的回答,请依次判断用户的回答满足以下列表:{}中的哪些项?\n" +
"以json数组的格式返回,格式示例[\"xxx\",\"xxx\"]。回答一定要来自于列表原文。不要胡乱编造。不需要推理过程。如果列表中项全部不满足,则返回:未找到";
String judgeAsk = StrUtil.format(template, question, userAnswer, CollUtil.join(candidateAnswerList, ";"));
String judgeAsk = StrUtil.format(template, question, userAnswer, JSONUtil.toJsonStr(candidateAnswerList));
log.info("conditionJudge问题是:{}", judgeAsk);
messageList.add(new MessageDTO("user", judgeAsk));
String judgeResult = AiUtil.chatByMessage(messageList);

@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
@ -88,19 +89,30 @@ public class AskServiceImpl implements AskService {
} else {
sessionParamDTO = BeanUtil.toBean(cache, SessionParamDTO.class);
}
// 如果前端传了角色设置ID,就更新缓存
if (StrUtil.isNotBlank(roundTalkReqVO.getRoleSetId())) {
sessionParamDTO.setRoleSetId(roundTalkReqVO.getRoleSetId());
redisTemplate.opsForValue().set(SESSION_PARAM + sessionId, sessionParamDTO);
}
// 判断,如果已经有确定的叶子节点了,这时,就可以直接根据意图来问了,就不要要提取实体了
if (ObjectUtil.isNotEmpty(sessionParamDTO.getMatchItemLeaf())) {
sessionParamDTO.setOriginalQuestion(roundTalkReqVO.getUserTalk());
String intent = identifyIntentHandler.identifyIntentExample(roundTalkReqVO.getUserTalk());
sessionParamDTO.setIntent(intent);
redisTemplate.opsForValue().set(SESSION_PARAM + sessionId, sessionParamDTO);
return afterMatchReturnAnswer(sessionParamDTO);
}
// 判断意图是否为空,如果意图为空,进行识别意图
if (StrUtil.isBlank(sessionParamDTO.getIntent())) {
String intent = identifyIntentHandler.identifyIntentExample(roundTalkReqVO.getUserTalk());
sessionParamDTO.setIntent(intent);
log.info("对问题:{}进行意图识别,识别的意图为:{}", roundTalkReqVO.getUserTalk(), intent);
redisTemplate.opsForValue().set(SESSION_PARAM + sessionId, sessionParamDTO);
}
// 识别出来意图之后,再去判断是否识别过实体
if (CollUtil.isEmpty(sessionParamDTO.getEntityValueByExtract())) {
// 识别出来意图之后,再去判断是否识别过实体(如果最终叶子节点已经确定了,就不需要再判断实体了)
if (CollUtil.isEmpty(sessionParamDTO.getEntityValueByExtract()) && ObjectUtil.isEmpty(sessionParamDTO.getMatchItemLeaf())) {
// 识别实体(先从图中获取所有的节点名称,然后识别)
List<String> allItemNode = findItemNodeHandler.findAllItemNode();
List<String> extractValue = itemExtractHandler.itemExtractByPossibleItemWithExample(sessionParamDTO.getOriginalQuestion(), allItemNode);
@ -150,17 +162,19 @@ public class AskServiceImpl implements AskService {
}
}
// 多轮问答支持设置角色,如果设置角色了,在这里应该先根据角色来排除一遍路径
filterUserRoleSet(sessionParamDTO);
if (ObjectUtil.isEmpty(sessionParamDTO.getMatchItemLeaf())) {
filterUserRoleSet(sessionParamDTO);
}
// 如果没有确定节点,且没有路径可供匹配,抛出异常
if (CollUtil.isEmpty(sessionParamDTO.getConditionPathMap())) {
throw new BusinessException("未找到条件判断路径");
}
// 如果判断过实体,这时就要判断是否已经确认了节点,如果没有确认,在这里进行确认
match:
if (ObjectUtil.isEmpty(sessionParamDTO.getMatchItemLeaf())) {
// 如果没有确定节点,且没有路径可供匹配,抛出异常
if (CollUtil.isEmpty(sessionParamDTO.getConditionPathMap())) {
throw new BusinessException("未找到条件判断路径");
}
// 判断待匹配的节点是不是只有一个了,如果有多个,就从路径中选择一个问题问前端
if (sessionParamDTO.getWaitMatchItemLeafMap().size() != 1) {
if (ObjectUtil.isNotEmpty(sessionParamDTO.getCurrentEntity())) {
// 如果当前对话实体不为空,说明当前问答就是上一个问题的回复,这个时候,就去大模型中进行匹配并排除路径
filterPath(sessionParamDTO, sessionParamDTO.getCurrentEntity().getCurrentEntityType(), sessionParamDTO.getCurrentEntity().getCurrentQuestion(), roundTalkReqVO.getUserTalk());
@ -173,6 +187,10 @@ public class AskServiceImpl implements AskService {
}
// 首先获取出现次数最多的实体类型
Map<String, Integer> newCountMap = countCondition(sessionParamDTO);
if (MapUtil.isEmpty(newCountMap)) {
log.info("为空了");
}
// 如果计数不为空,就继续进行筛选
String mostFrequentType = newCountMap.entrySet().stream()
.filter(entry -> !sessionParamDTO.getAlreadyMatchEntitySet().contains(entry.getKey()))
.max(Map.Entry.comparingByValue(Integer::compareTo))
@ -232,6 +250,10 @@ public class AskServiceImpl implements AskService {
private void filterPath(SessionParamDTO sessionParamDTO, String currentEntityType, String currentQuestion, String userTalk) {
// 遍历所有的path,找到回答
Set<String> possibleAnswerSet = findPossibleAnswerSet(sessionParamDTO, currentEntityType);
// 如果可能的回答为空,就不进行过滤,直接跳过
if (CollUtil.isEmpty(possibleAnswerSet)) {
return;
}
Set<String> judgeResultSet = conditionJudgeHandler.conditionJudgeAll(currentQuestion,
possibleAnswerSet,
userTalk);
@ -397,11 +419,9 @@ public class AskServiceImpl implements AskService {
try {
RetireRoleEnum retireRoleEnum = RetireRoleEnum.valueOf(roleSetNode.getItemEn());
if (ObjectUtils.isNotEmpty(retireRoleEnum)) {
Map<String, Integer> entityCountMap = sessionParamDTO.getEntityCountMap();
// 如果包含,就去尝试排除路径
if (entityCountMap.containsKey(retireRoleEnum.getZhName()) && ObjectUtil.isNotEmpty(roleSetNode.getValueNum())) {
if (MapUtil.isNotEmpty(entityCountMap) && entityCountMap.containsKey(retireRoleEnum.getZhName()) && ObjectUtil.isNotEmpty(roleSetNode.getValueNum())) {
List<Pair<Integer, String>> answerList = retireRoleEnum.getAnswerList();
for (Pair<Integer, String> pair : answerList) {
// 如果枚举的key和用户填写的value相等,就排除

Loading…
Cancel
Save