提示词管理代码架构
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -10,7 +10,7 @@
|
|||||||
</parent>
|
</parent>
|
||||||
<groupId>com.cst</groupId>
|
<groupId>com.cst</groupId>
|
||||||
<artifactId>AIDriverEEBackend</artifactId>
|
<artifactId>AIDriverEEBackend</artifactId>
|
||||||
<version>1.26040401.1-SNAPSHOT</version>
|
<version>1.26040419.6-SNAPSHOT</version>
|
||||||
<name>Langchain4j-rj</name>
|
<name>Langchain4j-rj</name>
|
||||||
<description>Langchain4j-rj20250803</description>
|
<description>Langchain4j-rj20250803</description>
|
||||||
<url/>
|
<url/>
|
||||||
|
|||||||
@@ -19,7 +19,11 @@ public enum AudioAnalysisSceneType {
|
|||||||
"prompts/audio_text_analysis_soft_sale_user_prompts.txt",
|
"prompts/audio_text_analysis_soft_sale_user_prompts.txt",
|
||||||
"qwen-plus"
|
"qwen-plus"
|
||||||
),
|
),
|
||||||
|
SCENARIO_SMALL_BEEUTIFUL_SALE(
|
||||||
|
"prompts/audio_text_analysis_soft_sale_system_prompts.txt",
|
||||||
|
"prompts/audio_text_analysis_soft_sale_user_prompts.txt",
|
||||||
|
"qwen-plus"
|
||||||
|
),
|
||||||
/**
|
/**
|
||||||
* 会议纪要/会议分析场景
|
* 会议纪要/会议分析场景
|
||||||
* 提示词文件和模型可根据实际需要进行调整。
|
* 提示词文件和模型可根据实际需要进行调整。
|
||||||
|
|||||||
202
src/main/java/com/rj/controller/AiPromptsController.java
Normal file
202
src/main/java/com/rj/controller/AiPromptsController.java
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
package com.rj.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.rj.entity.AiPrompts;
|
||||||
|
import com.rj.service.IAiPromptsService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表 ai_prompts 前端控制器
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/aiPrompts")
|
||||||
|
@Tag(name = "AI提示词配置(ai_prompts)", description = "增删改查与分页")
|
||||||
|
public class AiPromptsController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IAiPromptsService aiPromptsService;
|
||||||
|
|
||||||
|
@PostMapping("/add")
|
||||||
|
@Operation(summary = "新增")
|
||||||
|
public ResponseEntity<Map<String, Object>> add(
|
||||||
|
@Parameter(description = "实体", required = true) @RequestBody AiPrompts entity) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
try {
|
||||||
|
if (entity.getId() == null || entity.getId().trim().isEmpty()) {
|
||||||
|
entity.setId(UUID.randomUUID().toString());
|
||||||
|
}
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
if (entity.getCreateTime() == null) {
|
||||||
|
entity.setCreateTime(now);
|
||||||
|
}
|
||||||
|
entity.setUpdateTime(now);
|
||||||
|
boolean ok = aiPromptsService.save(entity);
|
||||||
|
if (ok) {
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "添加成功");
|
||||||
|
result.put("data", entity);
|
||||||
|
return ResponseEntity.ok(result);
|
||||||
|
}
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "添加失败");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("ai_prompts add error", e);
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "添加异常:" + e.getMessage());
|
||||||
|
return ResponseEntity.internalServerError().body(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get/{id}")
|
||||||
|
@Operation(summary = "按ID查询")
|
||||||
|
public ResponseEntity<Map<String, Object>> getById(@PathVariable String id) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
try {
|
||||||
|
AiPrompts one = aiPromptsService.getById(id);
|
||||||
|
if (one != null) {
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "查询成功");
|
||||||
|
result.put("data", one);
|
||||||
|
return ResponseEntity.ok(result);
|
||||||
|
}
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "记录不存在");
|
||||||
|
return ResponseEntity.notFound().build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("ai_prompts get error, id={}", id, e);
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "查询异常:" + e.getMessage());
|
||||||
|
return ResponseEntity.internalServerError().body(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
@Operation(summary = "分页查询")
|
||||||
|
public ResponseEntity<Map<String, Object>> list(
|
||||||
|
@RequestParam(defaultValue = "1") Integer current,
|
||||||
|
@RequestParam(defaultValue = "10") Integer size,
|
||||||
|
@RequestParam(required = false) String sceneCode,
|
||||||
|
@RequestParam(required = false) String categoryCode,
|
||||||
|
@RequestParam(required = false) String fieldCode,
|
||||||
|
@RequestParam(required = false) String promptKeyword,
|
||||||
|
@RequestParam(required = false) String createStartTime,
|
||||||
|
@RequestParam(required = false) String createEndTime) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
try {
|
||||||
|
Page<AiPrompts> page = new Page<>(current, size);
|
||||||
|
LambdaQueryWrapper<AiPrompts> q = new LambdaQueryWrapper<>();
|
||||||
|
if (sceneCode != null && !sceneCode.trim().isEmpty()) {
|
||||||
|
q.eq(AiPrompts::getSceneCode, sceneCode);
|
||||||
|
}
|
||||||
|
if (categoryCode != null && !categoryCode.trim().isEmpty()) {
|
||||||
|
q.eq(AiPrompts::getCategoryCode, categoryCode);
|
||||||
|
}
|
||||||
|
if (fieldCode != null && !fieldCode.trim().isEmpty()) {
|
||||||
|
q.eq(AiPrompts::getFieldCode, fieldCode);
|
||||||
|
}
|
||||||
|
if (promptKeyword != null && !promptKeyword.trim().isEmpty()) {
|
||||||
|
q.like(AiPrompts::getPromptText, promptKeyword);
|
||||||
|
}
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
if (createStartTime != null && !createStartTime.trim().isEmpty()) {
|
||||||
|
try {
|
||||||
|
q.ge(AiPrompts::getCreateTime, LocalDateTime.parse(createStartTime, formatter));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "创建开始时间格式错误,请使用:yyyy-MM-dd HH:mm:ss");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (createEndTime != null && !createEndTime.trim().isEmpty()) {
|
||||||
|
try {
|
||||||
|
q.le(AiPrompts::getCreateTime, LocalDateTime.parse(createEndTime, formatter));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "创建结束时间格式错误,请使用:yyyy-MM-dd HH:mm:ss");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
q.orderByDesc(AiPrompts::getCreateTime);
|
||||||
|
Page<AiPrompts> data = aiPromptsService.page(page, q);
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "查询成功");
|
||||||
|
result.put("data", data.getRecords());
|
||||||
|
result.put("total", data.getTotal());
|
||||||
|
result.put("current", data.getCurrent());
|
||||||
|
result.put("size", data.getSize());
|
||||||
|
result.put("pages", data.getPages());
|
||||||
|
return ResponseEntity.ok(result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("ai_prompts list error", e);
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "查询异常:" + e.getMessage());
|
||||||
|
return ResponseEntity.internalServerError().body(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/update")
|
||||||
|
@Operation(summary = "更新")
|
||||||
|
public ResponseEntity<Map<String, Object>> update(@RequestBody AiPrompts entity) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
try {
|
||||||
|
if (entity.getId() == null || entity.getId().trim().isEmpty()) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "ID不能为空");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
}
|
||||||
|
entity.setUpdateTime(LocalDateTime.now());
|
||||||
|
boolean ok = aiPromptsService.updateById(entity);
|
||||||
|
if (ok) {
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "更新成功");
|
||||||
|
result.put("data", aiPromptsService.getById(entity.getId()));
|
||||||
|
return ResponseEntity.ok(result);
|
||||||
|
}
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "更新失败");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("ai_prompts update error", e);
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "更新异常:" + e.getMessage());
|
||||||
|
return ResponseEntity.internalServerError().body(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/delete/{id}")
|
||||||
|
@Operation(summary = "删除")
|
||||||
|
public ResponseEntity<Map<String, Object>> delete(@PathVariable String id) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
try {
|
||||||
|
boolean ok = aiPromptsService.removeById(id);
|
||||||
|
if (ok) {
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "删除成功");
|
||||||
|
return ResponseEntity.ok(result);
|
||||||
|
}
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "删除失败");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("ai_prompts delete error", e);
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "删除异常:" + e.getMessage());
|
||||||
|
return ResponseEntity.internalServerError().body(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -370,7 +370,8 @@ public class AudioFileController {
|
|||||||
@Parameter(description = "音频文件", required = true)
|
@Parameter(description = "音频文件", required = true)
|
||||||
@RequestParam("file") MultipartFile file,
|
@RequestParam("file") MultipartFile file,
|
||||||
@Parameter(description = "录音ID", required = true)
|
@Parameter(description = "录音ID", required = true)
|
||||||
@RequestParam("audioId") String audioId) {
|
@RequestParam("audioId") String audioId,
|
||||||
|
@RequestParam("audioDuration") BigDecimal audioDuration ) {
|
||||||
|
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
|
||||||
@@ -388,7 +389,7 @@ public class AudioFileController {
|
|||||||
audioManagement.setUpdateTime(TimeZoneUtils.now());
|
audioManagement.setUpdateTime(TimeZoneUtils.now());
|
||||||
audioManagementService.updateById(audioManagement);
|
audioManagementService.updateById(audioManagement);
|
||||||
// 同步回写 audio_management_segments(子表)
|
// 同步回写 audio_management_segments(子表)
|
||||||
saveOrUpdateManualUploadSegment(audioManagement, file, localFileName, localFilePath, uploadResult);
|
saveOrUpdateManualUploadSegment(audioManagement, file,audioDuration, localFileName, localFilePath, uploadResult);
|
||||||
} else {
|
} else {
|
||||||
log.warn("手动上传后未找到录音记录,无法回写本地路径:audioId={}", audioId);
|
log.warn("手动上传后未找到录音记录,无法回写本地路径:audioId={}", audioId);
|
||||||
}
|
}
|
||||||
@@ -418,6 +419,7 @@ public class AudioFileController {
|
|||||||
*/
|
*/
|
||||||
private void saveOrUpdateManualUploadSegment(AudioManagement audioManagement,
|
private void saveOrUpdateManualUploadSegment(AudioManagement audioManagement,
|
||||||
MultipartFile file,
|
MultipartFile file,
|
||||||
|
BigDecimal audioDuration,
|
||||||
String localFileName,
|
String localFileName,
|
||||||
String localFilePath,
|
String localFilePath,
|
||||||
Map<String, Object> uploadResult) {
|
Map<String, Object> uploadResult) {
|
||||||
@@ -456,11 +458,7 @@ public class AudioFileController {
|
|||||||
segment.setAudioFileSize(file.getSize());
|
segment.setAudioFileSize(file.getSize());
|
||||||
segment.setUploadTime(now);
|
segment.setUploadTime(now);
|
||||||
segment.setRecordingTime(audioManagement.getRecordingTime() != null ? audioManagement.getRecordingTime() : now);
|
segment.setRecordingTime(audioManagement.getRecordingTime() != null ? audioManagement.getRecordingTime() : now);
|
||||||
|
segment.setDuration(audioDuration);
|
||||||
AudioManagement fileUrlObj = (AudioManagement)uploadResult.get("audioRecord");
|
|
||||||
if (fileUrlObj != null) {
|
|
||||||
segment.setAudioFileUrl(fileUrlObj.getAudioFileUrl());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isNew) {
|
if (isNew) {
|
||||||
audioManagementSegmentsService.save(segment);
|
audioManagementSegmentsService.save(segment);
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class AudioManagementController {
|
|||||||
// 场景常量,避免在解析逻辑中硬编码字符串
|
// 场景常量,避免在解析逻辑中硬编码字符串
|
||||||
private static final String SCENARIO_SOFT_SALE = "SOFT_SALE";
|
private static final String SCENARIO_SOFT_SALE = "SOFT_SALE";
|
||||||
private static final String SCENARIO_FURNITURE_SALE = "FURNITURE";
|
private static final String SCENARIO_FURNITURE_SALE = "FURNITURE";
|
||||||
private static final String SCENARIO_MEETING_SUMMARY = "MEETING_SUMMARY";
|
private static final String SCENARIO_SMALL_BEEUTIFUL_SALE = "smallBeautiful_sales";
|
||||||
private static final String SCENARIO_CAR_SALE = "CAR_SALE";
|
private static final String SCENARIO_CAR_SALE = "CAR_SALE";
|
||||||
private static final String SCENARIO_SUMMARY = "SUMMARY";
|
private static final String SCENARIO_SUMMARY = "SUMMARY";
|
||||||
private static final String SCENARIO_SPEAKING_TRAINING= "SPEAKING_TRAINING"; //租赁模式
|
private static final String SCENARIO_SPEAKING_TRAINING= "SPEAKING_TRAINING"; //租赁模式
|
||||||
@@ -763,6 +763,78 @@ public class AudioManagementController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/AIAnlyzByIdForDetail")
|
||||||
|
@Operation(summary = "AI分析", description = "AI分析的总入口")
|
||||||
|
public ResponseEntity<Map<String, Object>> AIAnlyByIdForDetail(
|
||||||
|
@Parameter(description = "录音信息", required = true)
|
||||||
|
@RequestBody AudioManagement audioManagement) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
boolean success = true;
|
||||||
|
try {
|
||||||
|
if (audioManagement.getId() == null || audioManagement.getId().trim().isEmpty()) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "录音ID不能为空");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 根据ID查询家具意向分析记录
|
||||||
|
AudioManagement audioManagementFromDB = audioManagementService.getById(audioManagement.getId());
|
||||||
|
if (audioManagementFromDB == null) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "记录不存在");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
}
|
||||||
|
// 2. 检查summary字段,如果已存在总结内容,直接返回提示,不进行AI分析
|
||||||
|
String summary = audioManagement.getSummary();
|
||||||
|
if (summary != null && !summary.trim().isEmpty()) {
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "AI分析已完成");
|
||||||
|
result.put("data", audioManagement);
|
||||||
|
// return ResponseEntity.ok(result);
|
||||||
|
}
|
||||||
|
// 3. 获取录音文本;如主表为空,则从分段表拼接
|
||||||
|
String recordingText = audioManagementFromDB.getRecordingText();
|
||||||
|
|
||||||
|
|
||||||
|
if (recordingText == null || recordingText.trim().isEmpty()) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "录音文本为空");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 根据场景动态选择业务场景类型,调用业务层通用服务生成总结
|
||||||
|
AudioAnalysisSceneType sceneType = resolveSceneType(audioManagementFromDB.getScenario());
|
||||||
|
|
||||||
|
AudioTextAnalysisFurniture furniture = audioTextAnalysisLlmService.generateSummaryAndSaveForDetail(
|
||||||
|
sceneType,
|
||||||
|
recordingText,
|
||||||
|
audioManagement.getId(),
|
||||||
|
audioManagement.getSalesName(),
|
||||||
|
audioManagement.getSalesPhone(),
|
||||||
|
audioManagement.getCustomerName(),
|
||||||
|
audioManagement.getCustomerPhone()
|
||||||
|
);
|
||||||
|
log.info("llm return furniture Analysis : ",furniture.toString() );
|
||||||
|
if (recordingText == null || recordingText.trim().isEmpty()) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "录音文本为空");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
} else {
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "录音finishServiceById更新成功");
|
||||||
|
result.put("data", audioManagement);
|
||||||
|
return ResponseEntity.ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "更新异常:" + e.getMessage());
|
||||||
|
return ResponseEntity.internalServerError().body(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据录音场景字符串解析为大模型分析场景类型
|
* 根据录音场景字符串解析为大模型分析场景类型
|
||||||
*/
|
*/
|
||||||
@@ -774,6 +846,10 @@ public class AudioManagementController {
|
|||||||
if (SCENARIO_SOFT_SALE.equals(s)) {
|
if (SCENARIO_SOFT_SALE.equals(s)) {
|
||||||
return AudioAnalysisSceneType.SCENARIO_SOFT_SALE;
|
return AudioAnalysisSceneType.SCENARIO_SOFT_SALE;
|
||||||
}
|
}
|
||||||
|
if (SCENARIO_SMALL_BEEUTIFUL_SALE.equals(s)) {
|
||||||
|
return AudioAnalysisSceneType.SCENARIO_SMALL_BEEUTIFUL_SALE;
|
||||||
|
}
|
||||||
|
|
||||||
if (SCENARIO_FURNITURE_SALE.equals(s)) {
|
if (SCENARIO_FURNITURE_SALE.equals(s)) {
|
||||||
return AudioAnalysisSceneType.SCENARIO_FURNITURE_SALE;
|
return AudioAnalysisSceneType.SCENARIO_FURNITURE_SALE;
|
||||||
}
|
}
|
||||||
|
|||||||
50
src/main/java/com/rj/entity/AiPrompts.java
Normal file
50
src/main/java/com/rj/entity/AiPrompts.java
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package com.rj.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI 提示词配置(表 ai_prompts)
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@TableName("ai_prompts")
|
||||||
|
@Schema(description = "AI提示词配置(ai_prompts)")
|
||||||
|
public class AiPrompts implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "主键,UUID")
|
||||||
|
@TableId("id")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Schema(description = "场景编码")
|
||||||
|
private String sceneCode;
|
||||||
|
|
||||||
|
@Schema(description = "分类编码")
|
||||||
|
private String categoryCode;
|
||||||
|
|
||||||
|
@Schema(description = "分类描述")
|
||||||
|
private String categoryDesc;
|
||||||
|
|
||||||
|
@Schema(description = "字段编码")
|
||||||
|
private String fieldCode;
|
||||||
|
|
||||||
|
@Schema(description = "提示词")
|
||||||
|
private String promptText;
|
||||||
|
|
||||||
|
@Schema(description = "备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
@Schema(description = "修改时间")
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
}
|
||||||
12
src/main/java/com/rj/mapper/AiPromptsMapper.java
Normal file
12
src/main/java/com/rj/mapper/AiPromptsMapper.java
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package com.rj.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.rj.entity.AiPrompts;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表 ai_prompts Mapper
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface AiPromptsMapper extends BaseMapper<AiPrompts> {
|
||||||
|
}
|
||||||
10
src/main/java/com/rj/service/IAiPromptsService.java
Normal file
10
src/main/java/com/rj/service/IAiPromptsService.java
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package com.rj.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.rj.entity.AiPrompts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表 ai_prompts 服务;常规 CRUD 与分页见 {@link IService}。
|
||||||
|
*/
|
||||||
|
public interface IAiPromptsService extends IService<AiPrompts> {
|
||||||
|
}
|
||||||
@@ -77,6 +77,15 @@ public interface IAudioTextAnalysisLlmService {
|
|||||||
String ownerPhone,
|
String ownerPhone,
|
||||||
String customerName,
|
String customerName,
|
||||||
String customerPhone);
|
String customerPhone);
|
||||||
|
|
||||||
|
AudioTextAnalysisFurniture generateSummaryAndSaveForDetail(
|
||||||
|
AudioAnalysisSceneType sceneType,
|
||||||
|
String recordingText,
|
||||||
|
String parentId,
|
||||||
|
String ownerName,
|
||||||
|
String ownerPhone,
|
||||||
|
String customerName,
|
||||||
|
String customerPhone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
14
src/main/java/com/rj/service/impl/AiPromptsServiceImpl.java
Normal file
14
src/main/java/com/rj/service/impl/AiPromptsServiceImpl.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package com.rj.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.rj.entity.AiPrompts;
|
||||||
|
import com.rj.mapper.AiPromptsMapper;
|
||||||
|
import com.rj.service.IAiPromptsService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表 ai_prompts 服务实现
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class AiPromptsServiceImpl extends ServiceImpl<AiPromptsMapper, AiPrompts> implements IAiPromptsService {
|
||||||
|
}
|
||||||
@@ -14,10 +14,7 @@ import com.fasterxml.jackson.databind.JsonNode;
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.rj.common.AudioAnalysisSceneType;
|
import com.rj.common.AudioAnalysisSceneType;
|
||||||
import com.rj.common.LocalLlmSummaryResult;
|
import com.rj.common.LocalLlmSummaryResult;
|
||||||
import com.rj.entity.AudioManagement;
|
import com.rj.entity.*;
|
||||||
import com.rj.entity.AudioTextAnalysisFurniture;
|
|
||||||
import com.rj.entity.AudioTextAnalysisSop;
|
|
||||||
import com.rj.entity.TodoItem;
|
|
||||||
import com.rj.service.IAudioManagementService;
|
import com.rj.service.IAudioManagementService;
|
||||||
import com.rj.service.IAudioTextAnalysisFurnitureService;
|
import com.rj.service.IAudioTextAnalysisFurnitureService;
|
||||||
import com.rj.service.IAudioTextAnalysisLlmService;
|
import com.rj.service.IAudioTextAnalysisLlmService;
|
||||||
@@ -37,10 +34,7 @@ import jakarta.annotation.PostConstruct;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Scanner;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@@ -532,6 +526,56 @@ public class AudioTextAnalysisLlmServiceImpl implements IAudioTextAnalysisLlmSer
|
|||||||
|
|
||||||
return furniture;
|
return furniture;
|
||||||
}
|
}
|
||||||
|
@Autowired
|
||||||
|
private com.rj.service.IAudioManagementSegmentsService audioManagementSegmentsService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AudioTextAnalysisFurniture generateSummaryAndSaveForDetail(
|
||||||
|
AudioAnalysisSceneType sceneType,
|
||||||
|
String recordingText,
|
||||||
|
String parentId,
|
||||||
|
String ownerName,
|
||||||
|
String ownerPhone,
|
||||||
|
String customerName,
|
||||||
|
String customerPhone) {
|
||||||
|
|
||||||
|
LambdaQueryWrapper<AudioManagementSegments> segQuery = new LambdaQueryWrapper<>();
|
||||||
|
segQuery.eq(AudioManagementSegments::getParentId, parentId)
|
||||||
|
.orderByAsc(AudioManagementSegments::getChunkIndex);
|
||||||
|
List<AudioManagementSegments> segmentList = audioManagementSegmentsService.list(segQuery);
|
||||||
|
int emptyCount = 0 ;
|
||||||
|
StringBuilder mergedText = new StringBuilder();
|
||||||
|
if (segmentList != null && !segmentList.isEmpty()) {
|
||||||
|
for (AudioManagementSegments seg : segmentList) {
|
||||||
|
String segText = seg.getRecordingText();
|
||||||
|
if (segText != null && !segText.trim().isEmpty()) {
|
||||||
|
if (mergedText.length() > 0) {
|
||||||
|
mergedText.append("\n");
|
||||||
|
}
|
||||||
|
mergedText.append(segText.trim());
|
||||||
|
}else {
|
||||||
|
emptyCount ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info(" AudioManagementSegments 总数是: {} ,未转文本记录条数是: {}",segmentList.size(), emptyCount);
|
||||||
|
|
||||||
|
|
||||||
|
LocalLlmSummaryResult llmResult = generateSummaryByLocalLLM(sceneType, mergedText.toString());
|
||||||
|
String rawContent = llmResult.rawContent();
|
||||||
|
if (rawContent == null || rawContent.trim().isEmpty()) {
|
||||||
|
log.warn("大模型返回内容为空");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
AudioTextAnalysisFurniture furniture = new AudioTextAnalysisFurniture();
|
||||||
|
AudioManagement audioManagement = new AudioManagement();
|
||||||
|
audioManagement.setId(parentId);
|
||||||
|
audioManagement.setSummary(rawContent);
|
||||||
|
applyLocalLlmTokenCountsToAudioManagement(audioManagement, llmResult);
|
||||||
|
audioManagementService.updateById(audioManagement);
|
||||||
|
|
||||||
|
return furniture;
|
||||||
|
}
|
||||||
|
|
||||||
private void applyDashScopeUsageToAudioManagement(AudioManagement target, GenerationResult result) {
|
private void applyDashScopeUsageToAudioManagement(AudioManagement target, GenerationResult result) {
|
||||||
if (result == null || result.getUsage() == null) {
|
if (result == null || result.getUsage() == null) {
|
||||||
|
|||||||
@@ -132,7 +132,6 @@
|
|||||||
"closing_cooperation": 75,
|
"closing_cooperation": 75,
|
||||||
"proactive_wechat_add": 80,
|
"proactive_wechat_add": 80,
|
||||||
"polite_farewell": 90
|
"polite_farewell": 90
|
||||||
|
|
||||||
}
|
}
|
||||||
SOP维度评分(每个维度0-100分,根据录音文本中销售顾问的实际表现进行评分):
|
SOP维度评分(每个维度0-100分,根据录音文本中销售顾问的实际表现进行评分):
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user