提取功能改为异步实现,添加ai辅助提取状态
This commit is contained in:
@@ -1,33 +1,30 @@
|
||||
package com.label.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.label.common.ai.AiServiceClient;
|
||||
import com.label.common.exception.BusinessException;
|
||||
import com.label.common.auth.TokenPrincipal;
|
||||
import com.label.common.statemachine.StateValidator;
|
||||
import com.label.common.statemachine.TaskStatus;
|
||||
import com.label.entity.AnnotationResult;
|
||||
import com.label.entity.TrainingDataset;
|
||||
import com.label.event.ExtractionApprovedEvent;
|
||||
import com.label.mapper.AnnotationResultMapper;
|
||||
import com.label.mapper.TrainingDatasetMapper;
|
||||
import com.label.entity.SourceData;
|
||||
import com.label.mapper.SourceDataMapper;
|
||||
import com.label.entity.AnnotationTask;
|
||||
import com.label.mapper.AnnotationTaskMapper;
|
||||
import com.label.service.TaskClaimService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.label.common.auth.TokenPrincipal;
|
||||
import com.label.common.exception.BusinessException;
|
||||
import com.label.common.statemachine.StateValidator;
|
||||
import com.label.common.statemachine.TaskStatus;
|
||||
import com.label.entity.AnnotationResult;
|
||||
import com.label.entity.AnnotationTask;
|
||||
import com.label.entity.SourceData;
|
||||
import com.label.event.ExtractionApprovedEvent;
|
||||
import com.label.mapper.AnnotationResultMapper;
|
||||
import com.label.mapper.AnnotationTaskMapper;
|
||||
import com.label.mapper.SourceDataMapper;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 提取阶段标注服务:AI 预标注、更新结果、提交、审批、驳回。
|
||||
@@ -43,12 +40,13 @@ public class ExtractionService {
|
||||
|
||||
private final AnnotationTaskMapper taskMapper;
|
||||
private final AnnotationResultMapper resultMapper;
|
||||
private final TrainingDatasetMapper datasetMapper;
|
||||
// private final TrainingDatasetMapper datasetMapper;
|
||||
private final SourceDataMapper sourceDataMapper;
|
||||
private final TaskClaimService taskClaimService;
|
||||
private final AiServiceClient aiServiceClient;
|
||||
// private final AiServiceClient aiServiceClient;
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final AiAnnotationAsyncService aiAnnotationAsyncService; // 注入异步服务
|
||||
|
||||
@Value("${rustfs.bucket:label-source-data}")
|
||||
private String bucket;
|
||||
@@ -67,32 +65,30 @@ public class ExtractionService {
|
||||
throw new BusinessException("NOT_FOUND", "关联资料不存在", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
// 调用 AI 服务(在事务外,避免长时间持有 DB 连接)
|
||||
AiServiceClient.ExtractionRequest req = AiServiceClient.ExtractionRequest.builder()
|
||||
.sourceId(source.getId())
|
||||
.filePath(source.getFilePath())
|
||||
.bucket(bucket)
|
||||
.build();
|
||||
|
||||
AiServiceClient.ExtractionResponse aiResponse;
|
||||
try {
|
||||
if ("IMAGE".equals(source.getDataType())) {
|
||||
aiResponse = aiServiceClient.extractImage(req);
|
||||
} else {
|
||||
aiResponse = aiServiceClient.extractText(req);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("AI 预标注调用失败(任务 {}):{}", taskId, e.getMessage());
|
||||
// AI 失败不阻塞流程,写入空结果
|
||||
aiResponse = new AiServiceClient.ExtractionResponse();
|
||||
aiResponse.setItems(Collections.emptyList());
|
||||
if (source.getFilePath() == null || source.getFilePath().isEmpty()) {
|
||||
throw new BusinessException("INVALID_SOURCE", "源文件路径不能为空", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
// 将 AI 结果写入 annotation_result(UPSERT 语义)
|
||||
writeOrUpdateResult(taskId, principal.getCompanyId(), aiResponse.getItems());
|
||||
}
|
||||
if (source.getDataType() == null || source.getDataType().isEmpty()) {
|
||||
throw new BusinessException("INVALID_SOURCE", "数据类型不能为空", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ 更新结果 --
|
||||
String dataType = source.getDataType().toUpperCase();
|
||||
if (!"IMAGE".equals(dataType) && !"TEXT".equals(dataType)) {
|
||||
log.warn("不支持的数据类型: {}, 任务ID: {}", dataType, taskId);
|
||||
throw new BusinessException("UNSUPPORTED_TYPE",
|
||||
"不支持的数据类型: " + dataType, HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
// 更新任务状态为 PROCESSING
|
||||
taskMapper.update(null, new LambdaUpdateWrapper<AnnotationTask>()
|
||||
.eq(AnnotationTask::getId, taskId)
|
||||
.set(AnnotationTask::getAiStatus, "PROCESSING"));
|
||||
|
||||
// 触发异步任务
|
||||
aiAnnotationAsyncService.processAnnotation(taskId, principal.getCompanyId(), source);
|
||||
// executeAiAnnotationAsync(taskId, principal.getCompanyId(), source);
|
||||
}
|
||||
|
||||
/**
|
||||
* 人工更新标注结果(整体覆盖,PUT 语义)。
|
||||
@@ -237,8 +233,7 @@ public class ExtractionService {
|
||||
"sourceType", source != null ? source.getDataType() : "",
|
||||
"sourceFilePath", source != null && source.getFilePath() != null ? source.getFilePath() : "",
|
||||
"isFinal", task.getIsFinal() != null && task.getIsFinal(),
|
||||
"resultJson", result != null ? result.getResultJson() : "[]"
|
||||
);
|
||||
"resultJson", result != null ? result.getResultJson() : "[]");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ 私有工具 --
|
||||
@@ -253,20 +248,4 @@ public class ExtractionService {
|
||||
}
|
||||
return task;
|
||||
}
|
||||
|
||||
private void writeOrUpdateResult(Long taskId, Long companyId, java.util.List<?> items) {
|
||||
try {
|
||||
String json = objectMapper.writeValueAsString(Map.of("items", items != null ? items : Collections.emptyList()));
|
||||
int updated = resultMapper.updateResultJson(taskId, json, companyId);
|
||||
if (updated == 0) {
|
||||
AnnotationResult result = new AnnotationResult();
|
||||
result.setTaskId(taskId);
|
||||
result.setCompanyId(companyId);
|
||||
result.setResultJson(json);
|
||||
resultMapper.insert(result);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("写入 AI 预标注结果失败: taskId={}", taskId, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user