Commit 686f95626c5aa971054773f5e8ad40c7e51cc2e6

Authored by qianbao
1 parent cbcf8d53

添加未清选择 改成动态引导语

src/main/java/com/xly/service/XlyErpService.java
@@ -464,6 +464,9 @@ public class XlyErpService { @@ -464,6 +464,9 @@ public class XlyErpService {
464 session.setBCleanMemory(false); 464 session.setBCleanMemory(false);
465 session.setCurrentRowData(null); 465 session.setCurrentRowData(null);
466 session.setQuoData(null); 466 session.setQuoData(null);
  467 + session.setSFunPrompts(StrUtil.EMPTY);
  468 + session.setArgs(new HashMap<>());
  469 + session.setSSystemPrompt(StrUtil.EMPTY);
467 ToolMeta toolMeta = session.getCurrentTool(); 470 ToolMeta toolMeta = session.getCurrentTool();
468 if(toolMeta!=null && ObjectUtil.isNotEmpty(toolMeta)){ 471 if(toolMeta!=null && ObjectUtil.isNotEmpty(toolMeta)){
469 List<ParamRule> data = toolMeta.getParamRuleListAll(); 472 List<ParamRule> data = toolMeta.getParamRuleListAll();
src/main/java/com/xly/tool/DynamicToolProvider.java
@@ -41,8 +41,6 @@ import org.springframework.stereotype.Service; @@ -41,8 +41,6 @@ import org.springframework.stereotype.Service;
41 import java.util.*; 41 import java.util.*;
42 42
43 import java.util.concurrent.ConcurrentHashMap; 43 import java.util.concurrent.ConcurrentHashMap;
44 -import java.util.concurrent.CopyOnWriteArrayList;  
45 -import java.util.concurrent.atomic.AtomicReference;  
46 import java.util.stream.Collectors; 44 import java.util.stream.Collectors;
47 import java.util.stream.IntStream; 45 import java.util.stream.IntStream;
48 46
@@ -181,6 +179,43 @@ public class DynamicToolProvider implements ToolProvider { @@ -181,6 +179,43 @@ public class DynamicToolProvider implements ToolProvider {
181 throw new RuntimeException("参数解析失败,请重新输入"); 179 throw new RuntimeException("参数解析失败,请重新输入");
182 } 180 }
183 181
  182 + //合并动态部件
  183 + String sDynamicValue = ObjectUtil.isNotEmpty(argsNew.get("动态部件"))
  184 + ? argsNew.get("动态部件").toString():( ObjectUtil.isNotEmpty(argsNew.get("sDynamicPart"))? argsNew.get("sDynamicPart").toString():StrUtil.EMPTY);
  185 + String sDynamicValueOld =StrUtil.EMPTY;
  186 + if(sDynamicValue.contains("{")){
  187 + sDynamicValue = StrUtil.EMPTY;
  188 + }
  189 + if(ObjectUtil.isNotEmpty(session.getArgs())){
  190 + Map<String,Object> argOld = session.getArgs();
  191 + sDynamicValueOld = ObjectUtil.isNotEmpty(argOld.get("动态部件"))
  192 + ? argOld.get("动态部件").toString():( ObjectUtil.isNotEmpty(argOld.get("sDynamicPart"))? argOld.get("sDynamicPart").toString():StrUtil.EMPTY);
  193 + }
  194 + Set<String> sDynamicData = new HashSet<>();
  195 + if(ObjectUtil.isNotEmpty(sDynamicValueOld)){
  196 + List<String> data = new ArrayList<>();
  197 + if (JSONUtil.isTypeJSONArray(sDynamicValueOld)) {
  198 + data = JSONUtil.toList(sDynamicValueOld, String.class);
  199 + } else {
  200 + data.add(sDynamicValueOld);
  201 + }
  202 + sDynamicData.addAll(data);
  203 + }
  204 + if(ObjectUtil.isNotEmpty(sDynamicValue)){
  205 + List<String> data = new ArrayList<>();
  206 + if (JSONUtil.isTypeJSONArray(sDynamicValue)) {
  207 + data = JSONUtil.toList(sDynamicValue, String.class);
  208 + } else {
  209 + data.add(sDynamicValue);
  210 + }
  211 + sDynamicData.addAll(data);
  212 + }
  213 + if(ObjectUtil.isNotEmpty(sDynamicData)){
  214 + session.getArgs().remove("动态部件");
  215 + session.getArgs().remove("sDynamicPart");
  216 + argsNew.put("动态部件",JSONUtil.toJsonStr(sDynamicData));
  217 + argsNew.put("sDynamicPart",JSONUtil.toJsonStr(sDynamicData));
  218 + }
184 //获取之前获取的参数 219 //获取之前获取的参数
185 Map<String, Object> args = session.getArgs(); 220 Map<String, Object> args = session.getArgs();
186 if(ObjectUtil.isEmpty(args)) args = new HashMap<>(); 221 if(ObjectUtil.isEmpty(args)) args = new HashMap<>();
@@ -197,7 +232,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -197,7 +232,7 @@ public class DynamicToolProvider implements ToolProvider {
197 finalArgs.remove("sDynamicPartDel"); 232 finalArgs.remove("sDynamicPartDel");
198 finalArgs.remove("删除动态部件"); 233 finalArgs.remove("删除动态部件");
199 } 234 }
200 - // 2 【补全动态参数】动态参数补全 235 + // 2 【补全动态参数】动态参数补全(中->英文)
201 try{ 236 try{
202 args = applyValues(args, meta.getParamRuleListCheck()); 237 args = applyValues(args, meta.getParamRuleListCheck());
203 }catch (Exception e){ 238 }catch (Exception e){
@@ -209,6 +244,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -209,6 +244,7 @@ public class DynamicToolProvider implements ToolProvider {
209 } 244 }
210 // 2.1 【自动补全】应用参数的默认值 245 // 2.1 【自动补全】应用参数的默认值
211 List<ParamRule> paramRuleData = meta.getParamRuleListAll(); 246 List<ParamRule> paramRuleData = meta.getParamRuleListAll();
  247 + //添加默认值
212 args = applyDefaultValues(args, paramRuleData); 248 args = applyDefaultValues(args, paramRuleData);
213 //客户选择行号转sSLaveId 249 //客户选择行号转sSLaveId
214 if(ObjectUtil.isNotEmpty(args) 250 if(ObjectUtil.isNotEmpty(args)
@@ -291,7 +327,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -291,7 +327,7 @@ public class DynamicToolProvider implements ToolProvider {
291 && one.getSParamValue().equals(d.getSParamValue()) 327 && one.getSParamValue().equals(d.getSParamValue())
292 ); 328 );
293 329
294 - String sValue = searMap.get(one.getSParam()).toString(); 330 + String sValue = ObjectUtil.isNotEmpty(one.getSParam())?searMap.get(one.getSParam()).toString():(ObjectUtil.isNotEmpty(one.getSParamValue())?searMap.get(one.getSParamValue()).toString():StrUtil.EMPTY);
295 List<String> addValue = new ArrayList<>(); 331 List<String> addValue = new ArrayList<>();
296 332
297 if (JSONUtil.isTypeJSONArray(sValue)) { 333 if (JSONUtil.isTypeJSONArray(sValue)) {
@@ -393,27 +429,19 @@ public class DynamicToolProvider implements ToolProvider { @@ -393,27 +429,19 @@ public class DynamicToolProvider implements ToolProvider {
393 String sValue = ObjectUtil.isNotEmpty(args.get(sDynamicPartOne.getSParam())) 429 String sValue = ObjectUtil.isNotEmpty(args.get(sDynamicPartOne.getSParam()))
394 ? args.get(sDynamicPartOne.getSParam()).toString() 430 ? args.get(sDynamicPartOne.getSParam()).toString()
395 : StrUtil.EMPTY; 431 : StrUtil.EMPTY;
396 - 432 + if(sValue.contains("{")){
  433 + sValue = StrUtil.EMPTY;
  434 + }
397 if (ObjectUtil.isNotEmpty(sValue)) { 435 if (ObjectUtil.isNotEmpty(sValue)) {
398 - List<String> addValueAdd = new ArrayList<>();  
399 List<String> addValueOld = new ArrayList<>(); 436 List<String> addValueOld = new ArrayList<>();
400 - Object sOldVal = session.getArgs().get(sDynamicPart.get(0).getSParam());  
401 - if(ObjectUtil.isNotEmpty(sOldVal)){ 437 + if(ObjectUtil.isNotEmpty(sValue)){
402 if (JSONUtil.isTypeJSONArray(sValue)) { 438 if (JSONUtil.isTypeJSONArray(sValue)) {
403 addValueOld = JSONUtil.toList(sValue, String.class); 439 addValueOld = JSONUtil.toList(sValue, String.class);
404 } else { 440 } else {
405 addValueOld.add(sValue); 441 addValueOld.add(sValue);
406 } 442 }
407 } 443 }
408 -  
409 - if (JSONUtil.isTypeJSONArray(sValue)) {  
410 - addValueAdd = JSONUtil.toList(sValue, String.class);  
411 - } else {  
412 - addValueAdd.add(sValue);  
413 - }  
414 - addValueOld.addAll(addValueAdd);  
415 addValueOld = new ArrayList<>(new LinkedHashSet<>(addValueOld)); 444 addValueOld = new ArrayList<>(new LinkedHashSet<>(addValueOld));
416 -  
417 //新增部件不在删除部件中的 445 //新增部件不在删除部件中的
418 List<String> finalSDynamicPartDelValue = sDynamicPartDelValue; 446 List<String> finalSDynamicPartDelValue = sDynamicPartDelValue;
419 List<String> addValue = addValueOld.stream().filter(one-> !finalSDynamicPartDelValue.contains(one)).collect(Collectors.toList()); 447 List<String> addValue = addValueOld.stream().filter(one-> !finalSDynamicPartDelValue.contains(one)).collect(Collectors.toList());
@@ -443,8 +471,6 @@ public class DynamicToolProvider implements ToolProvider { @@ -443,8 +471,6 @@ public class DynamicToolProvider implements ToolProvider {
443 String paramName = d.getSParam().split("-").length > 1 471 String paramName = d.getSParam().split("-").length > 1
444 ? d.getSParam().split("-")[1] 472 ? d.getSParam().split("-")[1]
445 : d.getSParam().split("-")[0]; 473 : d.getSParam().split("-")[0];
446 - copy.setSParam(sVal + "-" + paramName);  
447 -  
448 // 拼音转换 474 // 拼音转换
449 String firstLetters = ""; 475 String firstLetters = "";
450 try { 476 try {
@@ -453,6 +479,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -453,6 +479,7 @@ public class DynamicToolProvider implements ToolProvider {
453 log.warn("拼音转换失败: {}", sVal); 479 log.warn("拼音转换失败: {}", sVal);
454 firstLetters = sVal.substring(0, 1).toUpperCase(); 480 firstLetters = sVal.substring(0, 1).toUpperCase();
455 } 481 }
  482 + copy.setSParam(sVal + "-" + paramName);
456 copy.setSParamValue(firstLetters + d.getSParamValue()); 483 copy.setSParamValue(firstLetters + d.getSParamValue());
457 copy.setIOrder(d.getIOrder() + 100000); 484 copy.setIOrder(d.getIOrder() + 100000);
458 copy.setBDynamicParam(true); 485 copy.setBDynamicParam(true);
@@ -640,6 +667,7 @@ public class DynamicToolProvider implements ToolProvider { @@ -640,6 +667,7 @@ public class DynamicToolProvider implements ToolProvider {
640 try { 667 try {
641 List<ParamRule> paramRuleData = meta.getParamRuleList(); 668 List<ParamRule> paramRuleData = meta.getParamRuleList();
642 for (ParamRule paramRule : paramRuleData) { 669 for (ParamRule paramRule : paramRuleData) {
  670 + String paramName = paramRule.getSParamValue();
643 String paramDesc = paramRule.getSParam(); 671 String paramDesc = paramRule.getSParam();
644 String paramType = paramRule.getSType(); 672 String paramType = paramRule.getSType();
645 Boolean bEmpty = paramRule.getBEmpty(); 673 Boolean bEmpty = paramRule.getBEmpty();
@@ -676,6 +704,10 @@ public class DynamicToolProvider implements ToolProvider { @@ -676,6 +704,10 @@ public class DynamicToolProvider implements ToolProvider {
676 case "enum": 704 case "enum":
677 String constStr = getArrrayBySql(paramRule); 705 String constStr = getArrrayBySql(paramRule);
678 // String constStr = getConstMeg(paramRule); 706 // String constStr = getConstMeg(paramRule);
  707 + //屏蔽纸质配置 用逗号了
  708 + if(constStr.contains(",") && !constStr.contains("/")){
  709 + constStr = constStr.replace(",","/");
  710 + }
679 List<String> constList = StrUtil.isNotBlank(constStr) ? Arrays.asList(constStr.split("/")) : new ArrayList<>(); 711 List<String> constList = StrUtil.isNotBlank(constStr) ? Arrays.asList(constStr.split("/")) : new ArrayList<>();
680 if (constList.isEmpty()) { 712 if (constList.isEmpty()) {
681 schemaBuilder.addStringProperty(paramDesc, paramDesc); 713 schemaBuilder.addStringProperty(paramDesc, paramDesc);
@@ -746,6 +778,9 @@ public class DynamicToolProvider implements ToolProvider { @@ -746,6 +778,9 @@ public class DynamicToolProvider implements ToolProvider {
746 Boolean bCheckArray = !(RuleCode.SQL.getCode().equals(paramRule.getSRule())); 778 Boolean bCheckArray = !(RuleCode.SQL.getCode().equals(paramRule.getSRule()));
747 Boolean bCheckArray2= !("array".equals(paramRule.getSType()) || "enum".equals(paramRule.getSType())); 779 Boolean bCheckArray2= !("array".equals(paramRule.getSType()) || "enum".equals(paramRule.getSType()));
748 Boolean bCheckArray3= ObjectUtil.isEmpty(paramRule.getSParamConfig()); 780 Boolean bCheckArray3= ObjectUtil.isEmpty(paramRule.getSParamConfig());
  781 + if(ObjectUtil.isNotEmpty(paramRule.getSRuleTs())){
  782 + return paramRule.getSRuleTs();
  783 + }
749 if(bCheckArray || bCheckArray2 || bCheckArray3){ 784 if(bCheckArray || bCheckArray2 || bCheckArray3){
750 return getConstMeg(paramRule); 785 return getConstMeg(paramRule);
751 } 786 }
@@ -972,85 +1007,73 @@ public class DynamicToolProvider implements ToolProvider { @@ -972,85 +1007,73 @@ public class DynamicToolProvider implements ToolProvider {
972 result = transformationArgs( result, paramDefsCheck); 1007 result = transformationArgs( result, paramDefsCheck);
973 List<ParamRule> paramDefs = new ArrayList<>(paramDefsCheck); 1008 List<ParamRule> paramDefs = new ArrayList<>(paramDefsCheck);
974 paramDefs.sort(Comparator.comparing(ParamRule::getIOrder)); 1009 paramDefs.sort(Comparator.comparing(ParamRule::getIOrder));
975 - for (ParamRule pd : paramDefs) {  
976 - String name = pd.getSParam();  
977 - String sValue = pd.getSParamValue();  
978 - String sRule = pd.getSRule();  
979 - String sType = pd.getSType();  
980 -  
981 - Boolean bCheck = result.containsKey(name);  
982 - bCheck = bCheck && ObjectUtil.isNotEmpty(result.get(name));  
983 - bCheck = bCheck && RuleCode.SQL.getCode().equals(sRule);  
984 - bCheck = bCheck && ObjectUtil.isNotEmpty(pd.getSParamConfig());  
985 -  
986 - Boolean bCheck2 = result.containsKey(sValue);  
987 - bCheck2 = bCheck2 && ObjectUtil.isNotEmpty(result.get(sValue));  
988 - bCheck2 = bCheck2 && RuleCode.SQL.getCode().equals(sRule);  
989 - bCheck2 = bCheck2 && ObjectUtil.isNotEmpty(pd.getSParamConfig());  
990 -  
991 - if ((bCheck || bCheck2) &&("enum".equals(sType) || "string".equals(sType))){  
992 - String sSql = pd.getSParamConfig();  
993 - String sKey = bCheck?name:sValue;  
994 - String nameValue = result.get(sKey).toString();  
995 - List<Map<String,Object>> dataList = dynamicExeDbService.findSql(result,sSql);  
996 - if(ObjectUtil.isEmpty(dataList)){  
997 - throw new BusinessException(ErrorCode.PARAM_REQUIRED,String.format("%s 您描述的%s 不存在,请重新告诉我",name,nameValue));  
998 - }  
999 - if(ObjectUtil.isNotEmpty(args.get(name)) || ObjectUtil.isNotEmpty(args.get(sValue))){  
1000 - if(("enum".equals(sType) ||"string".equals(sType)) && (args.get(name) instanceof List || args.get(sValue) instanceof List)){  
1001 - if(args.get(name) instanceof List){  
1002 - args.put(name,((List<?>) args.get(name)).get(0));  
1003 - }  
1004 - if(args.get(sValue) instanceof List){  
1005 - args.put(sValue,((List<?>) args.get(sValue)).get(0));  
1006 - }  
1007 - }  
1008 - List<Map<String,Object>> dataListNew = dataList.stream().filter(one-> ObjectUtil.isNotEmpty(one.get(sValue)) &&(one.get(sValue).equals(args.get(name)) || one.get(sValue).equals(args.get(sValue)))).collect(Collectors.toUnmodifiableList());  
1009 - if("enum".equals(sType) && ObjectUtil.isEmpty(dataListNew)){  
1010 - args.remove(name);  
1011 - args.remove(sValue);  
1012 - result.remove(name);  
1013 - result.remove(sValue);  
1014 - continue;  
1015 - }  
1016 - if(ObjectUtil.isNotEmpty(dataListNew)){  
1017 - dataList = new ArrayList<>();  
1018 - dataList.add(dataListNew.get(0));  
1019 - }  
1020 - }  
1021 - if(ObjectUtil.isNotEmpty(dataList) && dataList.size()==1){  
1022 - String sCopyTo = pd.getSCopyTo();  
1023 - if(ObjectUtil.isEmpty(sCopyTo)){  
1024 - result.put(sValue, dataList.get(0).get(sValue));  
1025 - result.put(name, dataList.get(0).get(sValue));  
1026 - }else{  
1027 - String[] sCopyToA = sCopyTo.split(",");  
1028 - for(String sCopyToOne:sCopyToA){  
1029 - String[] sCopyToOneA = sCopyToOne.split(":");  
1030 - result.put(sCopyToOneA[0], dataList.get(0).get(sCopyToOneA[1]));  
1031 - result.put(name, dataList.get(0).get(sValue));  
1032 - }  
1033 - }  
1034 - }  
1035 - StringBuffer sData=new StringBuffer();  
1036 - if(dataList.size()>1){  
1037 - List<Map<String, Object>> finalDataList = dataList;  
1038 - IntStream.range(0, dataList.size())  
1039 - .forEach(iRowNum ->{  
1040 - sData.append((iRowNum + 1)).append(".").append(finalDataList.get(iRowNum).get(pd.getSParamValue()))  
1041 - .append("\n\n");  
1042 -  
1043 - });  
1044 - String sParamMissMemo = StrUtil.EMPTY;  
1045 - if(ObjectUtil.isEmpty(pd.getSParamMissMemo())){  
1046 - sParamMissMemo = pd.getSParam()+"存在多个,请选择:<br/>"+sData;  
1047 - }else{  
1048 - sParamMissMemo = StrUtil.format(pd.getSParamMissMemo(),sData.toString());  
1049 - }  
1050 - throw new BusinessException(ErrorCode.PARAM_REQUIRED,sParamMissMemo);  
1051 - }  
1052 - }  
1053 - } 1010 +// for (ParamRule pd : paramDefs) {
  1011 +// String name = pd.getSParam();
  1012 +// String sValue = pd.getSParamValue();
  1013 +// String sRule = pd.getSRule();
  1014 +// String sType = pd.getSType();
  1015 +//
  1016 +// Boolean bCheck = result.containsKey(name);
  1017 +// bCheck = bCheck && ObjectUtil.isNotEmpty(result.get(name));
  1018 +// bCheck = bCheck && RuleCode.SQL.getCode().equals(sRule);
  1019 +// bCheck = bCheck && ObjectUtil.isNotEmpty(pd.getSParamConfig());
  1020 +//
  1021 +// Boolean bCheck2 = result.containsKey(sValue);
  1022 +// bCheck2 = bCheck2 && ObjectUtil.isNotEmpty(result.get(sValue));
  1023 +// bCheck2 = bCheck2 && RuleCode.SQL.getCode().equals(sRule);
  1024 +// bCheck2 = bCheck2 && ObjectUtil.isNotEmpty(pd.getSParamConfig());
  1025 +//
  1026 +// if ((bCheck || bCheck2) &&("enum".equals(sType) || "string".equals(sType))){
  1027 +// String sSql = pd.getSParamConfig();
  1028 +// String sKey = bCheck?name:sValue;
  1029 +// String nameValue = result.get(sKey).toString();
  1030 +// List<Map<String,Object>> dataList = dynamicExeDbService.findSql(result,sSql);
  1031 +// if(ObjectUtil.isEmpty(dataList)){
  1032 +// throw new BusinessException(ErrorCode.PARAM_REQUIRED,String.format("%s 您描述的%s 不存在,请重新告诉我",name,nameValue));
  1033 +// }
  1034 +// if(ObjectUtil.isNotEmpty(args.get(name)) || ObjectUtil.isNotEmpty(args.get(sValue))){
  1035 +// if(("enum".equals(sType) ||"string".equals(sType)) && (args.get(name) instanceof List || args.get(sValue) instanceof List)){
  1036 +// if(args.get(name) instanceof List){
  1037 +// args.put(name,((List<?>) args.get(name)).get(0));
  1038 +// }
  1039 +// if(args.get(sValue) instanceof List){
  1040 +// args.put(sValue,((List<?>) args.get(sValue)).get(0));
  1041 +// }
  1042 +// }
  1043 +// List<Map<String,Object>> dataListNew = dataList.stream().filter(one->
  1044 +// ObjectUtil.isNotEmpty(one.get(sValue))
  1045 +// &&(one.get(sValue).equals(args.get(name))
  1046 +// || one.get(sValue).equals(args.get(sValue)))).collect(Collectors.toUnmodifiableList());
  1047 +//// if("enum".equals(sType) && ObjectUtil.isEmpty(dataListNew)){
  1048 +//// args.remove(name);
  1049 +//// args.remove(sValue);
  1050 +//// result.remove(name);
  1051 +//// result.remove(sValue);
  1052 +//// continue;
  1053 +//// }
  1054 +// if(ObjectUtil.isNotEmpty(dataListNew)){
  1055 +// dataList = new ArrayList<>();
  1056 +// dataList.add(dataListNew.get(0));
  1057 +// }
  1058 +// }
  1059 +// if(ObjectUtil.isNotEmpty(dataList)){
  1060 +// String sCopyTo = pd.getSCopyTo();
  1061 +// if(ObjectUtil.isEmpty(sCopyTo)){
  1062 +// result.put(sValue, dataList.get(0).get(sValue));
  1063 +// result.put(name, dataList.get(0).get(sValue));
  1064 +// }else{
  1065 +// String[] sCopyToA = sCopyTo.split(",");
  1066 +// for(String sCopyToOne:sCopyToA){
  1067 +// String[] sCopyToOneA = sCopyToOne.split(":");
  1068 +// result.put(sCopyToOneA[0], dataList.get(0).get(sCopyToOneA[1]));
  1069 +// result.put(name, dataList.get(0).get(sValue));
  1070 +// }
  1071 +// }
  1072 +// }
  1073 +// }
  1074 +//
  1075 +//
  1076 +// }
1054 return result; 1077 return result;
1055 } 1078 }
1056 1079
src/main/resources/application.yml
@@ -136,7 +136,7 @@ langchain4j: @@ -136,7 +136,7 @@ langchain4j:
136 # 聊天模型配置(用于一般对话) 136 # 聊天模型配置(用于一般对话)
137 base-url: http://112.82.245.194:41434 137 base-url: http://112.82.245.194:41434
138 # chat-model-name: qwen2.5:7b-instruct 138 # chat-model-name: qwen2.5:7b-instruct
139 -# chat-model-name: qwen3.6-27b-iq2:latest 139 +# chat-model-name: qwen3.6-27b-iq2xxs:latest
140 chat-model-name: qwen2.5:14b 140 chat-model-name: qwen2.5:14b
141 # chat-model-name: qwen3:14b 141 # chat-model-name: qwen3:14b
142 # chat-model-name: qwen3.5:9b 142 # chat-model-name: qwen3.5:9b