skyouc
7 小时以前 2265a4ba25b765d08795018f78ac9bceb87e4f45
src/main/java/com/zy/ai/service/impl/MainProcessPseudocodeServiceImpl.java
@@ -19,150 +19,150 @@
import java.util.List;
@Service("mainProcessPseudocodeService")
public class MainProcessPseudocodeServiceImpl implements MainProcessPseudocodeService {
public class MainProcessPseudocodeServiceImpl {
    private static final long SUCCESS_CACHE_SECONDS = 60 * 60 * 24;
    private static final long FAILURE_CACHE_SECONDS = 60 * 10;
    private static final String FAILURE_TEXT = "AI生成伪代码失败";
    private static final String PSEUDOCODE_SYSTEM_PROMPT = """
            你现在是一名高级 Java 架构师兼伪代码转换专家,专门负责把复杂的 Java 代码转换成结构清晰、适合大模型阅读与推理的伪代码。
            请严格遵守以下要求工作:
            核心目标
            输入是一段或多段 Java 代码。
            输出是一段人类可读、逻辑清晰、尽量语言中立的伪代码。
            这份伪代码将被用作后续大模型提问的“参考描述”,所以要:
            保留关键业务逻辑和判断条件;
            弱化语言细节(如具体库、注解、框架细节);
            用自然语言 + 简洁流程结构,帮助大模型快速理解代码意图。
            风格要求
            使用中文描述逻辑,但可以保留少量关键英文标识(例如类名、方法名、状态枚举)以便跟代码对应。
            伪代码要分层分块,尽量按:
            类职责说明
            重要字段 / 全局变量说明
            每个公开方法 / 核心私有方法的伪代码
            逻辑上使用类似:
            如果 ... 则 ...
            否则如果 ...
            循环遍历列表 ...
            调用服务/方法: ...
            返回 ...
            不追求严格语法,只追求易懂和准确。
            保留信息 & 抽象信息
            必须保留:
            关键业务含义(例如“生成入库任务”、“检查堆垛机任务是否完成”)
            关键条件判断(状态字段、枚举、重要配置开关)
            重要数据流向(从哪里读数据、写到哪里、调用了哪些服务)
            与外部系统交互(如 HTTP 调用 WMS、写 Redis 锁、写数据库)
            可以抽象或省略:
            日志打印的具体格式,只保留“记录日志:xxx”即可;
            具体框架注解(如 @Component, @Autowired 等);
            泛型、异常栈细节、工具类内部实现;
            结构模板(优先遵循)
            对于一段较大的 Java 类,请按以下结构输出伪代码:
            类整体说明
            简要说明这个类的用途和在系统中的角色。
            重要字段 / 配置说明
            列出关键静态变量 / 配置项 / 状态缓存,并用一行解释它们的含义。
            主流程方法(例如 run())
            用有序列表或伪代码,按调用顺序描述主要步骤。
            每个核心私有方法
            对于每个关键方法:
            先用一行中文总结功能;
            再给出伪代码流程(条件、循环、关键调用);
            与外部系统交互的说明
            单独强调有哪些地方调用了外部服务(HTTP、消息队列、数据库、Redis 等)。
            输出格式要求
            使用 Markdown 结构,方便复制给其他大模型:
            用 ## 标题区分“类说明”、“主流程伪代码”、“方法伪代码”等部分;
            伪代码块可以使用缩进和项目符号,或用 pseudo 代码块 包裹;
            不要直接逐行翻译代码,而是做抽象和整理;
            不要输出无关文本,例如道歉、寒暄或与任务无关的解释。
            伪代码示例风格(示意)
            例如当输入一个 run() 方法时,期望你的输出风格类似:
            函数 run():
                读取配置 enableFake, fakeRealTaskRequestWms
                如果 enableFake == "Y":
                    调用 checkInStationHasTask() 检测入库站并生成仿真站点数据
                    如果 fakeRealTaskRequestWms == "N":
                        调用 generateFakeInTask() 生成本地仿真入库任务
                        调用 generateFakeOutTask() 生成本地仿真出库任务
                计算所有站点的停留时间 calcAllStationStayTime()
                检查出库站点是否超时并重置 checkOutStationStayTimeOut()
                检查入库站点货物是否已被堆垛机取走 checkInStationCrnTake()
                如果 fakeRealTaskRequestWms == "Y":
                    调用 generateStoreWrkFile() 请求 WMS 生成真实任务
                调用 crnOperateUtils.crnIoExecute() 执行堆垛机任务
                调用 crnIoExecuteFinish() 处理堆垛机任务完成后的状态更新和仿真站点生成
                调用 stationOperateProcessUtils.submitStationInTasks(...) 按 lane 提交输送站入库任务
                调用 stationOperateProcessUtils.stationOutExecute() 执行输送站出库任务
                调用 stationOperateProcessUtils.stationOutExecuteFinish() 检查输送站出库任务完成
            对输入的要求
            如果用户给出的是多段代码或只给出片段:
            先推断这段代码的职责;
            再按你能理解到的范围进行伪代码转换;
            如果存在明显缺失的类/方法,只需在伪代码中用“调用 XXX(具体逻辑略)”标记即可。
            请始终以「让后续大模型能看懂这段代码逻辑并基于伪代码进行推理和提问」为最高优先级来组织你的输出。
            """;
    private static final String PSEUDOCODE_SYSTEM_PROMPT = "";//"
//            你现在是一名高级 Java 架构师兼伪代码转换专家,专门负责把复杂的 Java 代码转换成结构清晰、适合大模型阅读与推理的伪代码。
//
//            请严格遵守以下要求工作:
//
//            核心目标
//
//            输入是一段或多段 Java 代码。
//
//            输出是一段人类可读、逻辑清晰、尽量语言中立的伪代码。
//
//            这份伪代码将被用作后续大模型提问的“参考描述”,所以要:
//
//            保留关键业务逻辑和判断条件;
//
//            弱化语言细节(如具体库、注解、框架细节);
//
//            用自然语言 + 简洁流程结构,帮助大模型快速理解代码意图。
//
//            风格要求
//
//            使用中文描述逻辑,但可以保留少量关键英文标识(例如类名、方法名、状态枚举)以便跟代码对应。
//
//            伪代码要分层分块,尽量按:
//
//            类职责说明
//
//            重要字段 / 全局变量说明
//
//            每个公开方法 / 核心私有方法的伪代码
//
//            逻辑上使用类似:
//
//            如果 ... 则 ...
//
//            否则如果 ...
//
//            循环遍历列表 ...
//
//            调用服务/方法: ...
//
//            返回 ...
//
//            不追求严格语法,只追求易懂和准确。
//
//            保留信息 & 抽象信息
//
//            必须保留:
//
//            关键业务含义(例如“生成入库任务”、“检查堆垛机任务是否完成”)
//
//            关键条件判断(状态字段、枚举、重要配置开关)
//
//            重要数据流向(从哪里读数据、写到哪里、调用了哪些服务)
//
//            与外部系统交互(如 HTTP 调用 WMS、写 Redis 锁、写数据库)
//
//            可以抽象或省略:
//
//            日志打印的具体格式,只保留“记录日志:xxx”即可;
//
//            具体框架注解(如 @Component, @Autowired 等);
//
//            泛型、异常栈细节、工具类内部实现;
//
//            结构模板(优先遵循)
//
//            对于一段较大的 Java 类,请按以下结构输出伪代码:
//
//            类整体说明
//
//            简要说明这个类的用途和在系统中的角色。
//
//            重要字段 / 配置说明
//
//            列出关键静态变量 / 配置项 / 状态缓存,并用一行解释它们的含义。
//
//            主流程方法(例如 run())
//
//            用有序列表或伪代码,按调用顺序描述主要步骤。
//
//            每个核心私有方法
//
//            对于每个关键方法:
//
//            先用一行中文总结功能;
//
//            再给出伪代码流程(条件、循环、关键调用);
//
//            与外部系统交互的说明
//
//            单独强调有哪些地方调用了外部服务(HTTP、消息队列、数据库、Redis 等)。
//
//            输出格式要求
//
//            使用 Markdown 结构,方便复制给其他大模型:
//
//            用 ## 标题区分“类说明”、“主流程伪代码”、“方法伪代码”等部分;
//
//            伪代码块可以使用缩进和项目符号,或用 pseudo 代码块 包裹;
//
//            不要直接逐行翻译代码,而是做抽象和整理;
//
//            不要输出无关文本,例如道歉、寒暄或与任务无关的解释。
//
//            伪代码示例风格(示意)
//
//            例如当输入一个 run() 方法时,期望你的输出风格类似:
//
//            函数 run():
//                读取配置 enableFake, fakeRealTaskRequestWms
//                如果 enableFake == "Y":
//                    调用 checkInStationHasTask() 检测入库站并生成仿真站点数据
//                    如果 fakeRealTaskRequestWms == "N":
//                        调用 generateFakeInTask() 生成本地仿真入库任务
//                        调用 generateFakeOutTask() 生成本地仿真出库任务
//                计算所有站点的停留时间 calcAllStationStayTime()
//                检查出库站点是否超时并重置 checkOutStationStayTimeOut()
//                检查入库站点货物是否已被堆垛机取走 checkInStationCrnTake()
//                如果 fakeRealTaskRequestWms == "Y":
//                    调用 generateStoreWrkFile() 请求 WMS 生成真实任务
//                调用 crnOperateUtils.crnIoExecute() 执行堆垛机任务
//                调用 crnIoExecuteFinish() 处理堆垛机任务完成后的状态更新和仿真站点生成
//                调用 stationOperateProcessUtils.submitStationInTasks(...) 按 lane 提交输送站入库任务
//                调用 stationOperateProcessUtils.stationOutExecute() 执行输送站出库任务
//                调用 stationOperateProcessUtils.stationOutExecuteFinish() 检查输送站出库任务完成
//
//            对输入的要求
//
//            如果用户给出的是多段代码或只给出片段:
//
//            先推断这段代码的职责;
//
//            再按你能理解到的范围进行伪代码转换;
//
//            如果存在明显缺失的类/方法,只需在伪代码中用“调用 XXX(具体逻辑略)”标记即可。
//
//            请始终以「让后续大模型能看懂这段代码逻辑并基于伪代码进行推理和提问」为最高优先级来组织你的输出。
//            """;
    @Value("${mainProcessPlugin}")
    private String mainProcessPlugin;
@@ -172,112 +172,140 @@
    @Autowired
    private RedisUtil redisUtil;
    @Override
    public JSONObject queryMainProcessPseudocode(boolean refresh) {
        String cacheKey = RedisKeyType.MAIN_PROCESS_PSEUDOCODE.key;
        String cached = trimToNull(redisUtil.get(cacheKey));
        String pseudocode = cached;
        String status = "cached";
        String message = null;
        boolean generatedFresh = false;
//    @Override
//    public JSONObject queryMainProcessPseudocode(boolean refresh) {
//        String cacheKey = RedisKeyType.MAIN_PROCESS_PSEUDOCODE.key;
//        String cached = trimToNull(redisUtil.get(cacheKey));
//        String pseudocode = cached;
//        String status = "cached";
//        String message = null;
//        boolean generatedFresh = false;
//
//        if (refresh || pseudocode == null) {
//            String generated = generateAndCachePseudocode();
//            if (generated != null) {
//                pseudocode = generated;
//                generatedFresh = true;
//                status = refresh ? "refreshed" : "generated";
//            } else if (cached != null) {
//                pseudocode = cached;
//                status = "fallback_cached";
//                message = "重新生成失败,返回缓存中的伪代码";
//            } else {
//                pseudocode = FAILURE_TEXT;
//                status = "failed";
//                message = FAILURE_TEXT;
//                redisUtil.set(cacheKey, FAILURE_TEXT, FAILURE_CACHE_SECONDS);
//                News.info(FAILURE_TEXT);
//            }
//        }
//
//        JSONObject result = new JSONObject();
//        result.put("mainProcessPlugin", resolvePlugin());
//        result.put("mainProcessPluginClass", resolvePluginClassName());
//        result.put("refreshRequested", refresh);
//        result.put("generatedFresh", generatedFresh);
//        result.put("cacheHit", !generatedFresh && ("cached".equals(status) || "fallback_cached".equals(status)));
//        result.put("status", status);
//        result.put("expireSeconds", redisUtil.getExpire(cacheKey));
//        result.put("message", message);
//        result.put("pseudocode", pseudocode);
//        return result;
//    }
        if (refresh || pseudocode == null) {
            String generated = generateAndCachePseudocode();
            if (generated != null) {
                pseudocode = generated;
                generatedFresh = true;
                status = refresh ? "refreshed" : "generated";
            } else if (cached != null) {
                pseudocode = cached;
                status = "fallback_cached";
                message = "重新生成失败,返回缓存中的伪代码";
            } else {
                pseudocode = FAILURE_TEXT;
                status = "failed";
                message = FAILURE_TEXT;
                redisUtil.set(cacheKey, FAILURE_TEXT, FAILURE_CACHE_SECONDS);
                News.info(FAILURE_TEXT);
            }
        }
//    private String generateAndCachePseudocode() {
//        String code = loadSourceBundle();
//        if (code == null || code.isEmpty()) {
//            return null;
//        }
//
//        List<ChatCompletionRequest.Message> messages = new ArrayList<>();
//        ChatCompletionRequest.Message system = new ChatCompletionRequest.Message();
//        system.setRole("system");
//        system.setContent(PSEUDOCODE_SYSTEM_PROMPT);
//        messages.add(system);
//
//        ChatCompletionRequest.Message user = new ChatCompletionRequest.Message();
//        user.setRole("user");
//        user.setContent("主流程插件类源代码:\n\n" + code);
//        messages.add(user);
//
//        try {
//            String result = trimToNull(llmChatService.chat(messages, 0.2, 2048));
//            if (result == null) {
//                return null;
//            }
//            redisUtil.set(RedisKeyType.MAIN_PROCESS_PSEUDOCODE.key, result, SUCCESS_CACHE_SECONDS);
//            News.info("AI生成伪代码成功");
//            return result;
//        } catch (Exception ignore) {
//            return null;
//        }
//    }
//        String code = loadSourceBundle();
//        if (code == null || code.isEmpty()) {
//            return null;
//        }
//
//        List<ChatCompletionRequest.Message> messages = new ArrayList<>();
//        ChatCompletionRequest.Message system = new ChatCompletionRequest.Message();
//        system.setRole("system");
//        system.setContent(PSEUDOCODE_SYSTEM_PROMPT);
//        messages.add(system);
//
//        ChatCompletionRequest.Message user = new ChatCompletionRequest.Message();
//        user.setRole("user");
//        user.setContent("主流程插件类源代码:\n\n" + code);
//        messages.add(user);
//
//        try {
//            String result = trimToNull(llmChatService.chat(messages, 0.2, 2048));
//            if (result == null) {
//                return null;
//            }
//            redisUtil.set(RedisKeyType.MAIN_PROCESS_PSEUDOCODE.key, result, SUCCESS_CACHE_SECONDS);
//            News.info("AI生成伪代码成功");
//            return result;
//        } catch (Exception ignore) {
//            return null;
//        }
//    }
        JSONObject result = new JSONObject();
        result.put("mainProcessPlugin", resolvePlugin());
        result.put("mainProcessPluginClass", resolvePluginClassName());
        result.put("refreshRequested", refresh);
        result.put("generatedFresh", generatedFresh);
        result.put("cacheHit", !generatedFresh && ("cached".equals(status) || "fallback_cached".equals(status)));
        result.put("status", status);
        result.put("expireSeconds", redisUtil.getExpire(cacheKey));
        result.put("message", message);
        result.put("pseudocode", pseudocode);
        return result;
    }
//    private String loadSourceBundle() {
//        StringBuilder code = new StringBuilder();
//        appendSource(code, resolvePluginClassName());
//        appendSource(code, "com.zy.core.utils.CrnOperateProcessUtils");
//        appendSource(code, "com.zy.core.utils.StationOperateProcessUtils");
//        return code.toString();
//    }
    private String generateAndCachePseudocode() {
        String code = loadSourceBundle();
        if (code == null || code.isEmpty()) {
            return null;
        }
//    private void appendSource(StringBuilder code, String className) {
//        if (className == null || className.trim().isEmpty()) {
//            return;
//        }
//        String source = readJavaSource(className);
//        if (source == null || source.isEmpty()) {
//            return;
//        }
//        if (code.length() > 0) {
//            code.append("\n\n");
//        }
//        code.append("// ===== ").append(className).append(" =====\n");
//        code.append(source);
//    }
        List<ChatCompletionRequest.Message> messages = new ArrayList<>();
        ChatCompletionRequest.Message system = new ChatCompletionRequest.Message();
        system.setRole("system");
        system.setContent(PSEUDOCODE_SYSTEM_PROMPT);
        messages.add(system);
        ChatCompletionRequest.Message user = new ChatCompletionRequest.Message();
        user.setRole("user");
        user.setContent("主流程插件类源代码:\n\n" + code);
        messages.add(user);
        try {
            String result = trimToNull(llmChatService.chat(messages, 0.2, 2048));
            if (result == null) {
                return null;
            }
            redisUtil.set(RedisKeyType.MAIN_PROCESS_PSEUDOCODE.key, result, SUCCESS_CACHE_SECONDS);
            News.info("AI生成伪代码成功");
            return result;
        } catch (Exception ignore) {
            return null;
        }
    }
    private String loadSourceBundle() {
        StringBuilder code = new StringBuilder();
        appendSource(code, resolvePluginClassName());
        appendSource(code, "com.zy.core.utils.CrnOperateProcessUtils");
        appendSource(code, "com.zy.core.utils.StationOperateProcessUtils");
        return code.toString();
    }
    private void appendSource(StringBuilder code, String className) {
        if (className == null || className.trim().isEmpty()) {
            return;
        }
        String source = readJavaSource(className);
        if (source == null || source.isEmpty()) {
            return;
        }
        if (code.length() > 0) {
            code.append("\n\n");
        }
        code.append("// ===== ").append(className).append(" =====\n");
        code.append(source);
    }
    private String readJavaSource(String className) {
        try {
            String rel = className.replace('.', '/') + ".java";
            Path path = Paths.get(System.getProperty("user.dir"), "src", "main", "java", rel);
            if (!Files.exists(path)) {
                return null;
            }
            return Files.readString(path, StandardCharsets.UTF_8);
        } catch (Exception ignore) {
            return null;
        }
    }
//    private String readJavaSource(String className) {
//        try {
//            String rel = className.replace('.', '/') + ".java";
//            Path path = Paths.get(System.getProperty("user.dir"), "src", "main", "java", rel);
//            if (!Files.exists(path)) {
//                return null;
//            }
//            return Files.readString(path, StandardCharsets.UTF_8);
//        } catch (Exception ignore) {
//            return null;
//        }
//    }
    private String resolvePlugin() {
        String plugin = trimToNull(mainProcessPlugin);