package com.aicode.codemother.langgraph4j.node; import com.aicode.codemother.constant.AppConstant; import com.aicode.codemother.core.AiCodeGeneratorFacade; import com.aicode.codemother.langgraph4j.model.QualityResult; import com.aicode.codemother.langgraph4j.state.WorkflowContext; import com.aicode.codemother.model.enums.CodeGenTypeEnum; import com.aicode.codemother.utils.SpringContextUtil; import lombok.extern.slf4j.Slf4j; import org.bsc.langgraph4j.action.AsyncNodeAction; import org.bsc.langgraph4j.prebuilt.MessagesState; import reactor.core.publisher.Flux; import java.time.Duration; import static org.bsc.langgraph4j.action.AsyncNodeAction.node_async; /** * 网站代码生成节点 */ @Slf4j public class CodeGeneratorNode { public static AsyncNodeAction> create() { return node_async(state -> { WorkflowContext context = WorkflowContext.getContext(state); log.info("执行节点: 代码生成"); // 构造用户消息(包含原始提示词和可能的错误修复信息) String userMessage = buildUserMessage(context); CodeGenTypeEnum generationType = context.getGenerationType(); // 获取 AI 代码生成外观服务 AiCodeGeneratorFacade codeGeneratorFacade = SpringContextUtil.getBean(AiCodeGeneratorFacade.class); log.info("开始生成代码,类型: {} ({})", generationType.getValue(), generationType.getText()); // 先使用固定的 appId (后续再整合到业务中) Long appId = 0L; // 调用流式代码生成 Flux codeStream = codeGeneratorFacade.generateAndSaveCodeStream(userMessage, generationType, appId); // 同步等待流式输出完成 codeStream.blockLast(Duration.ofMinutes(10)); // 最多等待 10 分钟 // 根据类型设置生成目录 String generatedCodeDir = String.format("%s/%s_%s", AppConstant.CODE_OUTPUT_ROOT_DIR, generationType.getValue(), appId); log.info("AI 代码生成完成,生成目录: {}", generatedCodeDir); // 更新状态 context.setCurrentStep("代码生成"); context.setGeneratedCodeDir(generatedCodeDir); return WorkflowContext.saveContext(context); }); } /** * 构造用户消息,如果存在质检失败结果则添加错误修复信息 */ private static String buildUserMessage(WorkflowContext context) { String userMessage = context.getEnhancedPrompt(); // 检查是否存在质检失败结果 QualityResult qualityResult = context.getQualityResult(); if (isQualityCheckFailed(qualityResult)) { // 直接将错误修复信息作为新的提示词(起到了修改的作用) userMessage = buildErrorFixPrompt(qualityResult); } return userMessage; } /** * 判断质检是否失败 */ private static boolean isQualityCheckFailed(QualityResult qualityResult) { return qualityResult != null && !qualityResult.getIsValid() && qualityResult.getErrors() != null && !qualityResult.getErrors().isEmpty(); } /** * 构造错误修复提示词 */ private static String buildErrorFixPrompt(QualityResult qualityResult) { StringBuilder errorInfo = new StringBuilder(); errorInfo.append("\n\n## 上次生成的代码存在以下问题,请修复:\n"); // 添加错误列表 qualityResult.getErrors().forEach(error -> errorInfo.append("- ").append(error).append("\n")); // 添加修复建议(如果有) if (qualityResult.getSuggestions() != null && !qualityResult.getSuggestions().isEmpty()) { errorInfo.append("\n## 修复建议:\n"); qualityResult.getSuggestions().forEach(suggestion -> errorInfo.append("- ").append(suggestion).append("\n")); } errorInfo.append("\n请根据上述问题和建议重新生成代码,确保修复所有提到的问题。"); return errorInfo.toString(); } }