GRPCController.java 68 KB

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