Commit f2e11f8f5077e666818bcd7bb1e0cfd945c686c8

Authored by qianbao
1 parent c357bb83

添加向量库

src/main/java/com/xly/milvus/service/AiGlobalAgentQuestionSqlEmitterService.java
@@ -12,7 +12,7 @@ public interface AiGlobalAgentQuestionSqlEmitterService { @@ -12,7 +12,7 @@ public interface AiGlobalAgentQuestionSqlEmitterService {
12 * @return void 12 * @return void
13 * @Description 插入向量库 13 * @Description 插入向量库
14 **/ 14 **/
15 - void addAiGlobalAgentQuestionSqlEmitter(String sKey,Map<String,Object> data,String sQuestion,String sSqlContent,String cachType,String collectionName); 15 + void addAiGlobalAgentQuestionSqlEmitter(String sKey,Map<String,Object> data,String sQuestion,String sSqlContent,String cachType,String collectionName,Boolean isInit);
16 16
17 17
18 Map<String, Object> queryAiGlobalAgentQuestionSqlEmitter(String searchText, String collectionName); 18 Map<String, Object> queryAiGlobalAgentQuestionSqlEmitter(String searchText, String collectionName);
src/main/java/com/xly/milvus/service/MilvusService.java
@@ -22,6 +22,24 @@ public interface MilvusService { @@ -22,6 +22,24 @@ public interface MilvusService {
22 22
23 TTSResponseDTO initDataToMilvus(Map<String, Object> reqMap); 23 TTSResponseDTO initDataToMilvus(Map<String, Object> reqMap);
24 24
  25 + /***
  26 + * @Author 钱豹
  27 + * @Date 9:00 2026/4/1
  28 + * @Param [reqMap]
  29 + * @return com.xly.tts.bean.TTSResponseDTO
  30 + * @Description 客户问题库转入全局问题库
  31 + **/
  32 + TTSResponseDTO addGlobalAgentQuestion(Map<String, Object> reqMap);
  33 +
  34 + /***
  35 + * @Author 钱豹
  36 + * @Date 9:28 2026/4/1
  37 + * @Param [reqMap]
  38 + * @return com.xly.tts.bean.TTSResponseDTO
  39 + * @Description 初始化全局SQL进入向量库
  40 + **/
  41 + TTSResponseDTO initGlobalAgentQuestion(Map<String, Object> reqMap);
  42 +
25 43
26 /** 44 /**
27 * 创建集合(如果不存在) 45 * 创建集合(如果不存在)
src/main/java/com/xly/milvus/service/impl/AiGlobalAgentQuestionSqlEmitterServiceImpl.java
@@ -58,7 +58,7 @@ public class AiGlobalAgentQuestionSqlEmitterServiceImpl implements AiGlobalAgent @@ -58,7 +58,7 @@ public class AiGlobalAgentQuestionSqlEmitterServiceImpl implements AiGlobalAgent
58 * @Description 插入数据 58 * @Description 插入数据
59 **/ 59 **/
60 @Override 60 @Override
61 - public void addAiGlobalAgentQuestionSqlEmitter(String sKey,Map<String,Object> data,String sQuestion,String sSqlContent,String cachType,String collectionName) { 61 + public void addAiGlobalAgentQuestionSqlEmitter(String sKey,Map<String,Object> data,String sQuestion,String sSqlContent,String cachType,String collectionName,Boolean isInit) {
62 // 向量化 62 // 向量化
63 List<Float> vector = vectorizationService.textToVector(sKey); 63 List<Float> vector = vectorizationService.textToVector(sKey);
64 64
@@ -83,10 +83,12 @@ public class AiGlobalAgentQuestionSqlEmitterServiceImpl implements AiGlobalAgent @@ -83,10 +83,12 @@ public class AiGlobalAgentQuestionSqlEmitterServiceImpl implements AiGlobalAgent
83 .build(); 83 .build();
84 84
85 InsertResp insertResp = milvusClient.insert(insertReq); 85 InsertResp insertResp = milvusClient.insert(insertReq);
86 - //调用数据库插入数据库  
87 - Map<String, Object> searMap = dynamicExeDbService.getDoProMap(sProName, data);  
88 - dynamicExeDbService.getCallPro(searMap, sProName);  
89 - 86 + //是否初始化。初始化不需要插入到数据库
  87 + if(!isInit){
  88 + //调用数据库插入数据库
  89 + Map<String, Object> searMap = dynamicExeDbService.getDoProMap(sProName, data);
  90 + dynamicExeDbService.getCallPro(searMap, sProName);
  91 + }
90 System.out.println("成功插入 " + insertResp.getInsertCnt() + " 条数据"); 92 System.out.println("成功插入 " + insertResp.getInsertCnt() + " 条数据");
91 System.out.println(" - 数据预览:"); 93 System.out.println(" - 数据预览:");
92 } 94 }
src/main/java/com/xly/milvus/service/impl/MilvusServiceImpl.java
@@ -10,6 +10,7 @@ import com.google.common.reflect.TypeToken; @@ -10,6 +10,7 @@ import com.google.common.reflect.TypeToken;
10 import com.google.gson.Gson; 10 import com.google.gson.Gson;
11 import com.google.gson.JsonArray; 11 import com.google.gson.JsonArray;
12 import com.google.gson.JsonObject; 12 import com.google.gson.JsonObject;
  13 +import com.xly.milvus.service.AiGlobalAgentQuestionSqlEmitterService;
13 import com.xly.milvus.service.MilvusService; 14 import com.xly.milvus.service.MilvusService;
14 import com.xly.milvus.service.VectorizationService; 15 import com.xly.milvus.service.VectorizationService;
15 import com.xly.milvus.util.MapToJsonConverter; 16 import com.xly.milvus.util.MapToJsonConverter;
@@ -60,6 +61,7 @@ public class MilvusServiceImpl implements MilvusService { @@ -60,6 +61,7 @@ public class MilvusServiceImpl implements MilvusService {
60 private final MilvusClientV2 milvusClient; 61 private final MilvusClientV2 milvusClient;
61 private final VectorizationService vectorizationService; 62 private final VectorizationService vectorizationService;
62 private final DynamicExeDbService dynamicExeDbService; 63 private final DynamicExeDbService dynamicExeDbService;
  64 + private final AiGlobalAgentQuestionSqlEmitterService aiGlobalAgentQuestionSqlEmitterService;
63 private static final long NULL_TIMESTAMP = -1L; 65 private static final long NULL_TIMESTAMP = -1L;
64 // 日期格式常量 66 // 日期格式常量
65 private static final DateTimeFormatter ISO_FORMATTER = 67 private static final DateTimeFormatter ISO_FORMATTER =
@@ -128,6 +130,80 @@ public class MilvusServiceImpl implements MilvusService { @@ -128,6 +130,80 @@ public class MilvusServiceImpl implements MilvusService {
128 .build(); 130 .build();
129 } 131 }
130 132
  133 + /***
  134 + * @Author 钱豹
  135 + * @Date 9:20 2026/4/1
  136 + * @Param [reqMap]
  137 + * @return com.xly.tts.bean.TTSResponseDTO
  138 + * @Description 用户问题列表转换成全局问题
  139 + **/
  140 + @Override
  141 + public TTSResponseDTO addGlobalAgentQuestion(Map<String, Object> reqMap) {
  142 + if(ObjectUtil.isEmpty(reqMap.get("sRowData"))){
  143 + return TTSResponseDTO.builder()
  144 + .code(-1)
  145 + .message("请选择数据")
  146 + .build();
  147 + }
  148 + //遍历数据
  149 + List<Map<String,Object>> data = (List<Map<String, Object>>) reqMap.get("sRowData");
  150 + if(ObjectUtil.isEmpty(data)){
  151 + return TTSResponseDTO.builder()
  152 + .code(-1)
  153 + .message("请选择数据")
  154 + .build();
  155 + }
  156 + StringBuffer sb = new StringBuffer();
  157 + data.forEach(one->{
  158 + //查询向量库是否存在
  159 + String sSceneId = one.get("sSceneId").toString();
  160 + String sMethodId = one.get("sMethodId").toString();
  161 + String sUserInput = one.get("sUserInput").toString();
  162 + String sSqlContent = one.get("sSqlContent").toString();
  163 + String searchText = sSceneId+"_"+sMethodId+"_"+sUserInput;
  164 + if(ObjectUtil.isNotEmpty(sUserInput)){
  165 + //根据问题查询向量库
  166 + Map<String,Object> serMap = aiGlobalAgentQuestionSqlEmitterService.queryAiGlobalAgentQuestionSqlEmitter(searchText, "ai_global_agent_question_sql");
  167 + if(ObjectUtil.isNotEmpty(serMap)){
  168 + aiGlobalAgentQuestionSqlEmitterService.addAiGlobalAgentQuestionSqlEmitter(searchText,one,sUserInput,sSqlContent,"MYSQL","ai_global_agent_question_sql",false);
  169 + }else{
  170 + sb.append(sUserInput).append("已经存在").append("\n");
  171 + }
  172 + //更新数据是否是全局问题,等待朱总确定是否需要
  173 +
  174 +
  175 + }
  176 + });
  177 + if(ObjectUtil.isEmpty(sb)){
  178 + sb.append("操作成功");
  179 + }
  180 + return TTSResponseDTO.builder()
  181 + .code(200)
  182 + .message(sb.toString())
  183 + .build();
  184 + }
  185 +
  186 + @Override
  187 + public TTSResponseDTO initGlobalAgentQuestion(Map<String, Object> reqMap) {
  188 + //全局问题初始化
  189 + List<Map<String,Object>> data = getGlobalAgentQuestion();
  190 + data.forEach(one->{
  191 + //查询向量库是否存在
  192 + String sSceneId = one.get("sSceneId").toString();
  193 + String sMethodId = one.get("sMethodId").toString();
  194 + String sUserInput = one.get("sUserInput").toString();
  195 + String sSqlContent = one.get("sSqlContent").toString();
  196 + String searchText = sSceneId+"_"+sMethodId+"_"+sUserInput;
  197 + if(ObjectUtil.isNotEmpty(sUserInput)){
  198 + aiGlobalAgentQuestionSqlEmitterService.addAiGlobalAgentQuestionSqlEmitter(searchText,one,sUserInput,sSqlContent,"MYSQL","ai_global_agent_question_sql",true);
  199 + }
  200 + });
  201 + return TTSResponseDTO.builder()
  202 + .code(200)
  203 + .message("操作成功")
  204 + .build();
  205 + }
  206 +
131 public String getUpdateDateUp(String sInputTabelName) { 207 public String getUpdateDateUp(String sInputTabelName) {
132 Map<String,Object> serDataMap = new HashMap<>(); 208 Map<String,Object> serDataMap = new HashMap<>();
133 String sSql ="SELECT DATE_FORMAT(tUpdateDate,'%Y-%m-%d %H:%i:%s') AS tUpdateDate FROM ai_milvus_vector_record WHERE sInputTabelName = #{sInputTabelName}"; 209 String sSql ="SELECT DATE_FORMAT(tUpdateDate,'%Y-%m-%d %H:%i:%s') AS tUpdateDate FROM ai_milvus_vector_record WHERE sInputTabelName = #{sInputTabelName}";
@@ -139,6 +215,14 @@ public class MilvusServiceImpl implements MilvusService { @@ -139,6 +215,14 @@ public class MilvusServiceImpl implements MilvusService {
139 return data.get(0).get("tUpdateDate").toString(); 215 return data.get(0).get("tUpdateDate").toString();
140 } 216 }
141 217
  218 + public List<Map<String,Object>> getGlobalAgentQuestion() {
  219 + Map<String,Object> serDataMap = new HashMap<>();
  220 + String sSql ="SELECT * FROM ai_global_agent_question_sql";
  221 + //删除集合全部数据
  222 + List<Map<String,Object>> data = this.dynamicExeDbService.findSql(serDataMap,sSql);
  223 + return data;
  224 + }
  225 +
142 /*** 226 /***
143 * @Author 钱豹 227 * @Author 钱豹
144 * @Date 22:24 2026/3/24 228 * @Date 22:24 2026/3/24
src/main/java/com/xly/milvus/web/MilvusController.java
@@ -45,5 +45,31 @@ public class MilvusController { @@ -45,5 +45,31 @@ public class MilvusController {
45 return ResponseEntity.ok(responseDTO); 45 return ResponseEntity.ok(responseDTO);
46 } 46 }
47 47
  48 + /***
  49 + * @Author 钱豹
  50 + * @Date 14:32 2026/2/10
  51 + * @Param [request]
  52 + * @return org.springframework.http.ResponseEntity<com.xly.tts.bean.TTSResponseDTO>
  53 + * @Description 初始化AI所有变量 热启动
  54 + **/
  55 + @PostMapping("/addGlobalAgentQuestion")
  56 + public ResponseEntity<TTSResponseDTO> addGlobalAgentQuestion(@RequestBody Map<String,Object> reqMap) {
  57 + TTSResponseDTO responseDTO = milvusService.addGlobalAgentQuestion(reqMap);
  58 + return ResponseEntity.ok(responseDTO);
  59 + }
  60 +
  61 + /***
  62 + * @Author 钱豹
  63 + * @Date 14:32 2026/2/10
  64 + * @Param [request]
  65 + * @return org.springframework.http.ResponseEntity<com.xly.tts.bean.TTSResponseDTO>
  66 + * @Description 初始化全局SQL
  67 + **/
  68 + @PostMapping("/initGlobalAgentQuestion")
  69 + public ResponseEntity<TTSResponseDTO> initGlobalAgentQuestion(@RequestBody Map<String,Object> reqMap) {
  70 + TTSResponseDTO responseDTO = milvusService.initGlobalAgentQuestion(reqMap);
  71 + return ResponseEntity.ok(responseDTO);
  72 + }
  73 +
48 74
49 } 75 }
50 \ No newline at end of file 76 \ No newline at end of file
src/main/java/com/xly/ocr/service/OcrService.java
1 package com.xly.ocr.service; 1 package com.xly.ocr.service;
2 2
  3 +import com.xly.ocr.util.OcrUtil;
  4 +import lombok.extern.slf4j.Slf4j;
3 import net.sourceforge.tess4j.Tesseract; 5 import net.sourceforge.tess4j.Tesseract;
4 import net.sourceforge.tess4j.TesseractException; 6 import net.sourceforge.tess4j.TesseractException;
5 import org.slf4j.Logger; 7 import org.slf4j.Logger;
@@ -18,11 +20,16 @@ import java.nio.file.Path; @@ -18,11 +20,16 @@ import java.nio.file.Path;
18 import java.util.Arrays; 20 import java.util.Arrays;
19 import java.util.List; 21 import java.util.List;
20 22
21 -@Service 23 +@Slf4j
  24 +@Service("ocrService")
22 public class OcrService { 25 public class OcrService {
23 26
24 private static final Logger logger = LoggerFactory.getLogger(OcrService.class); 27 private static final Logger logger = LoggerFactory.getLogger(OcrService.class);
25 28
  29 + @Value("${ocr.tmpPath}")
  30 + private String tmpPath;
  31 +
  32 +
26 private final Tesseract tesseract; 33 private final Tesseract tesseract;
27 34
28 // 配置参数 35 // 配置参数
@@ -457,28 +464,8 @@ public class OcrService { @@ -457,28 +464,8 @@ public class OcrService {
457 logger.warn("不支持的文件格式: {}", originalFilename); 464 logger.warn("不支持的文件格式: {}", originalFilename);
458 return "不支持的文件格式,仅支持: " + String.join(", ", ALLOWED_EXTENSIONS); 465 return "不支持的文件格式,仅支持: " + String.join(", ", ALLOWED_EXTENSIONS);
459 } 466 }
460 -  
461 - Path tempFile = null;  
462 - try {  
463 - // 创建临时文件  
464 - String suffix = getFileExtension(originalFilename);  
465 - tempFile = Files.createTempFile("ocr_", suffix);  
466 - file.transferTo(tempFile.toFile());  
467 -  
468 - logger.info("临时文件创建成功: {}", tempFile);  
469 -  
470 - // 执行 OCR  
471 - String result = extractText(tempFile.toFile());  
472 -  
473 - return result;  
474 -  
475 - } catch (IOException e) {  
476 - logger.error("文件处理失败: {}", e.getMessage(), e);  
477 - return "文件处理失败: " + e.getMessage();  
478 - } finally {  
479 - // 清理临时文件  
480 - cleanupTempFile(tempFile);  
481 - } 467 + String sText = OcrUtil.ocrFile(file,tmpPath);
  468 + return sText;
482 } 469 }
483 470
484 /** 471 /**
src/main/java/com/xly/ocr/test/Test.java renamed to src/main/java/com/xly/ocr/util/OcrUtil.java
1 -package com.xly.ocr.test; 1 +package com.xly.ocr.util;
2 2
  3 +import cn.hutool.core.io.FileUtil;
  4 +import cn.hutool.core.util.StrUtil;
3 import com.benjaminwan.ocrlibrary.OcrResult; 5 import com.benjaminwan.ocrlibrary.OcrResult;
4 import com.benjaminwan.ocrlibrary.TextBlock; 6 import com.benjaminwan.ocrlibrary.TextBlock;
5 import io.github.mymonstercat.Model; 7 import io.github.mymonstercat.Model;
6 import io.github.mymonstercat.ocr.InferenceEngine; 8 import io.github.mymonstercat.ocr.InferenceEngine;
7 import io.github.mymonstercat.ocr.config.ParamConfig; 9 import io.github.mymonstercat.ocr.config.ParamConfig;
  10 +import lombok.extern.slf4j.Slf4j;
  11 +import org.springframework.web.multipart.MultipartFile;
8 12
9 import javax.imageio.ImageIO; 13 import javax.imageio.ImageIO;
10 import java.awt.*; 14 import java.awt.*;
@@ -13,7 +17,8 @@ import java.io.File; @@ -13,7 +17,8 @@ import java.io.File;
13 import java.io.IOException; 17 import java.io.IOException;
14 import java.util.List; 18 import java.util.List;
15 19
16 -public class Test { 20 +@Slf4j
  21 +public class OcrUtil {
17 22
18 static { 23 static {
19 try { 24 try {
@@ -35,71 +40,64 @@ public class Test { @@ -35,71 +40,64 @@ public class Test {
35 } 40 }
36 } 41 }
37 42
38 - public static void main(String[] args) { 43 + public static String ocrFile(MultipartFile imageFile, String sTmpPath){
  44 + String processedImagePath = StrUtil.EMPTY;
39 try { 45 try {
40 - System.out.println("OCR 程序开始执行...");  
41 - 46 + log.info("OCR 程序开始执行...");
42 // 1. 初始化引擎(使用 v4 模型) 47 // 1. 初始化引擎(使用 v4 模型)
43 - System.out.println("正在初始化 OCR 引擎 (PP-OCRv4)..."); 48 + log.info("正在初始化 OCR 引擎 (PP-OCRv4)...");
44 InferenceEngine engine = InferenceEngine.getInstance(Model.ONNX_PPOCR_V4); 49 InferenceEngine engine = InferenceEngine.getInstance(Model.ONNX_PPOCR_V4);
45 -  
46 // 2. 创建优化的参数配置 50 // 2. 创建优化的参数配置
47 ParamConfig config = createOptimizedParamConfig(); 51 ParamConfig config = createOptimizedParamConfig();
48 -  
49 - // 3. 图片路径  
50 - String imagePath = "E:/aa/b.jpg";  
51 - File imageFile = new File(imagePath);  
52 - if (!imageFile.exists()) {  
53 - System.err.println("图片文件不存在: " + imagePath);  
54 - return;  
55 - }  
56 -  
57 // 4. 图像预处理(直接处理原图,不保存临时文件) 52 // 4. 图像预处理(直接处理原图,不保存临时文件)
58 System.out.println("正在进行图像预处理..."); 53 System.out.println("正在进行图像预处理...");
59 - BufferedImage processedImage = preprocessImage(imageFile);  
60 - 54 + File file = multipartFileToFile(imageFile);
  55 + BufferedImage processedImage = preprocessImage(file);
61 // 5. 保存预处理后的图片到临时目录 56 // 5. 保存预处理后的图片到临时目录
62 - String processedImagePath = "D:/temp/ocrJava/processed_" + System.currentTimeMillis() + ".png"; 57 + if(!FileUtil.exist(sTmpPath)){
  58 + FileUtil.mkdir(sTmpPath);
  59 + }
  60 + processedImagePath = sTmpPath+"/processed_" + System.currentTimeMillis() + ".png";
63 ImageIO.write(processedImage, "png", new File(processedImagePath)); 61 ImageIO.write(processedImage, "png", new File(processedImagePath));
64 - System.out.println("预处理图片已保存: " + processedImagePath);  
65 - 62 + log.info("预处理图片已保存: " + processedImagePath);
66 // 6. 执行识别 63 // 6. 执行识别
67 - System.out.println("开始识别图片..."); 64 + log.info("开始识别图片...");
68 long startTime = System.currentTimeMillis(); 65 long startTime = System.currentTimeMillis();
69 OcrResult ocrResult = engine.runOcr(processedImagePath, config); 66 OcrResult ocrResult = engine.runOcr(processedImagePath, config);
70 long endTime = System.currentTimeMillis(); 67 long endTime = System.currentTimeMillis();
71 -  
72 // 7. 输出结果 68 // 7. 输出结果
73 String text = ocrResult.getStrRes().trim(); 69 String text = ocrResult.getStrRes().trim();
74 - System.out.println("\n==================================");  
75 - System.out.println("识别结果:");  
76 - System.out.println(text);  
77 - System.out.println("==================================");  
78 - System.out.println("识别耗时: " + (endTime - startTime) + " ms");  
79 - 70 + log.info("\n==================================");
  71 + log.info("识别结果:");
  72 + log.info(text);
  73 + log.info("==================================");
  74 + log.info("识别耗时: " + (endTime - startTime) + " ms");
80 // 8. 输出每个文本块 75 // 8. 输出每个文本块
81 - if (ocrResult.getTextBlocks() != null && !ocrResult.getTextBlocks().isEmpty()) {  
82 - System.out.println("\n文本块详情(共" + ocrResult.getTextBlocks().size() + "块):");  
83 - List<TextBlock> textBlocks = ocrResult.getTextBlocks();  
84 - for (int i = 0; i < textBlocks.size(); i++) {  
85 - TextBlock block = textBlocks.get(i);  
86 - System.out.printf(" 块%d: %s (置信度: %.2f)%n",  
87 - i + 1,  
88 - block.getText(),  
89 - block.getBoxScore()  
90 - );  
91 - }  
92 - }  
93 -  
94 - // 9. 清理临时文件  
95 - new File(processedImagePath).delete(); 76 +// if (ocrResult.getTextBlocks() != null && !ocrResult.getTextBlocks().isEmpty()) {
  77 +// System.out.println("\n文本块详情(共" + ocrResult.getTextBlocks().size() + "块):");
  78 +// List<TextBlock> textBlocks = ocrResult.getTextBlocks();
  79 +// for (int i = 0; i < textBlocks.size(); i++) {
  80 +// TextBlock block = textBlocks.get(i);
  81 +// System.out.printf(" 块%d: %s (置信度: %.2f)%n",
  82 +// i + 1,
  83 +// block.getText(),
  84 +// block.getBoxScore()
  85 +// );
  86 +// }
  87 +// }
  88 + return text;
96 89
97 } catch (Exception e) { 90 } catch (Exception e) {
98 System.err.println("OCR 识别失败: " + e.getMessage()); 91 System.err.println("OCR 识别失败: " + e.getMessage());
99 e.printStackTrace(); 92 e.printStackTrace();
  93 + }finally {
  94 + // 9. 清理临时文件
  95 + FileUtil.del(processedImagePath);
100 } 96 }
  97 + return StrUtil.EMPTY;
101 } 98 }
102 99
  100 +
103 /** 101 /**
104 * 优化的参数配置 102 * 优化的参数配置
105 */ 103 */
@@ -142,6 +140,20 @@ public class Test { @@ -142,6 +140,20 @@ public class Test {
142 140
143 return processed; 141 return processed;
144 } 142 }
  143 + /***
  144 + * @Author 钱豹
  145 + * @Date 11:01 2026/4/1
  146 + * @Param [multipartFile]
  147 + * @return java.io.File
  148 + * @Description 图片对象转换
  149 + **/
  150 + public static File multipartFileToFile(MultipartFile multipartFile) throws IOException {
  151 + // 创建临时文件
  152 + File file = File.createTempFile("temp", null);
  153 + // 将 MultipartFile 的内容传输到 File
  154 + multipartFile.transferTo(file);
  155 + return file;
  156 + }
145 157
146 /** 158 /**
147 * 调整图片大小 159 * 调整图片大小
@@ -179,4 +191,69 @@ public class Test { @@ -179,4 +191,69 @@ public class Test {
179 } 191 }
180 return result; 192 return result;
181 } 193 }
  194 +
  195 + public static void main(String[] args) {
  196 + try {
  197 + System.out.println("OCR 程序开始执行...");
  198 +
  199 + // 1. 初始化引擎(使用 v4 模型)
  200 + System.out.println("正在初始化 OCR 引擎 (PP-OCRv4)...");
  201 + InferenceEngine engine = InferenceEngine.getInstance(Model.ONNX_PPOCR_V4);
  202 +
  203 + // 2. 创建优化的参数配置
  204 + ParamConfig config = createOptimizedParamConfig();
  205 +
  206 + // 3. 图片路径
  207 + String imagePath = "E:/aa/b.jpg";
  208 + File imageFile = new File(imagePath);
  209 + if (!imageFile.exists()) {
  210 + System.err.println("图片文件不存在: " + imagePath);
  211 + return;
  212 + }
  213 +
  214 + // 4. 图像预处理(直接处理原图,不保存临时文件)
  215 + System.out.println("正在进行图像预处理...");
  216 + BufferedImage processedImage = preprocessImage(imageFile);
  217 +
  218 + // 5. 保存预处理后的图片到临时目录
  219 + String processedImagePath = "D:/temp/ocrJava/processed_" + System.currentTimeMillis() + ".png";
  220 + ImageIO.write(processedImage, "png", new File(processedImagePath));
  221 + System.out.println("预处理图片已保存: " + processedImagePath);
  222 +
  223 + // 6. 执行识别
  224 + System.out.println("开始识别图片...");
  225 + long startTime = System.currentTimeMillis();
  226 + OcrResult ocrResult = engine.runOcr(processedImagePath, config);
  227 + long endTime = System.currentTimeMillis();
  228 +
  229 + // 7. 输出结果
  230 + String text = ocrResult.getStrRes().trim();
  231 + System.out.println("\n==================================");
  232 + System.out.println("识别结果:");
  233 + System.out.println(text);
  234 + System.out.println("==================================");
  235 + System.out.println("识别耗时: " + (endTime - startTime) + " ms");
  236 +
  237 + // 8. 输出每个文本块
  238 + if (ocrResult.getTextBlocks() != null && !ocrResult.getTextBlocks().isEmpty()) {
  239 + System.out.println("\n文本块详情(共" + ocrResult.getTextBlocks().size() + "块):");
  240 + List<TextBlock> textBlocks = ocrResult.getTextBlocks();
  241 + for (int i = 0; i < textBlocks.size(); i++) {
  242 + TextBlock block = textBlocks.get(i);
  243 + System.out.printf(" 块%d: %s (置信度: %.2f)%n",
  244 + i + 1,
  245 + block.getText(),
  246 + block.getBoxScore()
  247 + );
  248 + }
  249 + }
  250 +
  251 + // 9. 清理临时文件
  252 + new File(processedImagePath).delete();
  253 +
  254 + } catch (Exception e) {
  255 + System.err.println("OCR 识别失败: " + e.getMessage());
  256 + e.printStackTrace();
  257 + }
  258 + }
182 } 259 }
183 \ No newline at end of file 260 \ No newline at end of file
src/main/java/com/xly/ocr/web/OcrController.java
1 -//package com.xly.ocr.web;  
2 -//  
3 -//import com.xly.ocr.service.OcrService;  
4 -//import org.springframework.beans.factory.annotation.Autowired;  
5 -//import org.springframework.http.ResponseEntity;  
6 -//import org.springframework.web.bind.annotation.*;  
7 -//import org.springframework.web.multipart.MultipartFile;  
8 -//  
9 -//import java.util.HashMap;  
10 -//import java.util.List;  
11 -//import java.util.Map;  
12 -//  
13 -//@RestController  
14 -//@RequestMapping("/api/ocr")  
15 -//public class OcrController {  
16 -//  
17 -// @Autowired  
18 -// private OcrService ocrService;  
19 -//  
20 -// @PostMapping("/extract")  
21 -// public ResponseEntity<Map<String, Object>> extractText(  
22 -// @RequestParam("file") MultipartFile file) {  
23 -//  
24 -// Map<String, Object> response = new HashMap<>();  
25 -// long startTime = System.currentTimeMillis();  
26 -//  
27 -// String result = ocrService.extractTextFromMultipartFile(file);  
28 -//  
29 -// response.put("text", result);  
30 -// response.put("time", System.currentTimeMillis() - startTime);  
31 -// response.put("success", !result.startsWith("错误") && !result.startsWith("失败"));  
32 -//  
33 -// return ResponseEntity.ok(response);  
34 -// }  
35 -//  
36 -// @PostMapping("/batch")  
37 -// public ResponseEntity<List<String>> batchExtract(  
38 -// @RequestParam("files") List<MultipartFile> files) {  
39 -// List<String> results = ocrService.batchExtractText(files);  
40 -// return ResponseEntity.ok(results);  
41 -// }  
42 -//}  
43 \ No newline at end of file 1 \ No newline at end of file
  2 +package com.xly.ocr.web;
  3 +
  4 +import com.xly.ocr.service.OcrService;
  5 +import com.xly.tts.bean.TTSResponseDTO;
  6 +import org.springframework.beans.factory.annotation.Autowired;
  7 +import org.springframework.http.ResponseEntity;
  8 +import org.springframework.web.bind.annotation.*;
  9 +import org.springframework.web.multipart.MultipartFile;
  10 +
  11 +import java.util.List;
  12 +
  13 +@RestController
  14 +@RequestMapping("/api/ocr")
  15 +public class OcrController {
  16 +
  17 + @Autowired
  18 + private OcrService ocrService;
  19 +
  20 + @PostMapping("/extract")
  21 + public ResponseEntity<TTSResponseDTO> extractText(
  22 + @RequestParam("file") MultipartFile file) {
  23 + String result = ocrService.extractTextFromMultipartFile(file);
  24 + TTSResponseDTO dto= TTSResponseDTO.builder()
  25 + .code(200)
  26 + .message("操作成功")
  27 + .processedText(result)
  28 + .build();
  29 + return ResponseEntity.ok(dto);
  30 + }
  31 +
  32 + @PostMapping("/batch")
  33 + public ResponseEntity<List<String>> batchExtract(
  34 + @RequestParam("files") List<MultipartFile> files) {
  35 + List<String> results = ocrService.batchExtractText(files);
  36 + return ResponseEntity.ok(results);
  37 + }
  38 +}
44 \ No newline at end of file 39 \ No newline at end of file
src/main/java/com/xly/service/XlyErpService.java
@@ -668,10 +668,8 @@ public class XlyErpService { @@ -668,10 +668,8 @@ public class XlyErpService {
668 //如果查询不到数据走向量库 668 //如果查询不到数据走向量库
669 if(ObjectUtil.isEmpty(sqlResult)){ 669 if(ObjectUtil.isEmpty(sqlResult)){
670 session.setDbType("X"); 670 session.setDbType("X");
671 -  
672 //数据集为空的也记录到历史问题中 671 //数据集为空的也记录到历史问题中
673 - doAiSqlErrorHistoryThread(session, cleanSql, StrUtil.EMPTY, StrUtil.EMPTY,input);  
674 - 672 + doAiSqlErrorHistoryThread(session, StrUtil.EMPTY,cleanSql, "结果为空",input);
675 return getMilvus(session, input, aiAgent,false); 673 return getMilvus(session, input, aiAgent,false);
676 } 674 }
677 // 5. 调用AI服务生成自然语言解释(传入表结构,让解释更贴合业务) 675 // 5. 调用AI服务生成自然语言解释(传入表结构,让解释更贴合业务)
@@ -679,7 +677,7 @@ public class XlyErpService { @@ -679,7 +677,7 @@ public class XlyErpService {
679 677
680 //执行正确去修改对应正确的SQl 678 //执行正确去修改对应正确的SQl
681 if(Integer.valueOf(iErroCount)>0){ 679 if(Integer.valueOf(iErroCount)>0){
682 - doAiSqlErrorHistoryThread(session, cleanSql, StrUtil.EMPTY, StrUtil.EMPTY,input); 680 + doAiSqlErrorHistoryThread(session, cleanSql, StrUtil.EMPTY, "执行正确去修改对应正确的SQl",input);
683 } 681 }
684 //插入常用操作 不包含where 条件 682 //插入常用操作 不包含where 条件
685 if(doAddSql){ 683 if(doAddSql){
@@ -733,7 +731,7 @@ public class XlyErpService { @@ -733,7 +731,7 @@ public class XlyErpService {
733 **/ 731 **/
734 private Map<String,Object> getDynamicTableCach(UserSceneSession session,String input){ 732 private Map<String,Object> getDynamicTableCach(UserSceneSession session,String input){
735 try{ 733 try{
736 - String searchText = session.getCurrentScene().getSId()+"_"+session.getCurrentTool().getSId()+input; 734 + String searchText = session.getCurrentScene().getSId()+"_"+session.getCurrentTool().getSId()+"_"+input;
737 //根据问题查询向量库 735 //根据问题查询向量库
738 Map<String,Object> serMap = aiGlobalAgentQuestionSqlEmitterService.queryAiGlobalAgentQuestionSqlEmitter(searchText, "ai_global_agent_question_sql"); 736 Map<String,Object> serMap = aiGlobalAgentQuestionSqlEmitterService.queryAiGlobalAgentQuestionSqlEmitter(searchText, "ai_global_agent_question_sql");
739 return serMap; 737 return serMap;
src/main/java/com/xly/thread/AiUserAgentQuestionThread.java
@@ -57,7 +57,7 @@ public class AiUserAgentQuestionThread implements Runnable { @@ -57,7 +57,7 @@ public class AiUserAgentQuestionThread implements Runnable {
57 // SqlValidateUtil.getsKey( sSceneId, sMethodId, SqlValidateUtil.getsQuestion(session.getSUserQuestionList())); 57 // SqlValidateUtil.getsKey( sSceneId, sMethodId, SqlValidateUtil.getsQuestion(session.getSUserQuestionList()));
58 //存入向量库 不包含where 条件 58 //存入向量库 不包含where 条件
59 if(!SqlWhereHelper.hasWhereButNoCompareOperators(sSqlContent)){ 59 if(!SqlWhereHelper.hasWhereButNoCompareOperators(sSqlContent)){
60 - aiGlobalAgentQuestionSqlEmitterService.addAiGlobalAgentQuestionSqlEmitter(sKey,data,sQuestion,sSqlContent,cachType,"ai_global_agent_question_sql"); 60 + aiGlobalAgentQuestionSqlEmitterService.addAiGlobalAgentQuestionSqlEmitter(sKey,data,sQuestion,sSqlContent,cachType,"ai_global_agent_question_sql",false);
61 } 61 }
62 //调用数据库插入数据库 62 //调用数据库插入数据库
63 Map<String, Object> searMap = dynamicExeDbService.getDoProMap(sProName, data); 63 Map<String, Object> searMap = dynamicExeDbService.getDoProMap(sProName, data);
src/main/resources/application.yml
@@ -65,6 +65,8 @@ spring: @@ -65,6 +65,8 @@ spring:
65 max-active: 8 # 连接池最大连接数 65 max-active: 8 # 连接池最大连接数
66 max-idle: 8 # 连接池最大空闲连接 66 max-idle: 8 # 连接池最大空闲连接
67 min-idle: 0 # 连接池最小空闲连接' 67 min-idle: 0 # 连接池最小空闲连接'
  68 +ocr:
  69 + tmpPath: D:/xlyweberp/ai/ocrtmp
68 70
69 milvus: 71 milvus:
70 host: 112.82.245.194 72 host: 112.82.245.194