|
@@ -668,92 +668,86 @@ public class TakaiAiServiceImpl implements ITakaiAiService {
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- @Override
|
|
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 异步上传文档,analysisFile最大并发5个
|
|
* 异步上传文档,analysisFile最大并发5个
|
|
|
* @return 成功处理的文件数量
|
|
* @return 成功处理的文件数量
|
|
|
*/
|
|
*/
|
|
|
- public CompletableFuture<Integer> uploadDocument(MultipartFile[] files, String knowledgeId) {
|
|
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public CompletableFuture<Integer> uploadDocument(MultipartFile[] files, String knowledgeId,List<TakaiSysOss> ossList,String updateBy) {
|
|
|
|
|
+ // 2. 循环处理每个文件
|
|
|
|
|
+ List<TakaiDocument> takaiDocuments = new ArrayList<>();
|
|
|
|
|
+ for (int i = 0; i < ossList.size(); i++) {
|
|
|
|
|
+ TakaiSysOss oss = ossList.get(i);
|
|
|
|
|
+ // 生成文档ID
|
|
|
|
|
+ SnowflakeDigitGenerator documentIdGenerator = new SnowflakeDigitGenerator(i, i);
|
|
|
|
|
+ long documentId = documentIdGenerator.nextId();
|
|
|
|
|
+ String docId = "a" + documentId;
|
|
|
|
|
+ // 构建上传参数
|
|
|
|
|
+ UploadDocumentParams param = new UploadDocumentParams();
|
|
|
|
|
+ param.setDocument_id(docId);
|
|
|
|
|
+ param.setName(oss.getOriginalName());
|
|
|
|
|
+ param.setUrl(oss.getUrl());
|
|
|
|
|
+ List<UploadDocumentParams> params = new ArrayList<>();
|
|
|
|
|
+ params.add(param);
|
|
|
|
|
+ // 3. 同步保存OSS到数据库
|
|
|
|
|
+ takaiSysOssMapper.insertSysOss(oss);
|
|
|
|
|
+ // 4. 保存文档信息到数据库
|
|
|
|
|
+ TakaiDocument document = TakaiDocument.builder()
|
|
|
|
|
+ .documentId(docId)
|
|
|
|
|
+ .knowledgeId(knowledgeId)
|
|
|
|
|
+ .customSeparator(String.format("[\"%s\"", "\\n") + "]")
|
|
|
|
|
+ .sentenceSize("300")
|
|
|
|
|
+ .name(oss.getOriginalName())
|
|
|
|
|
+ .url(oss.getUrl())
|
|
|
|
|
+ .status("0")
|
|
|
|
|
+ .build();
|
|
|
|
|
+ document.setCreateBy(updateBy);
|
|
|
|
|
+ int insertResult = takaiDocumentMapper.insertDocument(document);
|
|
|
|
|
+ takaiDocuments.add(document);
|
|
|
|
|
+ // 5. 保存文档设置
|
|
|
|
|
+ if (insertResult > 0) {
|
|
|
|
|
+ SnowflakeDigitGenerator settingsIdGenerator = new SnowflakeDigitGenerator(1, 1);
|
|
|
|
|
+ long settingsId = settingsIdGenerator.nextId();
|
|
|
|
|
+ TakaiDocumentSettings dSettings = new TakaiDocumentSettings();
|
|
|
|
|
+ dSettings.setId(String.valueOf(settingsId));
|
|
|
|
|
+ dSettings.setKnowledgeId(knowledgeId);
|
|
|
|
|
+ dSettings.setDocumentId(docId);
|
|
|
|
|
+ dSettings.setSetSlice("0"); // 默认 按标题段落切片
|
|
|
|
|
+ dSettings.setSetAnalyze("1"); // 默认 图片转换成标识符
|
|
|
|
|
+ dSettings.setSetTable("0"); // 默认 table转图片
|
|
|
|
|
+ takaiDocumentSettingsMapper.insertDocumentSettings(dSettings);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
// 整体逻辑异步执行(默认使用ForkJoinPool,也可指定自定义线程池)
|
|
// 整体逻辑异步执行(默认使用ForkJoinPool,也可指定自定义线程池)
|
|
|
return CompletableFuture.supplyAsync(() -> {
|
|
return CompletableFuture.supplyAsync(() -> {
|
|
|
// 记录成功处理的文件数
|
|
// 记录成功处理的文件数
|
|
|
AtomicInteger successCount = new AtomicInteger(0);
|
|
AtomicInteger successCount = new AtomicInteger(0);
|
|
|
// 收集analysisFile的异步任务,用于等待全部完成
|
|
// 收集analysisFile的异步任务,用于等待全部完成
|
|
|
List<CompletableFuture<Void>> analysisTasks = new ArrayList<>();
|
|
List<CompletableFuture<Void>> analysisTasks = new ArrayList<>();
|
|
|
-
|
|
|
|
|
- // 1. 先同步上传文件到MinIO(IO操作,建议后续也异步,这里先保留)
|
|
|
|
|
- List<TakaiSysOss> ossList;
|
|
|
|
|
- try {
|
|
|
|
|
- ossList = minioUtil.uploadMultiple(files);
|
|
|
|
|
- if (ossList == null || ossList.isEmpty()) {
|
|
|
|
|
- log.error("MinIO上传文件为空,直接返回");
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.error("MinIO上传文件失败", e);
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
// 2. 循环处理每个文件
|
|
// 2. 循环处理每个文件
|
|
|
- String updateBy = SecurityUtils.getLoginUser() == null ? "" : SecurityUtils.getLoginUser().getUserId();
|
|
|
|
|
- for (int i = 0; i < ossList.size(); i++) {
|
|
|
|
|
- TakaiSysOss oss = ossList.get(i);
|
|
|
|
|
|
|
+ for (int i = 0; i < takaiDocuments.size(); i++) {
|
|
|
|
|
+ TakaiDocument document = takaiDocuments.get(i);
|
|
|
try {
|
|
try {
|
|
|
- // 生成文档ID
|
|
|
|
|
- SnowflakeDigitGenerator documentIdGenerator = new SnowflakeDigitGenerator(i, i);
|
|
|
|
|
- long documentId = documentIdGenerator.nextId();
|
|
|
|
|
- String docId = "a" + documentId;
|
|
|
|
|
-
|
|
|
|
|
// 构建上传参数
|
|
// 构建上传参数
|
|
|
UploadDocumentParams param = new UploadDocumentParams();
|
|
UploadDocumentParams param = new UploadDocumentParams();
|
|
|
- param.setDocument_id(docId);
|
|
|
|
|
- param.setName(oss.getOriginalName());
|
|
|
|
|
- param.setUrl(oss.getUrl());
|
|
|
|
|
|
|
+ param.setDocument_id(document.getDocumentId());
|
|
|
|
|
+ param.setName(document.getName());
|
|
|
|
|
+ param.setUrl(document.getUrl());
|
|
|
List<UploadDocumentParams> params = new ArrayList<>();
|
|
List<UploadDocumentParams> params = new ArrayList<>();
|
|
|
params.add(param);
|
|
params.add(param);
|
|
|
-
|
|
|
|
|
- // 3. 同步保存OSS到数据库
|
|
|
|
|
- takaiSysOssMapper.insertSysOss(oss);
|
|
|
|
|
-
|
|
|
|
|
- // 4. 保存文档信息到数据库
|
|
|
|
|
- TakaiDocument document = TakaiDocument.builder()
|
|
|
|
|
- .documentId(docId)
|
|
|
|
|
- .knowledgeId(knowledgeId)
|
|
|
|
|
- .customSeparator(String.format("[\"%s\"", "\\n") + "]")
|
|
|
|
|
- .sentenceSize("300")
|
|
|
|
|
- .name(oss.getOriginalName())
|
|
|
|
|
- .url(oss.getUrl())
|
|
|
|
|
- .status("0")
|
|
|
|
|
- .build();
|
|
|
|
|
- document.setCreateBy(updateBy);
|
|
|
|
|
- int insertResult = takaiDocumentMapper.insertDocument(document);
|
|
|
|
|
-
|
|
|
|
|
- // 5. 保存文档设置
|
|
|
|
|
- if (insertResult > 0) {
|
|
|
|
|
- SnowflakeDigitGenerator settingsIdGenerator = new SnowflakeDigitGenerator(1, 1);
|
|
|
|
|
- long settingsId = settingsIdGenerator.nextId();
|
|
|
|
|
- TakaiDocumentSettings dSettings = new TakaiDocumentSettings();
|
|
|
|
|
- dSettings.setId(String.valueOf(settingsId));
|
|
|
|
|
- dSettings.setKnowledgeId(knowledgeId);
|
|
|
|
|
- dSettings.setDocumentId(docId);
|
|
|
|
|
- dSettings.setSetSlice("0"); // 默认 按标题段落切片
|
|
|
|
|
- dSettings.setSetAnalyze("1"); // 默认 图片转换成标识符
|
|
|
|
|
- dSettings.setSetTable("0"); // 默认 table转图片
|
|
|
|
|
- takaiDocumentSettingsMapper.insertDocumentSettings(dSettings);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
// 6. 异步调用analysisFile(限制5个并发)
|
|
// 6. 异步调用analysisFile(限制5个并发)
|
|
|
TakaiDocumentSettings settings = new TakaiDocumentSettings();
|
|
TakaiDocumentSettings settings = new TakaiDocumentSettings();
|
|
|
settings.setKnowledgeId(knowledgeId);
|
|
settings.setKnowledgeId(knowledgeId);
|
|
|
|
|
+ settings.setCreateBy(updateBy);
|
|
|
// 注意:捕获循环变量,避免闭包陷阱
|
|
// 注意:捕获循环变量,避免闭包陷阱
|
|
|
List<UploadDocumentParams> finalParams = new ArrayList<>(params);
|
|
List<UploadDocumentParams> finalParams = new ArrayList<>(params);
|
|
|
CompletableFuture<Void> analysisTask = CompletableFuture.runAsync(() -> {
|
|
CompletableFuture<Void> analysisTask = CompletableFuture.runAsync(() -> {
|
|
|
try {
|
|
try {
|
|
|
// 执行文件解析逻辑
|
|
// 执行文件解析逻辑
|
|
|
analysisFile(finalParams, settings, "upload");
|
|
analysisFile(finalParams, settings, "upload");
|
|
|
- log.info("文件解析完成:{}", oss.getOriginalName());
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
- log.error("文件解析失败:{}", oss.getOriginalName(), e);
|
|
|
|
|
|
|
+ log.error("文件解析失败:{}", e);
|
|
|
}
|
|
}
|
|
|
}, analysisFileExecutor); // 使用5线程池执行
|
|
}, analysisFileExecutor); // 使用5线程池执行
|
|
|
|
|
|
|
@@ -762,7 +756,7 @@ public class TakaiAiServiceImpl implements ITakaiAiService {
|
|
|
successCount.incrementAndGet();
|
|
successCount.incrementAndGet();
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
- log.error("处理文件失败:{}", oss.getOriginalName(), e);
|
|
|
|
|
|
|
+ log.error("处理文件失败:{}", e);
|
|
|
// 单个文件失败不影响其他文件,继续处理
|
|
// 单个文件失败不影响其他文件,继续处理
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
@@ -939,6 +933,62 @@ public class TakaiAiServiceImpl implements ITakaiAiService {
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public int delUnfinishedDocument(String documentId) {
|
|
|
|
|
+ TakaiDocument vo = takaiDocumentMapper.selectTargetDocument(TakaiDocument.builder().documentId(documentId).build());
|
|
|
|
|
+ if(vo != null){
|
|
|
|
|
+ String url = deepseekConfig.getBaseurl() + deepseekConfig.getCancelTask() + "/" + documentId ;
|
|
|
|
|
+ JSONObject json = new JSONObject();
|
|
|
|
|
+ //重新设置knowledgeIds为数组
|
|
|
|
|
+ json.put("documentId",documentId);
|
|
|
|
|
+
|
|
|
|
|
+ RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), json.toJSONString());
|
|
|
|
|
+ Request request = buildPostRequest(url,requestBody);
|
|
|
|
|
+ OkHttpClient client = buildOkHttpClient();
|
|
|
|
|
+ try {
|
|
|
|
|
+ Response response = client.newCall(request).execute();
|
|
|
|
|
+ if (response.isSuccessful()) {
|
|
|
|
|
+ String body = response.body().string();
|
|
|
|
|
+ logger.info("删除知识文件调用python接口返回结果:{}", body);
|
|
|
|
|
+ JSONObject obj = JSON.parseObject(body);
|
|
|
|
|
+ Integer code = obj.getInteger("code");
|
|
|
|
|
+ if (code == 200) {
|
|
|
|
|
+ List<TakaiMediaReplacement> list = takaiMediaReplacementMapper.selectMediaList(TakaiMediaReplacement.builder().documentId(documentId).build());
|
|
|
|
|
+
|
|
|
|
|
+ // 删除图片
|
|
|
|
|
+ takaiMediaReplacementMapper.deleteMedia(documentId);
|
|
|
|
|
+
|
|
|
|
|
+ // 删除document文件
|
|
|
|
|
+ int i = takaiDocumentMapper.delDocument(documentId);
|
|
|
|
|
+
|
|
|
|
|
+ if(i > 0){
|
|
|
|
|
+ //更新知识库
|
|
|
|
|
+ updateKnowledgeSize(vo.getKnowledgeId());
|
|
|
|
|
+ // 删除minio文件
|
|
|
|
|
+ try {
|
|
|
|
|
+ logger.info("删除minio文件");
|
|
|
|
|
+ minioUtil.remove("deepseek-doc", "/"+vo.getName());
|
|
|
|
|
+ if(list != null && list.size() > 0){
|
|
|
|
|
+ for (int k=1; k<=list.size(); k++ ) {
|
|
|
|
|
+ logger.info("删除minio图片{}", k);
|
|
|
|
|
+ minioUtil.remove("deepseek-doc" , "/pdf/"+vo.getKnowledgeId()+"/"+documentId+"/【示意图序号_"+documentId+"_"+k+"】.jpg");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ logger.error("删除minion文件失败", e.getMessage());
|
|
|
|
|
+ throw new RuntimeException(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ return i;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
|
+ logger.error("删除知识文件调用python接口失败", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
@Override
|
|
@Override
|
|
|
public void uploadUrl(TakaiDocumentObject object) {
|
|
public void uploadUrl(TakaiDocumentObject object) {
|
|
|
|
|
|
|
@@ -1239,6 +1289,7 @@ public class TakaiAiServiceImpl implements ITakaiAiService {
|
|
|
settings.setSliceValue(documentSettings.getSliceValue());
|
|
settings.setSliceValue(documentSettings.getSliceValue());
|
|
|
settings.setSetAnalyze(documentSettings.getSetAnalyze());
|
|
settings.setSetAnalyze(documentSettings.getSetAnalyze());
|
|
|
settings.setSetTable(documentSettings.getSetTable());
|
|
settings.setSetTable(documentSettings.getSetTable());
|
|
|
|
|
+ settings.setCreateBy(SecurityUtils.getUserId());
|
|
|
TakaiDocument document = takaiDocumentMapper.selectTargetDocument(TakaiDocument.builder().documentId(documentId).build());
|
|
TakaiDocument document = takaiDocumentMapper.selectTargetDocument(TakaiDocument.builder().documentId(documentId).build());
|
|
|
List<UploadDocumentParams> listParams = new ArrayList<>();
|
|
List<UploadDocumentParams> listParams = new ArrayList<>();
|
|
|
if (document != null) {
|
|
if (document != null) {
|
|
@@ -1787,6 +1838,7 @@ public class TakaiAiServiceImpl implements ITakaiAiService {
|
|
|
JSONObject json = new JSONObject();
|
|
JSONObject json = new JSONObject();
|
|
|
json.put("knowledge_id", settings.getKnowledgeId());
|
|
json.put("knowledge_id", settings.getKnowledgeId());
|
|
|
json.put("docs", result);
|
|
json.put("docs", result);
|
|
|
|
|
+ json.put("userId",settings.getCreateBy());
|
|
|
if ("upload".equals(flag)) {
|
|
if ("upload".equals(flag)) {
|
|
|
json.put("set_slice", "0");
|
|
json.put("set_slice", "0");
|
|
|
json.put("slice_value", null);
|
|
json.put("slice_value", null);
|