package com.xly.service; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson2.JSONObject; import com.xly.agent.DynamicPartAiAgent; import com.xly.agent.SystemPromptGenerator; import com.xly.entity.ParamRule; import com.xly.entity.UserSceneSession; import com.xly.tool.DynamicToolProvider; import com.xly.util.PinyinUtil; import com.xly.util.Validator; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; /*** * @Author 钱豹 * @Date 22:39 2026/1/30 * @Param * @return * @Description 动态部件提取类 **/ @Slf4j @Service("dynamicPartService") @RequiredArgsConstructor public class DynamicPartService { private final DynamicToolProvider dynamicToolProvider; private final DynamicPartAiAgent aiAgent; /*** * @Author 钱豹 * @Date 23:07 2026/7/29 * @Description AI识别获取方法(二级路由:在当前场景内选出一个 sMethodNo) **/ public List dynamicPartDTOChoiceResult(String userId, String userInput, UserSceneSession session) { //判断输入 Boolean isConfirmed = dynamicToolProvider.isConfirmed(userInput,session); if(ObjectUtil.isNotEmpty(session.getDynamicPartList())){ List partList =session.getDynamicPartList(); List partListBs = getPartBs(session); // 移除 partList 中存在于 partListBs 的所有元素 partList.removeAll(partListBs); // 找出 partList 中存在于 partListPz 的元素 List result = new ArrayList<>(partList); List partListPz = getPartPz(session); List partListAdd = new ArrayList<>(); if(isConfirmed){ //方法添加动态参数 partListAdd.addAll(partList); partList =null; session.setBConfirmedDynamicPartFist(true); } if(!isConfirmed){ //添加再配置中的动态 result.retainAll(partListPz); partListAdd.addAll(result); partList =null; session.setBConfirmedDynamicPartFist(true); } if(ObjectUtil.isNotEmpty(partListAdd)){ //部件添加数据 addToolMethod( partListAdd, session); } return partList; } //如果存在动态部件 if(ObjectUtil.isEmpty(session.getCurrentTool()) || ObjectUtil.isEmpty(session.getCurrentTool().getSdynamicMemo()) || session.getBConfirmedDynamicPart() ){ return null; } List partList = getPart(session); // 5. 生成系统提示词 String sSystemPrompt = SystemPromptGenerator.generateChoicePartPrompt(partList); // 3. 调大模型 String raw = aiAgent.getDynamicPartMethod(userId, userInput, sSystemPrompt).content(); log.debug("方法获取动态部件: userId={}, raw={}", userId, raw); // 4. 解析(含 ```json 容错) List result = parseChoice(raw); if (result == null || ObjectUtil.isEmpty(result)) { return null; } // 5. none / 阈值 / 白名单 三重校验 if ("none".equalsIgnoreCase(raw)) { log.info("方法动态方法:无匹配部件, input={}", userInput); return null; } session.setDynamicPartList(result); return result; } /*** * @Author 钱豹 * @Date 20:01 2026/7/30 * @Param [partListAdd, session] * @return void * @Description 动态方法 添加参数 **/ private void addToolMethod(List partListAdd, UserSceneSession session) { if (ObjectUtil.isEmpty(partListAdd)) { return; } List paramRuleDataAll = new ArrayList<>(session.getCurrentTool().getParamRuleListAll()); // 获取已有的动态部件名称,用于去重 Set existingDynamicParts = new HashSet<>(); // 筛选标准参数(只筛选一次,提高性能) List standardParams = paramRuleDataAll.stream() .filter(d -> ObjectUtil.isNotEmpty(d.getSGroup()) && !d.getBDynamicParam() && "部件".equals(d.getSGroup()) && d.getBStandardParam()) .collect(Collectors.toList()); if (ObjectUtil.isEmpty(standardParams)) { log.warn("未找到部件标准参数,无法添加动态部件"); return; } for (String sVal : partListAdd) { // 去重:如果该部件已存在,跳过 if (existingDynamicParts.contains(sVal)) { log.debug("部件已存在,跳过: {}", sVal); continue; } // 拼音转换 String firstLetters = ""; try { firstLetters = PinyinUtil.convertToPinyin(sVal); } catch (Exception e) { log.warn("拼音转换失败: {}", sVal, e); firstLetters = sVal.length() > 0 ? sVal.substring(0, 1).toUpperCase() : ""; } // 遍历标准参数,生成动态参数 for (ParamRule standard : standardParams) { ParamRule copy = new ParamRule(); BeanUtils.copyProperties(standard, copy); // 解析参数名:取 "-" 后的部分 String paramName = standard.getSParam(); if (paramName != null && paramName.contains("-")) { String[] parts = paramName.split("-"); paramName = parts.length > 1 ? parts[1] : parts[0]; } copy.setSParam(sVal + "-" + paramName); copy.setSParamValue(firstLetters + standard.getSParamValue()); copy.setIOrder(standard.getIOrder() + 100000); copy.setBDynamicParam(true); copy.setSDynamicParam(sVal); copy.setSDynamicParamName("sDynamicPart"); paramRuleDataAll.add(copy); } // 记录已添加的部件 existingDynamicParts.add(sVal); } // 重新筛选分类列表 List paramRuleList = paramRuleDataAll.stream() .filter(one -> Boolean.TRUE.equals(one.getBTipModel())) .collect(Collectors.toList()); List paramRuleListCheck = paramRuleDataAll.stream() .filter(one -> Boolean.TRUE.equals(one.getBEmpty())) .collect(Collectors.toList()); // 更新 session session.getCurrentTool().setParamRuleListAll(paramRuleDataAll); session.getCurrentTool().setParamRuleListCheck(paramRuleListCheck); session.getCurrentTool().setParamRuleList(paramRuleList); // 更新 args Map args = new HashMap<>(); if (ObjectUtil.isNotEmpty(session.getArgs())) { args.putAll(session.getArgs()); } args.put("sDynamicPart", JSONUtil.toJsonStr(partListAdd)); session.setArgs(args); } /*** * @Author 钱豹 * @Date 18:13 2026/7/30 * @Param [session] * @return java.util.List * @Description 获取部件 **/ private List getPart( UserSceneSession session){ // 1. 获取参数规则列表 List paramRuleAll = session.getCurrentTool().getParamRuleList(); // 2. 从 ParamRule 中提取符合条件的部件名称 Set partSet = new HashSet<>(); if (ObjectUtil.isNotEmpty(paramRuleAll)) { for (ParamRule rule : paramRuleAll) { String sGroup = rule.getSGroup(); String sParam = rule.getSParam(); if ("部件".equals(sGroup) && !"动态部件".equals(sParam) && !"删除动态部件".equals(sParam)) { // 取 "-" 前的部分作为部件名称 String partName = sParam.contains("-") ? sParam.split("-")[0] : sParam; partSet.add(partName); } } } // 3. 从 sSdynamicMemo 中获取已保存的部件 String sSdynamicMemo = session.getCurrentTool().getSdynamicMemo(); Set mergedSet = new LinkedHashSet<>(); // 先加入 sSdynamicMemo 中的部件(保持原有顺序) if (ObjectUtil.isNotEmpty(sSdynamicMemo)) { String[] memoParts = sSdynamicMemo.split(","); for (String part : memoParts) { String trimmed = part.trim(); if (!trimmed.isEmpty()) { mergedSet.add(trimmed); } } } // 再加入从 ParamRule 提取的部件(自动去重) mergedSet.addAll(partSet); // 4. 转为 List List partList = new ArrayList<>(mergedSet); return partList; } /*** * @Author 钱豹 * @Date 18:13 2026/7/30 * @Param [session] * @return java.util.List * @Description 获取部件 **/ private List getPartBs( UserSceneSession session){ // 1. 获取参数规则列表 List paramRuleAll = session.getCurrentTool().getParamRuleList(); // 2. 从 ParamRule 中提取符合条件的部件名称 Set partSet = new HashSet<>(); if (ObjectUtil.isNotEmpty(paramRuleAll)) { for (ParamRule rule : paramRuleAll) { String sGroup = rule.getSGroup(); String sParam = rule.getSParam(); if ("部件".equals(sGroup) && !"动态部件".equals(sParam) && !"删除动态部件".equals(sParam)) { // 取 "-" 前的部分作为部件名称 String partName = sParam.contains("-") ? sParam.split("-")[0] : sParam; partSet.add(partName); } } } return new ArrayList<>(partSet); } private List getPartPz( UserSceneSession session){ String sSdynamicMemo = session.getCurrentTool().getSdynamicMemo(); Set mergedSet = new LinkedHashSet<>(); // 先加入 sSdynamicMemo 中的部件(保持原有顺序) if (ObjectUtil.isNotEmpty(sSdynamicMemo)) { String[] memoParts = sSdynamicMemo.split(","); for (String part : memoParts) { String trimmed = part.trim(); if (!trimmed.isEmpty()) { mergedSet.add(trimmed); } } } return new ArrayList<>(mergedSet); } /*** * @Author 钱豹 * @Date 23:07 2026/7/29 * @Description **/ public String doCheckDynamicPart(String userId,String userInput,UserSceneSession session) { List partList = getPart(session); //判断是否存返回的部件是否有不存在 List dDynamicPartList = session.getDynamicPartList(); // 判断 dDynamicPartList 中不存在于 partList 的数据(即多余的、已失效的部件) List invalidParts = new ArrayList<>(); if (ObjectUtil.isNotEmpty(dDynamicPartList)) { // 将 partList 转为 Set 提高查询效率 Set partSet = new HashSet<>(partList); for (String dynamicPart : dDynamicPartList) { if (!partSet.contains(dynamicPart)) { invalidParts.add(dynamicPart); } } } //存在动态部件,没有采集 需要添加参数 if (ObjectUtil.isNotEmpty(dDynamicPartList) && ObjectUtil.isEmpty(invalidParts)) { List partListBs = getPartBs(session); // 移除 partList 中存在于 partListBs 的所有元素 dDynamicPartList.removeAll(partListBs); List partListAdd = new ArrayList<>(dDynamicPartList); addToolMethod(partListAdd,session); } if(ObjectUtil.isNotEmpty(invalidParts)){ return String.join(",", invalidParts)+"部件不存在,是否是部件,如果是,输入是,否则输入否"; } return null; } /** 解析模型输出,兼容被 ```json ... ``` 包裹或前后带杂字符的情况 */ private List parseChoice(String raw) { if (ObjectUtil.isEmpty(raw)) return null; try { return JSONUtil.toList(raw,String.class); } catch (Exception e) { log.error("方法路由结果解析失败, raw={}", raw, e); return null; } } }