123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128 |
- package com.slibra.web.controller.business;
- import com.alibaba.fastjson2.JSONObject;
- import com.alibaba.fastjson2.JSONWriter;
- import com.alibaba.fastjson2.JSON;
- import com.google.protobuf.ByteString;
- import com.slibra.business.domain.*;
- import com.slibra.business.mapper.*;
- import com.slibra.business.req.*;
- import com.slibra.business.res.WorkOrderRes;
- import com.slibra.business.service.IFrontService;
- import com.slibra.common.DecimalUtils;
- import com.slibra.common.config.BigModelConfig;
- import com.slibra.common.core.controller.BaseController;
- import com.slibra.common.core.domain.DecisionReq;
- import com.slibra.common.core.domain.TXinyiDaily;
- import com.slibra.common.enums.BusinessEnum;
- import com.slibra.common.exception.ServiceException;
- import com.slibra.common.utils.DateUtils;
- import com.slibra.common.utils.SecurityUtils;
- import com.slibra.common.utils.StringUtils;
- import com.slibra.common.utils.format.WaterFormat;
- import com.slibra.common.utils.ip.IpUtils;
- import com.slibra.common.utils.uuid.IdUtils;
- import io.grpc.ManagedChannel;
- import io.grpc.ManagedChannelBuilder;
- import lombok.extern.slf4j.Slf4j;
- import org.pytorch.serve.grpc.inference.InferenceAPIsServiceGrpc;
- import org.pytorch.serve.grpc.inference.PredictionResponse;
- import org.pytorch.serve.grpc.inference.PredictionsRequest;
- import org.springframework.beans.BeanUtils;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.util.CollectionUtils;
- import org.springframework.web.bind.annotation.*;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.util.*;
- import static com.slibra.common.constant.MyConstants.*;
- import static com.slibra.common.enums.BusinessEnum.BigModelBizEnum.DECISION_REPORT;
- import static com.slibra.common.enums.BusinessEnum.WarningCategoryEnum.*;
- import static com.slibra.common.enums.BusinessEnum.WarningCategoryEnum.CS_ZL;
- /**
- * 告警相关
- */
- @RestController
- @RequestMapping("/grpc")
- @Slf4j
- public class GRPCController extends BaseController {
- @Autowired
- private TXinyiChatRecordMapper chatRecordMapper;
- @Autowired
- private TXinyiIndustryMapper xinyiIndustryMapper;
- @Autowired
- private TXinyiDailyMapper xinyiDailyMapper;
- @Autowired
- private TXinyiChatRecordMapper xinyiChatRecordMapper;
- @Autowired
- private TXinyiWarningRecordMapper xinyiWarningRecordMapper;
- @Autowired
- private IFrontService frontService;
- @Autowired
- private TXinyiNormConfigMapper xinyiNormConfigMapper;
- @Autowired
- private BigModelConfig bigModelConfig;
- // 用户自定义的端口
- @Value("${token.port}")
- private String port;
- /**
- *
- * get请求测试决策输出
- *
- * @param response
- */
- @GetMapping(value = "/test/aaa")
- public void decisionStreamTest(HttpServletRequest httpServletRequest, HttpServletResponse response)
- // public void decisionStream(HttpServletResponse response, ChatReq chatReq)
- {
- log.info("进入了调⽤大模型决策接口");
- ChatReq chatReq = new ChatReq();
- HashMap<String, Object> map = new HashMap<>();
- map.put("2_2", "正常");
- map.put("4_25", "没有");
- map.put("2_28", "否");
- map.put("6_3", "超标");
- chatReq.setFeedback(JSON.toJSONString(map));
- chatReq.setCategory("出水氨氮");
- chatReq.setWarningId("782");
- chatReq.setSimulate("{}");
- // 获取输出流
- OutputStream outputStream = null;
- ManagedChannel channel = null;
- //response.setContentType("text/plain");
- response.setContentType("text/event-stream");
- response.setCharacterEncoding("utf-8");
- //2024年5月29日14:15:58 新增逻辑,判断报警状态是否已经结束了,如果结束了就直接模拟一个report返回给前端,不再调用大模型
- String warningId = chatReq.getWarningId();
- if(StringUtils.isBlank(warningId))
- throw new ServiceException("请输入正确的告警id");
- TXinyiWarningRecord xinyiWarningRecord = this.xinyiWarningRecordMapper.selectTXinyiWarningRecordById(Long.parseLong(warningId));
- if(Objects.isNull(xinyiWarningRecord))
- throw new ServiceException("请输入正确的告警id,没有查询到告警信息");
- if(1 == xinyiWarningRecord.getStatus() || 2 == xinyiWarningRecord.getStatus()){
- //已经关闭的报警,不允许再次点击报警了
- String message = this.buildMsg();
- try {
- outputStream = response.getOutputStream();
- outputStream.write(message.getBytes());
- outputStream.flush();
- return;//输出完提示信息就结束
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- StringBuilder sb = new StringBuilder();
- //大模型结果 放入一个结合中
- List<String> resultData = new ArrayList<>();
- //决策和问答不一样 没有历史的概念 所以sessionId都是新的 次数都是1
- String sessionId = IdUtils.simpleUUID();
- String feedback = chatReq.getFeedback();
- String simulate = chatReq.getSimulate();
- int type = 3;//仿真预测
- if(StringUtils.isBlank(simulate) || "{}".equals(simulate))
- type = 1;//决策
- //决策请求的业务参数
- List<DecisionReq> decisionReqs = getDecisionReqs();
- // String rows = JSON.toJSONString(decisionReqs, JSONWriter.Feature.WriteNulls);
- boolean needAdd = true;//标识变量是否可以保存
- String dataJson = "";
- String headerPort = httpServletRequest.getHeader(port);
- try {
- channel = ManagedChannelBuilder.forAddress(bigModelConfig.getIp(), StringUtils.isBlank(headerPort) ? bigModelConfig.getPort() : Integer.parseInt(headerPort))
- .usePlaintext()
- .build();
- InferenceAPIsServiceGrpc.InferenceAPIsServiceBlockingStub stub = InferenceAPIsServiceGrpc.newBlockingStub(channel);
- // 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 + "}}";
- //2024年6月24日17:59:17 优化,不再拼接JSON字符串
- dataJson = buildBigModelReqForDecision(chatReq, feedback, simulate, sessionId, decisionReqs, xinyiWarningRecord, chatReq.getTopP(), chatReq.getTemperature());
- // log.info("请求大模型的决策的参数为{}", dataJson);
- PredictionsRequest request = PredictionsRequest.newBuilder()
- .setModelName("slibra_bot")
- .putInput("method", ByteString.copyFrom("decision_stream", "utf-8"))//推理
- .putInput("data", ByteString.copyFrom(dataJson, "utf-8"))
- .buildPartial();
- outputStream = response.getOutputStream();
- Iterator<PredictionResponse> predictions = stub.streamPredictions(request);
- int i = 0 ;
- while (predictions.hasNext()) {
- String responseStr = predictions.next().getPrediction().toStringUtf8();
- // log.info("决策流式返回的结果是{}", responseStr);
- if(StringUtils.isBlank(responseStr)){
- log.info("大模型返回的流式决策内容存在空的值,跳过此次输出");
- continue;
- }
- String message = JSON.parseObject(responseStr).getString("message");
- //2024年5月25日16:37:16 按照大模型返回的类型解析数据
- String biz = JSON.parseObject(responseStr).getString("biz");
- // String message = JSON.parseObject(responseStr).getString("message");
- if(BusinessEnum.BigModelBizEnum.OK.getCode().equals(biz)){
- log.info("结尾语句并且是非JSON,无需处理,返回数据为{}", responseStr);
- //结束语句也流式输出,但是并不记录下来 2024年5月24日11:15:23 也不返回前端
- }else if(BusinessEnum.BigModelBizEnum.DECISION_DEBUGGER.getCode().equals(biz)){
- log.info("中间过程,目前只打印日志,不记录数据,也不返回给前端,返回数据为{}", responseStr);
- //结束语句也流式输出,但是并不记录下来 2024年5月24日11:15:23 也不返回前端
- //2024年6月23日14:55:19 如果大模型返回error了,不保存记录,并且提示一句错误语
- }else if(BusinessEnum.BigModelBizEnum.ERROR.getCode().equalsIgnoreCase(biz)){
- log.info("调用大模型的时候,返回的是ERROR,返回数据为{}", responseStr);
- needAdd = false;
- //返回的是error 给前端返回一句话
- try {
- String errMsg = this.buildErrMsg();
- outputStream.write(errMsg.getBytes());
- outputStream.flush();
- } catch (IOException ex) {
- throw new RuntimeException(ex);
- }
- } else{//其他 要么alert 要么出的报告
- // if(StringUtils.isBlank(message)){
- // log.info("×××××××××××××××××××××××××××为空的数据暂时不返回×××××××××××××××××××××××××××");
- // }else {
- // log.info("返回给前端的数据是{}", responseStr);
- resultData.add(responseStr);
- responseStr = responseStr + (i++) + "\n";
- outputStream.write(responseStr.getBytes());
- outputStream.flush();
- //2024年7月12日17:47:08 加个打印,处理只要report类型的拼接结果
- if(BusinessEnum.BigModelBizEnum.DECISION_REPORT.getCode().equalsIgnoreCase(biz)){
- sb.append(message);
- }
- // }
- }
- }
- } catch (Exception e) {
- // throw new RuntimeException(e);
- log.error("处理大模型推理异常,异常信息为{}", JSON.toJSONString(e));
- //出现异常 给前端返回一句话
- try {
- outputStream = response.getOutputStream();
- String errMsg = this.buildErrMsg();
- outputStream.write(errMsg.getBytes());
- outputStream.flush();
- } catch (IOException ex) {
- throw new RuntimeException(ex);
- }
- } finally {
- // log.info("sessionId是{}\n决策最终要保存的数据是{}", sessionId, JSON.toJSONString(resultData));
- // log.info("~~~~~~~~~~~~~~~决策最终返回的报告数据是{}", sb.toString());
- //保存聊天记录
- //将问答更新到数据库中
- needAdd = false;
- if(needAdd)
- addChatRecord(chatReq, sessionId, type, warningId, dataJson, resultData);
- // 关闭输出流
- try {
- outputStream.close();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }finally {
- channel.shutdown();
- }
- }
- }
- /**
- * 调⽤大模型决策接口 + 仿真预测
- * @return
- */
- @PostMapping(value = "/decisionStream")
- public void decisionStream(HttpServletRequest httpServletRequest, HttpServletResponse response, @RequestBody ChatReq chatReq)
- // public void decisionStream(HttpServletResponse response, ChatReq chatReq)
- {
- log.info("进入了调⽤大模型决策接口");
- // 获取输出流
- OutputStream outputStream = null;
- ManagedChannel channel = null;
- //response.setContentType("text/plain");
- response.setContentType("text/event-stream");
- response.setCharacterEncoding("utf-8");
- //2024年5月29日14:15:58 新增逻辑,判断报警状态是否已经结束了,如果结束了就直接模拟一个report返回给前端,不再调用大模型
- String warningId = chatReq.getWarningId();
- if(StringUtils.isBlank(warningId))
- throw new ServiceException("请输入正确的告警id");
- TXinyiWarningRecord xinyiWarningRecord = this.xinyiWarningRecordMapper.selectTXinyiWarningRecordById(Long.parseLong(warningId));
- if(Objects.isNull(xinyiWarningRecord))
- throw new ServiceException("请输入正确的告警id,没有查询到告警信息");
- if(1 == xinyiWarningRecord.getStatus() || 2 == xinyiWarningRecord.getStatus()){
- //已经关闭的报警,不允许再次点击报警了
- String message = this.buildMsg();
- try {
- outputStream = response.getOutputStream();
- outputStream.write(message.getBytes());
- outputStream.flush();
- return;//输出完提示信息就结束
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- // StringBuilder sb = new StringBuilder();
- //大模型结果 放入一个结合中
- List<String> resultData = new ArrayList<>();
- //决策和问答不一样 没有历史的概念 所以sessionId都是新的 次数都是1
- String sessionId = IdUtils.simpleUUID();
- String feedback = chatReq.getFeedback();
- String simulate = chatReq.getSimulate();
- int type = 3;//仿真预测
- if(StringUtils.isBlank(simulate) || "{}".equals(simulate))
- type = 1;//决策
- //决策请求的业务参数
- List<DecisionReq> decisionReqs = getDecisionReqs();
- // String rows = JSON.toJSONString(decisionReqs, JSONWriter.Feature.WriteNulls);
- boolean needAdd = true;//标识变量是否可以保存
- String dataJson = "";
- String headerPort = httpServletRequest.getHeader(port);
- try {
- channel = ManagedChannelBuilder.forAddress(bigModelConfig.getIp(), StringUtils.isBlank(headerPort) ? bigModelConfig.getPort() : Integer.parseInt(headerPort))
- .usePlaintext()
- .build();
- InferenceAPIsServiceGrpc.InferenceAPIsServiceBlockingStub stub = InferenceAPIsServiceGrpc.newBlockingStub(channel);
- // 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 + "}}";
- //2024年6月24日17:59:17 优化,不再拼接JSON字符串
- dataJson = buildBigModelReqForDecision(chatReq, feedback, simulate, sessionId, decisionReqs, xinyiWarningRecord, chatReq.getTopP(), chatReq.getTemperature());
- // log.info("请求大模型的决策的参数为{}", dataJson);
- PredictionsRequest request = PredictionsRequest.newBuilder()
- .setModelName("slibra_bot")
- .putInput("method", ByteString.copyFrom("decision_stream", "utf-8"))//推理
- .putInput("data", ByteString.copyFrom(dataJson, "utf-8"))
- .buildPartial();
- outputStream = response.getOutputStream();
- Iterator<PredictionResponse> predictions = stub.streamPredictions(request);
- while (predictions.hasNext()) {
- String responseStr = predictions.next().getPrediction().toStringUtf8();
- // log.info("决策流式返回的结果是{}", responseStr);
- if(StringUtils.isBlank(responseStr)){
- log.info("大模型返回的流式决策内容存在空的值,跳过此次输出");
- continue;
- }
- // String message = JSON.parseObject(responseStr).getString("message");
- //2024年5月25日16:37:16 按照大模型返回的类型解析数据
- String biz = JSON.parseObject(responseStr).getString("biz");
- // String message = JSON.parseObject(responseStr).getString("message");
- if(BusinessEnum.BigModelBizEnum.OK.getCode().equals(biz)){
- log.info("结尾语句并且是非JSON,无需处理,返回数据为{}", responseStr);
- //结束语句也流式输出,但是并不记录下来 2024年5月24日11:15:23 也不返回前端
- }else if(BusinessEnum.BigModelBizEnum.DECISION_DEBUGGER.getCode().equals(biz)){
- log.info("中间过程,目前只打印日志,不记录数据,也不返回给前端,返回数据为{}", responseStr);
- //结束语句也流式输出,但是并不记录下来 2024年5月24日11:15:23 也不返回前端
- //2024年6月23日14:55:19 如果大模型返回error了,不保存记录,并且提示一句错误语
- }else if(BusinessEnum.BigModelBizEnum.ERROR.getCode().equalsIgnoreCase(biz)){
- log.info("调用大模型的时候,返回的是ERROR,返回数据为{}", responseStr);
- needAdd = false;
- //返回的是error 给前端返回一句话
- try {
- String errMsg = this.buildErrMsg();
- outputStream.write(errMsg.getBytes());
- outputStream.flush();
- } catch (IOException ex) {
- throw new RuntimeException(ex);
- }
- } else{//其他 要么alert 要么出的报告
- // sb.append(responseStr);
- //2024年7月13日13:48:48 空的数据也返回,否则样式会有问题(当时加上这个是为了前端正常解析,否则他那里一次接受多个)
- /*if(StringUtils.isBlank(message)){
- log.info("×××××××××××××××××××××××××××为空的数据暂时不返回×××××××××××××××××××××××××××");
- }else {
- resultData.add(responseStr);
- outputStream.write(responseStr.getBytes());
- outputStream.flush();
- }*/
- resultData.add(responseStr);
- outputStream.write(responseStr.getBytes());
- outputStream.flush();
- }
- }
- } catch (Exception e) {
- needAdd = false;
- // throw new RuntimeException(e);
- log.error("处理大模型推理异常,异常信息为{}", JSON.toJSONString(e));
- //出现异常 给前端返回一句话
- try {
- outputStream = response.getOutputStream();
- String errMsg = this.buildErrMsg();
- outputStream.write(errMsg.getBytes());
- outputStream.flush();
- } catch (IOException ex) {
- // throw new RuntimeException(ex);
- log.error("输出异常信义的时候又被中断了,异常信息为{}", JSON.toJSONString(ex));
- }
- } finally {
- // log.info("sessionId是{}\n决策最终要保存的数据是{}", sessionId, JSON.toJSONString(resultData));
- //保存聊天记录
- //将问答更新到数据库中
- if(needAdd)
- addChatRecord(chatReq, sessionId, type, warningId, dataJson, resultData);
- // 关闭输出流
- try {
- outputStream.close();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }finally {
- channel.shutdown();
- }
- }
- }
- private String buildBigModelReqForDecision(ChatReq chatReq, String feedback, String simulate, String sessionId, List<DecisionReq> decisionReqs, TXinyiWarningRecord xinyiWarningRecord, Double topP, Double temperature) {
- PolicyReq policyReq = new PolicyReq();
- //2024年7月11日17:57:53 因为化验室的改了 但是 调用决策还得用原来的几个值
- String category = xinyiWarningRecord.getCategory();
- /*if(ROBOT_XSY_1.getCode().equalsIgnoreCase(category) || ROBOT_XSY_2.getCode().equalsIgnoreCase(category)){
- category = CS_ZD.getCode();
- } else if (ROBOT_ANDAN_1.getCode().equalsIgnoreCase(category) || ROBOT_ANDAN_2.getCode().equalsIgnoreCase(category)) {
- category = CS_AD.getCode();
- }else if (ROBOT_ECCZLSY.getCode().equalsIgnoreCase(category)) {
- category = CS_ZL.getCode();
- }*/
- //2024年08月25日15:40:31 处理数据映射,改成字母,但是显示的还是中文
- category = this.parseCategory(category);
- policyReq.setNorm(category);
- // policyReq.setNorm(chatReq.getCategory());//2024年7月12日16:23:24 因为有转义。。。
- policyReq.setFeedback(StringUtils.isBlank(feedback) ? null : JSON.parseObject(feedback, Map.class));
- policyReq.setSimulate(StringUtils.isBlank(simulate) ? null : JSON.parseObject(simulate, Map.class));
- policyReq.setSessionId(sessionId);
- //2024年7月5日13:24:10 temperature做区分
- GenerateArgs generateArgs = new GenerateArgs();
- generateArgs.setTemperature(Objects.isNull(temperature) ? bigModelConfig.getTemperature() : temperature);
- generateArgs.setTopP(Objects.isNull(topP) ? bigModelConfig.getTopP() : topP);
- policyReq.setGenerateArgs(generateArgs);
- HashMap<String, Object> map = new HashMap<>();
- map.put("rows", decisionReqs);
- //2024年6月25日14:16:05 增加报警是管控值报警还是标准值报警
- if(WARNING_LEVEL_ONE.equals(xinyiWarningRecord.getLevel()) || WARNING_LEVEL_TWO.equals(xinyiWarningRecord.getLevel()))
- map.put("source", "bzz");
- else
- map.put("source", "gkz");
- policyReq.setExtra(map);
- return JSON.toJSONString(policyReq, JSONWriter.Feature.WriteNulls);
- }
- private String parseCategory(String category) {
- switch (category) {
- case "进水COD" : return "js_cod";
- case "进水总磷" : return "js_tp";
- case "进水总氮" : return "js_tn";
- case "进水氨氮" : return "js_andan";
- case "进水SS" : return "js_ss";
- case "出水COD" : return "cs_cod";
- case "出水总磷" : return "cs_tp";
- case "出水总氮" : return "cs_tn";
- case "出水氨氮" : return "cs_andan";
- case "出水SS" : return "cs_ss";
- case "#1好氧硝酸盐" : return "cs_tn_lxjc1";
- case "#2好氧硝酸盐" : return "cs_tn_lxjc2";
- case "出水氨氮连续检测" : return "cs_andan_lxjc1";
- case "二沉池正磷酸盐" : return "cs_tp_lxjc";
- default: throw new ServiceException("暂时不支持的类型");
- }
- }
- private void addChatRecord(ChatReq chatReq, String sessionId, int type, String warningId, String question, List<String> resultData) {
- chatReq.setSessionId(sessionId);
- chatReq.setType(type);//类型(0问答 1决策 2本地 3仿真预测)
- chatReq.setModule(3);//0=专家问答,1=智能工单,2=智能体助手,3.告警
- // String showVal = this.buildShowValue(tXinyiWarningRecord, tXinyiIndustry, normConfig);
- // chatReq.setShowVal(feedback);//前端展示的数据和提问的数据不一致
- //如果主动调用决策 showVal应该是最新的那条历史记录对应的数据
- List<TXinyiChatRecord> tXinyiChatRecords = this.xinyiChatRecordMapper.selectTXinyiChatRecordList(TXinyiChatRecord.builder().warningId(warningId).build());
- if(!CollectionUtils.isEmpty(tXinyiChatRecords))
- chatReq.setShowVal(tXinyiChatRecords.get(0).getShowVal());
- chatReq.setQuestion(question);
- chatReq.setAnswer(JSON.toJSONString(resultData));
- chatReq.setWarningId(warningId);
- chatReq.setCounts(1);//问答次数
- String userId = SecurityUtils.getUserId().toString();
- String username = SecurityUtils.getUsername();
- chatReq.setUserId(userId);
- chatReq.setCreateBy(username);
- chatReq.setCreateTime(DateUtils.getNowDate());
- this.xinyiChatRecordMapper.insertTXinyiChatRecord(chatReq);
- }
- private List<DecisionReq> getDecisionReqs() {
- //List<HashMap<String, Object>> list = this.xinyiIndustryMapper.selectLast10RecordsForDecision();
- //2024年5月21日15:23:07 这里不能用关联查询处理,日报要获取最新的一条而不是今日的数据。
- List<DecisionReq> decisionReqs = this.xinyiIndustryMapper.selectLast10RecordsForDecisionOnlyIndustry();
- if(!CollectionUtils.isEmpty(decisionReqs)){
- //处理日报数据
- TXinyiDaily daily = this.xinyiDailyMapper.selectNewestData();
- for (DecisionReq decisionReq : decisionReqs) {
- if(!Objects.isNull(daily)){
- WaterFormat.getWaterDecimationData(decisionReq, daily);
- }
- }
- }
- return decisionReqs;
- }
- private String buildErrMsg() {
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("biz", DECISION_REPORT.getCode());
- jsonObject.put("message", "大模型决策方案生成有点问题,请稍后再试");
- return JSON.toJSONString(jsonObject);
- }
- private String buildMsg() {
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("biz", DECISION_REPORT.getCode());
- jsonObject.put("message", "此报警已经关闭了,无法生成决策方案");
- return JSON.toJSONString(jsonObject);
- }
- /**
- * RAG+⼤模型的调⽤参数
- * 2024年6月17日09:40:38 工单新增 自定义工单处理
- * @return
- */
- @PostMapping(value = "/inferStreamRag")
- public void inferStreamRag(HttpServletRequest httpServletRequest, HttpServletResponse response, @RequestBody ChatReq chatReq) {
- // public void inferStreamRag(HttpServletResponse response, ChatReq chatReq) {
- log.info("进入了调⽤RAG+⼤模型的调⽤参数");
- // 获取输出流
- OutputStream outputStream = null;
- ManagedChannel channel = null;
- // response.setContentType("text/plain");
- response.setContentType("text/event-stream");
- response.setCharacterEncoding("utf-8");
- //请求参数
- Integer module = chatReq.getModule();//来自那个模块
- Date reportDate = chatReq.getReportDate();//如果传过值来了 代表的是工单类型的问答
- String timeBegin = chatReq.getTimeBegin();
- String timeEnd = chatReq.getTimeEnd();
- if((Objects.isNull(reportDate) && StringUtils.isBlank(timeBegin) && StringUtils.isBlank(timeEnd)) && module == 1){//工单 必须要输入日期
- //智能工单需要传入一个时间的参数
- try {
- outputStream = response.getOutputStream();
- outputStream.write(CHAT_GONGDAN_1_ERROR_MSG.getBytes());
- outputStream.flush();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- return;
- }
- StringBuilder sb = new StringBuilder();
- String sessionId = chatReq.getSessionId();
- int isStrong = Objects.isNull(chatReq.getIsStrong()) ? 0 : chatReq.getIsStrong();
- String tools = STR_FALSE;//问答因为不确认是否走工具,所以传true; 但是工单一定是走工具的,传工具名称 2024年08月11日15:51:33 只有工具才是具体名称
- boolean useRag = true;//只有问答才传true,其他默认都false
- String extraStr = "";
- //如果是工单,需要特殊处理一下showVal和question
- if(1 == module){
- if(StringUtils.isBlank(timeBegin) && StringUtils.isBlank(timeEnd)){//按天生成工单
- //获取前一天的日期
- Date beforeYesterday = DateUtils.plusDate(-1, reportDate);
- //先用日期获取当天和前一天的数据,如果获取不到,则提示错误信息
- String date = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, reportDate);
- chatReq.setShowVal(GONGDAN_TITLE.replace("#{0}", date));//处理展示的标题
- /*String dateBefore = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, beforeYesterday);
- String currentDate = DateUtils.parseDateToStr(DateUtils.YYYYMMDD_TS, reportDate);
- String earlyDate = DateUtils.parseDateToStr(DateUtils.YYYYMMDD_TS, beforeYesterday);
- List<TXinyiDaily> tXinyiDailiesNow = this.xinyiDailyMapper.selectTXinyiDailyList(TXinyiDaily.builder().testDate(currentDate).build());
- List<TXinyiDaily> tXinyiDailiesBefore = this.xinyiDailyMapper.selectTXinyiDailyList(TXinyiDaily.builder().testDate(earlyDate).build());
- if(CollectionUtils.isEmpty(tXinyiDailiesNow) || CollectionUtils.isEmpty(tXinyiDailiesBefore)){
- //没有查询到数据
- try {
- outputStream = response.getOutputStream();
- outputStream.write(CHAT_GONGDAN_2_ERROR_MSG.getBytes());
- outputStream.flush();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- return;
- }
- //如果查询到了 拼装数据
- //2024年6月25日19:11:49 prompt优化
- chatReq.setQuestion(this.buildGDQuestionNew(date, dateBefore, tXinyiDailiesNow.get(0), tXinyiDailiesBefore.get(0)));*/
- //2024年7月29日11:38:53 工单改版,由大模型处理数据
- // chatReq.setQuestion(this.buildGDNormalQuestion(DateUtils.parseDateToStr(DateUtils.YYYYMMDD_TS, reportDate)));
- chatReq.setQuestion(MODULE_CONTENT_NORMAL);
- extraStr = this.buildGDNormalQuestion(DateUtils.parseDateToStr(DateUtils.YYYYMMDD_TS, reportDate));
- }else{//自定义工单
- chatReq.setShowVal(GONGDAN_TITLE_CUSTOM.replace("#{0}", timeBegin).replace("#{1}", timeEnd));//处理展示的标题
- WorkOrderReq workOrderReq = new WorkOrderReq();
- BeanUtils.copyProperties(chatReq, workOrderReq);
- //拿到数据
- List<WorkOrderRes> workOrderRes = frontService.customWorkOrder(workOrderReq);
- //拼接prompt
- /*String question = this.buildGDQuestionCustom(workOrderRes, workOrderReq);
- //2024年6月23日17:21:58 判断问题的长度,如果长度大于配置的值(5000),提示一句话
- if(question.length() > MAX_QUESTION_LENGTH){
- log.info("*************自定义工单超长了,组装完的参数为{}", question);
- try {
- outputStream = response.getOutputStream();
- outputStream.write(CHAT_GONGDAN_CUSTOM_ERROR_MSG.getBytes());
- outputStream.flush();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- return;
- }*/
- //2024年7月29日11:47:05 调整:图表以及大模型的数据都由大模型处理,这里拼接他需要的格式
- // chatReq.setQuestion(this.buildGDCustomQuestion(timeBegin, timeEnd, chatReq.getWhichWay()));
- chatReq.setQuestion(MODULE_CONTENT_CUSTOM);
- extraStr = buildGDCustomQuestion(timeBegin, timeEnd, chatReq);
- //2024年6月20日16:48:08 如果是自定义工单,需要处理图表 放到remark中
- chatReq.setRemark(JSON.toJSONString(frontService.customWorkOrderHandleByData(workOrderReq, workOrderRes), JSONWriter.Feature.WriteNulls));
- }
- isStrong = 0;//2024年7月29日14:15:47 工单不走文心一言了
- useRag = false;
- tools = TOOLS_WORK_ORDER;
- }
- String ipAddr = IpUtils.getIpAddr();//获取用户的ip地址 传给大模型
- int counts = 1;//默认是第一次
- List<String> historyDates = new ArrayList<>();
- //查询历史数据,放入集合中
- if(StringUtils.isBlank(sessionId))
- sessionId= IdUtils.simpleUUID();//第一次
- else{
- //通过sessionId获取所有的问答记录
- List<TXinyiChatRecord> chatRecords = this.chatRecordMapper.selectTXinyiChatRecordList(TXinyiChatRecord.builder().sessionId(sessionId).build());
- if(!CollectionUtils.isEmpty(chatRecords)){
- for (TXinyiChatRecord chatRecord : chatRecords) {
- historyDates.add(chatRecord.getQuestion());
- historyDates.add(chatRecord.getAnswer());
- }
- //问答次数增加
- counts = chatRecords.size() + 1;
- }
- }
- //将新的问题放入集合中
- historyDates.add(chatReq.getQuestion());
- String headerPort = httpServletRequest.getHeader(port);
- try {
- channel = ManagedChannelBuilder.forAddress(bigModelConfig.getIp(), StringUtils.isBlank(headerPort) ? bigModelConfig.getPort() : Integer.parseInt(headerPort))
- .usePlaintext()
- .build();
- InferenceAPIsServiceGrpc.InferenceAPIsServiceBlockingStub stub = InferenceAPIsServiceGrpc.newBlockingStub(channel);
- // 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) + "}";
- //2024年6月25日18:12:23 优化,不再使用拼接JSON字符串
- //2024年7月27日18:13:47 前端传过来tools
- String toolsReq = chatReq.getTools();
- //2024年7月29日14:20:22 先判断是不是走本地工具,再判断前端工具
- //2024年08月11日15:54:52 问答默认都是false了,只有前端指定工具才是具体的工具名称
- // if(StringUtils.isBlank(tools) || STR_TRUE.equals(tools)){
- if(StringUtils.isNotBlank(toolsReq)){
- useRag = false;//2024年7月27日18:20:23 走本地工具,不需要文本增强
- isStrong = 0;
- tools = toolsReq;
- }
- //2024年08月21日11:49:25 如果是智慧办公,useRag也是false
- if(2 == module){//智慧办公
- useRag = false;
- }
- // else
- // tools = tools;
- // }
- String dataJson = buildBigModelReqForChat(sessionId, historyDates, ipAddr, isStrong, chatReq.getTopP(), chatReq.getTemperature(), tools, useRag, extraStr, chatReq.getPrompt());
- log.info("******请求大模型的问答参数为{}", dataJson);
- PredictionsRequest request = PredictionsRequest.newBuilder()
- .setModelName("slibra_bot")
- .putInput("method", ByteString.copyFrom("infer_stream", "utf-8"))//推理
- .putInput("data", ByteString.copyFrom(dataJson, "utf-8"))
- .buildPartial();
- outputStream = response.getOutputStream();
- Iterator<PredictionResponse> predictions = stub.streamPredictions(request);
- //将结果记录到问答表
- while (predictions.hasNext()) {
- String responseStr = predictions.next().getPrediction().toStringUtf8();
- // log.info("大模型问答返回的原始结果为{}", responseStr);
- if(StringUtils.isBlank(responseStr)){
- log.error("大模型返回的是空,无法解析");
- continue;
- }
- responseStr = JSON.parseObject(responseStr).getString("message");
- //2024年7月13日14:30:19 为空字符串的(实际可能是\n这种的)也返回前端,否则样式有问题
- if("complete".equals(responseStr) || Objects.isNull(responseStr)){
- // System.out.println("结尾语句并且是非JSON,无需处理");
- log.info("返回的结果message为{},无需再次处理", responseStr);
- //结束语句也流式输出,但是并不记录下来 2024年5月24日11:15:23 也不返回前端
- }else{
- sb.append(responseStr);
- outputStream.write(responseStr.getBytes());
- outputStream.flush();
- }
- }
- //将问答更新到数据库中
- chatReq.setSessionId(sessionId);
- chatReq.setAnswer(sb.toString());
- chatReq.setType(0);//0问答 1决策 2本地 3仿真预测
- chatReq.setModule(module);//0专家问答 1智能工单 2智能体助手 3告警 4简报
- //2024年5月28日10:58:02 由于部分问题 展示的和调用大模型的不一样,所以这个由前端传过来
- // chatReq.setShowVal(question);
- chatReq.setCounts(counts);//问答次数
- String userId = SecurityUtils.getUserId().toString();
- String username = SecurityUtils.getUsername();
- chatReq.setUserId(userId);
- chatReq.setCreateBy(username);
- chatReq.setCreateTime(DateUtils.getNowDate());
- this.chatRecordMapper.insertTXinyiChatRecord(chatReq);
- outputStream.write((DEFAULT_ID_IDENTIFIER + chatReq.getId()).getBytes());
- outputStream.flush();
- } catch (IOException e) {
- throw new RuntimeException(e);
- } finally {
- // 关闭输出流
- try {
- outputStream.close();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }finally {
- channel.shutdown();
- }
- }
- // return AjaxResult.success("ok");
- }
- private String buildGDCustomQuestion(String timeBegin, String timeEnd, ChatReq chatReq) {
- //存放的JSON
- HashMap<String, Object> map = new HashMap<>();
- map.put(TIMEBEGIN, timeBegin);
- map.put(TIMEEND, timeEnd);
- map.put(MODULE, MODULE_CONTENT_CUSTOM);
- map.put(TYPE, CUSTOM_WORK_ORDER);
- //拼装的SQL
- HashMap<String, Object> sqlMap = new HashMap<>();
- StringBuilder sb = new StringBuilder();
- if(chatReq.getWhichWay() == 0){//日报
- // 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());
- //2024年7月31日10:32:14 要根据前端用户选择的不同指标来拼接不同的SQL
- //只要出现一个就可以拼接了
- if (chatReq.getJsSlq() || chatReq.getJsCod() || chatReq.getJsTn() || chatReq.getJsTp() || chatReq.getJsNh3() || chatReq.getJsSs()
- || chatReq.getCsSlqc() || chatReq.getCsCod() || chatReq.getCsTn() || chatReq.getCsTp() || chatReq.getCsNh3() || chatReq.getCsSs()){
- //拼接
- sb.append(TOOLS_WORK_ORDER_SQL_DAILY_BEGIN);
- if(chatReq.getJsSlq())
- sb.append(",AVG(JSL) 进水量");
- if(chatReq.getJsCod())
- sb.append(",AVG(JS_COD) 进水COD");
- if(chatReq.getJsTn())
- sb.append(",AVG(JS_TN) 进水总氮");
- if(chatReq.getJsTp())
- sb.append(",AVG(JS_TP) 进水总磷");
- if(chatReq.getJsNh3())
- sb.append(",AVG(JS_NH3) 进水氨氮");
- if(chatReq.getJsSs())
- sb.append(",AVG(JS_SS) 进水SS");
- if(chatReq.getCsSlqc())
- sb.append(",AVG(CSL) 出水量");
- if(chatReq.getCsCod())
- sb.append(",AVG(CS_COD) 出水COD");
- if(chatReq.getCsTn())
- sb.append(",AVG(CS_TN) 出水总氮");
- if(chatReq.getCsTp())
- sb.append(",AVG(CS_TP) 出水总磷");
- if(chatReq.getCsNh3())
- sb.append(",AVG(CS_NH3) 出水氨氮");
- if(chatReq.getCsSs())
- sb.append(",AVG(CS_SS) 出水SS");
- 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);
- sqlMap.put(REPORT, sb.toString());
- //清空
- sb = new StringBuilder();
- }
- }else{//工业库
- // 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());
- //2024年7月31日10:32:14 要根据前端用户选择的不同指标来拼接不同的SQL
- //只要出现一个就可以拼接了
- if (chatReq.getJsSlq() || chatReq.getJsCod() || chatReq.getJsTn() || chatReq.getJsTp() || chatReq.getJsNh3() || chatReq.getJsSs()
- || chatReq.getCsSlqc() || chatReq.getCsCod() || chatReq.getCsTn() || chatReq.getCsTp() || chatReq.getCsNh3() || chatReq.getCsSs()){
- //拼接
- sb.append(TOOLS_WORK_ORDER_SQL_INDUSTRY_BEGIN);
- if(chatReq.getJsSlq())
- sb.append(", AVG(JS_SLQ) 进水量");
- if(chatReq.getJsCod())
- sb.append(",AVG(JS_COD) 进水COD");
- if(chatReq.getJsTn())
- sb.append(",AVG(JS_TN) 进水总氮");
- if(chatReq.getJsTp())
- sb.append(",AVG(JS_TP) 进水总磷");
- if(chatReq.getJsNh3())
- sb.append(",AVG(JS_NH3) 进水氨氮");
- if(chatReq.getJsSs())
- sb.append(",AVG(JS_SS) 进水SS");
- if(chatReq.getCsSlqc())
- sb.append(",AVG(CS_SLQC) 出水量");
- if(chatReq.getCsCod())
- sb.append(",AVG(CS_COD) 出水COD");
- if(chatReq.getCsTn())
- sb.append(",AVG(CS_TN) 出水总氮");
- if(chatReq.getCsTp())
- sb.append(",AVG(CS_TP) 出水总磷");
- if(chatReq.getCsNh3())
- sb.append(",AVG(CS_NH3) 出水氨氮");
- if(chatReq.getCsSs())
- sb.append(",AVG(CS_SS) 出水SS");
- 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);
- sqlMap.put(ONLINE, sb.toString());
- //清空
- sb = new StringBuilder();
- }
- }
- // 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());
- //2024年7月31日10:32:14 要根据前端用户选择的不同指标来拼接不同的SQL
- //只要出现一个就可以拼接了
- if(chatReq.getNo3Hlj1Jqr() || chatReq.getNo3Hlj2Jqr() || chatReq.getNh31Jqr() || chatReq.getNh32Jqr()
- || chatReq.getNo3Qyc1Jqr() || chatReq.getNo3Qyc2Jqr() || chatReq.getTpRccJqr()){
- //拼接
- sb.append(TOOLS_WORK_ORDER_SQL_ROBOT_BEGIN);
- if(chatReq.getNo3Hlj1Jqr()){
- sb.append(", AVG(NO3_HLJ1_JQR) '#1好氧池硝酸盐'");
- }
- if(chatReq.getNo3Hlj2Jqr()){
- sb.append(",AVG(NO3_HLJ2_JQR) '#2好氧池硝酸盐'");
- }
- if(chatReq.getNh31Jqr()){
- sb.append(",AVG(NH3_1_JQR) '#1缺氧氨氮'");
- }
- if(chatReq.getNh32Jqr()){
- sb.append(",AVG(NH3_2_JQR) '#2缺氧氨氮'");
- }
- if(chatReq.getNo3Qyc1Jqr()){
- sb.append(",AVG(NO3_QYC_1_JQR) '#1缺氧池硝酸盐'");
- }
- if(chatReq.getNo3Qyc2Jqr()){
- sb.append(",AVG(NO3_QYC_2_JQR) '#2缺氧池硝酸盐'");
- }
- if(chatReq.getTpRccJqr()){
- sb.append(",AVG(TP_RCC_JQR) '二沉池正磷酸盐'");
- }
- 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);
- sqlMap.put(ROBOT, sb.toString());
- }
- map.put(DATA, sqlMap);
- return JSON.toJSONString(map);
- }
- private String buildGDNormalQuestion(String date) {
- //存放的JSON
- HashMap<String, Object> map = new HashMap<>();
- map.put(TIMEBEGIN, date);
- map.put(TIMEEND, date);
- map.put(MODULE, MODULE_CONTENT_NORMAL);
- map.put(TYPE, NORMAL_WORK_ORDER);
- return JSON.toJSONString(map);
- }
- private String buildBigModelReqForChat(String sessionId, List<String> historyDates, String ipAddr, int isStrong, Double topP, Double temperature, String tools, boolean useRag, String extraStr, String prompt) {
- ChatRequest chatRequest = new ChatRequest();
- chatRequest.setSessionId(sessionId);
- chatRequest.setHistoryDia(historyDates);
- //2024年7月5日13:24:10 temperature做区分
- GenerateArgs generateArgs = new GenerateArgs();
- generateArgs.setTemperature(Objects.isNull(temperature) ? bigModelConfig.getTemperature() : temperature);
- generateArgs.setTopP(Objects.isNull(topP) ? bigModelConfig.getTopP() : topP);
- chatRequest.setGenerateArgs(generateArgs);
- Map<String, Object> extra = new HashMap<>();
- extra.put("ip_address", ipAddr);
- if(StringUtils.isNotBlank(extraStr))
- extra.put(TOOLS_WORK_ORDER, extraStr);
- chatRequest.setExtra(extra);
- chatRequest.setStrengthen(isStrong == 1);
- chatRequest.setTools(tools);
- chatRequest.setUseRag(useRag);
- //2024年08月11日16:04:21 允许用户自定义prompt
- chatRequest.setPrompt(StringUtils.isBlank(prompt) ? DEFAULT_PROMPT : prompt);
- return JSON.toJSONString(chatRequest);
- }
- private String buildGDQuestionCustom(List<WorkOrderRes> workOrderRes, WorkOrderReq workOrderReq) {
- StringBuilder sb = new StringBuilder();
- sb.append(GONGDAN_PROMPT_CUSTOM_BEGIN.replace("#{0}", workOrderReq.getTimeBegin()).replace("#{1}", workOrderReq.getTimeEnd()));
- if(workOrderReq.getJsSlq() || workOrderReq.getJsSs() || workOrderReq.getJsTp() || workOrderReq.getJsTn() || workOrderReq.getJsCod() || workOrderReq.getJsNh3()){
- sb.append("进水:\n");
- for (WorkOrderRes workOrderRe : workOrderRes) {
- sb.append(workOrderRe.getTime()).append(":");
- if(workOrderReq.getJsCod())
- sb.append("进水COD:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsCod(), INT_2)).append("mg/L、");
- if(workOrderReq.getJsTn())
- sb.append("进水总氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsTn(), INT_2)).append("mg/L、");
- if(workOrderReq.getJsTp())
- sb.append("进水总磷:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsTp(), INT_2)).append("mg/L、");
- if(workOrderReq.getJsNh3())
- sb.append("进水氨氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsNh3(), INT_2)).append("mg/L、");
- if(workOrderReq.getJsSs())
- sb.append("进水SS:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsSs(), INT_2)).append("mg/L、");
- if(workOrderReq.getJsSlq())
- sb.append("进水水量:").append(DecimalUtils.getAbsAndScale(workOrderRe.getJsSlq(), INT_2)).append("m³/d、");
- }
- }
- if(workOrderReq.getCsSlqc() || workOrderReq.getCsSs() || workOrderReq.getCsTp() || workOrderReq.getCsTn() || workOrderReq.getCsCod() || workOrderReq.getCsNh3()){
- sb.append("出水:\n");
- for (WorkOrderRes workOrderRe : workOrderRes) {
- sb.append(workOrderRe.getTime()).append(":");
- if(workOrderReq.getCsCod())
- sb.append("出水COD:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsCod(), INT_2)).append("mg/L、");
- if(workOrderReq.getCsTn())
- sb.append("出水总氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsTn(), INT_2)).append("mg/L、");
- if(workOrderReq.getCsTp())
- sb.append("出水总磷:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsTp(), INT_2)).append("mg/L、");
- if(workOrderReq.getCsNh3())
- sb.append("出水氨氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsNh3(), INT_2)).append("mg/L、");
- if(workOrderReq.getCsSs())
- sb.append("出水SS:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsSs(), INT_2)).append("mg/L、");
- if(workOrderReq.getCsSlqc())
- sb.append("出水水量:").append(DecimalUtils.getAbsAndScale(workOrderRe.getCsSlqc(), INT_2)).append("m³/d、");
- }
- }
- if(workOrderReq.getNo3Hlj1Jqr() || workOrderReq.getNo3Hlj2Jqr() || workOrderReq.getNh31Jqr() || workOrderReq.getNh32Jqr()
- || workOrderReq.getNo3Qyc1Jqr() || workOrderReq.getNo3Qyc2Jqr() || workOrderReq.getTpRccJqr()){
- sb.append("过程指标:\n");
- for (WorkOrderRes workOrderRe : workOrderRes) {
- sb.append(workOrderRe.getTime()).append(":");
- if(workOrderReq.getNo3Hlj1Jqr())
- sb.append("#1好氧池硝酸盐:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNo3Hlj1Jqr(), INT_2)).append("mg/L、");
- if(workOrderReq.getNo3Hlj2Jqr())
- sb.append("#2好氧池硝酸盐:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNo3Hlj2Jqr(), INT_2)).append("mg/L、");
- if(workOrderReq.getNo3Qyc1Jqr())
- sb.append("#1缺氧池硝酸盐:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNo3Qyc1Jqr(), INT_2)).append("mg/L、");
- if(workOrderReq.getNo3Qyc2Jqr())
- sb.append("#2缺氧池硝酸盐:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNo3Qyc2Jqr(), INT_2)).append("mg/L、");
- if(workOrderReq.getTpRccJqr())
- sb.append("二沉池正磷酸盐:").append(DecimalUtils.getAbsAndScale(workOrderRe.getTpRccJqr(), INT_2)).append("mg/L、");
- if(workOrderReq.getNh31Jqr())
- sb.append("#1缺氧氨氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNh31Jqr(), INT_2)).append("mg/L、");
- if(workOrderReq.getNh32Jqr())
- sb.append("#2缺氧氨氮:").append(DecimalUtils.getAbsAndScale(workOrderRe.getNh32Jqr(), INT_2)).append("mg/L、");
- }
- }
- sb.append(GONGDAN_PROMPT_CUSTOM_END_1);
- if(workOrderReq.getJsCod() || workOrderReq.getCsCod())
- sb.append("化学需氧量(COD)、");
- if(workOrderReq.getJsTp() || workOrderReq.getCsTp())
- sb.append("总磷(TP)、");
- if(workOrderReq.getJsTn() || workOrderReq.getCsTn())
- sb.append("总氮(TN)、");
- if(workOrderReq.getJsSs() || workOrderReq.getCsSs())
- sb.append("SS、");
- if(workOrderReq.getJsNh3() || workOrderReq.getCsNh3())
- sb.append("氨氮、");
- sb.append(GONGDAN_PROMPT_CUSTOM_END_2);
- return sb.toString();
- }
- /**
- * 通过日期构建工单的请求参数 --new
- * @return
- */
- private String buildGDQuestionNew(String date, String dateBefore, TXinyiDaily tXinyiDaily, TXinyiDaily tXinyiDaily1) {
- StringBuilder sb = new StringBuilder(GONGDAN_PROMPT_BEGIN_PRE_1).append(date);
- // sb.append(GONGDAN_PROMPT_BEGIN.replace("#{0}", date));
- sb.append(GONGDAN_PROMPT_BEGIN_PRE_2).append(date);
- sb.append(GONGDAN_PROMPT_BEGIN_PRE_3);
- sb.append("进水COD:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJsCod(), INT_2)).append("mg/L、");
- sb.append("进水总氮:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJsTn(), INT_2)).append("mg/L、");
- sb.append("进水总磷:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJsTp(), INT_2)).append("mg/L、");
- sb.append("进水氨氮:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJsNh3(), INT_2)).append("mg/L、");
- sb.append("进水SS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJsSs(), INT_2)).append("mg/L、");
- sb.append("进水水量:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getJSL(), INT_2)).append("m³/d、");
- sb.append(";");
- sb.append("出水COD:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCsCod(), INT_2)).append("mg/L、");
- sb.append("出水总氮:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCsTn(), INT_2)).append("mg/L、");
- sb.append("出水总磷:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCsTp(), INT_2)).append("mg/L、");
- sb.append("出水氨氮:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCsNh3(), INT_2)).append("mg/L、");
- sb.append("出水SS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCsSs(), INT_2)).append("mg/L、");
- sb.append("出水水量:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getCSL(), INT_2)).append("m³/d。");
- sb.append("二、生化指标:\n");
- //todo 单位确认 下面的应该不是 mg/L
- sb.append("#1好氧池pH:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcOnePh(), INT_2)).append("、");
- sb.append("#1好氧池SV:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyOneSv(), INT_2)).append("、");
- sb.append("#1好氧池SVI:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyOneSvi(), INT_2)).append("、");
- sb.append("#1好氧池MLSS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyOneMlss(), INT_2)).append("、");
- sb.append("#1好氧池MLVSS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyOneMlvss(), INT_2)).append("、");
- sb.append("#1好氧池DO:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyOneDo(), INT_2)).append(";");
- sb.append("#2好氧池pH:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcTwoPh(), INT_2)).append("、");
- sb.append("#2好氧池SV:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyTwoSv(), INT_2)).append("、");
- sb.append("#2好氧池SVI:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyTwoSvi(), INT_2)).append("、");
- sb.append("#2好氧池MLSS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyTwoMlss(), INT_2)).append("、");
- sb.append("#2好氧池MLVSS:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyTwoMlvss(), INT_2)).append("、");
- sb.append("#2好氧池DO:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcHyTwoDo(), INT_2)).append(";");
- sb.append("#1厌氧池DO:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcYyOneDo(), INT_2)).append(";");
- sb.append("#2厌氧池DO:").append(DecimalUtils.getAbsAndScale(tXinyiDaily.getShcYyTwoDo(), INT_2)).append("。");
- sb.append("最近7天的数据如下:\n");
- List<TXinyiDaily> dailyTwoRecords = this.xinyiDailyMapper.selectNRecords(DAILY_REPORT_COUNT_RECORD);
- //正常不会有这种问题 因为日报有很多条
- if(CollectionUtils.isEmpty(dailyTwoRecords) || dailyTwoRecords.size() < DAILY_REPORT_COUNT_RECORD){
- log.error("进入了定时生成每日简报数据 获取最新的{}条数据不足,终止", DAILY_REPORT_COUNT_RECORD);
- return sb.toString();
- }
- //查询配置信息
- List<TXinyiNormConfig> tXinyiNormConfigs = this.xinyiNormConfigMapper.selectTXinyiNormConfigList(null);
- if(CollectionUtils.isEmpty(tXinyiNormConfigs))
- return null;
- TXinyiNormConfig normConfig = tXinyiNormConfigs.get(0);
- //获取数据
- for (TXinyiDaily dailyTwoRecord : dailyTwoRecords) {
- sb.append(formateDateStr(dailyTwoRecord.getTestDate())).append("进出水质数据:\n");
- sb.append("进水:\n");
- sb.append("进水COD").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsCod(), 2)).append("mg/L、");
- sb.append("进水总氮").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsTn(), 2)).append("mg/L、");
- sb.append("进水总磷").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsTp(), 2)).append("mg/L、");
- sb.append("进水氨氮").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsNh3(), 2)).append("mg/L、");
- sb.append("进水SS").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJsSs(), 2)).append("mg/L、");
- sb.append("进水水量").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getJSL(), 2)).append("m³/d").append(";\n");
- sb.append("出水:\n");
- sb.append("出水COD").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsCod(), 2)).append("mg/L、");
- sb.append("出水总氮").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsTn(), 2)).append("mg/L、");
- sb.append("出水总磷").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsTp(), 2)).append("mg/L、");
- sb.append("出水氨氮").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsNh3(), 2)).append("mg/L、");
- sb.append("出水SS").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCsSs(), 2)).append("mg/L、");
- sb.append("出水水量").append(DecimalUtils.getAbsAndScale(dailyTwoRecord.getCSL(), 2)).append("m³/d").append("。\n");
- }
- sb.append(SHORT_REPORT_END);
- sb.append("进水COD:").append(DecimalUtils.getAbsAndScale(normConfig.getJscodSjz(), 2)).append("mg/L、");
- sb.append("进水总氮:").append(DecimalUtils.getAbsAndScale(normConfig.getJszdSjz(), 2)).append("mg/L、");
- sb.append("进水总磷:").append(DecimalUtils.getAbsAndScale(normConfig.getJszlSjz(), 2)).append("mg/L、");
- sb.append("进水氨氮:").append(DecimalUtils.getAbsAndScale(normConfig.getJsadSjz(), 2)).append("mg/L、");
- sb.append("进水SS:").append(DecimalUtils.getAbsAndScale(normConfig.getJsssSjz(), 2)).append("mg/L、");
- sb.append("出水COD:").append(DecimalUtils.getAbsAndScale(normConfig.getCscodBzz(), 2)).append("mg/L、");
- sb.append("出水总氮:").append(DecimalUtils.getAbsAndScale(normConfig.getCszzBzz(), 2)).append("mg/L、");
- sb.append("出水总磷:").append(DecimalUtils.getAbsAndScale(normConfig.getCszlBzz(), 2)).append("mg/L、");
- sb.append("出水氨氮:").append(DecimalUtils.getAbsAndScale(normConfig.getCsadBzz(), 2)).append("mg/L、");
- sb.append("出水SS:").append(DecimalUtils.getAbsAndScale(normConfig.getCsssBzz(), 2)).append("mg/L").append("。");
- sb.append(GONGDAN_PROMPT_END);
- return sb.toString();
- }
- /**
- *
- * 2022/01/01 转成2022年01月01日 数据
- * @param testDate
- * @return
- */
- private String formateDateStr(String testDate) {
- if(StringUtils.isBlank(testDate))
- return "";
- if(!testDate.contains("/"))
- return testDate;
- String[] split = testDate.split("/");
- return split[0] + "年" + split[1] + "月" + split[2] + "日";
- }
- /**
- * 通过日期构建工单的请求参数
- * @return
- */
- private String buildGDQuestion(String date, String dateBefore, TXinyiDaily xinyiDailyNow, TXinyiDaily xinyiDailyBefore) {
- String result = GONGDAN_PROMPT;
- result = result.replace("{0}", date);
- result = result.replace("{1}", dateBefore);
- //替换各种指标
- result = result.replace("{2}", String.valueOf(xinyiDailyNow.getJsCod()));
- result = result.replace("{3}", String.valueOf(xinyiDailyNow.getJsTn()));
- result = result.replace("{4}", String.valueOf(xinyiDailyNow.getJsTp()));
- result = result.replace("{5}", String.valueOf(xinyiDailyNow.getJsNh3()));
- result = result.replace("{6}", String.valueOf(xinyiDailyNow.getJsSs()));
- result = result.replace("{7}", String.valueOf(xinyiDailyNow.getJSL()));
- result = result.replace("{8}", String.valueOf(xinyiDailyNow.getCsCod()));
- result = result.replace("{9}", String.valueOf(xinyiDailyNow.getCsTn()));
- result = result.replace("{10}", String.valueOf(xinyiDailyNow.getCsTp()));
- result = result.replace("{11}", String.valueOf(xinyiDailyNow.getCsNh3()));
- result = result.replace("{12}", String.valueOf(xinyiDailyNow.getCsSs()));
- result = result.replace("{13}", String.valueOf(xinyiDailyNow.getCSL()));
- result = result.replace("{14}", String.valueOf(xinyiDailyNow.getShcOnePh()));
- result = result.replace("{15}", String.valueOf(xinyiDailyNow.getShcHyOneSv()));
- result = result.replace("{16}", String.valueOf(xinyiDailyNow.getShcHyOneSvi()));
- result = result.replace("{17}", String.valueOf(xinyiDailyNow.getShcHyOneMlss()));
- result = result.replace("{18}", String.valueOf(xinyiDailyNow.getShcHyOneMlvss()));
- result = result.replace("{19}", String.valueOf(xinyiDailyNow.getShcHyOneDo()));
- result = result.replace("{20}", String.valueOf(xinyiDailyNow.getShcTwoPh()));
- result = result.replace("{21}", String.valueOf(xinyiDailyNow.getShcHyTwoSv()));
- result = result.replace("{22}", String.valueOf(xinyiDailyNow.getShcHyTwoSvi()));
- result = result.replace("{23}", String.valueOf(xinyiDailyNow.getShcHyTwoMlss()));
- result = result.replace("{24}", String.valueOf(xinyiDailyNow.getShcHyTwoMlvss()));
- result = result.replace("{25}", String.valueOf(xinyiDailyNow.getShcHyTwoDo()));
- result = result.replace("{26}", String.valueOf(xinyiDailyNow.getShcYyOneDo()));
- result = result.replace("{27}", String.valueOf(xinyiDailyNow.getShcYyTwoDo()));
- result = result.replace("{28}", String.valueOf(xinyiDailyBefore.getJsCod()));
- result = result.replace("{29}", String.valueOf(xinyiDailyBefore.getJsTn()));
- result = result.replace("{30}", String.valueOf(xinyiDailyBefore.getJsTp()));
- result = result.replace("{31}", String.valueOf(xinyiDailyBefore.getJsNh3()));
- result = result.replace("{32}", String.valueOf(xinyiDailyBefore.getJsSs()));
- result = result.replace("{33}", String.valueOf(xinyiDailyBefore.getJSL()));
- result = result.replace("{34}", String.valueOf(xinyiDailyBefore.getCsCod()));
- result = result.replace("{35}", String.valueOf(xinyiDailyBefore.getCsTn()));
- result = result.replace("{36}", String.valueOf(xinyiDailyBefore.getCsTp()));
- result = result.replace("{37}", String.valueOf(xinyiDailyBefore.getCsNh3()));
- result = result.replace("{38}", String.valueOf(xinyiDailyBefore.getCsSs()));
- result = result.replace("{39}", String.valueOf(xinyiDailyBefore.getCSL()));
- return result;
- }
- public static void main(String[] args) {
- // 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";
- // String decoded = decodeOctalToUtf8(encoded);
- // System.out.println(decoded);
- testPredictor();
- }
- public static void testPredictor(){
- // 获取输出流
- ManagedChannel channel = null;
- try {
- channel = ManagedChannelBuilder.forAddress("10.0.0.24", 27070)
- .usePlaintext()
- .build();
- InferenceAPIsServiceGrpc.InferenceAPIsServiceBlockingStub stub = InferenceAPIsServiceGrpc.newBlockingStub(channel);
- // String dataJson = "{\"bot_id\":\"b00001\",\"exp_id\":\"721\",\"norm\":\"出水氨氮\",\"session_id\":\" " + IdUtils.simpleUUID() + " \",\"extra\":{}}";
- //2024年6月27日13:23:25 优化:改成非拼接JSON字符串
- String dataJson = buildBigModelReqForPredictor("缺氧出水氨氮1");
- // String dataJson = buildBigModelReqForPredictor("qyxsy1");
- // log.info("请求大模型的预测的参数为{}", dataJson);
- PredictionsRequest request = PredictionsRequest.newBuilder()
- .setModelName("slibra_bot")
- .putInput("method", ByteString.copyFrom("predictor", "utf-8"))//推理
- .putInput("data", ByteString.copyFrom(dataJson, "utf-8"))
- .buildPartial();
- //2024年6月21日10:35:22 改成非流式输出
- /*Iterator<PredictionResponse> predictions = stub.streamPredictions(request);
- //将结果记录到问答表
- String responseStr = predictions.next().getPrediction().toStringUtf8();
- log.info("大模型问答返回的原始结果为{}", responseStr);*/
- PredictionResponse predictions = stub.predictions(request);
- String responseStr = predictions.getPrediction().toStringUtf8();
- log.info("大模型问答返回的原始结果为{}", responseStr);
- } catch (IOException e) {
- throw new RuntimeException(e);
- } finally {
- channel.shutdown();
- }
- }
- private static String buildBigModelReqForPredictor(String type) {
- PredictorRequest predictorRequest = new PredictorRequest();
- predictorRequest.setNorm(type);
- predictorRequest.setSessionId(IdUtils.simpleUUID());
- return JSON.toJSONString(predictorRequest);
- }
- }
|