Pārlūkot izejas kodu

自定义工单调用大模型获取流式输出调整

wangmiaomiao 10 mēneši atpakaļ
vecāks
revīzija
35dff260df

+ 1 - 1
slibra-admin/src/main/java/com/slibra/web/controller/business/FrontController.java

@@ -337,7 +337,7 @@ public class FrontController extends BaseController {
      * 自定义工单接口 获取数据接口
      * @return
      */
-    @GetMapping("/bigModel/custom/workOrder")
+    @PostMapping("/bigModel/custom/workOrder")
     public AjaxResult customWorkOrder(@RequestBody WorkOrderReq workOrderReq)
     {
         log.info("进入了 自定义工单接口 获取数据接口 接口");

+ 92 - 22
slibra-admin/src/main/java/com/slibra/web/controller/business/GRPCController.java

@@ -8,6 +8,9 @@ import com.slibra.business.domain.*;
 import com.slibra.business.mapper.*;
 import com.slibra.business.req.ChatReq;
 import com.slibra.business.req.DecisionReq;
+import com.slibra.business.req.WorkOrderReq;
+import com.slibra.business.res.WorkOrderRes;
+import com.slibra.business.service.IFrontService;
 import com.slibra.common.core.controller.BaseController;
 import com.slibra.common.enums.BusinessEnum;
 import com.slibra.common.exception.ServiceException;
@@ -22,6 +25,7 @@ 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.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
@@ -60,6 +64,9 @@ public class GRPCController extends BaseController {
     @Autowired
     private TXinyiWarningRecordMapper xinyiWarningRecordMapper;
 
+    @Autowired
+    private IFrontService frontService;
+
 
     /*private InferenceAPIsServiceGrpc.InferenceAPIsServiceBlockingStub getStub(){
         return InferenceAPIsServiceGrpc.newBlockingStub(ManagedChannelBuilder.forAddress("10.0.0.24", 17070)
@@ -262,6 +269,7 @@ public class GRPCController extends BaseController {
 
     /**
      * RAG+⼤模型的调⽤参数
+     * 2024年6月17日09:40:38 工单新增 自定义工单处理
      * @return
      */
     @PostMapping(value = "/inferStreamRag")
@@ -277,7 +285,9 @@ public class GRPCController extends BaseController {
         //请求参数
         Integer module = chatReq.getModule();//来自那个模块
         Date reportDate = chatReq.getReportDate();//如果传过值来了 代表的是工单类型的问答
-        if(Objects.isNull(reportDate) && module == 1){//工单 必须要输入日期
+        String timeBegin = chatReq.getTimeBegin();
+        String timeEnd = chatReq.getTimeEnd();
+        if((Objects.isNull(reportDate) || StringUtils.isBlank(timeBegin) && StringUtils.isBlank(timeEnd)) && module == 1){//工单 必须要输入日期
             //智能工单需要传入一个时间的参数
             try {
                 outputStream = response.getOutputStream();
@@ -293,29 +303,36 @@ public class GRPCController extends BaseController {
         int isStrong = Objects.isNull(chatReq.getIsStrong()) ? 0 : chatReq.getIsStrong();
         //如果是工单,需要特殊处理一下showVal和question
         if(1 == module){
-            //获取前一天的日期
-            Date beforeYesterday = DateUtils.plusDate(-1, reportDate);
-            //先用日期获取当天和前一天的数据,如果获取不到,则提示错误信息
-            String date = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, reportDate);
-            String dateBefore = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, beforeYesterday);
-            chatReq.setShowVal(GONGDAN_TITLE.replace("#{0}", date));//处理展示的标题
-            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);
+            if(StringUtils.isBlank(timeBegin) && StringUtils.isBlank(timeEnd)){//按天生成工单
+                //获取前一天的日期
+                Date beforeYesterday = DateUtils.plusDate(-1, reportDate);
+                //先用日期获取当天和前一天的数据,如果获取不到,则提示错误信息
+                String date = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, reportDate);
+                String dateBefore = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, beforeYesterday);
+                chatReq.setShowVal(GONGDAN_TITLE.replace("#{0}", date));//处理展示的标题
+                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;
                 }
-                return;
+                //如果查询到了 拼装数据
+                chatReq.setQuestion(this.buildGDQuestion(date, dateBefore, tXinyiDailiesNow.get(0), tXinyiDailiesBefore.get(0)));
+            }else{//自定义工单
+                chatReq.setShowVal(GONGDAN_TITLE_CUSTOM.replace("#{0}", timeBegin).replace("#{1}", timeEnd));//处理展示的标题
+                WorkOrderReq workOrderReq = new WorkOrderReq();
+                BeanUtils.copyProperties(chatReq, workOrderReq);
+                chatReq.setQuestion(this.buildGDQuestionCustom(frontService.customWorkOrder(workOrderReq), workOrderReq));
             }
-            //如果查询到了 拼装数据
-            chatReq.setQuestion(this.buildGDQuestion(date, dateBefore, tXinyiDailiesNow.get(0), tXinyiDailiesBefore.get(0)));
             isStrong = 1;
         }
         String ipAddr = IpUtils.getIpAddr();//获取用户的ip地址 传给大模型
@@ -402,6 +419,59 @@ public class GRPCController extends BaseController {
 //        return AjaxResult.success("ok");
     }
 
+    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(workOrderRe.getJsCod()).append("mg/L、");
+                if(workOrderReq.getJsTn())
+                    sb.append(workOrderRe.getJsTn()).append("mg/L、");
+                if(workOrderReq.getJsTp())
+                    sb.append(workOrderRe.getJsTp()).append("mg/L、");
+                if(workOrderReq.getJsNh3())
+                    sb.append(workOrderRe.getJsNh3()).append("mg/L、");
+                if(workOrderReq.getJsSs())
+                    sb.append(workOrderRe.getJsSs()).append("mg/L、");
+                if(workOrderReq.getJsSlq())
+                    sb.append(workOrderRe.getJsSlq()).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(workOrderRe.getCsCod()).append("mg/L、");
+                if(workOrderReq.getCsTn())
+                    sb.append(workOrderRe.getCsTn()).append("mg/L、");
+                if(workOrderReq.getCsTp())
+                    sb.append(workOrderRe.getCsTp()).append("mg/L、");
+                if(workOrderReq.getCsNh3())
+                    sb.append(workOrderRe.getCsNh3()).append("mg/L、");
+                if(workOrderReq.getCsSs())
+                    sb.append(workOrderRe.getCsSs()).append("mg/L、");
+                if(workOrderReq.getCsSlqc())
+                    sb.append(workOrderRe.getCsSlqc()).append("m³/d、");
+            }
+        }
+        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();
+    }
 
 
     /**

+ 17 - 1
slibra-common/src/main/java/com/slibra/common/constant/MyConstants.java

@@ -99,10 +99,11 @@ public class MyConstants {
             "       已知数据:#{0},标准值#{1}mg/L,现在值#{2}mg/L,预测值#{3}mg/L,预计三小时后发生超标情况\n" +
             "      根据已知数据生成超标解决方案,请输出一个解决方案,方案分为三部分,第一部分写问题总述,第二部分问题解决方案,第三部分用表格呈现与超标指标关系到的其他污水处理指标的处理的建议值、调整说明等内容。";
 
-    public static final String CHAT_GONGDAN_1_ERROR_MSG = "智能工单问答必须选择一个日期";
+    public static final String CHAT_GONGDAN_1_ERROR_MSG = "智能工单问答必须选择日期";
     public static final String CHAT_GONGDAN_2_ERROR_MSG = "很抱歉,当前日期指标没有数据,请查证后再试";
 
     public static final String GONGDAN_TITLE = "请生成#{0}智能工单分析报告";
+    public static final String GONGDAN_TITLE_CUSTOM = "请成生#{0}-#{1}日的日报工单";
 
     /**
      * 工单的prompt
@@ -166,4 +167,19 @@ public class MyConstants {
             "\n" +
             "对未来水质管理和监控工作提出建议和展望。";
 
+
+    public static final String GONGDAN_PROMPT_CUSTOM_BEGIN = "作为一个污水处理工艺分析师,请根据#{0}-#{1}的数据情况,输出一份详细的分析报告。报告需数据准确、分析深入,建议具体可行,以便为水务管理和决策提供支持。\n" +
+            "#{0}-#{1}的数据情况如下:";
+    public static final String GONGDAN_PROMPT_CUSTOM_END_1 = "根据以上内容,输出一份详细的分析报告。报告需数据准确、分析深入,建议具体可行,以便为水务管理和决策提供支持。包括以下:\n" +
+            "1、指标数据的分析:";
+
+    public static final String GONGDAN_PROMPT_CUSTOM_END_2 = "指标数据分析:\n" +
+            "分析所有关键水质和生化指标的达标情况,包括与国家标准和行业标准的对比。\n" +
+            "使用趋势分析法,分析水质情况\n" +
+            "2、综合分析与建议:\n" +
+            "根据上述数据,运用适当的分析方法,如工艺分析、数据趋势分析法、在线仪表与水质指标数据比对效果、预测分析法(分析出未来趋势),提出针对性的改善建议,包括但不限于优化处理工艺、加强水质监测、改善水源保护等。\n" +
+            "结论:\n" +
+            "总结分析报告的主要发现,强调当前水质和生化指标的整体状况。\n" +
+            "对未来水质管理和监控工作提出建议和展望。";
+
 }

+ 247 - 0
slibra-system/src/main/java/com/slibra/business/req/ChatReq.java

@@ -35,6 +35,76 @@ public class ChatReq extends TXinyiChatRecord {
     @JsonFormat(pattern = "yyyy-MM-dd")
     private Date reportDate;//yyyy-MM-dd格式的
 
+    //2024年6月17日09:46:53  自定义工单相关参数新增
+
+    /**  开始时间 */
+//    @JsonFormat(pattern = "yyyy-MM-dd")
+    private String timeBegin;
+
+    /** 截止时间 */
+//    @JsonFormat(pattern = "yyyy-MM-dd")
+    private String timeEnd;
+
+    private int whichWay;//统计方式  0:日报  1:工业库(在线仪表)
+
+    /** 进水水量Q进 */
+    private Boolean jsSlq = false;
+
+    /** 进水化学需氧量COD */
+    private Boolean jsCod = false;
+
+    /** 进水总氮TN */
+    private Boolean jsTn = false;
+
+    /** 进水总磷TP */
+    private Boolean jsTp = false;
+
+    /** 进水氨氮NH₃-N */
+    private Boolean jsNh3 = false;
+
+    /** 进水悬浮物SS */
+    private Boolean jsSs = false;
+
+
+    /** 出水水量Q出 */
+    private Boolean csSlqc = false;
+
+    /** 出水化学需氧量COD */
+    private Boolean csCod = false;
+
+    /** 出水总氮TN */
+    private Boolean csTn = false;
+
+    /** 出水总磷TP */
+    private Boolean csTp = false;
+
+    /** 出水氨氮NH₃-N */
+    private Boolean csNh3 = false;
+
+    /** 出水悬浮物SS */
+    private Boolean csSs = false;
+
+    /** 1#好氧池硝酸盐(内回流)+ 回流进水化验机器人有效值1(硝氮1池回流机器人) */
+    private Boolean no3Hlj1Jqr = false;
+
+    /** 2#好氧池硝酸盐(内回流) + 回流进水化验机器人有效值2(硝氮2池回流机器人) */
+    private Boolean no3Hlj2Jqr = false;
+
+    /** 1#缺氧氨氮 + 化验机器人氨氮化验有效值1(氨氮1池缺氧机器人) */
+    private Boolean nh31Jqr = false;
+
+    /** 2#缺氧氨氮 + 化验机器人氨氮化验有效值2(氨氮2池缺氧机器人) */
+    private Boolean nh32Jqr = false;
+
+    /** 1#缺氧出口硝酸盐 + 缺氧出水化验机器人有效值1(硝氮1池缺氧机器人) */
+    private Boolean no3Qyc1Jqr = false;
+
+    /** 2#缺氧出-硝酸盐 + 缺氧出水化验机器人有效值2(硝氮2池缺氧机器人) */
+    private Boolean no3Qyc2Jqr = false;
+
+    /** 二沉池-正磷酸盐 + 化验机器人正磷化验有效值二沉池(正磷二沉池机器人) */
+    private Boolean tpRccJqr = false;
+
     public String getFeedback() {
         return feedback;
     }
@@ -85,4 +155,181 @@ public class ChatReq extends TXinyiChatRecord {
     public void setReportDate(Date reportDate) {
         this.reportDate = reportDate;
     }
+
+
+    public String getTimeBegin() {
+        return timeBegin;
+    }
+
+    public void setTimeBegin(String timeBegin) {
+        this.timeBegin = timeBegin;
+    }
+
+    public String getTimeEnd() {
+        return timeEnd;
+    }
+
+    public void setTimeEnd(String timeEnd) {
+        this.timeEnd = timeEnd;
+    }
+
+    public int getWhichWay() {
+        return whichWay;
+    }
+
+    public void setWhichWay(int whichWay) {
+        this.whichWay = whichWay;
+    }
+
+    public Boolean getJsSlq() {
+        return jsSlq;
+    }
+
+    public void setJsSlq(Boolean jsSlq) {
+        this.jsSlq = jsSlq;
+    }
+
+    public Boolean getJsCod() {
+        return jsCod;
+    }
+
+    public void setJsCod(Boolean jsCod) {
+        this.jsCod = jsCod;
+    }
+
+    public Boolean getJsTn() {
+        return jsTn;
+    }
+
+    public void setJsTn(Boolean jsTn) {
+        this.jsTn = jsTn;
+    }
+
+    public Boolean getJsTp() {
+        return jsTp;
+    }
+
+    public void setJsTp(Boolean jsTp) {
+        this.jsTp = jsTp;
+    }
+
+    public Boolean getJsNh3() {
+        return jsNh3;
+    }
+
+    public void setJsNh3(Boolean jsNh3) {
+        this.jsNh3 = jsNh3;
+    }
+
+    public Boolean getJsSs() {
+        return jsSs;
+    }
+
+    public void setJsSs(Boolean jsSs) {
+        this.jsSs = jsSs;
+    }
+
+    public Boolean getCsSlqc() {
+        return csSlqc;
+    }
+
+    public void setCsSlqc(Boolean csSlqc) {
+        this.csSlqc = csSlqc;
+    }
+
+    public Boolean getCsCod() {
+        return csCod;
+    }
+
+    public void setCsCod(Boolean csCod) {
+        this.csCod = csCod;
+    }
+
+    public Boolean getCsTn() {
+        return csTn;
+    }
+
+    public void setCsTn(Boolean csTn) {
+        this.csTn = csTn;
+    }
+
+    public Boolean getCsTp() {
+        return csTp;
+    }
+
+    public void setCsTp(Boolean csTp) {
+        this.csTp = csTp;
+    }
+
+    public Boolean getCsNh3() {
+        return csNh3;
+    }
+
+    public void setCsNh3(Boolean csNh3) {
+        this.csNh3 = csNh3;
+    }
+
+    public Boolean getCsSs() {
+        return csSs;
+    }
+
+    public void setCsSs(Boolean csSs) {
+        this.csSs = csSs;
+    }
+
+    public Boolean getNo3Hlj1Jqr() {
+        return no3Hlj1Jqr;
+    }
+
+    public void setNo3Hlj1Jqr(Boolean no3Hlj1Jqr) {
+        this.no3Hlj1Jqr = no3Hlj1Jqr;
+    }
+
+    public Boolean getNo3Hlj2Jqr() {
+        return no3Hlj2Jqr;
+    }
+
+    public void setNo3Hlj2Jqr(Boolean no3Hlj2Jqr) {
+        this.no3Hlj2Jqr = no3Hlj2Jqr;
+    }
+
+    public Boolean getNh31Jqr() {
+        return nh31Jqr;
+    }
+
+    public void setNh31Jqr(Boolean nh31Jqr) {
+        this.nh31Jqr = nh31Jqr;
+    }
+
+    public Boolean getNh32Jqr() {
+        return nh32Jqr;
+    }
+
+    public void setNh32Jqr(Boolean nh32Jqr) {
+        this.nh32Jqr = nh32Jqr;
+    }
+
+    public Boolean getNo3Qyc1Jqr() {
+        return no3Qyc1Jqr;
+    }
+
+    public void setNo3Qyc1Jqr(Boolean no3Qyc1Jqr) {
+        this.no3Qyc1Jqr = no3Qyc1Jqr;
+    }
+
+    public Boolean getNo3Qyc2Jqr() {
+        return no3Qyc2Jqr;
+    }
+
+    public void setNo3Qyc2Jqr(Boolean no3Qyc2Jqr) {
+        this.no3Qyc2Jqr = no3Qyc2Jqr;
+    }
+
+    public Boolean getTpRccJqr() {
+        return tpRccJqr;
+    }
+
+    public void setTpRccJqr(Boolean tpRccJqr) {
+        this.tpRccJqr = tpRccJqr;
+    }
 }

+ 1 - 1
slibra-system/src/main/java/com/slibra/business/req/WorkOrderReq.java

@@ -23,7 +23,7 @@ public class WorkOrderReq {
 //    @JsonFormat(pattern = "yyyy-MM-dd")
     private String timeEnd;
 
-    private int type;//统计方式  0:日报  1:工业库(在线仪表)
+    private int whichWay;//统计方式  0:日报  1:工业库(在线仪表)
 
     /** 进水水量Q进 */
     private Boolean jsSlq = false;

+ 1 - 1
slibra-system/src/main/java/com/slibra/business/service/impl/FrontServiceImpl.java

@@ -183,7 +183,7 @@ public class FrontServiceImpl implements IFrontService {
             if(!Objects.isNull(xinyiRobot))
                 this.buildRobotData(xinyiRobot, workOrderRes, workOrderReq);
             //判断数据来源(进出水情况)
-            if(workOrderReq.getType() == 0){// 0:日报  1:工业库(在线仪表)
+            if(workOrderReq.getWhichWay() == 0){// 0:日报  1:工业库(在线仪表)
                 List<TXinyiDaily> tXinyiDailies = this.xinyiDailyMapper.selectTXinyiDailyList(TXinyiDaily.builder().testDate(date).build());
                 if(!CollectionUtils.isEmpty(tXinyiDailies)){
                     TXinyiDaily tXinyiDaily = tXinyiDailies.get(0);