家居大模型联调,分析sop执行情况
This commit is contained in:
@@ -14,9 +14,11 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.rj.entity.AudioManagement;
|
||||
import com.rj.entity.AudioTextAnalysisFurniture;
|
||||
import com.rj.entity.AudioTextAnalysisSop;
|
||||
import com.rj.entity.TodoItem;
|
||||
import com.rj.service.IAudioManagementService;
|
||||
import com.rj.service.IAudioTextAnalysisFurnitureService;
|
||||
import com.rj.service.IAudioTextAnalysisSopService;
|
||||
import com.rj.service.ITodoItemService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@@ -55,6 +57,9 @@ public class AudioTextAnalysisFurnitureController {
|
||||
@Autowired
|
||||
private ITodoItemService todoItemService;
|
||||
|
||||
@Autowired
|
||||
private IAudioTextAnalysisSopService sopService;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@@ -238,8 +243,9 @@ public class AudioTextAnalysisFurnitureController {
|
||||
}
|
||||
AudioTextAnalysisFurniture furniture = new AudioTextAnalysisFurniture();
|
||||
furniture.setRecordingText(recordingText);
|
||||
// 4. 调用大模型生成总结,传递待办事项所需的关联信息
|
||||
generateSummaryByLLM(furniture, id, audioManagement.getSalesName(), audioManagement.getSalesPhone());
|
||||
// 4. 调用大模型生成总结,传递待办事项和SOP所需的关联信息
|
||||
generateSummaryByLLM(furniture, id, audioManagement.getSalesName(), audioManagement.getSalesPhone(),
|
||||
audioManagement.getCustomerName(), audioManagement.getCustomerPhone());
|
||||
|
||||
|
||||
audioManagement = new AudioManagement();
|
||||
@@ -287,8 +293,11 @@ public class AudioTextAnalysisFurnitureController {
|
||||
* @param parentId 父ID(AudioManagement的ID)
|
||||
* @param ownerName 所属人姓名
|
||||
* @param ownerPhone 所属人电话
|
||||
* @param customerName 客户姓名
|
||||
* @param customerPhone 客户电话
|
||||
*/
|
||||
private void generateSummaryByLLM(AudioTextAnalysisFurniture furniture, String parentId, String ownerName, String ownerPhone) {
|
||||
private void generateSummaryByLLM(AudioTextAnalysisFurniture furniture, String parentId, String ownerName, String ownerPhone,
|
||||
String customerName, String customerPhone) {
|
||||
// 记录开始时间
|
||||
long startTime = System.currentTimeMillis();
|
||||
log.info("开始调用大模型生成总结");
|
||||
@@ -314,7 +323,7 @@ public class AudioTextAnalysisFurnitureController {
|
||||
GenerationResult call = gen.call(param);
|
||||
String rawContent = call.getOutput().getChoices().get(0).getMessage().getContent();
|
||||
log.info("大模型生成总结完成,结果长度: {},内容是:{}", rawContent.length(), rawContent);
|
||||
applyStructuredResult(furniture, rawContent, parentId, ownerName, ownerPhone);
|
||||
applyStructuredResult(furniture, rawContent, parentId, ownerName, ownerPhone, customerName, customerPhone);
|
||||
} catch (NoApiKeyException e) {
|
||||
log.error("API密钥未配置", e);
|
||||
throw new RuntimeException("API密钥未配置: " + e.getMessage(), e);
|
||||
@@ -583,7 +592,8 @@ public class AudioTextAnalysisFurnitureController {
|
||||
return prompt.toString();
|
||||
}
|
||||
|
||||
private void applyStructuredResult(AudioTextAnalysisFurniture furniture, String rawContent, String parentId, String ownerName, String ownerPhone) {
|
||||
private void applyStructuredResult(AudioTextAnalysisFurniture furniture, String rawContent, String parentId, String ownerName, String ownerPhone,
|
||||
String customerName, String customerPhone) {
|
||||
String normalized = normalizeJson(rawContent);
|
||||
try {
|
||||
JsonNode root = objectMapper.readTree(normalized);
|
||||
@@ -606,9 +616,13 @@ public class AudioTextAnalysisFurnitureController {
|
||||
furniture.setSecondaryBedroomCabinet(jsonObjectToString(root, "secondary_bedroom_cabinet"));
|
||||
furniture.setShoeCabinet(jsonObjectToString(root, "shoe_cabinet"));
|
||||
furniture.setBedAndMattress(jsonObjectToString(root, "bed_and_mattress"));
|
||||
|
||||
furniture.setSummary1(jsonObjectToString(root, "summary1"));
|
||||
furniture.setSummary2(jsonObjectToString(root, "summary2"));
|
||||
furniture.setSummary3(jsonObjectToString(root, "summary3"));
|
||||
// 解析并保存待办事项
|
||||
saveTodoItems(root, parentId, ownerName, ownerPhone);
|
||||
// 解析并保存SOP评分信息
|
||||
saveSopInfo(root, parentId, ownerName, ownerPhone, customerName, customerPhone);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.warn("解析大模型返回JSON失败,使用原始内容作为总结: {}", e.getMessage());
|
||||
furniture.setSummarySentence(rawContent);
|
||||
@@ -660,7 +674,7 @@ public class AudioTextAnalysisFurnitureController {
|
||||
todoItem.setStatus("待处理"); // 默认状态
|
||||
todoItem.setCreateTime(now);
|
||||
todoItem.setUpdateTime(now);
|
||||
|
||||
todoItem.setPendingDate(now.plusDays(3)); // 延期处理时间为当前时间加三天
|
||||
boolean success = todoItemService.save(todoItem);
|
||||
if (success) {
|
||||
savedCount++;
|
||||
@@ -719,5 +733,110 @@ public class AudioTextAnalysisFurnitureController {
|
||||
return node.isTextual() ? node.asText() : node.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析并保存SOP评分信息
|
||||
*
|
||||
* @param root JSON根节点
|
||||
* @param parentId 父ID(AudioManagement的ID)
|
||||
* @param ownerName 所属人姓名
|
||||
* @param ownerPhone 所属人电话
|
||||
* @param customerName 客户姓名
|
||||
* @param customerPhone 客户电话
|
||||
*/
|
||||
private void saveSopInfo(JsonNode root, String parentId, String ownerName, String ownerPhone,
|
||||
String customerName, String customerPhone) {
|
||||
try {
|
||||
// 检查是否存在SOP相关字段
|
||||
JsonNode comprehensiveScoreNode = root.get("comprehensive_score");
|
||||
if (comprehensiveScoreNode == null) {
|
||||
log.info("未找到SOP评分信息,跳过保存");
|
||||
return;
|
||||
}
|
||||
|
||||
AudioTextAnalysisSop sop = new AudioTextAnalysisSop();
|
||||
sop.setId(UUID.randomUUID().toString());
|
||||
sop.setParentId(parentId);
|
||||
sop.setOwnerName(ownerName);
|
||||
sop.setOwnerPhone(ownerPhone);
|
||||
sop.setCustomerName(customerName);
|
||||
sop.setCustomerPhone(customerPhone);
|
||||
sop.setIndustryType("furniture");
|
||||
|
||||
// 解析SOP评分字段
|
||||
sop.setComprehensiveScore(intValue(root, "comprehensive_score"));
|
||||
sop.setScoreSummaryReason(textValue(root, "score_summary_reason"));
|
||||
sop.setGreetingIceBreaking(intValue(root, "greeting_ice_breaking"));
|
||||
sop.setBrandIntroduction(intValue(root, "brand_introduction"));
|
||||
sop.setGoldenThreeQuestions(intValue(root, "golden_three_questions"));
|
||||
sop.setNeedsGuidance(intValue(root, "needs_guidance"));
|
||||
sop.setServiceProgression(intValue(root, "service_progression"));
|
||||
sop.setReassuranceHandbook(intValue(root, "reassurance_handbook"));
|
||||
sop.setThreeLevelPricing(intValue(root, "three_level_pricing"));
|
||||
sop.setObjectionHandling(intValue(root, "objection_handling"));
|
||||
sop.setActivityImplantation(intValue(root, "activity_implantation"));
|
||||
sop.setClosingCooperation(intValue(root, "closing_cooperation"));
|
||||
sop.setProactiveWechatAdd(intValue(root, "proactive_wechat_add"));
|
||||
sop.setPoliteFarewell(intValue(root, "polite_farewell"));
|
||||
|
||||
// 设置时间
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
sop.setCreatedAt(now);
|
||||
sop.setUpdatedAt(now);
|
||||
|
||||
// 检查是否已存在相同parentId的记录,如果存在则更新,否则新增
|
||||
LambdaQueryWrapper<AudioTextAnalysisSop> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(AudioTextAnalysisSop::getParentId, parentId);
|
||||
AudioTextAnalysisSop existingSop = sopService.getOne(wrapper);
|
||||
if (existingSop != null) {
|
||||
sop.setId(existingSop.getId());
|
||||
boolean success = sopService.updateById(sop);
|
||||
if (success) {
|
||||
log.info("更新SOP评分信息成功,ID: {}, parentId: {}", sop.getId(), parentId);
|
||||
} else {
|
||||
log.warn("更新SOP评分信息失败,parentId: {}", parentId);
|
||||
}
|
||||
} else {
|
||||
boolean success = sopService.save(sop);
|
||||
if (success) {
|
||||
log.info("保存SOP评分信息成功,ID: {}, parentId: {}", sop.getId(), parentId);
|
||||
} else {
|
||||
log.warn("保存SOP评分信息失败,parentId: {}", parentId);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("保存SOP评分信息时发生异常", e);
|
||||
// 不抛出异常,避免影响主流程
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从JSON节点中获取整数值
|
||||
*
|
||||
* @param root JSON根节点
|
||||
* @param field 字段名
|
||||
* @return 整数值,如果不存在或为null则返回null
|
||||
*/
|
||||
private Integer intValue(JsonNode root, String field) {
|
||||
JsonNode node = root.get(field);
|
||||
if (node == null || node.isNull()) {
|
||||
return null;
|
||||
}
|
||||
if (node.isInt()) {
|
||||
return node.asInt();
|
||||
} else if (node.isTextual()) {
|
||||
try {
|
||||
String text = node.asText();
|
||||
if (text == null || text.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return Integer.parseInt(text.trim());
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("无法将字段 {} 的值 {} 转换为整数", field, node.asText());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,10 @@ public class TodoItemController {
|
||||
if (todoItem.getId() == null || todoItem.getId().trim().isEmpty()) {
|
||||
todoItem.setId(UUID.randomUUID().toString());
|
||||
}
|
||||
// 如果待处理日期为空,则设置为当前时间加3天
|
||||
if (todoItem.getPendingDate() == null) {
|
||||
todoItem.setPendingDate(LocalDateTime.now().plusDays(3));
|
||||
}
|
||||
todoItem.setCreateTime(LocalDateTime.now());
|
||||
todoItem.setUpdateTime(LocalDateTime.now());
|
||||
boolean success = todoItemService.save(todoItem);
|
||||
@@ -331,6 +335,104 @@ public class TodoItemController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新待办事项状态为已完成
|
||||
*/
|
||||
@PostMapping("/updateTodoStatus")
|
||||
@Operation(summary = "更新待办事项状态为已完成", description = "根据ID将待办事项状态修改为已完成")
|
||||
public ResponseEntity<Map<String, Object>> updateTodoStatus(
|
||||
@Parameter(description = "包含id的请求体,格式:{\"id\": \"待办事项ID\"}", required = true)
|
||||
@RequestBody Map<String, String> request) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
try {
|
||||
String id = request.get("id");
|
||||
if (id == null || id.trim().isEmpty()) {
|
||||
result.put("success", false);
|
||||
result.put("message", "待办事项ID不能为空");
|
||||
return ResponseEntity.badRequest().body(result);
|
||||
}
|
||||
|
||||
TodoItem todoItem = todoItemService.getById(id);
|
||||
if (todoItem == null) {
|
||||
result.put("success", false);
|
||||
result.put("message", "待办事项不存在");
|
||||
return ResponseEntity.badRequest().body(result);
|
||||
}
|
||||
|
||||
todoItem.setStatus("已完成");
|
||||
todoItem.setUpdateTime(LocalDateTime.now());
|
||||
boolean success = todoItemService.updateById(todoItem);
|
||||
|
||||
if (success) {
|
||||
result.put("success", true);
|
||||
result.put("message", "状态更新成功");
|
||||
return ResponseEntity.ok(result);
|
||||
} else {
|
||||
result.put("success", false);
|
||||
result.put("message", "状态更新失败");
|
||||
return ResponseEntity.badRequest().body(result);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
result.put("success", false);
|
||||
result.put("message", "状态更新异常:" + e.getMessage());
|
||||
return ResponseEntity.internalServerError().body(result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 延期处理待办事项
|
||||
*/
|
||||
@PostMapping("/delayProcessTodo")
|
||||
@Operation(summary = "延期处理待办事项", description = "根据ID将待办事项的待处理日期延期3天")
|
||||
public ResponseEntity<Map<String, Object>> delayProcessTodo(
|
||||
@Parameter(description = "包含id的请求体,格式:{\"id\": \"待办事项ID\"}", required = true)
|
||||
@RequestBody Map<String, String> request) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
try {
|
||||
String id = request.get("id");
|
||||
if (id == null || id.trim().isEmpty()) {
|
||||
result.put("success", false);
|
||||
result.put("message", "待办事项ID不能为空");
|
||||
return ResponseEntity.badRequest().body(result);
|
||||
}
|
||||
|
||||
TodoItem todoItem = todoItemService.getById(id);
|
||||
if (todoItem == null) {
|
||||
result.put("success", false);
|
||||
result.put("message", "待办事项不存在");
|
||||
return ResponseEntity.badRequest().body(result);
|
||||
}
|
||||
|
||||
// 计算延期3天后的日期
|
||||
LocalDateTime newPendingDate;
|
||||
if (todoItem.getPendingDate() != null) {
|
||||
// 如果已有待处理日期,则在原日期基础上延期3天
|
||||
newPendingDate = todoItem.getPendingDate().plusDays(3);
|
||||
} else {
|
||||
// 如果没有待处理日期,则设置为当前日期+3天
|
||||
newPendingDate = LocalDateTime.now().plusDays(3);
|
||||
}
|
||||
|
||||
todoItem.setPendingDate(newPendingDate);
|
||||
todoItem.setUpdateTime(LocalDateTime.now());
|
||||
boolean success = todoItemService.updateById(todoItem);
|
||||
|
||||
if (success) {
|
||||
result.put("success", true);
|
||||
result.put("message", "延期处理成功,待处理日期已更新为:" + newPendingDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
return ResponseEntity.ok(result);
|
||||
} else {
|
||||
result.put("success", false);
|
||||
result.put("message", "延期处理失败");
|
||||
return ResponseEntity.badRequest().body(result);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
result.put("success", false);
|
||||
result.put("message", "延期处理异常:" + e.getMessage());
|
||||
return ResponseEntity.internalServerError().body(result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取待办事项统计信息
|
||||
*/
|
||||
|
||||
@@ -112,6 +112,18 @@ public class AudioTextAnalysisFurniture implements Serializable {
|
||||
@TableField("customer_id")
|
||||
private String customerId;
|
||||
|
||||
@Schema(description = "总结1")
|
||||
@TableField("summary1")
|
||||
private String summary1;
|
||||
|
||||
@Schema(description = "总结2")
|
||||
@TableField("summary2")
|
||||
private String summary2;
|
||||
|
||||
@Schema(description = "总结3")
|
||||
@TableField("summary3")
|
||||
private String summary3;
|
||||
|
||||
@Schema(description = "录音文本")
|
||||
@TableField(exist = false)
|
||||
private String recordingText;
|
||||
|
||||
@@ -53,6 +53,10 @@ public class TodoItem implements Serializable {
|
||||
@TableField("owner_phone")
|
||||
private String ownerPhone;
|
||||
|
||||
@Schema(description = "待处理日期")
|
||||
@TableField("pending_date")
|
||||
private LocalDateTime pendingDate;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@TableField("create_time")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
Reference in New Issue
Block a user