DynamicPartService.java
12.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
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<String> dynamicPartDTOChoiceResult(String userId, String userInput, UserSceneSession session) {
//判断输入
Boolean isConfirmed = dynamicToolProvider.isConfirmed(userInput,session);
if(ObjectUtil.isNotEmpty(session.getDynamicPartList())){
List<String> partList =session.getDynamicPartList();
List<String> partListBs = getPartBs(session);
// 移除 partList 中存在于 partListBs 的所有元素
partList.removeAll(partListBs);
// 找出 partList 中存在于 partListPz 的元素
List<String> result = new ArrayList<>(partList);
List<String> partListPz = getPartPz(session);
List<String> 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<String> 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<String> 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<String> partListAdd, UserSceneSession session) {
if (ObjectUtil.isEmpty(partListAdd)) {
return;
}
List<ParamRule> paramRuleDataAll = new ArrayList<>(session.getCurrentTool().getParamRuleListAll());
// 获取已有的动态部件名称,用于去重
Set<String> existingDynamicParts = new HashSet<>();
// 筛选标准参数(只筛选一次,提高性能)
List<ParamRule> 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<ParamRule> paramRuleList = paramRuleDataAll.stream()
.filter(one -> Boolean.TRUE.equals(one.getBTipModel()))
.collect(Collectors.toList());
List<ParamRule> 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<String, Object> 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<java.lang.String>
* @Description 获取部件
**/
private List<String> getPart( UserSceneSession session){
// 1. 获取参数规则列表
List<ParamRule> paramRuleAll = session.getCurrentTool().getParamRuleList();
// 2. 从 ParamRule 中提取符合条件的部件名称
Set<String> 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<String> 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<String> partList = new ArrayList<>(mergedSet);
return partList;
}
/***
* @Author 钱豹
* @Date 18:13 2026/7/30
* @Param [session]
* @return java.util.List<java.lang.String>
* @Description 获取部件
**/
private List<String> getPartBs( UserSceneSession session){
// 1. 获取参数规则列表
List<ParamRule> paramRuleAll = session.getCurrentTool().getParamRuleList();
// 2. 从 ParamRule 中提取符合条件的部件名称
Set<String> 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<String> getPartPz( UserSceneSession session){
String sSdynamicMemo = session.getCurrentTool().getSdynamicMemo();
Set<String> 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<String> partList = getPart(session);
//判断是否存返回的部件是否有不存在
List<String> dDynamicPartList = session.getDynamicPartList();
// 判断 dDynamicPartList 中不存在于 partList 的数据(即多余的、已失效的部件)
List<String> invalidParts = new ArrayList<>();
if (ObjectUtil.isNotEmpty(dDynamicPartList)) {
// 将 partList 转为 Set 提高查询效率
Set<String> partSet = new HashSet<>(partList);
for (String dynamicPart : dDynamicPartList) {
if (!partSet.contains(dynamicPart)) {
invalidParts.add(dynamicPart);
}
}
}
//存在动态部件,没有采集 需要添加参数
if (ObjectUtil.isNotEmpty(dDynamicPartList) && ObjectUtil.isEmpty(invalidParts)) {
List<String> partListBs = getPartBs(session);
// 移除 partList 中存在于 partListBs 的所有元素
dDynamicPartList.removeAll(partListBs);
List<String> partListAdd = new ArrayList<>(dDynamicPartList);
addToolMethod(partListAdd,session);
}
if(ObjectUtil.isNotEmpty(invalidParts)){
return String.join(",", invalidParts)+"部件不存在,是否是部件,如果是,输入是,否则输入否";
}
return null;
}
/** 解析模型输出,兼容被 ```json ... ``` 包裹或前后带杂字符的情况 */
private List<String> 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;
}
}
}