| src/main/java/com/zy/ai/entity/WcsDiagnosisRequest.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/ai/service/WcsDiagnosisService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/ai/utils/AiPromptUtils.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/ai/utils/AiUtils.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/main/java/com/zy/ai/entity/WcsDiagnosisRequest.java
@@ -1,6 +1,7 @@ package com.zy.ai.entity; import com.zy.asrs.entity.WrkMast; import com.zy.system.entity.Config; import lombok.Data; import java.util.List; @@ -50,6 +51,11 @@ private List<DeviceConfigsData> deviceConfigs; /** * 系统配置信息 */ private List<Config> systemConfigs; /** * 额外上下文,例如: * warehouseCode, shift, wcsVersion, plcVersion 等 */ src/main/java/com/zy/ai/service/WcsDiagnosisService.java
@@ -3,8 +3,11 @@ import com.alibaba.fastjson.JSON; import com.zy.ai.entity.ChatCompletionRequest; import com.zy.ai.entity.WcsDiagnosisRequest; import com.zy.ai.utils.AiPromptUtils; import com.zy.ai.utils.AiUtils; import com.zy.common.utils.RedisUtil; import com.zy.core.enums.RedisKeyType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -17,9 +20,16 @@ @RequiredArgsConstructor public class WcsDiagnosisService { private final LlmChatService llmChatService; private final RedisUtil redisUtil; private static final long CHAT_TTL_SECONDS = 7L * 24 * 3600; @Autowired private LlmChatService llmChatService; @Autowired private RedisUtil redisUtil; @Autowired private AiPromptUtils aiPromptUtils; @Autowired private AiUtils aiUtils; /** * 针对“系统不执行任务 / 不知道哪个设备没在运行”的通用 AI 诊断 @@ -30,29 +40,12 @@ // 1. system:定义专家身份 + 输出结构 ChatCompletionRequest.Message system = new ChatCompletionRequest.Message(); system.setRole("system"); system.setContent( "你是一名资深 WCS(仓储控制系统)与自动化立库专家,熟悉:堆垛机、输送线、提升机、穿梭车等设备的任务分配和运行逻辑," + "也熟悉常见的系统卡死、任务不执行、设备空闲但无任务等问题模式。\n\n" + "你将收到以下几类数据:\n" + "1)任务信息(tasks):当前待执行/在执行/挂起任务\n" + "2)设备实时数据(deviceRealtimeData):每台设备当前状态、是否在线、当前任务号等\n" + "3)设备配置信息(deviceConfigs):设备是否启用、服务区域、允许的任务类型等\n" + "4)系统日志(logs):按时间顺序的日志文本\n" + "5)额外上下文(extraContext):如仓库代码、WCS 版本等\n\n" + "你的目标是:帮助现场运维人员分析,为什么系统当前不执行任务,或者任务执行效率异常,指出可能是哪些设备导致的问题。\n\n" + "请按以下结构输出诊断结果(使用简体中文):\n" + "1. 问题概述(1-3 句话,概括当前系统状态)\n" + "2. 可疑设备列表(列出 1-N 个设备编号,并说明每个设备为什么可疑,例如:配置禁用/长时间空闲/状态异常/任务分配不到它等)\n" + "3. 可能原因(从任务分配、设备状态、配置错误、接口/通信异常等角度,列出 3-7 条)\n" + "4. 建议排查步骤(步骤 1、2、3...,每步要尽量具体、可操作,例如:在某页面查看某字段、检查某个开关、对比某个状态位等)\n" + "5. 风险评估(说明当前问题对业务影响程度:高/中/低,以及是否需要立即人工干预)\n" + "6. WCS 逻辑优化建议(如果从日志/数据看出可能的系统逻辑缺陷,请给出简要建议,例如增加某个防呆校验、告警、监控等)\n" ); system.setContent(aiPromptUtils.getAiDiagnosePrompt()); messages.add(system); ChatCompletionRequest.Message user = new ChatCompletionRequest.Message(); user.setRole("user"); user.setContent(buildDiagnosisUserContent(request)); user.setContent(aiUtils.buildDiagnosisUserContent(request)); messages.add(user); // 调用大模型 @@ -64,27 +57,12 @@ ChatCompletionRequest.Message system = new ChatCompletionRequest.Message(); system.setRole("system"); system.setContent( "你是一名资深 WCS(仓储控制系统)与自动化立库专家,熟悉:堆垛机、输送线、提升机、穿梭车等设备的任务分配和运行逻辑,也熟悉常见的系统卡死、任务不执行、设备空闲但无任务等问题模式。\n\n" + "你将收到以下几类数据:\n" + "1)任务信息(tasks):当前待执行/在执行/挂起任务\n" + "2)设备实时数据(deviceRealtimeData):每台设备当前状态、是否在线、当前任务号等\n" + "3)设备配置信息(deviceConfigs):设备是否启用、服务区域、允许的任务类型等\n" + "4)系统日志(logs):按时间顺序的日志文本\n" + "5)额外上下文(extraContext):如仓库代码、WCS 版本等\n\n" + "你的目标是:帮助现场运维人员分析,为什么系统当前不执行任务,或者任务执行效率异常,指出可能是哪些设备导致的问题。\n\n" + "请按以下结构输出诊断结果(使用简体中文):\n" + "1. 问题概述(1-3 句话,概括当前系统状态)\n" + "2. 可疑设备列表(列出 1-N 个设备编号,并说明每个设备为什么可疑,例如:配置禁用/长时间空闲/状态异常/任务分配不到它等)\n" + "3. 可能原因(从任务分配、设备状态、配置错误、接口/通信异常等角度,列出 3-7 条)\n" + "4. 建议排查步骤(步骤 1、2、3...,每步要尽量具体、可操作,例如:在某页面查看某字段、检查某个开关、对比某个状态位等)\n" + "5. 风险评估(说明当前问题对业务影响程度:高/中/低,以及是否需要立即人工干预)\n" ); system.setContent(aiPromptUtils.getAiDiagnosePrompt()); messages.add(system); ChatCompletionRequest.Message user = new ChatCompletionRequest.Message(); user.setRole("user"); user.setContent(buildDiagnosisUserContent(request)); user.setContent(aiUtils.buildDiagnosisUserContent(request)); messages.add(user); llmChatService.chatStream(messages, 0.2, 2048, s -> { @@ -110,10 +88,7 @@ ChatCompletionRequest.Message system = new ChatCompletionRequest.Message(); system.setRole("system"); system.setContent( "你是一名资深 WCS(仓储控制系统)与自动化立库专家,熟悉:堆垛机、输送线、提升机、穿梭车等设备的任务分配和运行逻辑,也熟悉常见的系统卡死、任务不执行、设备空闲但无任务等问题模式。\n\n" + "在回答用户问题时,需要结合下面给出的系统当前上下文信息(任务、设备实时状态、设备配置、系统日志等),以简洁、明确的中文作答,并在需要时给出可执行的排查建议。" ); system.setContent(aiPromptUtils.getWcsSensorPrompt()); base.add(system); List<ChatCompletionRequest.Message> history = null; @@ -140,7 +115,7 @@ ChatCompletionRequest.Message contextMsg = new ChatCompletionRequest.Message(); contextMsg.setRole("user"); contextMsg.setContent(buildAskUserContent(request)); contextMsg.setContent(aiUtils.buildAskUserContent(request)); base.add(contextMsg); ChatCompletionRequest.Message questionMsg = new ChatCompletionRequest.Message(); @@ -257,104 +232,4 @@ return p.length() > 20 ? p.substring(0, 20) : p; } private String buildDiagnosisUserContent(WcsDiagnosisRequest request) { StringBuilder sb = new StringBuilder(); if (request.getAlarmMessage() != null && !request.getAlarmMessage().isEmpty()) { sb.append("【问题描述】\n"); sb.append(request.getAlarmMessage()).append("\n\n"); } sb.append("【设备信息】\n"); sb.append("关注设备(如果有指定): ") .append(request.getCraneNo() != null ? request.getCraneNo() : "未指定,需整体分析") .append("\n\n"); Object pseudo = redisUtil.get(com.zy.core.enums.RedisKeyType.MAIN_PROCESS_PSEUDOCODE.key); if (pseudo != null) { sb.append("【主流程伪代码 mainProcessPseudo】\n"); sb.append(String.valueOf(pseudo)).append("\n\n"); } if (request.getExtraContext() != null && !request.getExtraContext().isEmpty()) { sb.append("【额外上下文 extraContext】\n"); sb.append(JSON.toJSONString(request.getExtraContext(), true)).append("\n\n"); } if (request.getTasks() != null && !request.getTasks().isEmpty()) { sb.append("【任务信息 tasks】\n"); sb.append("下面是当前相关任务列表的 JSON 数据:\n"); sb.append(JSON.toJSONString(request.getTasks(), true)).append("\n\n"); } else { sb.append("【任务信息 tasks】\n"); sb.append("当前未提供任务信息。\n\n"); } if (request.getDeviceRealtimeData() != null && !request.getDeviceRealtimeData().isEmpty()) { sb.append("【设备实时数据 deviceRealtimeData】\n"); sb.append("下面是各设备当前实时状态的 JSON 数据:\n"); sb.append(JSON.toJSONString(request.getDeviceRealtimeData(), true)).append("\n\n"); } else { sb.append("【设备实时数据 deviceRealtimeData】\n"); sb.append("当前未提供设备实时数据。\n\n"); } if (request.getDeviceConfigs() != null && !request.getDeviceConfigs().isEmpty()) { sb.append("【设备配置信息 deviceConfigs】\n"); sb.append("下面是各设备配置的 JSON 数据:\n"); sb.append(JSON.toJSONString(request.getDeviceConfigs(), true)).append("\n\n"); } else { sb.append("【设备配置信息 deviceConfigs】\n"); sb.append("当前未提供设备配置信息。\n\n"); } sb.append("【系统日志 logs(按时间顺序)】\n"); if (request.getLogs() != null && !request.getLogs().isEmpty()) { for (String logLine : request.getLogs()) { sb.append(logLine).append("\n"); } } else { sb.append("当前未提供日志信息。\n"); } sb.append("\n请根据以上所有信息,结合你的经验进行分析诊断。"); return sb.toString(); } private String buildAskUserContent(WcsDiagnosisRequest request) { StringBuilder sb = new StringBuilder(); if (request.getExtraContext() != null && !request.getExtraContext().isEmpty()) { sb.append("【额外上下文 extraContext】\n"); sb.append(JSON.toJSONString(request.getExtraContext(), true)).append("\n\n"); } if (request.getTasks() != null && !request.getTasks().isEmpty()) { sb.append("【任务信息 tasks】\n"); sb.append("下面是当前相关任务列表的 JSON 数据:\n"); sb.append(JSON.toJSONString(request.getTasks(), true)).append("\n\n"); } if (request.getDeviceRealtimeData() != null && !request.getDeviceRealtimeData().isEmpty()) { sb.append("【设备实时数据 deviceRealtimeData】\n"); sb.append("下面是各设备当前实时状态的 JSON 数据:\n"); sb.append(JSON.toJSONString(request.getDeviceRealtimeData(), true)).append("\n\n"); } if (request.getDeviceConfigs() != null && !request.getDeviceConfigs().isEmpty()) { sb.append("【设备配置信息 deviceConfigs】\n"); sb.append("下面是各设备配置的 JSON 数据:\n"); sb.append(JSON.toJSONString(request.getDeviceConfigs(), true)).append("\n\n"); } sb.append("【系统日志 logs(按时间顺序)】\n"); if (request.getLogs() != null && !request.getLogs().isEmpty()) { for (String logLine : request.getLogs()) { sb.append(logLine).append("\n"); } } return sb.toString(); } } src/main/java/com/zy/ai/utils/AiPromptUtils.java
New file @@ -0,0 +1,35 @@ package com.zy.ai.utils; import org.springframework.stereotype.Component; @Component public class AiPromptUtils { //AI诊断系统Prompt public String getAiDiagnosePrompt() { String prompt = "你是一名资深 WCS(仓储控制系统)与自动化立库专家,熟悉:堆垛机、输送线、提升机、穿梭车等设备的任务分配和运行逻辑,也熟悉常见的系统卡死、任务不执行、设备空闲但无任务等问题模式。\n\n" + "你将收到以下几类数据:\n" + "1)任务信息(tasks):当前待执行/在执行/挂起任务\n" + "2)设备实时数据(deviceRealtimeData):每台设备当前状态、是否在线、当前任务号等\n" + "3)设备配置信息(deviceConfigs):设备是否启用、服务区域、允许的任务类型等\n" + "4)系统日志(logs):按时间顺序的日志文本\n" + "5)额外上下文(extraContext):如仓库代码、WCS 版本等\n\n" + "6)系统配置信息(systemConfigs):系统的配置参数,数据库表名sys_config\n\n" + "你的目标是:帮助现场运维人员分析,为什么系统当前不执行任务,或者任务执行效率异常,指出可能是哪些设备导致的问题。\n\n" + "请按以下结构输出诊断结果(使用简体中文):\n" + "1. 问题概述(1-3 句话,概括当前系统状态)\n" + "2. 可疑设备列表(列出 1-N 个设备编号,并说明每个设备为什么可疑,例如:配置禁用/长时间空闲/状态异常/任务分配不到它等)\n" + "3. 可能原因(从任务分配、设备状态、配置错误、接口/通信异常等角度,列出 3-7 条)\n" + "4. 建议排查步骤(步骤 1、2、3...,每步要尽量具体、可操作,例如:在某页面查看某字段、检查某个开关、对比某个状态位等)\n" + "5. 风险评估(说明当前问题对业务影响程度:高/中/低,以及是否需要立即人工干预)\n"; return prompt; } //WCS高级专家Prompt public String getWcsSensorPrompt() { String prompt = "你是一名资深 WCS(仓储控制系统)与自动化立库专家,熟悉:堆垛机、输送线、提升机、穿梭车等设备的任务分配和运行逻辑,也熟悉常见的系统卡死、任务不执行、设备空闲但无任务等问题模式。\n\n" + "在回答用户问题时,需要结合下面给出的系统当前上下文信息(任务、设备实时状态、设备配置、系统日志、系统配置等),以简洁、明确的中文作答,并在需要时给出可执行的排查建议。"; return prompt; } } src/main/java/com/zy/ai/utils/AiUtils.java
@@ -1,5 +1,6 @@ package com.zy.ai.utils; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.zy.ai.entity.DeviceConfigsData; import com.zy.ai.entity.DeviceRealTimeData; @@ -11,6 +12,7 @@ import com.zy.asrs.service.BasCrnpService; import com.zy.asrs.service.BasDevpService; import com.zy.asrs.service.WrkMastService; import com.zy.common.utils.RedisUtil; import com.zy.core.cache.SlaveConnection; import com.zy.core.enums.SlaveType; import com.zy.core.model.StationObjModel; @@ -18,6 +20,8 @@ import com.zy.core.model.protocol.StationProtocol; import com.zy.core.thread.CrnThread; import com.zy.core.thread.StationThread; import com.zy.system.entity.Config; import com.zy.system.service.ConfigService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -34,6 +38,10 @@ private BasCrnpService basCrnpService; @Autowired private BasDevpService basDevpService; @Autowired private ConfigService configService; @Autowired private RedisUtil redisUtil; public WcsDiagnosisRequest makeAiRequest(int logLimit, String alarmMessage) { WcsDiagnosisRequest request = new WcsDiagnosisRequest(); @@ -124,6 +132,9 @@ deviceRealTimeDataList.add(stationData); } //剔除全部输送站点信息,以免数据量过大,后期看实际情况是否打开 basDevp.setStationList(null); DeviceConfigsData deviceConfigsData = new DeviceConfigsData(); deviceConfigsData.setDeviceNo(basDevp.getDevpNo()); deviceConfigsData.setDeviceType(String.valueOf(SlaveType.Devp)); @@ -133,7 +144,125 @@ request.setDeviceRealtimeData(deviceRealTimeDataList); request.setDeviceConfigs(deviceConfigsDataList); List<Config> systemConfigList = configService.selectList(new EntityWrapper<Config>().notIn("dingdingReportUrl")); request.setSystemConfigs(systemConfigList); return request; } public String buildDiagnosisUserContent(WcsDiagnosisRequest request) { StringBuilder sb = new StringBuilder(); if (request.getAlarmMessage() != null && !request.getAlarmMessage().isEmpty()) { sb.append("【问题描述】\n"); sb.append(request.getAlarmMessage()).append("\n\n"); } sb.append("【设备信息】\n"); sb.append("关注设备(如果有指定): ") .append(request.getCraneNo() != null ? request.getCraneNo() : "未指定,需整体分析") .append("\n\n"); Object pseudo = redisUtil.get(com.zy.core.enums.RedisKeyType.MAIN_PROCESS_PSEUDOCODE.key); if (pseudo != null) { sb.append("【主流程伪代码 mainProcessPseudo】\n"); sb.append(String.valueOf(pseudo)).append("\n\n"); } if (request.getExtraContext() != null && !request.getExtraContext().isEmpty()) { sb.append("【额外上下文 extraContext】\n"); sb.append(JSON.toJSONString(request.getExtraContext(), true)).append("\n\n"); } if (request.getTasks() != null && !request.getTasks().isEmpty()) { sb.append("【任务信息 tasks】\n"); sb.append("下面是当前相关任务列表的 JSON 数据:\n"); sb.append(JSON.toJSONString(request.getTasks(), true)).append("\n\n"); } else { sb.append("【任务信息 tasks】\n"); sb.append("当前未提供任务信息。\n\n"); } if (request.getDeviceRealtimeData() != null && !request.getDeviceRealtimeData().isEmpty()) { sb.append("【设备实时数据 deviceRealtimeData】\n"); sb.append("下面是各设备当前实时状态的 JSON 数据:\n"); sb.append(JSON.toJSONString(request.getDeviceRealtimeData(), true)).append("\n\n"); } else { sb.append("【设备实时数据 deviceRealtimeData】\n"); sb.append("当前未提供设备实时数据。\n\n"); } if (request.getDeviceConfigs() != null && !request.getDeviceConfigs().isEmpty()) { sb.append("【设备配置信息 deviceConfigs】\n"); sb.append("下面是各设备配置的 JSON 数据:\n"); sb.append(JSON.toJSONString(request.getDeviceConfigs(), true)).append("\n\n"); } else { sb.append("【设备配置信息 deviceConfigs】\n"); sb.append("当前未提供设备配置信息。\n\n"); } if (request.getLogs() != null && !request.getLogs().isEmpty()) { sb.append("【系统日志 logs(按时间顺序)】\n"); for (String logLine : request.getLogs()) { sb.append(logLine).append("\n"); } } else { sb.append("【系统日志 logs(按时间顺序)】\n"); sb.append("当前未提供日志信息。\n"); } if (request.getSystemConfigs() != null && !request.getSystemConfigs().isEmpty()) { sb.append("【系统配置 sys_config】\n"); sb.append("下面是各系统配置的 JSON 数据:\n"); sb.append(JSON.toJSONString(request.getSystemConfigs(), true)).append("\n\n"); } sb.append("\n请根据以上所有信息,结合你的经验进行分析诊断。"); return sb.toString(); } public String buildAskUserContent(WcsDiagnosisRequest request) { StringBuilder sb = new StringBuilder(); if (request.getExtraContext() != null && !request.getExtraContext().isEmpty()) { sb.append("【额外上下文 extraContext】\n"); sb.append(JSON.toJSONString(request.getExtraContext(), true)).append("\n\n"); } if (request.getTasks() != null && !request.getTasks().isEmpty()) { sb.append("【任务信息 tasks】\n"); sb.append("下面是当前相关任务列表的 JSON 数据:\n"); sb.append(JSON.toJSONString(request.getTasks(), true)).append("\n\n"); } if (request.getDeviceRealtimeData() != null && !request.getDeviceRealtimeData().isEmpty()) { sb.append("【设备实时数据 deviceRealtimeData】\n"); sb.append("下面是各设备当前实时状态的 JSON 数据:\n"); sb.append(JSON.toJSONString(request.getDeviceRealtimeData(), true)).append("\n\n"); } if (request.getDeviceConfigs() != null && !request.getDeviceConfigs().isEmpty()) { sb.append("【设备配置信息 deviceConfigs】\n"); sb.append("下面是各设备配置的 JSON 数据:\n"); sb.append(JSON.toJSONString(request.getDeviceConfigs(), true)).append("\n\n"); } if (request.getLogs() != null && !request.getLogs().isEmpty()) { sb.append("【系统日志 logs(按时间顺序)】\n"); for (String logLine : request.getLogs()) { sb.append(logLine).append("\n"); } } if (request.getSystemConfigs() != null && !request.getSystemConfigs().isEmpty()) { sb.append("【系统配置 sys_config】\n"); sb.append("下面是各系统配置的 JSON 数据:\n"); sb.append(JSON.toJSONString(request.getSystemConfigs(), true)).append("\n\n"); } return sb.toString(); } }