GRPCController.java 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128
  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. // 获取输出流
  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. //请求参数
  480. Integer module = chatReq.getModule();//来自那个模块
  481. Date reportDate = chatReq.getReportDate();//如果传过值来了 代表的是工单类型的问答
  482. String timeBegin = chatReq.getTimeBegin();
  483. String timeEnd = chatReq.getTimeEnd();
  484. if((Objects.isNull(reportDate) && StringUtils.isBlank(timeBegin) && StringUtils.isBlank(timeEnd)) && module == 1){//工单 必须要输入日期
  485. //智能工单需要传入一个时间的参数
  486. try {
  487. outputStream = response.getOutputStream();
  488. outputStream.write(CHAT_GONGDAN_1_ERROR_MSG.getBytes());
  489. outputStream.flush();
  490. } catch (IOException e) {
  491. throw new RuntimeException(e);
  492. }
  493. return;
  494. }
  495. StringBuilder sb = new StringBuilder();
  496. String sessionId = chatReq.getSessionId();
  497. int isStrong = Objects.isNull(chatReq.getIsStrong()) ? 0 : chatReq.getIsStrong();
  498. String tools = STR_FALSE;//问答因为不确认是否走工具,所以传true; 但是工单一定是走工具的,传工具名称 2024年08月11日15:51:33 只有工具才是具体名称
  499. boolean useRag = true;//只有问答才传true,其他默认都false
  500. String extraStr = "";
  501. //如果是工单,需要特殊处理一下showVal和question
  502. if(1 == module){
  503. if(StringUtils.isBlank(timeBegin) && StringUtils.isBlank(timeEnd)){//按天生成工单
  504. //获取前一天的日期
  505. Date beforeYesterday = DateUtils.plusDate(-1, reportDate);
  506. //先用日期获取当天和前一天的数据,如果获取不到,则提示错误信息
  507. String date = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, reportDate);
  508. chatReq.setShowVal(GONGDAN_TITLE.replace("#{0}", date));//处理展示的标题
  509. /*String dateBefore = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, beforeYesterday);
  510. String currentDate = DateUtils.parseDateToStr(DateUtils.YYYYMMDD_TS, reportDate);
  511. String earlyDate = DateUtils.parseDateToStr(DateUtils.YYYYMMDD_TS, beforeYesterday);
  512. List<TXinyiDaily> tXinyiDailiesNow = this.xinyiDailyMapper.selectTXinyiDailyList(TXinyiDaily.builder().testDate(currentDate).build());
  513. List<TXinyiDaily> tXinyiDailiesBefore = this.xinyiDailyMapper.selectTXinyiDailyList(TXinyiDaily.builder().testDate(earlyDate).build());
  514. if(CollectionUtils.isEmpty(tXinyiDailiesNow) || CollectionUtils.isEmpty(tXinyiDailiesBefore)){
  515. //没有查询到数据
  516. try {
  517. outputStream = response.getOutputStream();
  518. outputStream.write(CHAT_GONGDAN_2_ERROR_MSG.getBytes());
  519. outputStream.flush();
  520. } catch (IOException e) {
  521. throw new RuntimeException(e);
  522. }
  523. return;
  524. }
  525. //如果查询到了 拼装数据
  526. //2024年6月25日19:11:49 prompt优化
  527. chatReq.setQuestion(this.buildGDQuestionNew(date, dateBefore, tXinyiDailiesNow.get(0), tXinyiDailiesBefore.get(0)));*/
  528. //2024年7月29日11:38:53 工单改版,由大模型处理数据
  529. // chatReq.setQuestion(this.buildGDNormalQuestion(DateUtils.parseDateToStr(DateUtils.YYYYMMDD_TS, reportDate)));
  530. chatReq.setQuestion(MODULE_CONTENT_NORMAL);
  531. extraStr = this.buildGDNormalQuestion(DateUtils.parseDateToStr(DateUtils.YYYYMMDD_TS, reportDate));
  532. }else{//自定义工单
  533. chatReq.setShowVal(GONGDAN_TITLE_CUSTOM.replace("#{0}", timeBegin).replace("#{1}", timeEnd));//处理展示的标题
  534. WorkOrderReq workOrderReq = new WorkOrderReq();
  535. BeanUtils.copyProperties(chatReq, workOrderReq);
  536. //拿到数据
  537. List<WorkOrderRes> workOrderRes = frontService.customWorkOrder(workOrderReq);
  538. //拼接prompt
  539. /*String question = this.buildGDQuestionCustom(workOrderRes, workOrderReq);
  540. //2024年6月23日17:21:58 判断问题的长度,如果长度大于配置的值(5000),提示一句话
  541. if(question.length() > MAX_QUESTION_LENGTH){
  542. log.info("*************自定义工单超长了,组装完的参数为{}", question);
  543. try {
  544. outputStream = response.getOutputStream();
  545. outputStream.write(CHAT_GONGDAN_CUSTOM_ERROR_MSG.getBytes());
  546. outputStream.flush();
  547. } catch (IOException e) {
  548. throw new RuntimeException(e);
  549. }
  550. return;
  551. }*/
  552. //2024年7月29日11:47:05 调整:图表以及大模型的数据都由大模型处理,这里拼接他需要的格式
  553. // chatReq.setQuestion(this.buildGDCustomQuestion(timeBegin, timeEnd, chatReq.getWhichWay()));
  554. chatReq.setQuestion(MODULE_CONTENT_CUSTOM);
  555. extraStr = buildGDCustomQuestion(timeBegin, timeEnd, chatReq);
  556. //2024年6月20日16:48:08 如果是自定义工单,需要处理图表 放到remark中
  557. chatReq.setRemark(JSON.toJSONString(frontService.customWorkOrderHandleByData(workOrderReq, workOrderRes), JSONWriter.Feature.WriteNulls));
  558. }
  559. isStrong = 0;//2024年7月29日14:15:47 工单不走文心一言了
  560. useRag = false;
  561. tools = TOOLS_WORK_ORDER;
  562. }
  563. String ipAddr = IpUtils.getIpAddr();//获取用户的ip地址 传给大模型
  564. int counts = 1;//默认是第一次
  565. List<String> historyDates = new ArrayList<>();
  566. //查询历史数据,放入集合中
  567. if(StringUtils.isBlank(sessionId))
  568. sessionId= IdUtils.simpleUUID();//第一次
  569. else{
  570. //通过sessionId获取所有的问答记录
  571. List<TXinyiChatRecord> chatRecords = this.chatRecordMapper.selectTXinyiChatRecordList(TXinyiChatRecord.builder().sessionId(sessionId).build());
  572. if(!CollectionUtils.isEmpty(chatRecords)){
  573. for (TXinyiChatRecord chatRecord : chatRecords) {
  574. historyDates.add(chatRecord.getQuestion());
  575. historyDates.add(chatRecord.getAnswer());
  576. }
  577. //问答次数增加
  578. counts = chatRecords.size() + 1;
  579. }
  580. }
  581. //将新的问题放入集合中
  582. historyDates.add(chatReq.getQuestion());
  583. String headerPort = httpServletRequest.getHeader(port);
  584. try {
  585. channel = ManagedChannelBuilder.forAddress(bigModelConfig.getIp(), StringUtils.isBlank(headerPort) ? bigModelConfig.getPort() : Integer.parseInt(headerPort))
  586. .usePlaintext()
  587. .build();
  588. InferenceAPIsServiceGrpc.InferenceAPIsServiceBlockingStub stub = InferenceAPIsServiceGrpc.newBlockingStub(channel);
  589. // 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) + "}";
  590. //2024年6月25日18:12:23 优化,不再使用拼接JSON字符串
  591. //2024年7月27日18:13:47 前端传过来tools
  592. String toolsReq = chatReq.getTools();
  593. //2024年7月29日14:20:22 先判断是不是走本地工具,再判断前端工具
  594. //2024年08月11日15:54:52 问答默认都是false了,只有前端指定工具才是具体的工具名称
  595. // if(StringUtils.isBlank(tools) || STR_TRUE.equals(tools)){
  596. if(StringUtils.isNotBlank(toolsReq)){
  597. useRag = false;//2024年7月27日18:20:23 走本地工具,不需要文本增强
  598. isStrong = 0;
  599. tools = toolsReq;
  600. }
  601. //2024年08月21日11:49:25 如果是智慧办公,useRag也是false
  602. if(2 == module){//智慧办公
  603. useRag = false;
  604. }
  605. // else
  606. // tools = tools;
  607. // }
  608. String dataJson = buildBigModelReqForChat(sessionId, historyDates, ipAddr, isStrong, chatReq.getTopP(), chatReq.getTemperature(), tools, useRag, extraStr, chatReq.getPrompt());
  609. log.info("******请求大模型的问答参数为{}", dataJson);
  610. PredictionsRequest request = PredictionsRequest.newBuilder()
  611. .setModelName("slibra_bot")
  612. .putInput("method", ByteString.copyFrom("infer_stream", "utf-8"))//推理
  613. .putInput("data", ByteString.copyFrom(dataJson, "utf-8"))
  614. .buildPartial();
  615. outputStream = response.getOutputStream();
  616. Iterator<PredictionResponse> predictions = stub.streamPredictions(request);
  617. //将结果记录到问答表
  618. while (predictions.hasNext()) {
  619. String responseStr = predictions.next().getPrediction().toStringUtf8();
  620. // log.info("大模型问答返回的原始结果为{}", responseStr);
  621. if(StringUtils.isBlank(responseStr)){
  622. log.error("大模型返回的是空,无法解析");
  623. continue;
  624. }
  625. responseStr = JSON.parseObject(responseStr).getString("message");
  626. //2024年7月13日14:30:19 为空字符串的(实际可能是\n这种的)也返回前端,否则样式有问题
  627. if("complete".equals(responseStr) || Objects.isNull(responseStr)){
  628. // System.out.println("结尾语句并且是非JSON,无需处理");
  629. log.info("返回的结果message为{},无需再次处理", responseStr);
  630. //结束语句也流式输出,但是并不记录下来 2024年5月24日11:15:23 也不返回前端
  631. }else{
  632. sb.append(responseStr);
  633. outputStream.write(responseStr.getBytes());
  634. outputStream.flush();
  635. }
  636. }
  637. //将问答更新到数据库中
  638. chatReq.setSessionId(sessionId);
  639. chatReq.setAnswer(sb.toString());
  640. chatReq.setType(0);//0问答 1决策 2本地 3仿真预测
  641. chatReq.setModule(module);//0专家问答 1智能工单 2智能体助手 3告警 4简报
  642. //2024年5月28日10:58:02 由于部分问题 展示的和调用大模型的不一样,所以这个由前端传过来
  643. // chatReq.setShowVal(question);
  644. chatReq.setCounts(counts);//问答次数
  645. String userId = SecurityUtils.getUserId().toString();
  646. String username = SecurityUtils.getUsername();
  647. chatReq.setUserId(userId);
  648. chatReq.setCreateBy(username);
  649. chatReq.setCreateTime(DateUtils.getNowDate());
  650. this.chatRecordMapper.insertTXinyiChatRecord(chatReq);
  651. outputStream.write((DEFAULT_ID_IDENTIFIER + chatReq.getId()).getBytes());
  652. outputStream.flush();
  653. } catch (IOException e) {
  654. throw new RuntimeException(e);
  655. } finally {
  656. // 关闭输出流
  657. try {
  658. outputStream.close();
  659. } catch (IOException e) {
  660. throw new RuntimeException(e);
  661. }finally {
  662. channel.shutdown();
  663. }
  664. }
  665. // return AjaxResult.success("ok");
  666. }
  667. private String buildGDCustomQuestion(String timeBegin, String timeEnd, ChatReq chatReq) {
  668. //存放的JSON
  669. HashMap<String, Object> map = new HashMap<>();
  670. map.put(TIMEBEGIN, timeBegin);
  671. map.put(TIMEEND, timeEnd);
  672. map.put(MODULE, MODULE_CONTENT_CUSTOM);
  673. map.put(TYPE, CUSTOM_WORK_ORDER);
  674. //拼装的SQL
  675. HashMap<String, Object> sqlMap = new HashMap<>();
  676. StringBuilder sb = new StringBuilder();
  677. if(chatReq.getWhichWay() == 0){//日报
  678. // 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());
  679. //2024年7月31日10:32:14 要根据前端用户选择的不同指标来拼接不同的SQL
  680. //只要出现一个就可以拼接了
  681. if (chatReq.getJsSlq() || chatReq.getJsCod() || chatReq.getJsTn() || chatReq.getJsTp() || chatReq.getJsNh3() || chatReq.getJsSs()
  682. || chatReq.getCsSlqc() || chatReq.getCsCod() || chatReq.getCsTn() || chatReq.getCsTp() || chatReq.getCsNh3() || chatReq.getCsSs()){
  683. //拼接
  684. sb.append(TOOLS_WORK_ORDER_SQL_DAILY_BEGIN);
  685. if(chatReq.getJsSlq())
  686. sb.append(",AVG(JSL) 进水量");
  687. if(chatReq.getJsCod())
  688. sb.append(",AVG(JS_COD) 进水COD");
  689. if(chatReq.getJsTn())
  690. sb.append(",AVG(JS_TN) 进水总氮");
  691. if(chatReq.getJsTp())
  692. sb.append(",AVG(JS_TP) 进水总磷");
  693. if(chatReq.getJsNh3())
  694. sb.append(",AVG(JS_NH3) 进水氨氮");
  695. if(chatReq.getJsSs())
  696. sb.append(",AVG(JS_SS) 进水SS");
  697. if(chatReq.getCsSlqc())
  698. sb.append(",AVG(CSL) 出水量");
  699. if(chatReq.getCsCod())
  700. sb.append(",AVG(CS_COD) 出水COD");
  701. if(chatReq.getCsTn())
  702. sb.append(",AVG(CS_TN) 出水总氮");
  703. if(chatReq.getCsTp())
  704. sb.append(",AVG(CS_TP) 出水总磷");
  705. if(chatReq.getCsNh3())
  706. sb.append(",AVG(CS_NH3) 出水氨氮");
  707. if(chatReq.getCsSs())
  708. sb.append(",AVG(CS_SS) 出水SS");
  709. 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);
  710. sqlMap.put(REPORT, sb.toString());
  711. //清空
  712. sb = new StringBuilder();
  713. }
  714. }else{//工业库
  715. // 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());
  716. //2024年7月31日10:32:14 要根据前端用户选择的不同指标来拼接不同的SQL
  717. //只要出现一个就可以拼接了
  718. if (chatReq.getJsSlq() || chatReq.getJsCod() || chatReq.getJsTn() || chatReq.getJsTp() || chatReq.getJsNh3() || chatReq.getJsSs()
  719. || chatReq.getCsSlqc() || chatReq.getCsCod() || chatReq.getCsTn() || chatReq.getCsTp() || chatReq.getCsNh3() || chatReq.getCsSs()){
  720. //拼接
  721. sb.append(TOOLS_WORK_ORDER_SQL_INDUSTRY_BEGIN);
  722. if(chatReq.getJsSlq())
  723. sb.append(", AVG(JS_SLQ) 进水量");
  724. if(chatReq.getJsCod())
  725. sb.append(",AVG(JS_COD) 进水COD");
  726. if(chatReq.getJsTn())
  727. sb.append(",AVG(JS_TN) 进水总氮");
  728. if(chatReq.getJsTp())
  729. sb.append(",AVG(JS_TP) 进水总磷");
  730. if(chatReq.getJsNh3())
  731. sb.append(",AVG(JS_NH3) 进水氨氮");
  732. if(chatReq.getJsSs())
  733. sb.append(",AVG(JS_SS) 进水SS");
  734. if(chatReq.getCsSlqc())
  735. sb.append(",AVG(CS_SLQC) 出水量");
  736. if(chatReq.getCsCod())
  737. sb.append(",AVG(CS_COD) 出水COD");
  738. if(chatReq.getCsTn())
  739. sb.append(",AVG(CS_TN) 出水总氮");
  740. if(chatReq.getCsTp())
  741. sb.append(",AVG(CS_TP) 出水总磷");
  742. if(chatReq.getCsNh3())
  743. sb.append(",AVG(CS_NH3) 出水氨氮");
  744. if(chatReq.getCsSs())
  745. sb.append(",AVG(CS_SS) 出水SS");
  746. 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);
  747. sqlMap.put(ONLINE, sb.toString());
  748. //清空
  749. sb = new StringBuilder();
  750. }
  751. }
  752. // 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());
  753. //2024年7月31日10:32:14 要根据前端用户选择的不同指标来拼接不同的SQL
  754. //只要出现一个就可以拼接了
  755. if(chatReq.getNo3Hlj1Jqr() || chatReq.getNo3Hlj2Jqr() || chatReq.getNh31Jqr() || chatReq.getNh32Jqr()
  756. || chatReq.getNo3Qyc1Jqr() || chatReq.getNo3Qyc2Jqr() || chatReq.getTpRccJqr()){
  757. //拼接
  758. sb.append(TOOLS_WORK_ORDER_SQL_ROBOT_BEGIN);
  759. if(chatReq.getNo3Hlj1Jqr()){
  760. sb.append(", AVG(NO3_HLJ1_JQR) '#1好氧池硝酸盐'");
  761. }
  762. if(chatReq.getNo3Hlj2Jqr()){
  763. sb.append(",AVG(NO3_HLJ2_JQR) '#2好氧池硝酸盐'");
  764. }
  765. if(chatReq.getNh31Jqr()){
  766. sb.append(",AVG(NH3_1_JQR) '#1缺氧氨氮'");
  767. }
  768. if(chatReq.getNh32Jqr()){
  769. sb.append(",AVG(NH3_2_JQR) '#2缺氧氨氮'");
  770. }
  771. if(chatReq.getNo3Qyc1Jqr()){
  772. sb.append(",AVG(NO3_QYC_1_JQR) '#1缺氧池硝酸盐'");
  773. }
  774. if(chatReq.getNo3Qyc2Jqr()){
  775. sb.append(",AVG(NO3_QYC_2_JQR) '#2缺氧池硝酸盐'");
  776. }
  777. if(chatReq.getTpRccJqr()){
  778. sb.append(",AVG(TP_RCC_JQR) '二沉池正磷酸盐'");
  779. }
  780. 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);
  781. sqlMap.put(ROBOT, sb.toString());
  782. }
  783. map.put(DATA, sqlMap);
  784. return JSON.toJSONString(map);
  785. }
  786. private String buildGDNormalQuestion(String date) {
  787. //存放的JSON
  788. HashMap<String, Object> map = new HashMap<>();
  789. map.put(TIMEBEGIN, date);
  790. map.put(TIMEEND, date);
  791. map.put(MODULE, MODULE_CONTENT_NORMAL);
  792. map.put(TYPE, NORMAL_WORK_ORDER);
  793. return JSON.toJSONString(map);
  794. }
  795. private String buildBigModelReqForChat(String sessionId, List<String> historyDates, String ipAddr, int isStrong, Double topP, Double temperature, String tools, boolean useRag, String extraStr, String prompt) {
  796. ChatRequest chatRequest = new ChatRequest();
  797. chatRequest.setSessionId(sessionId);
  798. chatRequest.setHistoryDia(historyDates);
  799. //2024年7月5日13:24:10 temperature做区分
  800. GenerateArgs generateArgs = new GenerateArgs();
  801. generateArgs.setTemperature(Objects.isNull(temperature) ? bigModelConfig.getTemperature() : temperature);
  802. generateArgs.setTopP(Objects.isNull(topP) ? bigModelConfig.getTopP() : topP);
  803. chatRequest.setGenerateArgs(generateArgs);
  804. Map<String, Object> extra = new HashMap<>();
  805. extra.put("ip_address", ipAddr);
  806. if(StringUtils.isNotBlank(extraStr))
  807. extra.put(TOOLS_WORK_ORDER, extraStr);
  808. chatRequest.setExtra(extra);
  809. chatRequest.setStrengthen(isStrong == 1);
  810. chatRequest.setTools(tools);
  811. chatRequest.setUseRag(useRag);
  812. //2024年08月11日16:04:21 允许用户自定义prompt
  813. chatRequest.setPrompt(StringUtils.isBlank(prompt) ? DEFAULT_PROMPT : prompt);
  814. return JSON.toJSONString(chatRequest);
  815. }
  816. private String buildGDQuestionCustom(List<WorkOrderRes> workOrderRes, WorkOrderReq workOrderReq) {
  817. StringBuilder sb = new StringBuilder();
  818. sb.append(GONGDAN_PROMPT_CUSTOM_BEGIN.replace("#{0}", workOrderReq.getTimeBegin()).replace("#{1}", workOrderReq.getTimeEnd()));
  819. if(workOrderReq.getJsSlq() || workOrderReq.getJsSs() || workOrderReq.getJsTp() || workOrderReq.getJsTn() || workOrderReq.getJsCod() || workOrderReq.getJsNh3()){
  820. sb.append("进水:\n");
  821. for (WorkOrderRes workOrderRe : workOrderRes) {
  822. sb.append(workOrderRe.getTime()).append(":");
  823. if(workOrderReq.getJsCod())
  824. sb.append("进水COD:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsCod(), INT_2)).append("mg/L、");
  825. if(workOrderReq.getJsTn())
  826. sb.append("进水总氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsTn(), INT_2)).append("mg/L、");
  827. if(workOrderReq.getJsTp())
  828. sb.append("进水总磷:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsTp(), INT_2)).append("mg/L、");
  829. if(workOrderReq.getJsNh3())
  830. sb.append("进水氨氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsNh3(), INT_2)).append("mg/L、");
  831. if(workOrderReq.getJsSs())
  832. sb.append("进水SS:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsSs(), INT_2)).append("mg/L、");
  833. if(workOrderReq.getJsSlq())
  834. sb.append("进水水量:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsSlq(), INT_2)).append("m³/d、");
  835. }
  836. }
  837. if(workOrderReq.getCsSlqc() || workOrderReq.getCsSs() || workOrderReq.getCsTp() || workOrderReq.getCsTn() || workOrderReq.getCsCod() || workOrderReq.getCsNh3()){
  838. sb.append("出水:\n");
  839. for (WorkOrderRes workOrderRe : workOrderRes) {
  840. sb.append(workOrderRe.getTime()).append(":");
  841. if(workOrderReq.getCsCod())
  842. sb.append("出水COD:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsCod(), INT_2)).append("mg/L、");
  843. if(workOrderReq.getCsTn())
  844. sb.append("出水总氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsTn(), INT_2)).append("mg/L、");
  845. if(workOrderReq.getCsTp())
  846. sb.append("出水总磷:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsTp(), INT_2)).append("mg/L、");
  847. if(workOrderReq.getCsNh3())
  848. sb.append("出水氨氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsNh3(), INT_2)).append("mg/L、");
  849. if(workOrderReq.getCsSs())
  850. sb.append("出水SS:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsSs(), INT_2)).append("mg/L、");
  851. if(workOrderReq.getCsSlqc())
  852. sb.append("出水水量:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsSlqc(), INT_2)).append("m³/d、");
  853. }
  854. }
  855. if(workOrderReq.getNo3Hlj1Jqr() || workOrderReq.getNo3Hlj2Jqr() || workOrderReq.getNh31Jqr() || workOrderReq.getNh32Jqr()
  856. || workOrderReq.getNo3Qyc1Jqr() || workOrderReq.getNo3Qyc2Jqr() || workOrderReq.getTpRccJqr()){
  857. sb.append("过程指标:\n");
  858. for (WorkOrderRes workOrderRe : workOrderRes) {
  859. sb.append(workOrderRe.getTime()).append(":");
  860. if(workOrderReq.getNo3Hlj1Jqr())
  861. sb.append("#1好氧池硝酸盐:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNo3Hlj1Jqr(), INT_2)).append("mg/L、");
  862. if(workOrderReq.getNo3Hlj2Jqr())
  863. sb.append("#2好氧池硝酸盐:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNo3Hlj2Jqr(), INT_2)).append("mg/L、");
  864. if(workOrderReq.getNo3Qyc1Jqr())
  865. sb.append("#1缺氧池硝酸盐:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNo3Qyc1Jqr(), INT_2)).append("mg/L、");
  866. if(workOrderReq.getNo3Qyc2Jqr())
  867. sb.append("#2缺氧池硝酸盐:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNo3Qyc2Jqr(), INT_2)).append("mg/L、");
  868. if(workOrderReq.getTpRccJqr())
  869. sb.append("二沉池正磷酸盐:").append(DecimalUtils.getAbsAndScale(workOrderRe.getTpRccJqr(), INT_2)).append("mg/L、");
  870. if(workOrderReq.getNh31Jqr())
  871. sb.append("#1缺氧氨氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNh31Jqr(), INT_2)).append("mg/L、");
  872. if(workOrderReq.getNh32Jqr())
  873. sb.append("#2缺氧氨氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNh32Jqr(), INT_2)).append("mg/L、");
  874. }
  875. }
  876. sb.append(GONGDAN_PROMPT_CUSTOM_END_1);
  877. if(workOrderReq.getJsCod() || workOrderReq.getCsCod())
  878. sb.append("化学需氧量(COD)、");
  879. if(workOrderReq.getJsTp() || workOrderReq.getCsTp())
  880. sb.append("总磷(TP)、");
  881. if(workOrderReq.getJsTn() || workOrderReq.getCsTn())
  882. sb.append("总氮(TN)、");
  883. if(workOrderReq.getJsSs() || workOrderReq.getCsSs())
  884. sb.append("SS、");
  885. if(workOrderReq.getJsNh3() || workOrderReq.getCsNh3())
  886. sb.append("氨氮、");
  887. sb.append(GONGDAN_PROMPT_CUSTOM_END_2);
  888. return sb.toString();
  889. }
  890. /**
  891. * 通过日期构建工单的请求参数 --new
  892. * @return
  893. */
  894. private String buildGDQuestionNew(String date, String dateBefore, TXinyiDaily tXinyiDaily, TXinyiDaily tXinyiDaily1) {
  895. StringBuilder sb = new StringBuilder(GONGDAN_PROMPT_BEGIN_PRE_1).append(date);
  896. // sb.append(GONGDAN_PROMPT_BEGIN.replace("#{0}", date));
  897. sb.append(GONGDAN_PROMPT_BEGIN_PRE_2).append(date);
  898. sb.append(GONGDAN_PROMPT_BEGIN_PRE_3);
  899. sb.append("进水COD:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJsCod(), INT_2)).append("mg/L、");
  900. sb.append("进水总氮:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJsTn(), INT_2)).append("mg/L、");
  901. sb.append("进水总磷:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJsTp(), INT_2)).append("mg/L、");
  902. sb.append("进水氨氮:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJsNh3(), INT_2)).append("mg/L、");
  903. sb.append("进水SS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJsSs(), INT_2)).append("mg/L、");
  904. sb.append("进水水量:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJSL(), INT_2)).append("m³/d、");
  905. sb.append(";");
  906. sb.append("出水COD:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCsCod(), INT_2)).append("mg/L、");
  907. sb.append("出水总氮:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCsTn(), INT_2)).append("mg/L、");
  908. sb.append("出水总磷:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCsTp(), INT_2)).append("mg/L、");
  909. sb.append("出水氨氮:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCsNh3(), INT_2)).append("mg/L、");
  910. sb.append("出水SS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCsSs(), INT_2)).append("mg/L、");
  911. sb.append("出水水量:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCSL(), INT_2)).append("m³/d。");
  912. sb.append("二、生化指标:\n");
  913. //todo 单位确认 下面的应该不是 mg/L
  914. sb.append("#1好氧池pH:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcOnePh(), INT_2)).append("、");
  915. sb.append("#1好氧池SV:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyOneSv(), INT_2)).append("、");
  916. sb.append("#1好氧池SVI:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyOneSvi(), INT_2)).append("、");
  917. sb.append("#1好氧池MLSS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyOneMlss(), INT_2)).append("、");
  918. sb.append("#1好氧池MLVSS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyOneMlvss(), INT_2)).append("、");
  919. sb.append("#1好氧池DO:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyOneDo(), INT_2)).append(";");
  920. sb.append("#2好氧池pH:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcTwoPh(), INT_2)).append("、");
  921. sb.append("#2好氧池SV:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyTwoSv(), INT_2)).append("、");
  922. sb.append("#2好氧池SVI:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyTwoSvi(), INT_2)).append("、");
  923. sb.append("#2好氧池MLSS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyTwoMlss(), INT_2)).append("、");
  924. sb.append("#2好氧池MLVSS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyTwoMlvss(), INT_2)).append("、");
  925. sb.append("#2好氧池DO:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyTwoDo(), INT_2)).append(";");
  926. sb.append("#1厌氧池DO:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcYyOneDo(), INT_2)).append(";");
  927. sb.append("#2厌氧池DO:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcYyTwoDo(), INT_2)).append("。");
  928. sb.append("最近7天的数据如下:\n");
  929. List<TXinyiDaily> dailyTwoRecords = this.xinyiDailyMapper.selectNRecords(DAILY_REPORT_COUNT_RECORD);
  930. //正常不会有这种问题 因为日报有很多条
  931. if(CollectionUtils.isEmpty(dailyTwoRecords) || dailyTwoRecords.size() < DAILY_REPORT_COUNT_RECORD){
  932. log.error("进入了定时生成每日简报数据 获取最新的{}条数据不足,终止", DAILY_REPORT_COUNT_RECORD);
  933. return sb.toString();
  934. }
  935. //查询配置信息
  936. List<TXinyiNormConfig> tXinyiNormConfigs = this.xinyiNormConfigMapper.selectTXinyiNormConfigList(null);
  937. if(CollectionUtils.isEmpty(tXinyiNormConfigs))
  938. return null;
  939. TXinyiNormConfig normConfig = tXinyiNormConfigs.get(0);
  940. //获取数据
  941. for (TXinyiDaily dailyTwoRecord : dailyTwoRecords) {
  942. sb.append(formateDateStr(dailyTwoRecord.getTestDate())).append("进出水质数据:\n");
  943. sb.append("进水:\n");
  944. sb.append("进水COD").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsCod(), 2)).append("mg/L、");
  945. sb.append("进水总氮").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsTn(), 2)).append("mg/L、");
  946. sb.append("进水总磷").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsTp(), 2)).append("mg/L、");
  947. sb.append("进水氨氮").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsNh3(), 2)).append("mg/L、");
  948. sb.append("进水SS").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsSs(), 2)).append("mg/L、");
  949. sb.append("进水水量").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJSL(), 2)).append("m³/d").append(";\n");
  950. sb.append("出水:\n");
  951. sb.append("出水COD").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsCod(), 2)).append("mg/L、");
  952. sb.append("出水总氮").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsTn(), 2)).append("mg/L、");
  953. sb.append("出水总磷").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsTp(), 2)).append("mg/L、");
  954. sb.append("出水氨氮").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsNh3(), 2)).append("mg/L、");
  955. sb.append("出水SS").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsSs(), 2)).append("mg/L、");
  956. sb.append("出水水量").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCSL(), 2)).append("m³/d").append("。\n");
  957. }
  958. sb.append(SHORT_REPORT_END);
  959. sb.append("进水COD:").append(DecimalUtils.getAbsAndScale(normConfig.getJscodSjz(), 2)).append("mg/L、");
  960. sb.append("进水总氮:").append(DecimalUtils.getAbsAndScale(normConfig.getJszdSjz(), 2)).append("mg/L、");
  961. sb.append("进水总磷:").append(DecimalUtils.getAbsAndScale(normConfig.getJszlSjz(), 2)).append("mg/L、");
  962. sb.append("进水氨氮:").append(DecimalUtils.getAbsAndScale(normConfig.getJsadSjz(), 2)).append("mg/L、");
  963. sb.append("进水SS:").append(DecimalUtils.getAbsAndScale(normConfig.getJsssSjz(), 2)).append("mg/L、");
  964. sb.append("出水COD:").append(DecimalUtils.getAbsAndScale(normConfig.getCscodBzz(), 2)).append("mg/L、");
  965. sb.append("出水总氮:").append(DecimalUtils.getAbsAndScale(normConfig.getCszzBzz(), 2)).append("mg/L、");
  966. sb.append("出水总磷:").append(DecimalUtils.getAbsAndScale(normConfig.getCszlBzz(), 2)).append("mg/L、");
  967. sb.append("出水氨氮:").append(DecimalUtils.getAbsAndScale(normConfig.getCsadBzz(), 2)).append("mg/L、");
  968. sb.append("出水SS:").append(DecimalUtils.getAbsAndScale(normConfig.getCsssBzz(), 2)).append("mg/L").append("。");
  969. sb.append(GONGDAN_PROMPT_END);
  970. return sb.toString();
  971. }
  972. /**
  973. *
  974. * 2022/01/01 转成2022年01月01日 数据
  975. * @param testDate
  976. * @return
  977. */
  978. private String formateDateStr(String testDate) {
  979. if(StringUtils.isBlank(testDate))
  980. return "";
  981. if(!testDate.contains("/"))
  982. return testDate;
  983. String[] split = testDate.split("/");
  984. return split[0] + "年" + split[1] + "月" + split[2] + "日";
  985. }
  986. /**
  987. * 通过日期构建工单的请求参数
  988. * @return
  989. */
  990. private String buildGDQuestion(String date, String dateBefore, TXinyiDaily xinyiDailyNow, TXinyiDaily xinyiDailyBefore) {
  991. String result = GONGDAN_PROMPT;
  992. result = result.replace("{0}", date);
  993. result = result.replace("{1}", dateBefore);
  994. //替换各种指标
  995. result = result.replace("{2}", String.valueOf(xinyiDailyNow.getJsCod()));
  996. result = result.replace("{3}", String.valueOf(xinyiDailyNow.getJsTn()));
  997. result = result.replace("{4}", String.valueOf(xinyiDailyNow.getJsTp()));
  998. result = result.replace("{5}", String.valueOf(xinyiDailyNow.getJsNh3()));
  999. result = result.replace("{6}", String.valueOf(xinyiDailyNow.getJsSs()));
  1000. result = result.replace("{7}", String.valueOf(xinyiDailyNow.getJSL()));
  1001. result = result.replace("{8}", String.valueOf(xinyiDailyNow.getCsCod()));
  1002. result = result.replace("{9}", String.valueOf(xinyiDailyNow.getCsTn()));
  1003. result = result.replace("{10}", String.valueOf(xinyiDailyNow.getCsTp()));
  1004. result = result.replace("{11}", String.valueOf(xinyiDailyNow.getCsNh3()));
  1005. result = result.replace("{12}", String.valueOf(xinyiDailyNow.getCsSs()));
  1006. result = result.replace("{13}", String.valueOf(xinyiDailyNow.getCSL()));
  1007. result = result.replace("{14}", String.valueOf(xinyiDailyNow.getShcOnePh()));
  1008. result = result.replace("{15}", String.valueOf(xinyiDailyNow.getShcHyOneSv()));
  1009. result = result.replace("{16}", String.valueOf(xinyiDailyNow.getShcHyOneSvi()));
  1010. result = result.replace("{17}", String.valueOf(xinyiDailyNow.getShcHyOneMlss()));
  1011. result = result.replace("{18}", String.valueOf(xinyiDailyNow.getShcHyOneMlvss()));
  1012. result = result.replace("{19}", String.valueOf(xinyiDailyNow.getShcHyOneDo()));
  1013. result = result.replace("{20}", String.valueOf(xinyiDailyNow.getShcTwoPh()));
  1014. result = result.replace("{21}", String.valueOf(xinyiDailyNow.getShcHyTwoSv()));
  1015. result = result.replace("{22}", String.valueOf(xinyiDailyNow.getShcHyTwoSvi()));
  1016. result = result.replace("{23}", String.valueOf(xinyiDailyNow.getShcHyTwoMlss()));
  1017. result = result.replace("{24}", String.valueOf(xinyiDailyNow.getShcHyTwoMlvss()));
  1018. result = result.replace("{25}", String.valueOf(xinyiDailyNow.getShcHyTwoDo()));
  1019. result = result.replace("{26}", String.valueOf(xinyiDailyNow.getShcYyOneDo()));
  1020. result = result.replace("{27}", String.valueOf(xinyiDailyNow.getShcYyTwoDo()));
  1021. result = result.replace("{28}", String.valueOf(xinyiDailyBefore.getJsCod()));
  1022. result = result.replace("{29}", String.valueOf(xinyiDailyBefore.getJsTn()));
  1023. result = result.replace("{30}", String.valueOf(xinyiDailyBefore.getJsTp()));
  1024. result = result.replace("{31}", String.valueOf(xinyiDailyBefore.getJsNh3()));
  1025. result = result.replace("{32}", String.valueOf(xinyiDailyBefore.getJsSs()));
  1026. result = result.replace("{33}", String.valueOf(xinyiDailyBefore.getJSL()));
  1027. result = result.replace("{34}", String.valueOf(xinyiDailyBefore.getCsCod()));
  1028. result = result.replace("{35}", String.valueOf(xinyiDailyBefore.getCsTn()));
  1029. result = result.replace("{36}", String.valueOf(xinyiDailyBefore.getCsTp()));
  1030. result = result.replace("{37}", String.valueOf(xinyiDailyBefore.getCsNh3()));
  1031. result = result.replace("{38}", String.valueOf(xinyiDailyBefore.getCsSs()));
  1032. result = result.replace("{39}", String.valueOf(xinyiDailyBefore.getCSL()));
  1033. return result;
  1034. }
  1035. public static void main(String[] args) {
  1036. // 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";
  1037. // String decoded = decodeOctalToUtf8(encoded);
  1038. // System.out.println(decoded);
  1039. testPredictor();
  1040. }
  1041. public static void testPredictor(){
  1042. // 获取输出流
  1043. ManagedChannel channel = null;
  1044. try {
  1045. channel = ManagedChannelBuilder.forAddress("10.0.0.24", 27070)
  1046. .usePlaintext()
  1047. .build();
  1048. InferenceAPIsServiceGrpc.InferenceAPIsServiceBlockingStub stub = InferenceAPIsServiceGrpc.newBlockingStub(channel);
  1049. // String dataJson = "{\"bot_id\":\"b00001\",\"exp_id\":\"721\",\"norm\":\"出水氨氮\",\"session_id\":\" " + IdUtils.simpleUUID() + " \",\"extra\":{}}";
  1050. //2024年6月27日13:23:25 优化:改成非拼接JSON字符串
  1051. String dataJson = buildBigModelReqForPredictor("缺氧出水氨氮1");
  1052. // String dataJson = buildBigModelReqForPredictor("qyxsy1");
  1053. // log.info("请求大模型的预测的参数为{}", dataJson);
  1054. PredictionsRequest request = PredictionsRequest.newBuilder()
  1055. .setModelName("slibra_bot")
  1056. .putInput("method", ByteString.copyFrom("predictor", "utf-8"))//推理
  1057. .putInput("data", ByteString.copyFrom(dataJson, "utf-8"))
  1058. .buildPartial();
  1059. //2024年6月21日10:35:22 改成非流式输出
  1060. /*Iterator<PredictionResponse> predictions = stub.streamPredictions(request);
  1061. //将结果记录到问答表
  1062. String responseStr = predictions.next().getPrediction().toStringUtf8();
  1063. log.info("大模型问答返回的原始结果为{}", responseStr);*/
  1064. PredictionResponse predictions = stub.predictions(request);
  1065. String responseStr = predictions.getPrediction().toStringUtf8();
  1066. log.info("大模型问答返回的原始结果为{}", responseStr);
  1067. } catch (IOException e) {
  1068. throw new RuntimeException(e);
  1069. } finally {
  1070. channel.shutdown();
  1071. }
  1072. }
  1073. private static String buildBigModelReqForPredictor(String type) {
  1074. PredictorRequest predictorRequest = new PredictorRequest();
  1075. predictorRequest.setNorm(type);
  1076. predictorRequest.setSessionId(IdUtils.simpleUUID());
  1077. return JSON.toJSONString(predictorRequest);
  1078. }
  1079. }