package com.supervision.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.supervision.dto.roundAsk.ItemNodeDTO; import com.supervision.dto.roundAsk.SessionParamDTO; import com.supervision.handler.gpt.IdentifyIntentHandler; import com.supervision.handler.gpt.ItemExtractHandler; import com.supervision.handler.graph.FindConditionPathHandler; import com.supervision.handler.graph.FindItemNodeHandler; import com.supervision.ngbatis.domain.tag.Condition; import com.supervision.ngbatis.domain.tag.ItemLeaf; import com.supervision.service.AskService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @Slf4j @Service @RequiredArgsConstructor public class AskServiceImpl implements AskService { private final RedisTemplate redisTemplate; private final IdentifyIntentHandler identifyIntentHandler; private final ItemExtractHandler itemExtractHandler; private final FindItemNodeHandler findItemNodeHandler; private final FindConditionPathHandler findConditionPathHandler; private static final String SESSION_PARAM = "KBQA:ASK:SESSION_PARAM:"; @Override public void ask(String sessionId, String question) { // 去Redis中,首先判断session处在哪个阶段,是否有识别的意图 Object cache = redisTemplate.opsForValue().get(SESSION_PARAM + sessionId); SessionParamDTO sessionParamDTO; if (ObjectUtil.isEmpty(cache)) { sessionParamDTO = new SessionParamDTO(); sessionParamDTO.setOriginalQuestion(question); sessionParamDTO.setSessionId(sessionId); redisTemplate.opsForValue().set(SESSION_PARAM + sessionId, sessionParamDTO); } else { sessionParamDTO = BeanUtil.toBean(cache, SessionParamDTO.class); } // 判断意图是否为空,如果意图为空,进行识别意图 if (StrUtil.isBlank(sessionParamDTO.getIntent())) { String intent = identifyIntentHandler.identifyIntent(question); sessionParamDTO.setIntent(intent); redisTemplate.opsForValue().set(SESSION_PARAM + sessionId, sessionParamDTO); } // 识别出来意图之后,再去判断是否识别过实体 if (StrUtil.isBlank(sessionParamDTO.getEntityValueByExtract())) { // 识别实体 String extractValue = itemExtractHandler.itemExtract(sessionParamDTO.getOriginalQuestion()); sessionParamDTO.setEntityValueByExtract(extractValue); // 根据提取的内容,开始在知识图谱中寻找节点(首先找叶子节点,如果叶子节点有数据,直接返回,如果叶子节点没数据,再去找分支节点) List allMatchLeafNode = findItemNodeHandler.findAllMatchLeafNode(extractValue); // 如果找到的节点只有1个,那么说明问的就是这个节点,那么直接缓存起来进行下一步 if (allMatchLeafNode.size() == 1) { ItemLeaf itemLeaf = allMatchLeafNode.get(0); sessionParamDTO.setMatchItemLeaf(itemLeaf); redisTemplate.opsForValue().set(SESSION_PARAM + sessionId, sessionParamDTO); } else { // 如果不等于1,说明可能有不确定的节点,这时就要开始找节点 Map waitMatchItemLeafMap = allMatchLeafNode.stream().collect(Collectors.toMap(ItemLeaf::getVid, Function.identity(), (k1, k2) -> k1)); sessionParamDTO.setWaitMatchItemLeafMap(waitMatchItemLeafMap); // 开始寻找条件路径 Set itemLeafIdSet = waitMatchItemLeafMap.keySet(); // 所有的实体类型以及出现次数计数 Map entityCountMap = new HashMap<>(); for (String leafId : itemLeafIdSet) { List> conditionPath = findConditionPathHandler.findConditionPath(leafId); if (CollUtil.isEmpty(conditionPath)) { waitMatchItemLeafMap.remove(leafId); } else { // 如果路径不为空,则放到缓存中去 for (List conditions : conditionPath) { for (Condition condition : conditions) { // 如果不存在,就添加进计数.如果存在,就+1 entityCountMap.compute(condition.getEntityType(), (k, v) -> v == null ? 1 : v + 1); } } } } } } } }