加入ai大模型
This commit is contained in:
@@ -0,0 +1,308 @@
|
||||
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<MultimodalResult> 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<MultimodalResult> 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<List<MultimodalResult>> processTasksBatch(@RequestBody List<MultimodalTask> tasks) {
|
||||
try {
|
||||
logger.info("开始批量处理任务,数量: {}", tasks.size());
|
||||
|
||||
// 验证所有任务的图片路径
|
||||
for (MultimodalTask task : tasks) {
|
||||
validateImagePaths(task.getImagePaths());
|
||||
}
|
||||
|
||||
// 批量处理任务
|
||||
List<MultimodalResult> 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<Map<String, Object>> processFromDirectory(@RequestBody Map<String, Object> 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<Map<String, Object>> apps = parseJsonArray(tasksJson);
|
||||
|
||||
// 收集所有任务
|
||||
List<MultimodalTask> allTasks = new ArrayList<>();
|
||||
for (Map<String, Object> app : apps) {
|
||||
String appName = (String) app.get("appName");
|
||||
List<Map<String, Object>> taskList = (List<Map<String, Object>>) app.get("taskList");
|
||||
|
||||
if (taskList != null) {
|
||||
for (Map<String, Object> 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<String> 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<MultimodalResult> results = multimodalService.processTasksBatch(allTasks);
|
||||
|
||||
// 按应用分组保存结果
|
||||
Map<String, List<MultimodalResult>> appResults = results.stream()
|
||||
.collect(Collectors.groupingBy(MultimodalResult::getAppName));
|
||||
|
||||
// 保存结果到文件
|
||||
for (Map.Entry<String, List<MultimodalResult>> entry : appResults.entrySet()) {
|
||||
String appName = entry.getKey();
|
||||
List<MultimodalResult> appResultList = entry.getValue();
|
||||
|
||||
Path outFile = resultDir.resolve(appName + ".json");
|
||||
|
||||
// 读取现有结果
|
||||
List<MultimodalResult> 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<String, Object> 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<String, Object> response = new HashMap<>();
|
||||
response.put("success", false);
|
||||
response.put("error", e.getMessage());
|
||||
|
||||
return ResponseEntity.badRequest().body(response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证图片路径
|
||||
* @param imagePaths 图片路径列表
|
||||
*/
|
||||
private void validateImagePaths(List<String> 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<Map<String, Object>> 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<MultimodalResult> 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<MultimodalResult> 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<Map<String, Object>> health() {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("status", "UP");
|
||||
response.put("service", "Multimodal Analysis Service");
|
||||
response.put("timestamp", new Date());
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package com.klp.controller;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import com.klp.common.annotation.Log;
|
||||
import com.klp.common.core.controller.BaseController;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.common.enums.BusinessType;
|
||||
import com.klp.domain.bo.WmsSalesScriptGeneratorBo;
|
||||
import com.klp.domain.vo.WmsProductSalesScriptVo;
|
||||
import com.klp.service.IWmsSalesScriptGeneratorService;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* 销售话术生成器
|
||||
*
|
||||
* @author klp
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/wms/salesScriptGenerator")
|
||||
public class WmsSalesScriptGeneratorController extends BaseController {
|
||||
|
||||
private final IWmsSalesScriptGeneratorService iWmsSalesScriptGeneratorService;
|
||||
|
||||
/**
|
||||
* 为单个产品生成销售话术
|
||||
*/
|
||||
@Log(title = "销售话术生成", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/generateForProduct")
|
||||
public R<List<WmsProductSalesScriptVo>> generateForProduct(@RequestBody WmsSalesScriptGeneratorBo bo) {
|
||||
List<WmsProductSalesScriptVo> scripts = iWmsSalesScriptGeneratorService.generateScriptsForProduct(bo);
|
||||
return R.ok(scripts);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量生成销售话术
|
||||
*/
|
||||
@Log(title = "批量销售话术生成", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/generateBatch")
|
||||
public R<Map<String, Object>> generateBatch(@RequestBody WmsSalesScriptGeneratorBo bo) {
|
||||
Map<String, Object> result = iWmsSalesScriptGeneratorService.generateScriptsBatch(bo);
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为指定产品ID列表生成话术
|
||||
*/
|
||||
@Log(title = "指定产品话术生成", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/generateForProductIds")
|
||||
public R<Map<String, Object>> generateForProductIds(@RequestBody WmsSalesScriptGeneratorBo bo) {
|
||||
Map<String, Object> result = iWmsSalesScriptGeneratorService.generateScriptsForProductIds(bo);
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试AI连接
|
||||
*/
|
||||
@GetMapping("/testConnection")
|
||||
public R<Map<String, Object>> testConnection() {
|
||||
Map<String, Object> result = iWmsSalesScriptGeneratorService.testAiConnection();
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取生成配置
|
||||
*/
|
||||
@GetMapping("/config")
|
||||
public R<Map<String, Object>> getConfig() {
|
||||
Map<String, Object> config = iWmsSalesScriptGeneratorService.getGenerationConfig();
|
||||
return R.ok(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新生成配置
|
||||
*/
|
||||
@Log(title = "更新话术生成配置", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/config")
|
||||
public R<Void> updateConfig(@RequestBody Map<String, Object> config) {
|
||||
iWmsSalesScriptGeneratorService.updateGenerationConfig(config);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可用的产品列表
|
||||
*/
|
||||
@GetMapping("/availableProducts")
|
||||
public R<List<Map<String, Object>>> getAvailableProducts() {
|
||||
List<Map<String, Object>> products = iWmsSalesScriptGeneratorService.getAvailableProducts();
|
||||
return R.ok(products);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取生成历史
|
||||
*/
|
||||
@GetMapping("/history")
|
||||
public TableDataInfo<Map<String, Object>> getGenerationHistory(PageQuery pageQuery) {
|
||||
return iWmsSalesScriptGeneratorService.getGenerationHistory(pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新生成指定话术
|
||||
*/
|
||||
@Log(title = "重新生成话术", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/regenerate/{scriptId}")
|
||||
public R<WmsProductSalesScriptVo> regenerateScript(@NotNull(message = "话术ID不能为空")
|
||||
@PathVariable Long scriptId) {
|
||||
WmsProductSalesScriptVo script = iWmsSalesScriptGeneratorService.regenerateScript(scriptId);
|
||||
return R.ok(script);
|
||||
}
|
||||
|
||||
/**
|
||||
* 预览话术生成(不保存到数据库)
|
||||
*/
|
||||
@PostMapping("/preview")
|
||||
public R<List<Map<String, Object>>> previewScripts(@RequestBody WmsSalesScriptGeneratorBo bo) {
|
||||
List<Map<String, Object>> previews = iWmsSalesScriptGeneratorService.previewScripts(bo);
|
||||
return R.ok(previews);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户类型列表
|
||||
*/
|
||||
@GetMapping("/customerTypes")
|
||||
public R<List<Map<String, Object>>> getCustomerTypes() {
|
||||
List<Map<String, Object>> customerTypes = iWmsSalesScriptGeneratorService.getCustomerTypes();
|
||||
return R.ok(customerTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取产品特性关键词
|
||||
*/
|
||||
@GetMapping("/featureKeywords")
|
||||
public R<List<String>> getFeatureKeywords() {
|
||||
List<String> keywords = iWmsSalesScriptGeneratorService.getFeatureKeywords();
|
||||
return R.ok(keywords);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分析产品信息并生成话术建议
|
||||
*/
|
||||
@PostMapping("/analyzeProduct")
|
||||
public R<Map<String, Object>> analyzeProduct(@RequestBody WmsSalesScriptGeneratorBo bo) {
|
||||
Map<String, Object> analysis = iWmsSalesScriptGeneratorService.analyzeProduct(bo);
|
||||
return R.ok(analysis);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user