任务管理优化

This commit is contained in:
wh
2026-04-28 20:14:14 +08:00
parent 343df65c69
commit ca81514d43
13 changed files with 291 additions and 195 deletions

View File

@@ -25,11 +25,15 @@ import com.labelsys.backend.dto.response.TaskPromptConfigResponse;
import com.labelsys.backend.entity.AnnotationTask;
import com.labelsys.backend.entity.AnnotationTaskResource;
import com.labelsys.backend.entity.SourceResource;
import com.labelsys.backend.entity.SysConfig;
import com.labelsys.backend.enums.IndustryType;
import com.labelsys.backend.enums.SourceStatus;
import com.labelsys.backend.enums.TaskStatus;
import com.labelsys.backend.enums.TaskType;
import com.labelsys.backend.mapper.AnnotationTaskMapper;
import com.labelsys.backend.mapper.AnnotationTaskResourceMapper;
import com.labelsys.backend.mapper.SourceResourceMapper;
import com.labelsys.backend.mapper.SysConfigMapper;
import com.labelsys.backend.util.IdGenerator;
import lombok.RequiredArgsConstructor;
@@ -43,44 +47,36 @@ public class AnnotationTaskService {
private final AnnotationTaskMapper annotationTaskMapper;
private final AnnotationTaskResourceMapper annotationTaskResourceMapper;
private final SourceResourceMapper sourceResourceMapper;
private final SysConfigMapper sysConfigMapper;
private final SysConfigService sysConfigService;
private final DataPermissionService dataPermissionService;
@Transactional
public AnnotationTaskResponse createTask(LoginUser currentUser, CreateAnnotationTaskRequest request) {
List<SourceResource> resources = loadAndValidateResources(currentUser, request.resourceIds());
SysConfigService.ResolvedModelConfig extractModel = sysConfigService.resolveModelConfig(currentUser, request.extractModel());
SysConfigService.ResolvedModelConfig verifyModel = sysConfigService.resolveModelConfig(currentUser, request.verifyModel());
SysConfigService.ResolvedPromptConfig extractPrompt = sysConfigService.resolvePromptConfig(currentUser, request.extractPrompt());
SysConfigService.ResolvedPromptConfig verifyPrompt = sysConfigService.resolvePromptConfig(currentUser, request.verifyPrompt());
SysConfigService.ResolvedModelConfig extractModel = sysConfigService.resolveModelConfig(currentUser,
request.extractModel());
SysConfigService.ResolvedModelConfig verifyModel = sysConfigService.resolveModelConfig(currentUser,
request.verifyModel());
SysConfigService.ResolvedPromptConfig extractPrompt = sysConfigService.resolvePromptConfig(currentUser,
request.extractPrompt());
SysConfigService.ResolvedPromptConfig verifyPrompt = sysConfigService.resolvePromptConfig(currentUser,
request.verifyPrompt());
AnnotationTask task = AnnotationTask.builder()
.id(IdGenerator.nextId())
.companyId(currentUser.companyId())
.creatorId(currentUser.userId())
.creatorRole(currentUser.role())
.taskName(request.taskName())
.industryType(defaultIndustryType(request.industryType()))
.taskType(defaultTaskType(request.taskType()))
.extractModelConfigId(extractModel.configId())
.extractModelName(extractModel.modelName())
.extractModelUrl(extractModel.modelUrl())
.extractModelApiKey(extractModel.apiKey())
.verifyModelConfigId(verifyModel.configId())
.verifyModelName(verifyModel.modelName())
.verifyModelUrl(verifyModel.modelUrl())
.verifyModelApiKey(verifyModel.apiKey())
.extractPromptConfigId(extractPrompt.configId())
.extractPrompt(extractPrompt.promptText())
.verifyPromptConfigId(verifyPrompt.configId())
.verifyPrompt(verifyPrompt.promptText())
.taskStatus(TaskStatus.PENDING.name())
.isDeleted(false)
.build();
AnnotationTask task = AnnotationTask.builder().id(IdGenerator.nextId()).companyId(currentUser.companyId())
.creatorId(currentUser.userId()).creatorRole(currentUser.role()).taskName(request.taskName())
.industryType(defaultIndustryType(request.industryType())).taskType(defaultTaskType(request.taskType()))
.extractModelConfigId(extractModel.configId()).extractModelName(extractModel.modelName())
.extractModelUrl(extractModel.modelUrl()).extractModelApiKey(extractModel.apiKey())
.verifyModelConfigId(verifyModel.configId()).verifyModelName(verifyModel.modelName())
.verifyModelUrl(verifyModel.modelUrl()).verifyModelApiKey(verifyModel.apiKey())
.extractPromptConfigId(extractPrompt.configId()).extractPrompt(extractPrompt.promptText())
.verifyPromptConfigId(verifyPrompt.configId()).verifyPrompt(verifyPrompt.promptText())
.taskStatus(TaskStatus.PENDING.name()).isDeleted(false).build();
annotationTaskMapper.insert(task);
saveTaskBindings(task.getId(), currentUser.companyId(), resources);
log.info("created annotation task, companyId={}, userId={}, taskId={}, resourceCount={}",
currentUser.companyId(), currentUser.userId(), task.getId(), resources.size());
currentUser.companyId(), currentUser.userId(), task.getId(), resources.size());
return buildTaskResponse(task, resourceIds(resources), extractModel, verifyModel, extractPrompt, verifyPrompt);
}
@@ -92,42 +88,77 @@ public class AnnotationTaskService {
}
assertTaskPermission(currentUser, task);
List<Long> currentResourceIds = normalizeIds(annotationTaskResourceMapper.listResourceIdsByTaskId(taskId));
List<Long> targetResourceIds = normalizeIds(request.resourceIds());
boolean resourcesChanged = !currentResourceIds.equals(targetResourceIds);
if (TaskStatus.RUNNING.name().equals(task.getTaskStatus()) && resourcesChanged) {
throw new BusinessException(ResultCode.CONFLICT, "运行中的任务不允许修改资源");
boolean resourcesChanged = false;
List<SourceResource> resources = null;
if (request.resourceIds() != null && !request.resourceIds().isEmpty()) {
List<Long> currentResourceIds = normalizeIds(annotationTaskResourceMapper.listResourceIdsByTaskId(taskId));
List<Long> targetResourceIds = normalizeIds(request.resourceIds());
resourcesChanged = !currentResourceIds.equals(targetResourceIds);
if (TaskStatus.RUNNING.name().equals(task.getTaskStatus()) && resourcesChanged) {
throw new BusinessException(ResultCode.CONFLICT, "运行中的任务不允许修改资源");
}
resources = loadAndValidateResources(currentUser, request.resourceIds());
}
List<SourceResource> resources = loadAndValidateResources(currentUser, request.resourceIds());
SysConfigService.ResolvedModelConfig extractModel = sysConfigService.resolveModelConfig(currentUser, request.extractModel());
SysConfigService.ResolvedModelConfig verifyModel = sysConfigService.resolveModelConfig(currentUser, request.verifyModel());
SysConfigService.ResolvedPromptConfig extractPrompt = sysConfigService.resolvePromptConfig(currentUser, request.extractPrompt());
SysConfigService.ResolvedPromptConfig verifyPrompt = sysConfigService.resolvePromptConfig(currentUser, request.verifyPrompt());
SysConfigService.ResolvedModelConfig extractModel = null;
SysConfigService.ResolvedModelConfig verifyModel = null;
SysConfigService.ResolvedPromptConfig extractPrompt = null;
SysConfigService.ResolvedPromptConfig verifyPrompt = null;
if (request.extractModel() != null) {
extractModel = sysConfigService.resolveModelConfig(currentUser, request.extractModel());
task.setExtractModelConfigId(extractModel.configId());
task.setExtractModelName(extractModel.modelName());
task.setExtractModelUrl(extractModel.modelUrl());
task.setExtractModelApiKey(extractModel.apiKey());
}
if (request.verifyModel() != null) {
verifyModel = sysConfigService.resolveModelConfig(currentUser, request.verifyModel());
task.setVerifyModelConfigId(verifyModel.configId());
task.setVerifyModelName(verifyModel.modelName());
task.setVerifyModelUrl(verifyModel.modelUrl());
task.setVerifyModelApiKey(verifyModel.apiKey());
}
if (request.extractPrompt() != null) {
extractPrompt = sysConfigService.resolvePromptConfig(currentUser, request.extractPrompt());
task.setExtractPromptConfigId(extractPrompt.configId());
task.setExtractPrompt(extractPrompt.promptText());
}
if (request.verifyPrompt() != null) {
verifyPrompt = sysConfigService.resolvePromptConfig(currentUser, request.verifyPrompt());
task.setVerifyPromptConfigId(verifyPrompt.configId());
task.setVerifyPrompt(verifyPrompt.promptText());
}
if (request.industryType() != null) {
task.setIndustryType(request.industryType());
}
if (request.taskType() != null) {
task.setTaskType(request.taskType());
}
task.setIndustryType(defaultIndustryType(request.industryType()));
task.setTaskType(defaultTaskType(request.taskType()));
task.setExtractModelConfigId(extractModel.configId());
task.setExtractModelName(extractModel.modelName());
task.setExtractModelUrl(extractModel.modelUrl());
task.setExtractModelApiKey(extractModel.apiKey());
task.setVerifyModelConfigId(verifyModel.configId());
task.setVerifyModelName(verifyModel.modelName());
task.setVerifyModelUrl(verifyModel.modelUrl());
task.setVerifyModelApiKey(verifyModel.apiKey());
task.setExtractPromptConfigId(extractPrompt.configId());
task.setExtractPrompt(extractPrompt.promptText());
task.setVerifyPromptConfigId(verifyPrompt.configId());
task.setVerifyPrompt(verifyPrompt.promptText());
annotationTaskMapper.updateById(task);
if (resourcesChanged) {
if (resourcesChanged && resources != null) {
annotationTaskResourceMapper.deleteByTaskId(taskId);
saveTaskBindings(taskId, currentUser.companyId(), resources);
}
log.info("updated annotation task, companyId={}, userId={}, taskId={}, resourcesChanged={}",
currentUser.companyId(), currentUser.userId(), taskId, resourcesChanged);
return buildTaskResponse(task, resourceIds(resources), extractModel, verifyModel, extractPrompt, verifyPrompt);
currentUser.companyId(), currentUser.userId(), taskId, resourcesChanged);
List<Long> finalResourceIds = resources != null ? resourceIds(resources)
: normalizeIds(annotationTaskResourceMapper.listResourceIdsByTaskId(taskId));
if (extractModel == null || verifyModel == null || extractPrompt == null || verifyPrompt == null) {
return buildTaskResponse(task, finalResourceIds);
}
return buildTaskResponse(task, finalResourceIds, extractModel, verifyModel, extractPrompt, verifyPrompt);
}
public AnnotationTaskResponse getTask(LoginUser currentUser, Long taskId) {
@@ -142,33 +173,35 @@ public class AnnotationTaskService {
public PageResult<AnnotationTaskResponse> pageTasks(LoginUser currentUser, AnnotationTaskPageQuery query) {
List<String> allowedRoles = dataPermissionService.getAllowedRoles(currentUser);
boolean shouldFilterByUserId = dataPermissionService.shouldFilterByUserId(currentUser);
LambdaQueryWrapper<AnnotationTask> wrapper = new LambdaQueryWrapper<AnnotationTask>()
.eq(AnnotationTask::getCompanyId, currentUser.companyId())
.eq(StringUtils.hasText(query.taskType()), AnnotationTask::getTaskType, query.taskType())
.eq(StringUtils.hasText(query.taskStatus()), AnnotationTask::getTaskStatus, query.taskStatus())
.eq(query.isDeleted() != null, AnnotationTask::getIsDeleted, query.isDeleted())
.like(StringUtils.hasText(query.keyword()), AnnotationTask::getTaskName, query.keyword());
.eq(AnnotationTask::getCompanyId, currentUser.companyId())
.eq(query.taskType() != null, AnnotationTask::getTaskType, query.taskType())
.eq(StringUtils.hasText(query.taskStatus()), AnnotationTask::getTaskStatus, query.taskStatus())
.eq(query.isDeleted() != null, AnnotationTask::getIsDeleted, query.isDeleted())
.like(StringUtils.hasText(query.keyword()), AnnotationTask::getTaskName, query.keyword());
if (shouldFilterByUserId) {
wrapper.eq(AnnotationTask::getCreatorId, currentUser.userId());
} else if (!allowedRoles.isEmpty()) {
wrapper.in(AnnotationTask::getCreatorRole, allowedRoles);
}
wrapper.orderByDesc(AnnotationTask::getCreatedAt);
Page<AnnotationTask> page = new Page<>(query.pageNo(), query.pageSize());
Page<AnnotationTask> resultPage = annotationTaskMapper.selectPage(page, wrapper);
List<AnnotationTaskResponse> records = resultPage.getRecords().stream()
.filter(task -> query.resourceId() == null ||
annotationTaskResourceMapper.listResourceIdsByTaskId(task.getId()).contains(query.resourceId()))
.map(task -> buildTaskResponse(task,
normalizeIds(annotationTaskResourceMapper.listResourceIdsByTaskId(task.getId()))))
.toList();
.filter(task -> query.resourceId() == null
|| annotationTaskResourceMapper.listResourceIdsByTaskId(task.getId())
.contains(query.resourceId()))
.map(task -> buildTaskResponse(task,
normalizeIds(annotationTaskResourceMapper.listResourceIdsByTaskId(task.getId()))))
.toList();
return new PageResult<>(records, resultPage.getTotal(), (int) resultPage.getCurrent(), (int) resultPage.getSize());
return new PageResult<>(records, resultPage.getTotal(), (int) resultPage.getCurrent(),
(int) resultPage.getSize());
}
@Transactional
@@ -183,8 +216,8 @@ public class AnnotationTaskService {
}
task.setIsDeleted(true);
annotationTaskMapper.updateById(task);
log.info("deleted annotation task logically, companyId={}, userId={}, taskId={}",
currentUser.companyId(), currentUser.userId(), taskId);
log.info("deleted annotation task logically, companyId={}, userId={}, taskId={}", currentUser.companyId(),
currentUser.userId(), taskId);
}
private List<SourceResource> loadAndValidateResources(LoginUser currentUser, List<Long> resourceIds) {
@@ -192,12 +225,14 @@ public class AnnotationTaskService {
throw new BusinessException(ResultCode.BAD_REQUEST, "任务资源不能为空");
}
List<Long> normalizedIds = normalizeIds(resourceIds);
List<SourceResource> resources = sourceResourceMapper.selectByCompanyIdAndIds(currentUser.companyId(), normalizedIds);
List<SourceResource> resources = sourceResourceMapper.selectByCompanyIdAndIds(currentUser.companyId(),
normalizedIds);
if (resources.size() != normalizedIds.size()) {
throw new BusinessException(ResultCode.BAD_REQUEST, "存在无效资源");
}
for (SourceResource resource : resources) {
if (!dataPermissionService.canAccessCreator(currentUser, resource.getCreatorId(), resource.getCreatorRole())) {
if (!dataPermissionService.canAccessCreator(currentUser, resource.getCreatorId(),
resource.getCreatorRole())) {
throw new BusinessException(ResultCode.FORBIDDEN, "无权访问资源");
}
if (!SourceStatus.READY.name().equals(resource.getSourceStatus())) {
@@ -210,52 +245,39 @@ public class AnnotationTaskService {
private void saveTaskBindings(Long taskId, Long companyId, List<SourceResource> resources) {
for (SourceResource resource : resources) {
annotationTaskResourceMapper.insert(AnnotationTaskResource.builder()
.id(IdGenerator.nextId())
.companyId(companyId)
.taskId(taskId)
.resourceId(resource.getId())
.build());
annotationTaskResourceMapper.insert(AnnotationTaskResource.builder().id(IdGenerator.nextId())
.companyId(companyId).taskId(taskId).resourceId(resource.getId()).build());
}
}
private AnnotationTaskResponse buildTaskResponse(AnnotationTask task,
List<Long> resourceIds,
SysConfigService.ResolvedModelConfig extractModel,
SysConfigService.ResolvedModelConfig verifyModel,
SysConfigService.ResolvedPromptConfig extractPrompt,
SysConfigService.ResolvedPromptConfig verifyPrompt) {
return new AnnotationTaskResponse(
task.getId(),
task.getTaskName(),
task.getIndustryType(),
task.getTaskType(),
task.getTaskStatus(),
resourceIds,
sysConfigService.toResponse(extractModel),
sysConfigService.toResponse(verifyModel),
sysConfigService.toResponse(extractPrompt),
sysConfigService.toResponse(verifyPrompt),
task.getCreatedAt(),
task.getUpdatedAt());
private AnnotationTaskResponse buildTaskResponse(AnnotationTask task, List<Long> resourceIds,
SysConfigService.ResolvedModelConfig extractModel, SysConfigService.ResolvedModelConfig verifyModel,
SysConfigService.ResolvedPromptConfig extractPrompt, SysConfigService.ResolvedPromptConfig verifyPrompt) {
return new AnnotationTaskResponse(task.getId(), task.getTaskName(), task.getIndustryType(), task.getTaskType(),
task.getTaskStatus(), resourceIds, sysConfigService.toResponse(extractModel),
sysConfigService.toResponse(verifyModel), sysConfigService.toResponse(extractPrompt),
sysConfigService.toResponse(verifyPrompt), task.getCreatedAt(), task.getUpdatedAt());
}
private AnnotationTaskResponse buildTaskResponse(AnnotationTask task, List<Long> resourceIds) {
return new AnnotationTaskResponse(
task.getId(),
task.getTaskName(),
task.getIndustryType(),
task.getTaskType(),
task.getTaskStatus(),
resourceIds,
new TaskModelConfigResponse(task.getExtractModelConfigId(), null, task.getExtractModelName(),
task.getExtractModelUrl(), maskSecret(task.getExtractModelApiKey())),
new TaskModelConfigResponse(task.getVerifyModelConfigId(), null, task.getVerifyModelName(),
task.getVerifyModelUrl(), maskSecret(task.getVerifyModelApiKey())),
new TaskPromptConfigResponse(task.getExtractPromptConfigId(), null, task.getExtractPrompt()),
new TaskPromptConfigResponse(task.getVerifyPromptConfigId(), null, task.getVerifyPrompt()),
task.getCreatedAt(),
task.getUpdatedAt());
String extractModelConfigName = resolveConfigName(task.getExtractModelConfigId());
String verifyModelConfigName = resolveConfigName(task.getVerifyModelConfigId());
String extractPromptConfigName = resolveConfigName(task.getExtractPromptConfigId());
String verifyPromptConfigName = resolveConfigName(task.getVerifyPromptConfigId());
return new AnnotationTaskResponse(task.getId(), task.getTaskName(), task.getIndustryType(), task.getTaskType(),
task.getTaskStatus(), resourceIds,
new TaskModelConfigResponse(task.getExtractModelConfigId(), extractModelConfigName,
task.getExtractModelName(),
task.getExtractModelUrl(), maskSecret(task.getExtractModelApiKey())),
new TaskModelConfigResponse(task.getVerifyModelConfigId(), verifyModelConfigName,
task.getVerifyModelName(),
task.getVerifyModelUrl(), maskSecret(task.getVerifyModelApiKey())),
new TaskPromptConfigResponse(task.getExtractPromptConfigId(), extractPromptConfigName,
task.getExtractPrompt()),
new TaskPromptConfigResponse(task.getVerifyPromptConfigId(), verifyPromptConfigName,
task.getVerifyPrompt()),
task.getCreatedAt(), task.getUpdatedAt());
}
private List<Long> resourceIds(List<SourceResource> resources) {
@@ -275,12 +297,12 @@ public class AnnotationTaskService {
}
}
private String defaultIndustryType(String industryType) {
return StringUtils.hasText(industryType) ? industryType : "transport";
private IndustryType defaultIndustryType(IndustryType industryType) {
return industryType != null ? industryType : IndustryType.TRANSPORT;
}
private String defaultTaskType(String taskType) {
return StringUtils.hasText(taskType) ? taskType : "EXTRACT_QA";
private TaskType defaultTaskType(TaskType taskType) {
return taskType != null ? taskType : TaskType.EXTRACT_QA;
}
private String maskSecret(String secret) {
@@ -292,4 +314,12 @@ public class AnnotationTaskService {
}
return "****" + secret.substring(secret.length() - 4);
}
private String resolveConfigName(Long configId) {
if (configId == null) {
return null;
}
SysConfig config = sysConfigMapper.selectById(configId);
return config != null ? config.getConfigName() : null;
}
}