GRPCController.java 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156
  1. package com.slibra.web.controller.business;
  2. import com.alibaba.fastjson2.JSONObject;
  3. import com.alibaba.fastjson2.JSONWriter;
  4. import com.alibaba.fastjson2.JSON;
  5. import com.google.protobuf.ByteString;
  6. import com.slibra.business.domain.*;
  7. import com.slibra.business.mapper.*;
  8. import com.slibra.business.req.*;
  9. import com.slibra.business.res.WorkOrderRes;
  10. import com.slibra.business.service.IFrontService;
  11. import com.slibra.common.DecimalUtils;
  12. import com.slibra.common.config.BigModelConfig;
  13. import com.slibra.common.core.controller.BaseController;
  14. import com.slibra.common.core.domain.DecisionReq;
  15. import com.slibra.common.core.domain.TXinyiDaily;
  16. import com.slibra.common.enums.BusinessEnum;
  17. import com.slibra.common.exception.ServiceException;
  18. import com.slibra.common.utils.DateUtils;
  19. import com.slibra.common.utils.SecurityUtils;
  20. import com.slibra.common.utils.StringUtils;
  21. import com.slibra.common.utils.format.WaterFormat;
  22. import com.slibra.common.utils.ip.IpUtils;
  23. import com.slibra.common.utils.uuid.IdUtils;
  24. import io.grpc.ManagedChannel;
  25. import io.grpc.ManagedChannelBuilder;
  26. import lombok.extern.slf4j.Slf4j;
  27. import org.pytorch.serve.grpc.inference.InferenceAPIsServiceGrpc;
  28. import org.pytorch.serve.grpc.inference.PredictionResponse;
  29. import org.pytorch.serve.grpc.inference.PredictionsRequest;
  30. import org.springframework.beans.BeanUtils;
  31. import org.springframework.beans.factory.annotation.Autowired;
  32. import org.springframework.beans.factory.annotation.Value;
  33. import org.springframework.util.CollectionUtils;
  34. import org.springframework.web.bind.annotation.*;
  35. import javax.servlet.http.HttpServletRequest;
  36. import javax.servlet.http.HttpServletResponse;
  37. import java.io.IOException;
  38. import java.io.OutputStream;
  39. import java.util.*;
  40. import static com.slibra.common.constant.MyConstants.*;
  41. import static com.slibra.common.enums.BusinessEnum.BigModelBizEnum.DECISION_REPORT;
  42. /**
  43. * 告警相关
  44. */
  45. @RestController
  46. @RequestMapping("/grpc")
  47. @Slf4j
  48. public class GRPCController extends BaseController {
  49. @Autowired
  50. private TXinyiChatRecordMapper chatRecordMapper;
  51. @Autowired
  52. private TXinyiIndustryMapper xinyiIndustryMapper;
  53. @Autowired
  54. private TXinyiDailyMapper xinyiDailyMapper;
  55. @Autowired
  56. private TXinyiChatRecordMapper xinyiChatRecordMapper;
  57. @Autowired
  58. private TXinyiWarningRecordMapper xinyiWarningRecordMapper;
  59. @Autowired
  60. private IFrontService frontService;
  61. @Autowired
  62. private TXinyiNormConfigMapper xinyiNormConfigMapper;
  63. @Autowired
  64. private BigModelConfig bigModelConfig;
  65. // 用户自定义的端口
  66. @Value("${token.port}")
  67. private String port;
  68. /**
  69. *
  70. * get请求测试决策输出
  71. *
  72. * @param response
  73. */
  74. @GetMapping(value = "/test/aaa")
  75. public void decisionStreamTest(HttpServletRequest httpServletRequest, HttpServletResponse response)
  76. // public void decisionStream(HttpServletResponse response, ChatReq chatReq)
  77. {
  78. log.info("进入了调⽤大模型决策接口");
  79. ChatReq chatReq = new ChatReq();
  80. HashMap<String, Object> map = new HashMap<>();
  81. map.put("2_2", "正常");
  82. map.put("4_25", "没有");
  83. map.put("2_28", "否");
  84. map.put("6_3", "超标");
  85. chatReq.setFeedback(JSON.toJSONString(map));
  86. chatReq.setCategory("出水氨氮");
  87. chatReq.setWarningId("782");
  88. chatReq.setSimulate("{}");
  89. // 获取输出流
  90. OutputStream outputStream = null;
  91. ManagedChannel channel = null;
  92. //response.setContentType("text/plain");
  93. response.setContentType("text/event-stream");
  94. response.setCharacterEncoding("utf-8");
  95. //2024年5月29日14:15:58 新增逻辑,判断报警状态是否已经结束了,如果结束了就直接模拟一个report返回给前端,不再调用大模型
  96. String warningId = chatReq.getWarningId();
  97. if(StringUtils.isBlank(warningId))
  98. throw new ServiceException("请输入正确的告警id");
  99. TXinyiWarningRecord xinyiWarningRecord = this.xinyiWarningRecordMapper.selectTXinyiWarningRecordById(Long.parseLong(warningId));
  100. if(Objects.isNull(xinyiWarningRecord))
  101. throw new ServiceException("请输入正确的告警id,没有查询到告警信息");
  102. if(1 == xinyiWarningRecord.getStatus() || 2 == xinyiWarningRecord.getStatus()){
  103. //已经关闭的报警,不允许再次点击报警了
  104. String message = this.buildMsg();
  105. try {
  106. outputStream = response.getOutputStream();
  107. outputStream.write(message.getBytes());
  108. outputStream.flush();
  109. return;//输出完提示信息就结束
  110. } catch (IOException e) {
  111. throw new RuntimeException(e);
  112. }
  113. }
  114. StringBuilder sb = new StringBuilder();
  115. //大模型结果 放入一个结合中
  116. List<String> resultData = new ArrayList<>();
  117. //决策和问答不一样 没有历史的概念 所以sessionId都是新的 次数都是1
  118. String sessionId = IdUtils.simpleUUID();
  119. String feedback = chatReq.getFeedback();
  120. String simulate = chatReq.getSimulate();
  121. int type = 3;//仿真预测
  122. if(StringUtils.isBlank(simulate) || "{}".equals(simulate))
  123. type = 1;//决策
  124. //决策请求的业务参数
  125. List<DecisionReq> decisionReqs = getDecisionReqs();
  126. // String rows = JSON.toJSONString(decisionReqs, JSONWriter.Feature.WriteNulls);
  127. boolean needAdd = true;//标识变量是否可以保存
  128. String dataJson = "";
  129. String headerPort = httpServletRequest.getHeader(port);
  130. try {
  131. channel = ManagedChannelBuilder.forAddress(bigModelConfig.getIp(), StringUtils.isBlank(headerPort) ? bigModelConfig.getPort() : Integer.parseInt(headerPort))
  132. .usePlaintext()
  133. .build();
  134. InferenceAPIsServiceGrpc.InferenceAPIsServiceBlockingStub stub = InferenceAPIsServiceGrpc.newBlockingStub(channel);
  135. // dataJson = "{\"bot_id\":\"b00001\",\"exp_id\":\"721\",\"norm\":\"" + chatReq.getCategory() + "\",\"feedback\":" + feedback + ",\"simulate\":" + simulate + ",\"session_id\":" + "\"" + sessionId + "\"" + ",\"generate_args\":{\"max_new_tokens\":1024,\"max_length\":4096,\"num_beams\":1,\"do_sample\":true,\"top_p\":0.7,\"temperature\":0.95},\"extra\":{\"rows\":" + rows + "}}";
  136. //2024年6月24日17:59:17 优化,不再拼接JSON字符串
  137. dataJson = buildBigModelReqForDecision(chatReq, feedback, simulate, sessionId, decisionReqs, xinyiWarningRecord, chatReq.getTopP(), chatReq.getTemperature());
  138. // log.info("请求大模型的决策的参数为{}", dataJson);
  139. PredictionsRequest request = PredictionsRequest.newBuilder()
  140. .setModelName("slibra_bot")
  141. .putInput("method", ByteString.copyFrom("decision_stream", "utf-8"))//推理
  142. .putInput("data", ByteString.copyFrom(dataJson, "utf-8"))
  143. .buildPartial();
  144. outputStream = response.getOutputStream();
  145. Iterator<PredictionResponse> predictions = stub.streamPredictions(request);
  146. int i = 0 ;
  147. while (predictions.hasNext()) {
  148. String responseStr = predictions.next().getPrediction().toStringUtf8();
  149. // log.info("决策流式返回的结果是{}", responseStr);
  150. if(StringUtils.isBlank(responseStr)){
  151. log.info("大模型返回的流式决策内容存在空的值,跳过此次输出");
  152. continue;
  153. }
  154. String message = JSON.parseObject(responseStr).getString("message");
  155. //2024年5月25日16:37:16 按照大模型返回的类型解析数据
  156. String biz = JSON.parseObject(responseStr).getString("biz");
  157. // String message = JSON.parseObject(responseStr).getString("message");
  158. if(BusinessEnum.BigModelBizEnum.OK.getCode().equals(biz)){
  159. log.info("结尾语句并且是非JSON,无需处理,返回数据为{}", responseStr);
  160. //结束语句也流式输出,但是并不记录下来 2024年5月24日11:15:23 也不返回前端
  161. }else if(BusinessEnum.BigModelBizEnum.DECISION_DEBUGGER.getCode().equals(biz)){
  162. log.info("中间过程,目前只打印日志,不记录数据,也不返回给前端,返回数据为{}", responseStr);
  163. //结束语句也流式输出,但是并不记录下来 2024年5月24日11:15:23 也不返回前端
  164. //2024年6月23日14:55:19 如果大模型返回error了,不保存记录,并且提示一句错误语
  165. }else if(BusinessEnum.BigModelBizEnum.ERROR.getCode().equalsIgnoreCase(biz)){
  166. log.info("调用大模型的时候,返回的是ERROR,返回数据为{}", responseStr);
  167. needAdd = false;
  168. //返回的是error 给前端返回一句话
  169. try {
  170. String errMsg = this.buildErrMsg();
  171. outputStream.write(errMsg.getBytes());
  172. outputStream.flush();
  173. } catch (IOException ex) {
  174. throw new RuntimeException(ex);
  175. }
  176. } else{//其他 要么alert 要么出的报告
  177. // if(StringUtils.isBlank(message)){
  178. // log.info("×××××××××××××××××××××××××××为空的数据暂时不返回×××××××××××××××××××××××××××");
  179. // }else {
  180. // log.info("返回给前端的数据是{}", responseStr);
  181. resultData.add(responseStr);
  182. responseStr = responseStr + (i++) + "\n";
  183. outputStream.write(responseStr.getBytes());
  184. outputStream.flush();
  185. //2024年7月12日17:47:08 加个打印,处理只要report类型的拼接结果
  186. if(BusinessEnum.BigModelBizEnum.DECISION_REPORT.getCode().equalsIgnoreCase(biz)){
  187. sb.append(message);
  188. }
  189. // }
  190. }
  191. }
  192. } catch (Exception e) {
  193. // throw new RuntimeException(e);
  194. log.error("处理大模型推理异常,异常信息为{}", JSON.toJSONString(e));
  195. //出现异常 给前端返回一句话
  196. try {
  197. outputStream = response.getOutputStream();
  198. String errMsg = this.buildErrMsg();
  199. outputStream.write(errMsg.getBytes());
  200. outputStream.flush();
  201. } catch (IOException ex) {
  202. throw new RuntimeException(ex);
  203. }
  204. } finally {
  205. // log.info("sessionId是{}\n决策最终要保存的数据是{}", sessionId, JSON.toJSONString(resultData));
  206. // log.info("~~~~~~~~~~~~~~~决策最终返回的报告数据是{}", sb.toString());
  207. //保存聊天记录
  208. //将问答更新到数据库中
  209. needAdd = false;
  210. if(needAdd)
  211. addChatRecord(chatReq, sessionId, type, warningId, dataJson, resultData);
  212. // 关闭输出流
  213. try {
  214. outputStream.close();
  215. } catch (IOException e) {
  216. throw new RuntimeException(e);
  217. }finally {
  218. channel.shutdown();
  219. }
  220. }
  221. }
  222. /**
  223. * 调⽤大模型决策接口 + 仿真预测
  224. * @return
  225. */
  226. @PostMapping(value = "/decisionStream")
  227. public void decisionStream(HttpServletRequest httpServletRequest, HttpServletResponse response, @RequestBody ChatReq chatReq)
  228. // public void decisionStream(HttpServletResponse response, ChatReq chatReq)
  229. {
  230. log.info("进入了调⽤大模型决策接口");
  231. // 获取输出流
  232. OutputStream outputStream = null;
  233. ManagedChannel channel = null;
  234. //response.setContentType("text/plain");
  235. response.setContentType("text/event-stream");
  236. response.setCharacterEncoding("utf-8");
  237. //2024年5月29日14:15:58 新增逻辑,判断报警状态是否已经结束了,如果结束了就直接模拟一个report返回给前端,不再调用大模型
  238. String warningId = chatReq.getWarningId();
  239. if(StringUtils.isBlank(warningId))
  240. throw new ServiceException("请输入正确的告警id");
  241. TXinyiWarningRecord xinyiWarningRecord = this.xinyiWarningRecordMapper.selectTXinyiWarningRecordById(Long.parseLong(warningId));
  242. if(Objects.isNull(xinyiWarningRecord))
  243. throw new ServiceException("请输入正确的告警id,没有查询到告警信息");
  244. if(1 == xinyiWarningRecord.getStatus() || 2 == xinyiWarningRecord.getStatus()){
  245. //已经关闭的报警,不允许再次点击报警了
  246. String message = this.buildMsg();
  247. try {
  248. outputStream = response.getOutputStream();
  249. outputStream.write(message.getBytes());
  250. outputStream.flush();
  251. return;//输出完提示信息就结束
  252. } catch (IOException e) {
  253. throw new RuntimeException(e);
  254. }
  255. }
  256. // StringBuilder sb = new StringBuilder();
  257. //大模型结果 放入一个结合中
  258. List<String> resultData = new ArrayList<>();
  259. //决策和问答不一样 没有历史的概念 所以sessionId都是新的 次数都是1
  260. String sessionId = IdUtils.simpleUUID();
  261. String feedback = chatReq.getFeedback();
  262. String simulate = chatReq.getSimulate();
  263. int type = 3;//仿真预测
  264. if(StringUtils.isBlank(simulate) || "{}".equals(simulate))
  265. type = 1;//决策
  266. //决策请求的业务参数
  267. List<DecisionReq> decisionReqs = getDecisionReqs();
  268. // String rows = JSON.toJSONString(decisionReqs, JSONWriter.Feature.WriteNulls);
  269. boolean needAdd = true;//标识变量是否可以保存
  270. String dataJson = "";
  271. String headerPort = httpServletRequest.getHeader(port);
  272. try {
  273. channel = ManagedChannelBuilder.forAddress(bigModelConfig.getIp(), StringUtils.isBlank(headerPort) ? bigModelConfig.getPort() : Integer.parseInt(headerPort))
  274. .usePlaintext()
  275. .build();
  276. InferenceAPIsServiceGrpc.InferenceAPIsServiceBlockingStub stub = InferenceAPIsServiceGrpc.newBlockingStub(channel);
  277. // dataJson = "{\"bot_id\":\"b00001\",\"exp_id\":\"721\",\"norm\":\"" + chatReq.getCategory() + "\",\"feedback\":" + feedback + ",\"simulate\":" + simulate + ",\"session_id\":" + "\"" + sessionId + "\"" + ",\"generate_args\":{\"max_new_tokens\":1024,\"max_length\":4096,\"num_beams\":1,\"do_sample\":true,\"top_p\":0.7,\"temperature\":0.95},\"extra\":{\"rows\":" + rows + "}}";
  278. //2024年6月24日17:59:17 优化,不再拼接JSON字符串
  279. dataJson = buildBigModelReqForDecision(chatReq, feedback, simulate, sessionId, decisionReqs, xinyiWarningRecord, chatReq.getTopP(), chatReq.getTemperature());
  280. // log.info("请求大模型的决策的参数为{}", dataJson);
  281. PredictionsRequest request = PredictionsRequest.newBuilder()
  282. .setModelName("slibra_bot")
  283. .putInput("method", ByteString.copyFrom("decision_stream", "utf-8"))//推理
  284. .putInput("data", ByteString.copyFrom(dataJson, "utf-8"))
  285. .buildPartial();
  286. outputStream = response.getOutputStream();
  287. Iterator<PredictionResponse> predictions = stub.streamPredictions(request);
  288. while (predictions.hasNext()) {
  289. String responseStr = predictions.next().getPrediction().toStringUtf8();
  290. // log.info("决策流式返回的结果是{}", responseStr);
  291. if(StringUtils.isBlank(responseStr)){
  292. log.info("大模型返回的流式决策内容存在空的值,跳过此次输出");
  293. continue;
  294. }
  295. // String message = JSON.parseObject(responseStr).getString("message");
  296. //2024年5月25日16:37:16 按照大模型返回的类型解析数据
  297. String biz = JSON.parseObject(responseStr).getString("biz");
  298. // String message = JSON.parseObject(responseStr).getString("message");
  299. if(BusinessEnum.BigModelBizEnum.OK.getCode().equals(biz)){
  300. log.info("结尾语句并且是非JSON,无需处理,返回数据为{}", responseStr);
  301. //结束语句也流式输出,但是并不记录下来 2024年5月24日11:15:23 也不返回前端
  302. }else if(BusinessEnum.BigModelBizEnum.DECISION_DEBUGGER.getCode().equals(biz)){
  303. log.info("中间过程,目前只打印日志,不记录数据,也不返回给前端,返回数据为{}", responseStr);
  304. //结束语句也流式输出,但是并不记录下来 2024年5月24日11:15:23 也不返回前端
  305. //2024年6月23日14:55:19 如果大模型返回error了,不保存记录,并且提示一句错误语
  306. }else if(BusinessEnum.BigModelBizEnum.ERROR.getCode().equalsIgnoreCase(biz)){
  307. log.info("调用大模型的时候,返回的是ERROR,返回数据为{}", responseStr);
  308. needAdd = false;
  309. //返回的是error 给前端返回一句话
  310. try {
  311. String errMsg = this.buildErrMsg();
  312. outputStream.write(errMsg.getBytes());
  313. outputStream.flush();
  314. } catch (IOException ex) {
  315. throw new RuntimeException(ex);
  316. }
  317. } else{//其他 要么alert 要么出的报告
  318. // sb.append(responseStr);
  319. //2024年7月13日13:48:48 空的数据也返回,否则样式会有问题(当时加上这个是为了前端正常解析,否则他那里一次接受多个)
  320. /*if(StringUtils.isBlank(message)){
  321. log.info("×××××××××××××××××××××××××××为空的数据暂时不返回×××××××××××××××××××××××××××");
  322. }else {
  323. resultData.add(responseStr);
  324. outputStream.write(responseStr.getBytes());
  325. outputStream.flush();
  326. }*/
  327. resultData.add(responseStr);
  328. outputStream.write(responseStr.getBytes());
  329. outputStream.flush();
  330. }
  331. }
  332. } catch (Exception e) {
  333. needAdd = false;
  334. // throw new RuntimeException(e);
  335. log.error("处理大模型推理异常,异常信息为{}", JSON.toJSONString(e));
  336. //出现异常 给前端返回一句话
  337. try {
  338. outputStream = response.getOutputStream();
  339. String errMsg = this.buildErrMsg();
  340. outputStream.write(errMsg.getBytes());
  341. outputStream.flush();
  342. } catch (IOException ex) {
  343. // throw new RuntimeException(ex);
  344. log.error("输出异常信义的时候又被中断了,异常信息为{}", JSON.toJSONString(ex));
  345. }
  346. } finally {
  347. // log.info("sessionId是{}\n决策最终要保存的数据是{}", sessionId, JSON.toJSONString(resultData));
  348. //保存聊天记录
  349. //将问答更新到数据库中
  350. if(needAdd)
  351. addChatRecord(chatReq, sessionId, type, warningId, dataJson, resultData);
  352. // 关闭输出流
  353. try {
  354. outputStream.close();
  355. } catch (IOException e) {
  356. throw new RuntimeException(e);
  357. }finally {
  358. channel.shutdown();
  359. }
  360. }
  361. }
  362. private String buildBigModelReqForDecision(ChatReq chatReq, String feedback, String simulate, String sessionId, List<DecisionReq> decisionReqs, TXinyiWarningRecord xinyiWarningRecord, Double topP, Double temperature) {
  363. PolicyReq policyReq = new PolicyReq();
  364. //2024年7月11日17:57:53 因为化验室的改了 但是 调用决策还得用原来的几个值
  365. String category = xinyiWarningRecord.getCategory();
  366. /*if(ROBOT_XSY_1.getCode().equalsIgnoreCase(category) || ROBOT_XSY_2.getCode().equalsIgnoreCase(category)){
  367. category = CS_ZD.getCode();
  368. } else if (ROBOT_ANDAN_1.getCode().equalsIgnoreCase(category) || ROBOT_ANDAN_2.getCode().equalsIgnoreCase(category)) {
  369. category = CS_AD.getCode();
  370. }else if (ROBOT_ECCZLSY.getCode().equalsIgnoreCase(category)) {
  371. category = CS_ZL.getCode();
  372. }*/
  373. //2024年08月25日15:40:31 处理数据映射,改成字母,但是显示的还是中文
  374. category = this.parseCategory(category);
  375. policyReq.setNorm(category);
  376. // policyReq.setNorm(chatReq.getCategory());//2024年7月12日16:23:24 因为有转义。。。
  377. policyReq.setFeedback(StringUtils.isBlank(feedback) ? null : JSON.parseObject(feedback, Map.class));
  378. policyReq.setSimulate(StringUtils.isBlank(simulate) ? null : JSON.parseObject(simulate, Map.class));
  379. policyReq.setSessionId(sessionId);
  380. //2024年7月5日13:24:10 temperature做区分
  381. GenerateArgs generateArgs = new GenerateArgs();
  382. generateArgs.setTemperature(Objects.isNull(temperature) ? bigModelConfig.getTemperature() : temperature);
  383. generateArgs.setTopP(Objects.isNull(topP) ? bigModelConfig.getTopP() : topP);
  384. policyReq.setGenerateArgs(generateArgs);
  385. HashMap<String, Object> map = new HashMap<>();
  386. map.put("rows", decisionReqs);
  387. //2024年6月25日14:16:05 增加报警是管控值报警还是标准值报警
  388. if(WARNING_LEVEL_ONE.equals(xinyiWarningRecord.getLevel()) || WARNING_LEVEL_TWO.equals(xinyiWarningRecord.getLevel()))
  389. map.put("source", "bzz");
  390. else
  391. map.put("source", "gkz");
  392. policyReq.setExtra(map);
  393. return JSON.toJSONString(policyReq, JSONWriter.Feature.WriteNulls);
  394. }
  395. private String parseCategory(String category) {
  396. switch (category) {
  397. case "进水COD" : return "js_cod";
  398. case "进水总磷" : return "js_tp";
  399. case "进水总氮" : return "js_tn";
  400. case "进水氨氮" : return "js_andan";
  401. case "进水SS" : return "js_ss";
  402. case "出水COD" : return "cs_cod";
  403. case "出水总磷" : return "cs_tp";
  404. case "出水总氮" : return "cs_tn";
  405. case "出水氨氮" : return "cs_andan";
  406. case "出水SS" : return "cs_ss";
  407. case "#1好氧硝酸盐" : return "cs_tn_lxjc1";
  408. case "#2好氧硝酸盐" : return "cs_tn_lxjc2";
  409. case "出水氨氮连续检测" : return "cs_andan_lxjc1";
  410. case "二沉池正磷酸盐" : return "cs_tp_lxjc";
  411. default: throw new ServiceException("暂时不支持的类型");
  412. }
  413. }
  414. private void addChatRecord(ChatReq chatReq, String sessionId, int type, String warningId, String question, List<String> resultData) {
  415. chatReq.setSessionId(sessionId);
  416. chatReq.setType(type);//类型(0问答 1决策 2本地 3仿真预测)
  417. chatReq.setModule(3);//0=专家问答,1=智能工单,2=智能体助手,3.告警
  418. // String showVal = this.buildShowValue(tXinyiWarningRecord, tXinyiIndustry, normConfig);
  419. // chatReq.setShowVal(feedback);//前端展示的数据和提问的数据不一致
  420. //如果主动调用决策 showVal应该是最新的那条历史记录对应的数据
  421. List<TXinyiChatRecord> tXinyiChatRecords = this.xinyiChatRecordMapper.selectTXinyiChatRecordList(TXinyiChatRecord.builder().warningId(warningId).build());
  422. if(!CollectionUtils.isEmpty(tXinyiChatRecords))
  423. chatReq.setShowVal(tXinyiChatRecords.get(0).getShowVal());
  424. chatReq.setQuestion(question);
  425. chatReq.setAnswer(JSON.toJSONString(resultData));
  426. chatReq.setWarningId(warningId);
  427. chatReq.setCounts(1);//问答次数
  428. String userId = SecurityUtils.getUserId().toString();
  429. String username = SecurityUtils.getUsername();
  430. chatReq.setUserId(userId);
  431. chatReq.setCreateBy(username);
  432. chatReq.setCreateTime(DateUtils.getNowDate());
  433. this.xinyiChatRecordMapper.insertTXinyiChatRecord(chatReq);
  434. }
  435. private List<DecisionReq> getDecisionReqs() {
  436. //List<HashMap<String, Object>> list = this.xinyiIndustryMapper.selectLast10RecordsForDecision();
  437. //2024年5月21日15:23:07 这里不能用关联查询处理,日报要获取最新的一条而不是今日的数据。
  438. List<DecisionReq> decisionReqs = this.xinyiIndustryMapper.selectLast10RecordsForDecisionOnlyIndustry();
  439. if(!CollectionUtils.isEmpty(decisionReqs)){
  440. //处理日报数据
  441. TXinyiDaily daily = this.xinyiDailyMapper.selectNewestData();
  442. for (DecisionReq decisionReq : decisionReqs) {
  443. if(!Objects.isNull(daily)){
  444. WaterFormat.getWaterDecimationData(decisionReq, daily);
  445. }
  446. }
  447. }
  448. return decisionReqs;
  449. }
  450. private String buildErrMsg() {
  451. JSONObject jsonObject = new JSONObject();
  452. jsonObject.put("biz", DECISION_REPORT.getCode());
  453. jsonObject.put("message", "大模型决策方案生成有点问题,请稍后再试");
  454. return JSON.toJSONString(jsonObject);
  455. }
  456. private String buildMsg() {
  457. JSONObject jsonObject = new JSONObject();
  458. jsonObject.put("biz", DECISION_REPORT.getCode());
  459. jsonObject.put("message", "此报警已经关闭了,无法生成决策方案");
  460. return JSON.toJSONString(jsonObject);
  461. }
  462. /**
  463. * RAG+⼤模型的调⽤参数
  464. * 2024年6月17日09:40:38 工单新增 自定义工单处理
  465. * @return
  466. */
  467. @PostMapping(value = "/inferStreamRag")
  468. public void inferStreamRag(HttpServletRequest httpServletRequest, HttpServletResponse response, @RequestBody ChatReq chatReq) {
  469. // public void inferStreamRag(HttpServletResponse response, ChatReq chatReq) {
  470. log.info("进入了调⽤RAG+⼤模型的调⽤参数");
  471. long time1 = System.currentTimeMillis();
  472. log.info("开始进来的时间是{}",time1);
  473. // 获取输出流
  474. OutputStream outputStream = null;
  475. ManagedChannel channel = null;
  476. // response.setContentType("text/plain");
  477. response.setContentType("text/event-stream");
  478. response.setCharacterEncoding("utf-8");
  479. //2025年04月14日09:12:38 小程序,真机调用失败,尝试修改
  480. // 1. 设置传输编码为chunked
  481. // response.setHeader("Transfer-Encoding", "chunked");
  482. // // 2. 禁用内容长度(否则会禁用chunked模式)
  483. // response.setHeader("Content-Length", null);
  484. //请求参数
  485. Integer module = chatReq.getModule();//来自那个模块
  486. Date reportDate = chatReq.getReportDate();//如果传过值来了 代表的是工单类型的问答
  487. String timeBegin = chatReq.getTimeBegin();
  488. String timeEnd = chatReq.getTimeEnd();
  489. if((Objects.isNull(reportDate) && StringUtils.isBlank(timeBegin) && StringUtils.isBlank(timeEnd)) && module == 1){//工单 必须要输入日期
  490. //智能工单需要传入一个时间的参数
  491. try {
  492. outputStream = response.getOutputStream();
  493. outputStream.write(CHAT_GONGDAN_1_ERROR_MSG.getBytes());
  494. outputStream.flush();
  495. } catch (IOException e) {
  496. throw new RuntimeException(e);
  497. }
  498. return;
  499. }
  500. StringBuilder sb = new StringBuilder();
  501. String sessionId = chatReq.getSessionId();
  502. int isStrong = Objects.isNull(chatReq.getIsStrong()) ? 0 : chatReq.getIsStrong();
  503. String tools = STR_FALSE;//问答因为不确认是否走工具,所以传true; 但是工单一定是走工具的,传工具名称 2024年08月11日15:51:33 只有工具才是具体名称
  504. boolean useRag = true;//只有问答才传true,其他默认都false
  505. String extraStr = "";
  506. //如果是工单,需要特殊处理一下showVal和question
  507. if(1 == module){
  508. if(StringUtils.isBlank(timeBegin) && StringUtils.isBlank(timeEnd)){//按天生成工单
  509. //获取前一天的日期
  510. Date beforeYesterday = DateUtils.plusDate(-1, reportDate);
  511. //先用日期获取当天和前一天的数据,如果获取不到,则提示错误信息
  512. String date = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, reportDate);
  513. chatReq.setShowVal(GONGDAN_TITLE.replace("#{0}", date));//处理展示的标题
  514. /*String dateBefore = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, beforeYesterday);
  515. String currentDate = DateUtils.parseDateToStr(DateUtils.YYYYMMDD_TS, reportDate);
  516. String earlyDate = DateUtils.parseDateToStr(DateUtils.YYYYMMDD_TS, beforeYesterday);
  517. List<TXinyiDaily> tXinyiDailiesNow = this.xinyiDailyMapper.selectTXinyiDailyList(TXinyiDaily.builder().testDate(currentDate).build());
  518. List<TXinyiDaily> tXinyiDailiesBefore = this.xinyiDailyMapper.selectTXinyiDailyList(TXinyiDaily.builder().testDate(earlyDate).build());
  519. if(CollectionUtils.isEmpty(tXinyiDailiesNow) || CollectionUtils.isEmpty(tXinyiDailiesBefore)){
  520. //没有查询到数据
  521. try {
  522. outputStream = response.getOutputStream();
  523. outputStream.write(CHAT_GONGDAN_2_ERROR_MSG.getBytes());
  524. outputStream.flush();
  525. } catch (IOException e) {
  526. throw new RuntimeException(e);
  527. }
  528. return;
  529. }
  530. //如果查询到了 拼装数据
  531. //2024年6月25日19:11:49 prompt优化
  532. chatReq.setQuestion(this.buildGDQuestionNew(date, dateBefore, tXinyiDailiesNow.get(0), tXinyiDailiesBefore.get(0)));*/
  533. //2024年7月29日11:38:53 工单改版,由大模型处理数据
  534. // chatReq.setQuestion(this.buildGDNormalQuestion(DateUtils.parseDateToStr(DateUtils.YYYYMMDD_TS, reportDate)));
  535. chatReq.setQuestion(MODULE_CONTENT_NORMAL);
  536. extraStr = this.buildGDNormalQuestion(DateUtils.parseDateToStr(DateUtils.YYYYMMDD_TS, reportDate));
  537. }else{//自定义工单
  538. chatReq.setShowVal(GONGDAN_TITLE_CUSTOM.replace("#{0}", timeBegin).replace("#{1}", timeEnd));//处理展示的标题
  539. WorkOrderReq workOrderReq = new WorkOrderReq();
  540. BeanUtils.copyProperties(chatReq, workOrderReq);
  541. //拿到数据
  542. List<WorkOrderRes> workOrderRes = frontService.customWorkOrder(workOrderReq);
  543. //拼接prompt
  544. /*String question = this.buildGDQuestionCustom(workOrderRes, workOrderReq);
  545. //2024年6月23日17:21:58 判断问题的长度,如果长度大于配置的值(5000),提示一句话
  546. if(question.length() > MAX_QUESTION_LENGTH){
  547. log.info("*************自定义工单超长了,组装完的参数为{}", question);
  548. try {
  549. outputStream = response.getOutputStream();
  550. outputStream.write(CHAT_GONGDAN_CUSTOM_ERROR_MSG.getBytes());
  551. outputStream.flush();
  552. } catch (IOException e) {
  553. throw new RuntimeException(e);
  554. }
  555. return;
  556. }*/
  557. //2024年7月29日11:47:05 调整:图表以及大模型的数据都由大模型处理,这里拼接他需要的格式
  558. // chatReq.setQuestion(this.buildGDCustomQuestion(timeBegin, timeEnd, chatReq.getWhichWay()));
  559. chatReq.setQuestion(MODULE_CONTENT_CUSTOM);
  560. extraStr = buildGDCustomQuestion(timeBegin, timeEnd, chatReq);
  561. //2024年6月20日16:48:08 如果是自定义工单,需要处理图表 放到remark中
  562. chatReq.setRemark(JSON.toJSONString(frontService.customWorkOrderHandleByData(workOrderReq, workOrderRes), JSONWriter.Feature.WriteNulls));
  563. }
  564. isStrong = 0;//2024年7月29日14:15:47 工单不走文心一言了
  565. useRag = false;
  566. tools = TOOLS_WORK_ORDER;
  567. }
  568. String ipAddr = IpUtils.getIpAddr();//获取用户的ip地址 传给大模型
  569. int counts = 1;//默认是第一次
  570. List<String> historyDates = new ArrayList<>();
  571. //查询历史数据,放入集合中
  572. if(StringUtils.isBlank(sessionId))
  573. sessionId= IdUtils.simpleUUID();//第一次
  574. else{
  575. //通过sessionId获取所有的问答记录
  576. List<TXinyiChatRecord> chatRecords = this.chatRecordMapper.selectTXinyiChatRecordList(TXinyiChatRecord.builder().sessionId(sessionId).build());
  577. if(!CollectionUtils.isEmpty(chatRecords)){
  578. for (TXinyiChatRecord chatRecord : chatRecords) {
  579. historyDates.add(chatRecord.getQuestion());
  580. historyDates.add(chatRecord.getAnswer());
  581. }
  582. //问答次数增加
  583. counts = chatRecords.size() + 1;
  584. }
  585. }
  586. //将新的问题放入集合中
  587. historyDates.add(chatReq.getQuestion());
  588. String headerPort = httpServletRequest.getHeader(port);
  589. long time2 = System.currentTimeMillis();
  590. log.info("开始调用大模型的的时间是{}",time2);
  591. log.info("调用大模型之前,处理历史会话等操作的时间为{}", (time2 - time1)/1000);
  592. try {
  593. channel = ManagedChannelBuilder.forAddress(bigModelConfig.getIp(), StringUtils.isBlank(headerPort) ? bigModelConfig.getPort() : Integer.parseInt(headerPort))
  594. .usePlaintext()
  595. .build();
  596. InferenceAPIsServiceGrpc.InferenceAPIsServiceBlockingStub stub = InferenceAPIsServiceGrpc.newBlockingStub(channel);
  597. // String dataJson = "{\"bot_id\":\"721\",\"exp_id\":\"721\",\"session_id\":\"" + sessionId + "\",\"use_rag\":\"true\",\"prompt\":\"你是LibraAI水务大模型,由红杉天枰开发的水务垂直大语言模型,能够提供水务行业专家问答、智能决策、报表分析、智能工单管理等一系列功能,作为水务人的AI助手,你会竭尽全力帮助我处理工作问题。\",\"history_dia\":" + JSON.toJSONString(historyDates) + ",\"generate_args\":{\"max_new_tokens\":2048,\"max_length\":4096,\"num_beams\":1,\"do_sample\":true,\"top_p\":0.7,\"temperature\":0.95},\"extra\":{ \"ip_address\": \"" + ipAddr + "\" },\"strengthen\":" + (isStrong == 1) + "}";
  598. //2024年6月25日18:12:23 优化,不再使用拼接JSON字符串
  599. //2024年7月27日18:13:47 前端传过来tools
  600. String toolsReq = chatReq.getTools();
  601. //2024年7月29日14:20:22 先判断是不是走本地工具,再判断前端工具
  602. //2024年08月11日15:54:52 问答默认都是false了,只有前端指定工具才是具体的工具名称
  603. // if(StringUtils.isBlank(tools) || STR_TRUE.equals(tools)){
  604. if(StringUtils.isNotBlank(toolsReq)){
  605. useRag = false;//2024年7月27日18:20:23 走本地工具,不需要文本增强
  606. isStrong = 0;
  607. tools = toolsReq;
  608. }
  609. //2024年08月21日11:49:25 如果是智慧办公,useRag也是false
  610. if(2 == module){//智慧办公
  611. useRag = false;
  612. }
  613. // else
  614. // tools = tools;
  615. // }
  616. String dataJson = buildBigModelReqForChat(sessionId, historyDates, ipAddr, isStrong, chatReq.getTopP(), chatReq.getTemperature(), tools, useRag, extraStr, chatReq.getPrompt(), chatReq.getModelType(), chatReq.getOnlineSearch());
  617. log.info("******请求大模型的问答参数为{}", dataJson);
  618. PredictionsRequest request = PredictionsRequest.newBuilder()
  619. .setModelName("slibra_bot")
  620. .putInput("method", ByteString.copyFrom("infer_stream", "utf-8"))//推理
  621. .putInput("data", ByteString.copyFrom(dataJson, "utf-8"))
  622. .buildPartial();
  623. outputStream = response.getOutputStream();
  624. Iterator<PredictionResponse> predictions = stub.streamPredictions(request);
  625. //将结果记录到问答表
  626. while (predictions.hasNext()) {
  627. String responseStr = predictions.next().getPrediction().toStringUtf8();
  628. // log.info("大模型问答返回的原始结果为{}", responseStr);
  629. if(StringUtils.isBlank(responseStr)){
  630. log.error("大模型返回的是空,无法解析");
  631. continue;
  632. }
  633. responseStr = JSON.parseObject(responseStr).getString("message");
  634. //2025年04月14日11:16:23 由于小程序演示,需要把“信义”替换成“LibraAI”
  635. //todo 演示结束后,去掉下面的替换
  636. responseStr = responseStr.replaceAll("信义", "LibraAI");
  637. //2024年7月13日14:30:19 为空字符串的(实际可能是\n这种的)也返回前端,否则样式有问题
  638. // if("complete".equals(responseStr) || StringUtils.isBlank(responseStr)){
  639. if("complete".equals(responseStr)){
  640. // System.out.println("结尾语句并且是非JSON,无需处理");
  641. log.info("返回的结果message为{},无需再次处理", responseStr);
  642. //结束语句也流式输出,但是并不记录下来 2024年5月24日11:15:23 也不返回前端
  643. }else{
  644. sb.append(responseStr);
  645. outputStream.write(responseStr.getBytes());
  646. outputStream.flush();
  647. }
  648. }
  649. long time3 = System.currentTimeMillis();
  650. log.info("结束调用大模型的的时间是{}",time3);
  651. log.info("调用的时间为{}", (time3 - time2)/1000);
  652. //将问答更新到数据库中
  653. chatReq.setSessionId(sessionId);
  654. chatReq.setAnswer(sb.toString());
  655. chatReq.setType(0);//0问答 1决策 2本地 3仿真预测
  656. chatReq.setModule(module);//0专家问答 1智能工单 2智能体助手 3告警 4简报
  657. //2024年5月28日10:58:02 由于部分问题 展示的和调用大模型的不一样,所以这个由前端传过来
  658. // chatReq.setShowVal(question);
  659. chatReq.setCounts(counts);//问答次数
  660. String userId = SecurityUtils.getUserId().toString();
  661. String username = SecurityUtils.getUsername();
  662. chatReq.setUserId(userId);
  663. chatReq.setCreateBy(username);
  664. chatReq.setCreateTime(DateUtils.getNowDate());
  665. this.chatRecordMapper.insertTXinyiChatRecord(chatReq);
  666. outputStream.write((DEFAULT_ID_IDENTIFIER + chatReq.getId()).getBytes());
  667. outputStream.flush();
  668. long time4 = System.currentTimeMillis();
  669. log.info("最后操作的时间是{}",time4);
  670. log.info("最后操作的时间是{}", (time4 - time3)/1000);
  671. } catch (IOException e) {
  672. throw new RuntimeException(e);
  673. } finally {
  674. // 关闭输出流
  675. try {
  676. outputStream.close();
  677. } catch (IOException e) {
  678. throw new RuntimeException(e);
  679. }finally {
  680. channel.shutdown();
  681. }
  682. }
  683. // return AjaxResult.success("ok");
  684. }
  685. private String buildGDCustomQuestion(String timeBegin, String timeEnd, ChatReq chatReq) {
  686. //存放的JSON
  687. HashMap<String, Object> map = new HashMap<>();
  688. map.put(TIMEBEGIN, timeBegin);
  689. map.put(TIMEEND, timeEnd);
  690. map.put(MODULE, MODULE_CONTENT_CUSTOM);
  691. map.put(TYPE, CUSTOM_WORK_ORDER);
  692. //拼装的SQL
  693. HashMap<String, Object> sqlMap = new HashMap<>();
  694. StringBuilder sb = new StringBuilder();
  695. if(chatReq.getWhichWay() == 0){//日报
  696. // sqlMap.put(REPORT, sb.append(TOOLS_WORK_ORDER_SQL_DAILY).append(TOOLS_WORK_ORDER_SQL_DIAN_BEGIN).append(TIMEBEGIN).append(TOOLS_WORK_ORDER_SQL_DIAN_END).append(TOOLS_WORK_ORDER_SQL_AND).append(TOOLS_WORK_ORDER_SQL_DIAN_BEGIN).append(TIMEEND).append(TOOLS_WORK_ORDER_SQL_DIAN_END).append(TOOLS_WORK_ORDER_SQL_END).toString());
  697. //2024年7月31日10:32:14 要根据前端用户选择的不同指标来拼接不同的SQL
  698. //只要出现一个就可以拼接了
  699. if (chatReq.getJsSlq() || chatReq.getJsCod() || chatReq.getJsTn() || chatReq.getJsTp() || chatReq.getJsNh3() || chatReq.getJsSs()
  700. || chatReq.getCsSlqc() || chatReq.getCsCod() || chatReq.getCsTn() || chatReq.getCsTp() || chatReq.getCsNh3() || chatReq.getCsSs()){
  701. //拼接
  702. sb.append(TOOLS_WORK_ORDER_SQL_DAILY_BEGIN);
  703. if(chatReq.getJsSlq())
  704. sb.append(",AVG(JSL) 进水量");
  705. if(chatReq.getJsCod())
  706. sb.append(",AVG(JS_COD) 进水COD");
  707. if(chatReq.getJsTn())
  708. sb.append(",AVG(JS_TN) 进水总氮");
  709. if(chatReq.getJsTp())
  710. sb.append(",AVG(JS_TP) 进水总磷");
  711. if(chatReq.getJsNh3())
  712. sb.append(",AVG(JS_NH3) 进水氨氮");
  713. if(chatReq.getJsSs())
  714. sb.append(",AVG(JS_SS) 进水SS");
  715. if(chatReq.getCsSlqc())
  716. sb.append(",AVG(CSL) 出水量");
  717. if(chatReq.getCsCod())
  718. sb.append(",AVG(CS_COD) 出水COD");
  719. if(chatReq.getCsTn())
  720. sb.append(",AVG(CS_TN) 出水总氮");
  721. if(chatReq.getCsTp())
  722. sb.append(",AVG(CS_TP) 出水总磷");
  723. if(chatReq.getCsNh3())
  724. sb.append(",AVG(CS_NH3) 出水氨氮");
  725. if(chatReq.getCsSs())
  726. sb.append(",AVG(CS_SS) 出水SS");
  727. sb.append(TOOLS_WORK_ORDER_SQL_DAILY_END).append(TOOLS_WORK_ORDER_SQL_DIAN_BEGIN).append(TIMEBEGIN).append(TOOLS_WORK_ORDER_SQL_DIAN_END).append(TOOLS_WORK_ORDER_SQL_AND).append(TOOLS_WORK_ORDER_SQL_DIAN_BEGIN).append(TIMEEND).append(TOOLS_WORK_ORDER_SQL_DIAN_END).append(TOOLS_WORK_ORDER_SQL_END);
  728. sqlMap.put(REPORT, sb.toString());
  729. //清空
  730. sb = new StringBuilder();
  731. }
  732. }else{//工业库
  733. // sqlMap.put(ONLINE, sb.append(TOOLS_WORK_ORDER_SQL_INDUSTRY).append(TOOLS_WORK_ORDER_SQL_DIAN_BEGIN).append(TIMEBEGIN).append(TOOLS_WORK_ORDER_SQL_DIAN_END).append(TOOLS_WORK_ORDER_SQL_AND).append(TOOLS_WORK_ORDER_SQL_DIAN_BEGIN).append(TIMEEND).append(TOOLS_WORK_ORDER_SQL_DIAN_END).append(TOOLS_WORK_ORDER_SQL_END).toString());
  734. //2024年7月31日10:32:14 要根据前端用户选择的不同指标来拼接不同的SQL
  735. //只要出现一个就可以拼接了
  736. if (chatReq.getJsSlq() || chatReq.getJsCod() || chatReq.getJsTn() || chatReq.getJsTp() || chatReq.getJsNh3() || chatReq.getJsSs()
  737. || chatReq.getCsSlqc() || chatReq.getCsCod() || chatReq.getCsTn() || chatReq.getCsTp() || chatReq.getCsNh3() || chatReq.getCsSs()){
  738. //拼接
  739. sb.append(TOOLS_WORK_ORDER_SQL_INDUSTRY_BEGIN);
  740. if(chatReq.getJsSlq())
  741. sb.append(", AVG(JS_SLQ) 进水量");
  742. if(chatReq.getJsCod())
  743. sb.append(",AVG(JS_COD) 进水COD");
  744. if(chatReq.getJsTn())
  745. sb.append(",AVG(JS_TN) 进水总氮");
  746. if(chatReq.getJsTp())
  747. sb.append(",AVG(JS_TP) 进水总磷");
  748. if(chatReq.getJsNh3())
  749. sb.append(",AVG(JS_NH3) 进水氨氮");
  750. if(chatReq.getJsSs())
  751. sb.append(",AVG(JS_SS) 进水SS");
  752. if(chatReq.getCsSlqc())
  753. sb.append(",AVG(CS_SLQC) 出水量");
  754. if(chatReq.getCsCod())
  755. sb.append(",AVG(CS_COD) 出水COD");
  756. if(chatReq.getCsTn())
  757. sb.append(",AVG(CS_TN) 出水总氮");
  758. if(chatReq.getCsTp())
  759. sb.append(",AVG(CS_TP) 出水总磷");
  760. if(chatReq.getCsNh3())
  761. sb.append(",AVG(CS_NH3) 出水氨氮");
  762. if(chatReq.getCsSs())
  763. sb.append(",AVG(CS_SS) 出水SS");
  764. sb.append(TOOLS_WORK_ORDER_SQL_INDUSTRY_END).append(TOOLS_WORK_ORDER_SQL_DIAN_BEGIN).append(TIMEBEGIN).append(TOOLS_WORK_ORDER_SQL_DIAN_END).append(TOOLS_WORK_ORDER_SQL_AND).append(TOOLS_WORK_ORDER_SQL_DIAN_BEGIN).append(TIMEEND).append(TOOLS_WORK_ORDER_SQL_DIAN_END).append(TOOLS_WORK_ORDER_SQL_END);
  765. sqlMap.put(ONLINE, sb.toString());
  766. //清空
  767. sb = new StringBuilder();
  768. }
  769. }
  770. // sqlMap.put(ROBOT, sb.append(TOOLS_WORK_ORDER_SQL_ROBOT).append(TOOLS_WORK_ORDER_SQL_DIAN_BEGIN).append(TIMEBEGIN).append(TOOLS_WORK_ORDER_SQL_DIAN_END).append(TOOLS_WORK_ORDER_SQL_AND).append(TOOLS_WORK_ORDER_SQL_DIAN_BEGIN).append(TIMEEND).append(TOOLS_WORK_ORDER_SQL_DIAN_END).append(TOOLS_WORK_ORDER_SQL_END).toString());
  771. //2024年7月31日10:32:14 要根据前端用户选择的不同指标来拼接不同的SQL
  772. //只要出现一个就可以拼接了
  773. if(chatReq.getNo3Hlj1Jqr() || chatReq.getNo3Hlj2Jqr() || chatReq.getNh31Jqr() || chatReq.getNh32Jqr()
  774. || chatReq.getNo3Qyc1Jqr() || chatReq.getNo3Qyc2Jqr() || chatReq.getTpRccJqr()){
  775. //拼接
  776. sb.append(TOOLS_WORK_ORDER_SQL_ROBOT_BEGIN);
  777. if(chatReq.getNo3Hlj1Jqr()){
  778. sb.append(", AVG(NO3_HLJ1_JQR) '#1好氧池硝酸盐'");
  779. }
  780. if(chatReq.getNo3Hlj2Jqr()){
  781. sb.append(",AVG(NO3_HLJ2_JQR) '#2好氧池硝酸盐'");
  782. }
  783. if(chatReq.getNh31Jqr()){
  784. sb.append(",AVG(NH3_1_JQR) '#1缺氧氨氮'");
  785. }
  786. if(chatReq.getNh32Jqr()){
  787. sb.append(",AVG(NH3_2_JQR) '#2缺氧氨氮'");
  788. }
  789. if(chatReq.getNo3Qyc1Jqr()){
  790. sb.append(",AVG(NO3_QYC_1_JQR) '#1缺氧池硝酸盐'");
  791. }
  792. if(chatReq.getNo3Qyc2Jqr()){
  793. sb.append(",AVG(NO3_QYC_2_JQR) '#2缺氧池硝酸盐'");
  794. }
  795. if(chatReq.getTpRccJqr()){
  796. sb.append(",AVG(TP_RCC_JQR) '二沉池正磷酸盐'");
  797. }
  798. sb.append(TOOLS_WORK_ORDER_SQL_ROBOT_END).append(TOOLS_WORK_ORDER_SQL_DIAN_BEGIN).append(TIMEBEGIN).append(TOOLS_WORK_ORDER_SQL_DIAN_END).append(TOOLS_WORK_ORDER_SQL_AND).append(TOOLS_WORK_ORDER_SQL_DIAN_BEGIN).append(TIMEEND).append(TOOLS_WORK_ORDER_SQL_DIAN_END).append(TOOLS_WORK_ORDER_SQL_END);
  799. sqlMap.put(ROBOT, sb.toString());
  800. }
  801. map.put(DATA, sqlMap);
  802. return JSON.toJSONString(map);
  803. }
  804. private String buildGDNormalQuestion(String date) {
  805. //存放的JSON
  806. HashMap<String, Object> map = new HashMap<>();
  807. map.put(TIMEBEGIN, date);
  808. map.put(TIMEEND, date);
  809. map.put(MODULE, MODULE_CONTENT_NORMAL);
  810. map.put(TYPE, NORMAL_WORK_ORDER);
  811. return JSON.toJSONString(map);
  812. }
  813. private String buildBigModelReqForChat(String sessionId, List<String> historyDates, String ipAddr, int isStrong, Double topP, Double temperature, String tools, boolean useRag, String extraStr, String prompt, int modelType, Boolean onlineSearch) {
  814. ChatRequest chatRequest = new ChatRequest();
  815. chatRequest.setSessionId(sessionId);
  816. chatRequest.setHistoryDia(historyDates);
  817. //2024年7月5日13:24:10 temperature做区分
  818. GenerateArgs generateArgs = new GenerateArgs();
  819. generateArgs.setTemperature(Objects.isNull(temperature) ? bigModelConfig.getTemperature() : temperature);
  820. generateArgs.setTopP(Objects.isNull(topP) ? bigModelConfig.getTopP() : topP);
  821. chatRequest.setGenerateArgs(generateArgs);
  822. Map<String, Object> extra = new HashMap<>();
  823. extra.put("ip_address", ipAddr);
  824. if(StringUtils.isNotBlank(extraStr))
  825. extra.put(TOOLS_WORK_ORDER, extraStr);
  826. chatRequest.setExtra(extra);
  827. chatRequest.setStrengthen(isStrong == 1);
  828. chatRequest.setTools(tools);
  829. chatRequest.setUseRag(useRag);
  830. //todo 后期删掉,应对大模型备案,如果对应的用户是特殊的,那么useRag区分一下
  831. Long userId = SecurityUtils.getUserId();
  832. if(userId >= 144L && userId <= 153L)
  833. chatRequest.setUseRag(false);
  834. //2024年08月11日16:04:21 允许用户自定义prompt
  835. chatRequest.setPrompt(StringUtils.isBlank(prompt) ? DEFAULT_PROMPT : prompt);
  836. //2025年02月24日11:41:38 新增的 区分模型的
  837. chatRequest.setModelType(modelType);
  838. //2025年02月27日10:58:16 新增的 是否使用在线搜索
  839. chatRequest.setOnlineSearch(onlineSearch);
  840. return JSON.toJSONString(chatRequest);
  841. }
  842. private String buildGDQuestionCustom(List<WorkOrderRes> workOrderRes, WorkOrderReq workOrderReq) {
  843. StringBuilder sb = new StringBuilder();
  844. sb.append(GONGDAN_PROMPT_CUSTOM_BEGIN.replace("#{0}", workOrderReq.getTimeBegin()).replace("#{1}", workOrderReq.getTimeEnd()));
  845. if(workOrderReq.getJsSlq() || workOrderReq.getJsSs() || workOrderReq.getJsTp() || workOrderReq.getJsTn() || workOrderReq.getJsCod() || workOrderReq.getJsNh3()){
  846. sb.append("进水:\n");
  847. for (WorkOrderRes workOrderRe : workOrderRes) {
  848. sb.append(workOrderRe.getTime()).append(":");
  849. if(workOrderReq.getJsCod())
  850. sb.append("进水COD:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsCod(), INT_2)).append("mg/L、");
  851. if(workOrderReq.getJsTn())
  852. sb.append("进水总氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsTn(), INT_2)).append("mg/L、");
  853. if(workOrderReq.getJsTp())
  854. sb.append("进水总磷:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsTp(), INT_2)).append("mg/L、");
  855. if(workOrderReq.getJsNh3())
  856. sb.append("进水氨氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsNh3(), INT_2)).append("mg/L、");
  857. if(workOrderReq.getJsSs())
  858. sb.append("进水SS:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsSs(), INT_2)).append("mg/L、");
  859. if(workOrderReq.getJsSlq())
  860. sb.append("进水水量:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsSlq(), INT_2)).append("m³/d、");
  861. }
  862. }
  863. if(workOrderReq.getCsSlqc() || workOrderReq.getCsSs() || workOrderReq.getCsTp() || workOrderReq.getCsTn() || workOrderReq.getCsCod() || workOrderReq.getCsNh3()){
  864. sb.append("出水:\n");
  865. for (WorkOrderRes workOrderRe : workOrderRes) {
  866. sb.append(workOrderRe.getTime()).append(":");
  867. if(workOrderReq.getCsCod())
  868. sb.append("出水COD:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsCod(), INT_2)).append("mg/L、");
  869. if(workOrderReq.getCsTn())
  870. sb.append("出水总氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsTn(), INT_2)).append("mg/L、");
  871. if(workOrderReq.getCsTp())
  872. sb.append("出水总磷:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsTp(), INT_2)).append("mg/L、");
  873. if(workOrderReq.getCsNh3())
  874. sb.append("出水氨氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsNh3(), INT_2)).append("mg/L、");
  875. if(workOrderReq.getCsSs())
  876. sb.append("出水SS:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsSs(), INT_2)).append("mg/L、");
  877. if(workOrderReq.getCsSlqc())
  878. sb.append("出水水量:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsSlqc(), INT_2)).append("m³/d、");
  879. }
  880. }
  881. if(workOrderReq.getNo3Hlj1Jqr() || workOrderReq.getNo3Hlj2Jqr() || workOrderReq.getNh31Jqr() || workOrderReq.getNh32Jqr()
  882. || workOrderReq.getNo3Qyc1Jqr() || workOrderReq.getNo3Qyc2Jqr() || workOrderReq.getTpRccJqr()){
  883. sb.append("过程指标:\n");
  884. for (WorkOrderRes workOrderRe : workOrderRes) {
  885. sb.append(workOrderRe.getTime()).append(":");
  886. if(workOrderReq.getNo3Hlj1Jqr())
  887. sb.append("#1好氧池硝酸盐:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNo3Hlj1Jqr(), INT_2)).append("mg/L、");
  888. if(workOrderReq.getNo3Hlj2Jqr())
  889. sb.append("#2好氧池硝酸盐:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNo3Hlj2Jqr(), INT_2)).append("mg/L、");
  890. if(workOrderReq.getNo3Qyc1Jqr())
  891. sb.append("#1缺氧池硝酸盐:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNo3Qyc1Jqr(), INT_2)).append("mg/L、");
  892. if(workOrderReq.getNo3Qyc2Jqr())
  893. sb.append("#2缺氧池硝酸盐:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNo3Qyc2Jqr(), INT_2)).append("mg/L、");
  894. if(workOrderReq.getTpRccJqr())
  895. sb.append("二沉池正磷酸盐:").append(DecimalUtils.getAbsAndScale(workOrderRe.getTpRccJqr(), INT_2)).append("mg/L、");
  896. if(workOrderReq.getNh31Jqr())
  897. sb.append("#1缺氧氨氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNh31Jqr(), INT_2)).append("mg/L、");
  898. if(workOrderReq.getNh32Jqr())
  899. sb.append("#2缺氧氨氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNh32Jqr(), INT_2)).append("mg/L、");
  900. }
  901. }
  902. sb.append(GONGDAN_PROMPT_CUSTOM_END_1);
  903. if(workOrderReq.getJsCod() || workOrderReq.getCsCod())
  904. sb.append("化学需氧量(COD)、");
  905. if(workOrderReq.getJsTp() || workOrderReq.getCsTp())
  906. sb.append("总磷(TP)、");
  907. if(workOrderReq.getJsTn() || workOrderReq.getCsTn())
  908. sb.append("总氮(TN)、");
  909. if(workOrderReq.getJsSs() || workOrderReq.getCsSs())
  910. sb.append("SS、");
  911. if(workOrderReq.getJsNh3() || workOrderReq.getCsNh3())
  912. sb.append("氨氮、");
  913. sb.append(GONGDAN_PROMPT_CUSTOM_END_2);
  914. return sb.toString();
  915. }
  916. /**
  917. * 通过日期构建工单的请求参数 --new
  918. * @return
  919. */
  920. private String buildGDQuestionNew(String date, String dateBefore, TXinyiDaily tXinyiDaily, TXinyiDaily tXinyiDaily1) {
  921. StringBuilder sb = new StringBuilder(GONGDAN_PROMPT_BEGIN_PRE_1).append(date);
  922. // sb.append(GONGDAN_PROMPT_BEGIN.replace("#{0}", date));
  923. sb.append(GONGDAN_PROMPT_BEGIN_PRE_2).append(date);
  924. sb.append(GONGDAN_PROMPT_BEGIN_PRE_3);
  925. sb.append("进水COD:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJsCod(), INT_2)).append("mg/L、");
  926. sb.append("进水总氮:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJsTn(), INT_2)).append("mg/L、");
  927. sb.append("进水总磷:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJsTp(), INT_2)).append("mg/L、");
  928. sb.append("进水氨氮:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJsNh3(), INT_2)).append("mg/L、");
  929. sb.append("进水SS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJsSs(), INT_2)).append("mg/L、");
  930. sb.append("进水水量:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJSL(), INT_2)).append("m³/d、");
  931. sb.append(";");
  932. sb.append("出水COD:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCsCod(), INT_2)).append("mg/L、");
  933. sb.append("出水总氮:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCsTn(), INT_2)).append("mg/L、");
  934. sb.append("出水总磷:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCsTp(), INT_2)).append("mg/L、");
  935. sb.append("出水氨氮:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCsNh3(), INT_2)).append("mg/L、");
  936. sb.append("出水SS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCsSs(), INT_2)).append("mg/L、");
  937. sb.append("出水水量:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCSL(), INT_2)).append("m³/d。");
  938. sb.append("二、生化指标:\n");
  939. //todo 单位确认 下面的应该不是 mg/L
  940. sb.append("#1好氧池pH:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcOnePh(), INT_2)).append("、");
  941. sb.append("#1好氧池SV:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyOneSv(), INT_2)).append("、");
  942. sb.append("#1好氧池SVI:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyOneSvi(), INT_2)).append("、");
  943. sb.append("#1好氧池MLSS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyOneMlss(), INT_2)).append("、");
  944. sb.append("#1好氧池MLVSS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyOneMlvss(), INT_2)).append("、");
  945. sb.append("#1好氧池DO:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyOneDo(), INT_2)).append(";");
  946. sb.append("#2好氧池pH:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcTwoPh(), INT_2)).append("、");
  947. sb.append("#2好氧池SV:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyTwoSv(), INT_2)).append("、");
  948. sb.append("#2好氧池SVI:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyTwoSvi(), INT_2)).append("、");
  949. sb.append("#2好氧池MLSS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyTwoMlss(), INT_2)).append("、");
  950. sb.append("#2好氧池MLVSS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyTwoMlvss(), INT_2)).append("、");
  951. sb.append("#2好氧池DO:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyTwoDo(), INT_2)).append(";");
  952. sb.append("#1厌氧池DO:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcYyOneDo(), INT_2)).append(";");
  953. sb.append("#2厌氧池DO:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcYyTwoDo(), INT_2)).append("。");
  954. sb.append("最近7天的数据如下:\n");
  955. List<TXinyiDaily> dailyTwoRecords = this.xinyiDailyMapper.selectNRecords(DAILY_REPORT_COUNT_RECORD);
  956. //正常不会有这种问题 因为日报有很多条
  957. if(CollectionUtils.isEmpty(dailyTwoRecords) || dailyTwoRecords.size() < DAILY_REPORT_COUNT_RECORD){
  958. log.error("进入了定时生成每日简报数据 获取最新的{}条数据不足,终止", DAILY_REPORT_COUNT_RECORD);
  959. return sb.toString();
  960. }
  961. //查询配置信息
  962. List<TXinyiNormConfig> tXinyiNormConfigs = this.xinyiNormConfigMapper.selectTXinyiNormConfigList(null);
  963. if(CollectionUtils.isEmpty(tXinyiNormConfigs))
  964. return null;
  965. TXinyiNormConfig normConfig = tXinyiNormConfigs.get(0);
  966. //获取数据
  967. for (TXinyiDaily dailyTwoRecord : dailyTwoRecords) {
  968. sb.append(formateDateStr(dailyTwoRecord.getTestDate())).append("进出水质数据:\n");
  969. sb.append("进水:\n");
  970. sb.append("进水COD").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsCod(), 2)).append("mg/L、");
  971. sb.append("进水总氮").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsTn(), 2)).append("mg/L、");
  972. sb.append("进水总磷").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsTp(), 2)).append("mg/L、");
  973. sb.append("进水氨氮").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsNh3(), 2)).append("mg/L、");
  974. sb.append("进水SS").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsSs(), 2)).append("mg/L、");
  975. sb.append("进水水量").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJSL(), 2)).append("m³/d").append(";\n");
  976. sb.append("出水:\n");
  977. sb.append("出水COD").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsCod(), 2)).append("mg/L、");
  978. sb.append("出水总氮").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsTn(), 2)).append("mg/L、");
  979. sb.append("出水总磷").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsTp(), 2)).append("mg/L、");
  980. sb.append("出水氨氮").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsNh3(), 2)).append("mg/L、");
  981. sb.append("出水SS").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsSs(), 2)).append("mg/L、");
  982. sb.append("出水水量").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCSL(), 2)).append("m³/d").append("。\n");
  983. }
  984. sb.append(SHORT_REPORT_END);
  985. sb.append("进水COD:").append(DecimalUtils.getAbsAndScale(normConfig.getJscodSjz(), 2)).append("mg/L、");
  986. sb.append("进水总氮:").append(DecimalUtils.getAbsAndScale(normConfig.getJszdSjz(), 2)).append("mg/L、");
  987. sb.append("进水总磷:").append(DecimalUtils.getAbsAndScale(normConfig.getJszlSjz(), 2)).append("mg/L、");
  988. sb.append("进水氨氮:").append(DecimalUtils.getAbsAndScale(normConfig.getJsadSjz(), 2)).append("mg/L、");
  989. sb.append("进水SS:").append(DecimalUtils.getAbsAndScale(normConfig.getJsssSjz(), 2)).append("mg/L、");
  990. sb.append("出水COD:").append(DecimalUtils.getAbsAndScale(normConfig.getCscodBzz(), 2)).append("mg/L、");
  991. sb.append("出水总氮:").append(DecimalUtils.getAbsAndScale(normConfig.getCszzBzz(), 2)).append("mg/L、");
  992. sb.append("出水总磷:").append(DecimalUtils.getAbsAndScale(normConfig.getCszlBzz(), 2)).append("mg/L、");
  993. sb.append("出水氨氮:").append(DecimalUtils.getAbsAndScale(normConfig.getCsadBzz(), 2)).append("mg/L、");
  994. sb.append("出水SS:").append(DecimalUtils.getAbsAndScale(normConfig.getCsssBzz(), 2)).append("mg/L").append("。");
  995. sb.append(GONGDAN_PROMPT_END);
  996. return sb.toString();
  997. }
  998. /**
  999. *
  1000. * 2022/01/01 转成2022年01月01日 数据
  1001. * @param testDate
  1002. * @return
  1003. */
  1004. private String formateDateStr(String testDate) {
  1005. if(StringUtils.isBlank(testDate))
  1006. return "";
  1007. if(!testDate.contains("/"))
  1008. return testDate;
  1009. String[] split = testDate.split("/");
  1010. return split[0] + "年" + split[1] + "月" + split[2] + "日";
  1011. }
  1012. /**
  1013. * 通过日期构建工单的请求参数
  1014. * @return
  1015. */
  1016. private String buildGDQuestion(String date, String dateBefore, TXinyiDaily xinyiDailyNow, TXinyiDaily xinyiDailyBefore) {
  1017. String result = GONGDAN_PROMPT;
  1018. result = result.replace("{0}", date);
  1019. result = result.replace("{1}", dateBefore);
  1020. //替换各种指标
  1021. result = result.replace("{2}", String.valueOf(xinyiDailyNow.getJsCod()));
  1022. result = result.replace("{3}", String.valueOf(xinyiDailyNow.getJsTn()));
  1023. result = result.replace("{4}", String.valueOf(xinyiDailyNow.getJsTp()));
  1024. result = result.replace("{5}", String.valueOf(xinyiDailyNow.getJsNh3()));
  1025. result = result.replace("{6}", String.valueOf(xinyiDailyNow.getJsSs()));
  1026. result = result.replace("{7}", String.valueOf(xinyiDailyNow.getJSL()));
  1027. result = result.replace("{8}", String.valueOf(xinyiDailyNow.getCsCod()));
  1028. result = result.replace("{9}", String.valueOf(xinyiDailyNow.getCsTn()));
  1029. result = result.replace("{10}", String.valueOf(xinyiDailyNow.getCsTp()));
  1030. result = result.replace("{11}", String.valueOf(xinyiDailyNow.getCsNh3()));
  1031. result = result.replace("{12}", String.valueOf(xinyiDailyNow.getCsSs()));
  1032. result = result.replace("{13}", String.valueOf(xinyiDailyNow.getCSL()));
  1033. result = result.replace("{14}", String.valueOf(xinyiDailyNow.getShcOnePh()));
  1034. result = result.replace("{15}", String.valueOf(xinyiDailyNow.getShcHyOneSv()));
  1035. result = result.replace("{16}", String.valueOf(xinyiDailyNow.getShcHyOneSvi()));
  1036. result = result.replace("{17}", String.valueOf(xinyiDailyNow.getShcHyOneMlss()));
  1037. result = result.replace("{18}", String.valueOf(xinyiDailyNow.getShcHyOneMlvss()));
  1038. result = result.replace("{19}", String.valueOf(xinyiDailyNow.getShcHyOneDo()));
  1039. result = result.replace("{20}", String.valueOf(xinyiDailyNow.getShcTwoPh()));
  1040. result = result.replace("{21}", String.valueOf(xinyiDailyNow.getShcHyTwoSv()));
  1041. result = result.replace("{22}", String.valueOf(xinyiDailyNow.getShcHyTwoSvi()));
  1042. result = result.replace("{23}", String.valueOf(xinyiDailyNow.getShcHyTwoMlss()));
  1043. result = result.replace("{24}", String.valueOf(xinyiDailyNow.getShcHyTwoMlvss()));
  1044. result = result.replace("{25}", String.valueOf(xinyiDailyNow.getShcHyTwoDo()));
  1045. result = result.replace("{26}", String.valueOf(xinyiDailyNow.getShcYyOneDo()));
  1046. result = result.replace("{27}", String.valueOf(xinyiDailyNow.getShcYyTwoDo()));
  1047. result = result.replace("{28}", String.valueOf(xinyiDailyBefore.getJsCod()));
  1048. result = result.replace("{29}", String.valueOf(xinyiDailyBefore.getJsTn()));
  1049. result = result.replace("{30}", String.valueOf(xinyiDailyBefore.getJsTp()));
  1050. result = result.replace("{31}", String.valueOf(xinyiDailyBefore.getJsNh3()));
  1051. result = result.replace("{32}", String.valueOf(xinyiDailyBefore.getJsSs()));
  1052. result = result.replace("{33}", String.valueOf(xinyiDailyBefore.getJSL()));
  1053. result = result.replace("{34}", String.valueOf(xinyiDailyBefore.getCsCod()));
  1054. result = result.replace("{35}", String.valueOf(xinyiDailyBefore.getCsTn()));
  1055. result = result.replace("{36}", String.valueOf(xinyiDailyBefore.getCsTp()));
  1056. result = result.replace("{37}", String.valueOf(xinyiDailyBefore.getCsNh3()));
  1057. result = result.replace("{38}", String.valueOf(xinyiDailyBefore.getCsSs()));
  1058. result = result.replace("{39}", String.valueOf(xinyiDailyBefore.getCSL()));
  1059. return result;
  1060. }
  1061. public static void main(String[] args) {
  1062. // String encoded = "\\345\\216\\214\\346\\260\\247\\346\\261\\240\\347\\241\\235\\351\\205\\270\\347\\233\\220\\346\\260\\256\\346\\230\\257\\345\\220\\246\\345\\244\\247\\344\\272";
  1063. // String decoded = decodeOctalToUtf8(encoded);
  1064. // System.out.println(decoded);
  1065. testPredictor();
  1066. }
  1067. public static void testPredictor(){
  1068. // 获取输出流
  1069. ManagedChannel channel = null;
  1070. try {
  1071. channel = ManagedChannelBuilder.forAddress("10.0.0.24", 27070)
  1072. .usePlaintext()
  1073. .build();
  1074. InferenceAPIsServiceGrpc.InferenceAPIsServiceBlockingStub stub = InferenceAPIsServiceGrpc.newBlockingStub(channel);
  1075. // String dataJson = "{\"bot_id\":\"b00001\",\"exp_id\":\"721\",\"norm\":\"出水氨氮\",\"session_id\":\" " + IdUtils.simpleUUID() + " \",\"extra\":{}}";
  1076. //2024年6月27日13:23:25 优化:改成非拼接JSON字符串
  1077. String dataJson = buildBigModelReqForPredictor("缺氧出水氨氮1");
  1078. // String dataJson = buildBigModelReqForPredictor("qyxsy1");
  1079. // log.info("请求大模型的预测的参数为{}", dataJson);
  1080. PredictionsRequest request = PredictionsRequest.newBuilder()
  1081. .setModelName("slibra_bot")
  1082. .putInput("method", ByteString.copyFrom("predictor", "utf-8"))//推理
  1083. .putInput("data", ByteString.copyFrom(dataJson, "utf-8"))
  1084. .buildPartial();
  1085. //2024年6月21日10:35:22 改成非流式输出
  1086. /*Iterator<PredictionResponse> predictions = stub.streamPredictions(request);
  1087. //将结果记录到问答表
  1088. String responseStr = predictions.next().getPrediction().toStringUtf8();
  1089. log.info("大模型问答返回的原始结果为{}", responseStr);*/
  1090. PredictionResponse predictions = stub.predictions(request);
  1091. String responseStr = predictions.getPrediction().toStringUtf8();
  1092. log.info("大模型问答返回的原始结果为{}", responseStr);
  1093. } catch (IOException e) {
  1094. throw new RuntimeException(e);
  1095. } finally {
  1096. channel.shutdown();
  1097. }
  1098. }
  1099. private static String buildBigModelReqForPredictor(String type) {
  1100. PredictorRequest predictorRequest = new PredictorRequest();
  1101. predictorRequest.setNorm(type);
  1102. predictorRequest.setSessionId(IdUtils.simpleUUID());
  1103. return JSON.toJSONString(predictorRequest);
  1104. }
  1105. }