package com.klp.controller; import com.klp.domain.MultimodalResult; import com.klp.domain.MultimodalTask; import com.klp.service.MultimodalService; import com.klp.utils.ImageUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; import java.util.stream.Collectors; /** * 多模态分析控制器 */ @RestController @RequestMapping("/multimodal") public class WmsMultimodalController { private static final Logger logger = LoggerFactory.getLogger(WmsMultimodalController.class); @Autowired private MultimodalService multimodalService; /** * 处理单个任务 * @param task 任务信息 * @return 分析结果 */ @PostMapping("/process-task") public ResponseEntity processTask(@RequestBody MultimodalTask task) { try { logger.info("开始处理任务: {}", task.getTaskId()); // 验证图片路径 validateImagePaths(task.getImagePaths()); // 处理任务 MultimodalResult result = multimodalService.processTask(task); logger.info("任务处理完成: {}", task.getTaskId()); return ResponseEntity.ok(result); } catch (Exception e) { logger.error("处理任务失败: {}", task.getTaskId(), e); return ResponseEntity.badRequest().build(); } } /** * 多轮投票处理任务 * @param task 任务信息 * @param rounds 投票轮数 * @return 分析结果 */ @PostMapping("/process-task-voting") public ResponseEntity processTaskWithVoting( @RequestBody MultimodalTask task, @RequestParam(defaultValue = "3") int rounds) { try { logger.info("开始多轮投票处理任务: {}, 轮数: {}", task.getTaskId(), rounds); // 验证图片路径 validateImagePaths(task.getImagePaths()); // 处理任务 MultimodalResult result = multimodalService.processTaskWithVoting(task, rounds); logger.info("多轮投票任务处理完成: {}", task.getTaskId()); return ResponseEntity.ok(result); } catch (Exception e) { logger.error("多轮投票处理任务失败: {}", task.getTaskId(), e); return ResponseEntity.badRequest().build(); } } /** * 批量处理任务 * @param tasks 任务列表 * @return 分析结果列表 */ @PostMapping("/process-tasks-batch") public ResponseEntity> processTasksBatch(@RequestBody List tasks) { try { logger.info("开始批量处理任务,数量: {}", tasks.size()); // 验证所有任务的图片路径 for (MultimodalTask task : tasks) { validateImagePaths(task.getImagePaths()); } // 批量处理任务 List results = multimodalService.processTasksBatch(tasks); logger.info("批量任务处理完成,成功数量: {}", results.size()); return ResponseEntity.ok(results); } catch (Exception e) { logger.error("批量处理任务失败", e); return ResponseEntity.badRequest().build(); } } /** * 从目录处理任务(模拟Python脚本的功能) * @param request 请求参数 * @return 处理结果 */ @PostMapping("/process-from-directory") public ResponseEntity> processFromDirectory(@RequestBody Map request) { try { String time = (String) request.get("time"); String phoneName = (String) request.get("phoneName"); String projectRoot = (String) request.get("projectRoot"); logger.info("开始从目录处理任务: time={}, phoneName={}", time, phoneName); // 构建路径 Path dataRoot = Paths.get(projectRoot, "data", phoneName); Path resultDir = Paths.get(projectRoot, "result", phoneName); Path tasksPath = Paths.get(projectRoot, "gen", phoneName, time, "tasks.json"); // 创建结果目录 Files.createDirectories(resultDir); // 读取任务配置 if (!Files.exists(tasksPath)) { throw new RuntimeException("任务配置文件不存在: " + tasksPath); } String tasksJson = new String(Files.readAllBytes(tasksPath)); List> apps = parseJsonArray(tasksJson); // 收集所有任务 List allTasks = new ArrayList<>(); for (Map app : apps) { String appName = (String) app.get("appName"); List> taskList = (List>) app.get("taskList"); if (taskList != null) { for (Map taskData : taskList) { String order = String.valueOf(taskData.get("order")); Path folder = dataRoot.resolve(appName + "_task_" + order + "_result"); if (!Files.exists(folder)) { logger.warn("目录不存在:{},跳过 Task#{}", folder, order); continue; } // 获取有效图片 List validImages = ImageUtils.getValidImageFiles(folder.toString()); if (validImages.isEmpty()) { logger.warn("目录下无有效图片:{},跳过 Task#{}", folder, order); continue; } // 创建任务对象 MultimodalTask task = new MultimodalTask( appName, (String) taskData.get("content"), (String) taskData.get("taskCategory"), (String) taskData.get("time"), (String) taskData.get("security"), folder.toString(), (String) taskData.get("task_id"), validImages ); allTasks.add(task); } } } logger.info("收集到 {} 个任务", allTasks.size()); // 批量处理任务 List results = multimodalService.processTasksBatch(allTasks); // 按应用分组保存结果 Map> appResults = results.stream() .collect(Collectors.groupingBy(MultimodalResult::getAppName)); // 保存结果到文件 for (Map.Entry> entry : appResults.entrySet()) { String appName = entry.getKey(); List appResultList = entry.getValue(); Path outFile = resultDir.resolve(appName + ".json"); // 读取现有结果 List existing = new ArrayList<>(); if (Files.exists(outFile)) { try { String existingJson = new String(Files.readAllBytes(outFile)); existing = parseResultList(existingJson); } catch (Exception e) { logger.warn("读取现有结果文件失败: {}", outFile, e); } } // 合并结果 existing.addAll(appResultList); // 保存到文件 String jsonResult = convertToJson(existing); Files.write(outFile, jsonResult.getBytes()); logger.info("保存结果: {} (总条目: {})", outFile, existing.size()); } Map response = new HashMap<>(); response.put("success", true); response.put("totalTasks", allTasks.size()); response.put("processedTasks", results.size()); response.put("resultDir", resultDir.toString()); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("从目录处理任务失败", e); Map response = new HashMap<>(); response.put("success", false); response.put("error", e.getMessage()); return ResponseEntity.badRequest().body(response); } } /** * 验证图片路径 * @param imagePaths 图片路径列表 */ private void validateImagePaths(List imagePaths) { if (imagePaths == null || imagePaths.isEmpty()) { throw new RuntimeException("图片路径列表不能为空"); } for (String imagePath : imagePaths) { if (!ImageUtils.isValidImageFile(imagePath)) { throw new RuntimeException("无效的图片文件: " + imagePath); } } } /** * 解析JSON数组 * @param json JSON字符串 * @return 对象列表 */ private List> parseJsonArray(String json) { try { com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper(); return mapper.readValue(json, List.class); } catch (Exception e) { throw new RuntimeException("解析JSON失败", e); } } /** * 解析结果列表 * @param json JSON字符串 * @return 结果列表 */ private List parseResultList(String json) { try { com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper(); return mapper.readValue(json, mapper.getTypeFactory().constructCollectionType(List.class, MultimodalResult.class)); } catch (Exception e) { throw new RuntimeException("解析结果JSON失败", e); } } /** * 转换为JSON字符串 * @param results 结果列表 * @return JSON字符串 */ private String convertToJson(List results) { try { com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper(); return mapper.writeValueAsString(results); } catch (Exception e) { throw new RuntimeException("转换为JSON失败", e); } } /** * 健康检查接口 * @return 健康状态 */ @GetMapping("/health") public ResponseEntity> health() { Map response = new HashMap<>(); response.put("status", "UP"); response.put("service", "Multimodal Analysis Service"); response.put("timestamp", new Date()); return ResponseEntity.ok(response); } }