Merge branch 'dev54'

# Conflicts:
#	src/main/resources/sql/schema.sql
This commit is contained in:
wh
2026-05-10 16:44:11 +08:00
22 changed files with 390 additions and 142 deletions

View File

@@ -111,8 +111,8 @@
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version> <version>3.11.0</version>
<configuration> <configuration>
<source>${java.version}</source> <source>21</source>
<target>${java.version}</target> <target>21</target>
<annotationProcessorPaths> <annotationProcessorPaths>
<path> <path>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
@@ -120,6 +120,7 @@
<version>1.18.30</version> <version>1.18.30</version>
</path> </path>
</annotationProcessorPaths> </annotationProcessorPaths>
<compilerArgs>--enable-preview</compilerArgs>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@@ -3,8 +3,8 @@ package com.labelsys.backend.controller;
import com.labelsys.backend.context.UserContext; import com.labelsys.backend.context.UserContext;
import com.labelsys.backend.dto.common.PageResult; import com.labelsys.backend.dto.common.PageResult;
import com.labelsys.backend.dto.request.AnnotationResultHistoryPageQuery; import com.labelsys.backend.dto.request.AnnotationResultHistoryPageQuery;
import com.labelsys.backend.dto.response.AnnotationResultHistoryDetailResponse;
import com.labelsys.backend.dto.response.AnnotationResultHistoryResponse; import com.labelsys.backend.dto.response.AnnotationResultHistoryResponse;
import com.labelsys.backend.dto.response.FileContentResponse;
import com.labelsys.backend.service.AnnotationResultArchiveService; import com.labelsys.backend.service.AnnotationResultArchiveService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
@@ -34,17 +34,18 @@ public class AnnotationResultArchiveController {
@Operation(summary = "查询归档历史详情") @Operation(summary = "查询归档历史详情")
@GetMapping("/{id}") @GetMapping("/{id}")
public ResponseEntity<AnnotationResultHistoryResponse> getHistory( public ResponseEntity<AnnotationResultHistoryDetailResponse> getHistory(
@Parameter(description = "历史记录ID", example = "901") @Parameter(description = "历史记录ID", example = "901")
@PathVariable Long id) { @PathVariable Long id) {
return ResponseEntity.ok(annotationResultArchiveService.getHistory(UserContext.requireUser(), id)); return ResponseEntity.ok(annotationResultArchiveService.getHistory(UserContext.requireUser(), id));
} }
}
@Operation(summary = "加载归档文件内容") // @Operation(summary = "加载归档文件内容")
@GetMapping("/{id}/content") // @GetMapping("/{id}/content")
public ResponseEntity<FileContentResponse> loadFileContent( // public ResponseEntity<FileContentResponse> loadFileContent(
@Parameter(description = "历史记录ID", example = "901") // @Parameter(description = "历史记录ID", example = "901")
@PathVariable Long id) { // @PathVariable Long id) {
return ResponseEntity.ok(annotationResultArchiveService.loadFileContent(UserContext.requireUser(), id)); // return ResponseEntity.ok(annotationResultArchiveService.loadFileContent(UserContext.requireUser(), id));
} // }
} //}

View File

@@ -1,6 +1,5 @@
package com.labelsys.backend.dto.request; package com.labelsys.backend.dto.request;
import com.labelsys.backend.enums.IndustryType;
import com.labelsys.backend.enums.TaskType; import com.labelsys.backend.enums.TaskType;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
@@ -12,7 +11,6 @@ import java.util.List;
@Schema(description = "创建标注任务请求") @Schema(description = "创建标注任务请求")
public record CreateAnnotationTaskRequest( public record CreateAnnotationTaskRequest(
@Schema(description = "任务名称", example = "运输文档问答抽取任务") @NotBlank(message = "任务名称不能为空") String taskName, @Schema(description = "任务名称", example = "运输文档问答抽取任务") @NotBlank(message = "任务名称不能为空") String taskName,
@Schema(description = "行业类型", defaultValue = "TRANSPORT", example = "TRANSPORT") @NotNull(message = "行业类型不能为空") IndustryType industryType,
@Schema(description = "任务类型", defaultValue = "EXTRACT_QA", example = "EXTRACT_QA") @NotNull(message = "任务类型不能为空") TaskType taskType, @Schema(description = "任务类型", defaultValue = "EXTRACT_QA", example = "EXTRACT_QA") @NotNull(message = "任务类型不能为空") TaskType taskType,
@Schema(description = "资源ID列表", example = "[191000000000000101,191000000000000102]") @NotEmpty(message = "资源列表不能为空") List<Long> resourceIds) { @Schema(description = "资源ID列表", example = "[191000000000000101,191000000000000102]") @NotEmpty(message = "资源列表不能为空") List<Long> resourceIds) {
} }

View File

@@ -9,7 +9,7 @@ public record MergeReviewResultRequest(
@Schema(description = "合并后的答案映射key为qa记录IDvalue为合并后的答案") @Schema(description = "合并后的答案映射key为qa记录IDvalue为合并后的答案")
Map<String, String> mergedAnswers, Map<String, String> mergedAnswers,
@Schema(description = "审核备注") @Schema(description = "每条QA记录的审核评论映射key为qa记录IDvalue为审核评论")
String reviewComment Map<String, String> reviewComments
) { ) {
} }

View File

@@ -2,14 +2,12 @@ package com.labelsys.backend.dto.request;
import java.util.List; import java.util.List;
import com.labelsys.backend.enums.IndustryType;
import com.labelsys.backend.enums.TaskType; import com.labelsys.backend.enums.TaskType;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "更新标注任务请求") @Schema(description = "更新标注任务请求")
public record UpdateAnnotationTaskRequest( public record UpdateAnnotationTaskRequest(
@Schema(description = "行业类型", example = "TRANSPORT") IndustryType industryType,
@Schema(description = "任务类型", example = "EXTRACT_QA") TaskType taskType, @Schema(description = "任务类型", example = "EXTRACT_QA") TaskType taskType,
@Schema(description = "资源ID列表", example = "[191000000000000101,191000000000000102]") List<Long> resourceIds) { @Schema(description = "资源ID列表", example = "[191000000000000101,191000000000000102]") List<Long> resourceIds) {
} }

View File

@@ -18,10 +18,25 @@ public record AnnotationResultCompareResponse(
@Schema(description = "问答记录") @Schema(description = "问答记录")
public record QaRecord( public record QaRecord(
@Schema(description = "记录ID", example = "qa_001") String id, @Schema(description = "记录ID", example = "qa_001") String id,
@Schema(description = "批次ID", example = "50") Long batchId,
@Schema(description = "问题", example = "运输时效是多久?") String question, @Schema(description = "问题", example = "运输时效是多久?") String question,
@Schema(description = "答案", example = "3天") String answer, @Schema(description = "答案", example = "3天") String answer,
@Schema(description = "是否需要审核", example = "true") Boolean requiresReview @Schema(description = "是否需要审核", example = "true") Boolean requiresReview,
) {} @Schema(description = "源片段信息") SourceSegments sourceSegments,
@Schema(description = "问题分类") String questionCategory,
@Schema(description = "评分") Scores scores,
@Schema(description = "审核评论") String reviewComment
) {
}
@Schema(description = "源片段信息")
public record SourceSegments(
@Schema(description = "片段内容") String segment,
@Schema(description = "块索引", example = "0") Integer chunkIndex,
@Schema(description = "块标题") String chunkTitle,
@Schema(description = "块内容") String chunkContent
) {
}
@Schema(description = "差异记录") @Schema(description = "差异记录")
public record DiffRecord( public record DiffRecord(
@@ -30,6 +45,19 @@ public record AnnotationResultCompareResponse(
@Schema(description = "提取模型答案", example = "3天") String extractAnswer, @Schema(description = "提取模型答案", example = "3天") String extractAnswer,
@Schema(description = "校验模型答案", example = "72小时") String verifyAnswer, @Schema(description = "校验模型答案", example = "72小时") String verifyAnswer,
@Schema(description = "差异原因", example = "时间单位不一致") String diffReason, @Schema(description = "差异原因", example = "时间单位不一致") String diffReason,
@Schema(description = "合并后的最终答案", example = "72小时3天") String mergedAnswer @Schema(description = "合并后的最终答案", example = "72小时3天") String mergedAnswer,
) {} @Schema(description = "问题分类") String questionCategory,
@Schema(description = "评分") Scores scores
) {
}
@Schema(description = "评分结构")
public record Scores(
@Schema(description = "相似度", example = "0.7") Double similarity,
@Schema(description = "置信度1", example = "0.9") Double confidence1,
@Schema(description = "置信度2", example = "0.85") Double confidence2,
@Schema(description = "幻觉检测", example = "0.9") Double hallucination,
@Schema(description = "信任度", example = "0.64") Double trust
) {
}
} }

View File

@@ -25,8 +25,6 @@ public record AnnotationResultDetailResponse(
@Schema(description = "问答内容") QaContentDto qaContent, @Schema(description = "问答内容") QaContentDto qaContent,
@Schema(description = "差异摘要(需要审核时有值)") DiffContentDto diffSummary, @Schema(description = "差异摘要(需要审核时有值)") DiffContentDto diffSummary,
@Schema(description = "审核备注", example = "需统一时间字段口径。") String reviewComment,
@Schema(description = "审核时间", example = "2026-04-27T11:00:00") LocalDateTime reviewedAt,
@Schema(description = "创建时间", example = "2026-04-27T10:40:00") LocalDateTime createdAt @Schema(description = "创建时间", example = "2026-04-27T10:40:00") LocalDateTime createdAt
) { ) {
@Schema(description = "问答内容结构") @Schema(description = "问答内容结构")
@@ -38,9 +36,23 @@ public record AnnotationResultDetailResponse(
@Schema(description = "问答记录") @Schema(description = "问答记录")
public record QaRecordDto( public record QaRecordDto(
@Schema(description = "记录ID", example = "q1") String id, @Schema(description = "记录ID", example = "q1") String id,
@Schema(description = "批次ID", example = "50") Long batchId,
@Schema(description = "问题", example = "产品重量是多少?") String question, @Schema(description = "问题", example = "产品重量是多少?") String question,
@Schema(description = "答案", example = "5kg") String answer, @Schema(description = "答案", example = "5kg") String answer,
@Schema(description = "是否需要审核", example = "false") Boolean requiresReview @Schema(description = "是否需要审核", example = "false") Boolean requiresReview,
@Schema(description = "源片段信息") SourceSegmentsDto sourceSegments,
@Schema(description = "问题分类") String questionCategory,
@Schema(description = "评分") ScoresDto scores,
@Schema(description = "审核评论") String reviewComment
) {
}
@Schema(description = "源片段信息")
public record SourceSegmentsDto(
@Schema(description = "片段内容") String segment,
@Schema(description = "块索引", example = "0") Integer chunkIndex,
@Schema(description = "块标题") String chunkTitle,
@Schema(description = "块内容") String chunkContent
) { ) {
} }
@@ -57,7 +69,19 @@ public record AnnotationResultDetailResponse(
@Schema(description = "抽取答案", example = "2年") String extractAnswer, @Schema(description = "抽取答案", example = "2年") String extractAnswer,
@Schema(description = "验证答案", example = "3年") String verifyAnswer, @Schema(description = "验证答案", example = "3年") String verifyAnswer,
@Schema(description = "差异原因", example = "抽取与验证结果不一致") String diffReason, @Schema(description = "差异原因", example = "抽取与验证结果不一致") String diffReason,
@Schema(description = "合并后答案") String mergedAnswer @Schema(description = "合并后答案") String mergedAnswer,
@Schema(description = "问题分类") String questionCategory,
@Schema(description = "评分") ScoresDto scores
) {
}
@Schema(description = "评分结构")
public record ScoresDto(
@Schema(description = "相似度", example = "0.7") Double similarity,
@Schema(description = "置信度1", example = "0.9") Double confidence1,
@Schema(description = "置信度2", example = "0.85") Double confidence2,
@Schema(description = "幻觉检测", example = "0.9") Double hallucination,
@Schema(description = "信任度", example = "0.64") Double trust
) { ) {
} }
} }

View File

@@ -0,0 +1,63 @@
package com.labelsys.backend.dto.response;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "归档历史详情响应")
public record AnnotationResultHistoryDetailResponse(
@Schema(description = "历史记录ID", example = "901") Long id,
@Schema(description = "任务ID", example = "191000000000000301") Long taskId,
@Schema(description = "任务名称", example = "产品说明书标注") String taskName,
@Schema(description = "资源ID", example = "191000000000000101") Long resourceId,
@Schema(description = "资源名称", example = "产品A说明书.pdf") String resourceName,
@Schema(description = "问答内容文件路径", example = "annotation-results/2/qa/802.json") String qaContentFilePath,
@Schema(description = "问答内容") QaContentDto qaContent,
@Schema(description = "归档原因", example = "审核通过后归档") String archiveReason,
@Schema(description = "归档操作人ID", example = "5") Long archivedBy,
@Schema(description = "归档时间", example = "2026-05-06T10:30:00") LocalDateTime archivedAt,
@Schema(description = "创建时间", example = "2026-05-06T10:30:00") LocalDateTime createdAt,
@Schema(description = "审核人ID自动归档时为null", example = "5") Long reviewerId,
@Schema(description = "审核人姓名自动归档时为auto", example = "张三") String reviewerName
) {
@Schema(description = "问答内容结构")
public record QaContentDto(
@Schema(description = "问答记录列表") List<QaRecordDto> records
) {
}
@Schema(description = "问答记录")
public record QaRecordDto(
@Schema(description = "记录ID", example = "q1") String id,
@Schema(description = "批次ID", example = "50") Long batchId,
@Schema(description = "问题", example = "产品重量是多少?") String question,
@Schema(description = "答案", example = "5kg") String answer,
@Schema(description = "是否需要审核", example = "false") Boolean requiresReview,
@Schema(description = "源片段信息") SourceSegmentsDto sourceSegments,
@Schema(description = "问题分类") String questionCategory,
@Schema(description = "评分") ScoresDto scores,
@Schema(description = "审核评论") String reviewComment
) {
}
@Schema(description = "源片段信息")
public record SourceSegmentsDto(
@Schema(description = "片段内容") String segment,
@Schema(description = "块索引", example = "0") Integer chunkIndex,
@Schema(description = "块标题") String chunkTitle,
@Schema(description = "块内容") String chunkContent
) {
}
@Schema(description = "评分结构")
public record ScoresDto(
@Schema(description = "相似度", example = "0.7") Double similarity,
@Schema(description = "置信度1", example = "0.9") Double confidence1,
@Schema(description = "置信度2", example = "0.85") Double confidence2,
@Schema(description = "幻觉检测", example = "0.9") Double hallucination,
@Schema(description = "信任度", example = "0.64") Double trust
) {
}
}

View File

@@ -20,7 +20,6 @@ public record AnnotationResultHistoryResponse(
@Schema(description = "归档时间", example = "2026-05-06T10:30:00") LocalDateTime archivedAt, @Schema(description = "归档时间", example = "2026-05-06T10:30:00") LocalDateTime archivedAt,
@Schema(description = "创建时间", example = "2026-05-06T10:30:00") LocalDateTime createdAt, @Schema(description = "创建时间", example = "2026-05-06T10:30:00") LocalDateTime createdAt,
@Schema(description = "审核人ID自动归档时为null", example = "5") Long reviewerId, @Schema(description = "审核人ID自动归档时为null", example = "5") Long reviewerId,
@Schema(description = "审核人姓名自动归档时为auto", example = "张三") String reviewerName, @Schema(description = "审核人姓名自动归档时为auto", example = "张三") String reviewerName
@Schema(description = "审核意见自动归档时为auto", example = "内容符合要求") String reviewerComment
) { ) {
} }

View File

@@ -17,8 +17,6 @@ public record AnnotationResultResponse(
@Schema(description = "是否已删除", example = "false") Boolean isDeleted, @Schema(description = "是否已删除", example = "false") Boolean isDeleted,
@Schema(description = "问答内容文件路径", example = "annotation-results/2/qa/801.json") String qaContentFilePath, @Schema(description = "问答内容文件路径", example = "annotation-results/2/qa/801.json") String qaContentFilePath,
@Schema(description = "差异摘要文件路径", example = "annotation-results/2/diff/801.json") String diffSummaryFilePath, @Schema(description = "差异摘要文件路径", example = "annotation-results/2/diff/801.json") String diffSummaryFilePath,
@Schema(description = "审核备注", example = "需统一时间字段口径。") String reviewComment,
@Schema(description = "审核时间", example = "2026-04-27T11:00:00") LocalDateTime reviewedAt,
@Schema(description = "创建时间", example = "2026-04-27T10:40:00") LocalDateTime createdAt @Schema(description = "创建时间", example = "2026-04-27T10:40:00") LocalDateTime createdAt
) { ) {
} }

View File

@@ -1,6 +1,5 @@
package com.labelsys.backend.dto.response; package com.labelsys.backend.dto.response;
import com.labelsys.backend.enums.IndustryType;
import com.labelsys.backend.enums.TaskType; import com.labelsys.backend.enums.TaskType;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
@@ -11,7 +10,6 @@ import java.util.List;
public record AnnotationTaskResponse( public record AnnotationTaskResponse(
@Schema(description = "任务ID", example = "191000000000000301") Long id, @Schema(description = "任务ID", example = "191000000000000301") Long id,
@Schema(description = "任务名称", example = "运输文档问答抽取任务") String taskName, @Schema(description = "任务名称", example = "运输文档问答抽取任务") String taskName,
@Schema(description = "行业类型", example = "transport") IndustryType industryType,
@Schema(description = "任务类型", example = "EXTRACT_QA") TaskType taskType, @Schema(description = "任务类型", example = "EXTRACT_QA") TaskType taskType,
@Schema(description = "任务状态", example = "PENDING") String taskStatus, @Schema(description = "任务状态", example = "PENDING") String taskStatus,
@Schema(description = "资源ID列表", example = "[191000000000000101,191000000000000102]") List<Long> resourceIds, @Schema(description = "资源ID列表", example = "[191000000000000101,191000000000000102]") List<Long> resourceIds,

View File

@@ -56,12 +56,6 @@ public class AnnotationResult {
@TableField("reviewer_id") @TableField("reviewer_id")
private Long reviewerId; private Long reviewerId;
@TableField("review_comment")
private String reviewComment;
@TableField("reviewed_at")
private LocalDateTime reviewedAt;
@TableField("created_at") @TableField("created_at")
private LocalDateTime createdAt; private LocalDateTime createdAt;

View File

@@ -37,5 +37,4 @@ public class AnnotationResultHistory {
// 新增审核人相关字段 // 新增审核人相关字段
private Long reviewerId; private Long reviewerId;
private String reviewerName; private String reviewerName;
private String reviewerComment;
} }

View File

@@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.labelsys.backend.enums.IndustryType;
import com.labelsys.backend.enums.TaskType; import com.labelsys.backend.enums.TaskType;
import com.labelsys.backend.enums.UserRole; import com.labelsys.backend.enums.UserRole;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@@ -26,7 +25,6 @@ public class AnnotationTask {
private Long creatorId; private Long creatorId;
private UserRole creatorRole; private UserRole creatorRole;
private String taskName; private String taskName;
private IndustryType industryType;
private TaskType taskType; private TaskType taskType;
private String taskStatus; private String taskStatus;
@TableLogic(value = "false", delval = "true") @TableLogic(value = "false", delval = "true")

View File

@@ -11,7 +11,9 @@ public interface AnnotationResultMapper extends BaseMapper<AnnotationResult> {
int markArchived(@Param("id") Long id, int markArchived(@Param("id") Long id,
@Param("companyId") Long companyId, @Param("companyId") Long companyId,
@Param("reviewerId") Long reviewerId, @Param("reviewerId") Long reviewerId);
@Param("reviewComment") String reviewComment,
@Param("reviewedAt") LocalDateTime reviewedAt); int markReviewedAndArchived(@Param("id") Long id,
} @Param("companyId") Long companyId,
@Param("reviewerId") Long reviewerId);
}

View File

@@ -8,6 +8,7 @@ import com.labelsys.backend.common.exception.BusinessException;
import com.labelsys.backend.context.LoginUser; import com.labelsys.backend.context.LoginUser;
import com.labelsys.backend.dto.common.PageResult; import com.labelsys.backend.dto.common.PageResult;
import com.labelsys.backend.dto.request.AnnotationResultHistoryPageQuery; import com.labelsys.backend.dto.request.AnnotationResultHistoryPageQuery;
import com.labelsys.backend.dto.response.AnnotationResultHistoryDetailResponse;
import com.labelsys.backend.dto.response.AnnotationResultHistoryResponse; import com.labelsys.backend.dto.response.AnnotationResultHistoryResponse;
import com.labelsys.backend.dto.response.FileContentResponse; import com.labelsys.backend.dto.response.FileContentResponse;
import com.labelsys.backend.dto.response.MergeReviewResultResponse; import com.labelsys.backend.dto.response.MergeReviewResultResponse;
@@ -29,6 +30,8 @@ import java.time.Duration;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import static org.springframework.util.StringUtils.hasText;
@Slf4j @Slf4j
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
@@ -66,6 +69,7 @@ public class AnnotationResultArchiveService {
var page = new Page<AnnotationResultHistory>(query.pageNo(), query.pageSize()); var page = new Page<AnnotationResultHistory>(query.pageNo(), query.pageSize());
var resultPage = annotationResultHistoryMapper.selectPage(page, wrapper); var resultPage = annotationResultHistoryMapper.selectPage(page, wrapper);
// 分页查询不加载 qa 内容
var records = resultPage.getRecords().stream() var records = resultPage.getRecords().stream()
.map(this::toResponse) .map(this::toResponse)
.toList(); .toList();
@@ -79,14 +83,17 @@ public class AnnotationResultArchiveService {
} }
} }
public AnnotationResultHistoryResponse getHistory(LoginUser currentUser, Long historyId) { public AnnotationResultHistoryDetailResponse getHistory(LoginUser currentUser, Long historyId) {
try { try {
AnnotationResultHistory history = annotationResultHistoryMapper.selectById(historyId); AnnotationResultHistory history = annotationResultHistoryMapper.selectById(historyId);
if (history == null || !history.getCompanyId().equals(currentUser.companyId())) { if (history == null || !history.getCompanyId().equals(currentUser.companyId())) {
throw new BusinessException(ResultCode.NOT_FOUND, "历史记录不存在"); throw new BusinessException(ResultCode.NOT_FOUND, "历史记录不存在");
} }
assertHistoryPermission(currentUser, history); assertHistoryPermission(currentUser, history);
return toResponse(history);
// 详情查询加载 QA 内容
QaContent qaContent = loadQaContent(history.getQaContentFilePath());
return toDetailResponse(history, qaContent);
} catch (Exception e) { } catch (Exception e) {
log.error("getHistory failed, companyId={}, userId={}, historyId={}, error={}", log.error("getHistory failed, companyId={}, userId={}, historyId={}, error={}",
currentUser.companyId(), currentUser.userId(), historyId, e.getMessage(), e); currentUser.companyId(), currentUser.userId(), historyId, e.getMessage(), e);
@@ -104,19 +111,66 @@ public class AnnotationResultArchiveService {
private AnnotationResultHistoryResponse toResponse(AnnotationResultHistory history) { private AnnotationResultHistoryResponse toResponse(AnnotationResultHistory history) {
return new AnnotationResultHistoryResponse( return new AnnotationResultHistoryResponse(
history.getId(), history.getId(),
// history.getSourceResultId(),
history.getTaskId(), history.getTaskId(),
history.getTaskName(), // 新增 history.getTaskName(),
history.getResourceId(), history.getResourceId(),
history.getResourceName(), // 新增 history.getResourceName(),
history.getQaContentFilePath(), history.getQaContentFilePath(),
history.getArchiveReason(), history.getArchiveReason(),
history.getArchivedBy(), history.getArchivedBy(),
history.getArchivedAt(), history.getArchivedAt(),
history.getCreatedAt(), history.getCreatedAt(),
history.getReviewerId(), history.getReviewerId(),
history.getReviewerName(), history.getReviewerName()
history.getReviewerComment() );
}
private AnnotationResultHistoryDetailResponse toDetailResponse(AnnotationResultHistory history,
QaContent qaContent) {
// 转换 QA 内容
AnnotationResultHistoryDetailResponse.QaContentDto qaContentDto = null;
if (qaContent != null && qaContent.records() != null) {
qaContentDto = new AnnotationResultHistoryDetailResponse.QaContentDto(
qaContent.records().stream()
.map(r -> new AnnotationResultHistoryDetailResponse.QaRecordDto(
r.id(),
r.batchId(),
r.question(),
r.answer(),
r.requiresReview(),
r.sourceSegments() != null ?
new AnnotationResultHistoryDetailResponse.SourceSegmentsDto(
r.sourceSegments().segment(),
r.sourceSegments().chunkIndex(),
r.sourceSegments().chunkTitle(),
r.sourceSegments().chunkContent()) :
null,
r.questionCategory(),
r.scores() != null ? new AnnotationResultHistoryDetailResponse.ScoresDto(
r.scores().similarity(),
r.scores().confidence1(),
r.scores().confidence2(),
r.scores().hallucination(),
r.scores().trust()) : null,
r.reviewComment()))
.toList()
);
}
return new AnnotationResultHistoryDetailResponse(
history.getId(),
history.getTaskId(),
history.getTaskName(),
history.getResourceId(),
history.getResourceName(),
history.getQaContentFilePath(),
qaContentDto,
history.getArchiveReason(),
history.getArchivedBy(),
history.getArchivedAt(),
history.getCreatedAt(),
history.getReviewerId(),
history.getReviewerName()
); );
} }
@@ -124,13 +178,14 @@ public class AnnotationResultArchiveService {
public int autoArchiveEligibleResults() { public int autoArchiveEligibleResults() {
try { try {
LocalDateTime cutoff = LocalDateTime.now().minus(autoArchiveTimeout); LocalDateTime cutoff = LocalDateTime.now().minus(autoArchiveTimeout);
List<AnnotationResult> results = annotationResultMapper.selectList(new LambdaQueryWrapper<AnnotationResult>() List<AnnotationResult> results = annotationResultMapper.selectList(
.eq(AnnotationResult::getIsDeleted, false) new LambdaQueryWrapper<AnnotationResult>()
.eq(AnnotationResult::getRequiresManualReview, false) .eq(AnnotationResult::getIsDeleted, false)
.lt(AnnotationResult::getCreatedAt, cutoff)); .eq(AnnotationResult::getRequiresManualReview, false)
.lt(AnnotationResult::getCreatedAt, cutoff));
int archivedCount = 0; int archivedCount = 0;
for (AnnotationResult result : results) { for (AnnotationResult result : results) {
if (archiveRuntimeResult(result, null, "AUTO_ARCHIVE", null) != null) { if (archiveRuntimeResult(result, null, "AUTO_ARCHIVE") != null) {
archivedCount++; archivedCount++;
} }
} }
@@ -153,12 +208,16 @@ public class AnnotationResultArchiveService {
*/ */
private MergeReviewResultResponse archiveRuntimeResult(AnnotationResult result, private MergeReviewResultResponse archiveRuntimeResult(AnnotationResult result,
Long reviewerId, Long reviewerId,
String archiveReason, String archiveReason) {
String reviewComment) {
LocalDateTime archivedAt = LocalDateTime.now(); LocalDateTime archivedAt = LocalDateTime.now();
// 从对象存储读取 qa.json 内容 int updated = annotationResultMapper.markArchived(
// String qaContentJson = loadQaContentJson(result); result.getId(),
result.getCompanyId(),
reviewerId);
if (updated == 0) {
return null;
}
AnnotationResultHistory history = AnnotationResultHistory.builder() AnnotationResultHistory history = AnnotationResultHistory.builder()
.id(IdGenerator.nextId()) .id(IdGenerator.nextId())
@@ -175,24 +234,59 @@ public class AnnotationResultArchiveService {
.archiveReason(archiveReason) .archiveReason(archiveReason)
.archivedBy(reviewerId) .archivedBy(reviewerId)
.archivedAt(archivedAt) .archivedAt(archivedAt)
.createdAt(archivedAt)
.reviewerId(null) .reviewerId(null)
.reviewerName("auto") .reviewerName("auto")
.reviewerComment("auto")
.build(); .build();
annotationResultHistoryMapper.insert(history); annotationResultHistoryMapper.insert(history);
int updated = annotationResultMapper.markArchived(
result.getId(),
result.getCompanyId(),
reviewerId,
reviewComment,
archivedAt);
if (updated == 0) {
return null;
}
return new MergeReviewResultResponse(result.getId(), history.getId(), archiveReason, archivedAt); return new MergeReviewResultResponse(result.getId(), history.getId(), archiveReason, archivedAt);
} }
/**
* 加载 QA 内容
*/
private QaContent loadQaContent(String filePath) {
try {
if (!hasText(filePath)) {
log.warn("QA content file path is empty");
return new QaContent(null, null, List.of(), null);
}
String bucketName = extractBucketName(filePath);
String objectKey = extractObjectKey(filePath);
byte[] content = objectStorageService.download(bucketName, objectKey);
String jsonContent = new String(content, StandardCharsets.UTF_8);
return objectMapper.readValue(jsonContent, new com.fasterxml.jackson.core.type.TypeReference<QaContent>() {
});
} catch (Exception e) {
log.warn("Failed to load QA content, returning empty content. filePath={}, error={}", filePath,
e.getMessage());
return new QaContent(null, null, List.of(), null);
}
}
// 内部类qa.json 结构
private record QaContent(
Long taskId,
Long resourceId,
List<QaRecord> records,
Metadata metadata
) {
private record QaRecord(String id, Long batchId, String question, String answer,
Boolean requiresReview, SourceSegments sourceSegments,
String questionCategory, Scores scores, String reviewComment) {
}
private record SourceSegments(String segment, Integer chunkIndex, String chunkTitle, String chunkContent) {
}
private record Scores(Double similarity, Double confidence1, Double confidence2,
Double hallucination, Double trust) {
}
private record Metadata(String createdAt, String updatedAt) {
}
}
/** /**
* 从对象存储读取 qa.json 内容 * 从对象存储读取 qa.json 内容
*/ */
@@ -239,8 +333,9 @@ public class AnnotationResultArchiveService {
/** /**
* 加载归档记录的文件内容 * 加载归档记录的文件内容
*
* @param currentUser 当前用户 * @param currentUser 当前用户
* @param historyId 历史记录ID * @param historyId 历史记录ID
* @return 文件内容响应 * @return 文件内容响应
*/ */
public FileContentResponse loadFileContent(LoginUser currentUser, Long historyId) { public FileContentResponse loadFileContent(LoginUser currentUser, Long historyId) {
@@ -250,17 +345,17 @@ public class AnnotationResultArchiveService {
throw new BusinessException(ResultCode.NOT_FOUND, "历史记录不存在"); throw new BusinessException(ResultCode.NOT_FOUND, "历史记录不存在");
} }
//assertHistoryPermission(currentUser, history); //assertHistoryPermission(currentUser, history);
String filePath = history.getQaContentFilePath(); String filePath = history.getQaContentFilePath();
if (filePath == null || filePath.isEmpty()) { if (filePath == null || filePath.isEmpty()) {
throw new BusinessException(ResultCode.ERROR, "文件路径为空"); throw new BusinessException(ResultCode.ERROR, "文件路径为空");
} }
String bucketName = extractBucketName(filePath); String bucketName = extractBucketName(filePath);
String objectKey = extractObjectKey(filePath); String objectKey = extractObjectKey(filePath);
byte[] content = objectStorageService.download(bucketName, objectKey); byte[] content = objectStorageService.download(bucketName, objectKey);
String contentStr = new String(content, StandardCharsets.UTF_8); String contentStr = new String(content, StandardCharsets.UTF_8);
return new FileContentResponse(filePath, contentStr, content.length); return new FileContentResponse(filePath, contentStr, content.length);
} catch (BusinessException e) { } catch (BusinessException e) {
throw e; throw e;
@@ -270,4 +365,5 @@ public class AnnotationResultArchiveService {
throw new BusinessException(ResultCode.ERROR, "加载文件内容失败"); throw new BusinessException(ResultCode.ERROR, "加载文件内容失败");
} }
} }
}
}

View File

@@ -116,7 +116,24 @@ public class AnnotationResultService {
AnnotationResultDetailResponse.QaContentDto qaContentDto = new AnnotationResultDetailResponse.QaContentDto( AnnotationResultDetailResponse.QaContentDto qaContentDto = new AnnotationResultDetailResponse.QaContentDto(
qaContent.records().stream() qaContent.records().stream()
.map(r -> new AnnotationResultDetailResponse.QaRecordDto( .map(r -> new AnnotationResultDetailResponse.QaRecordDto(
r.id(), r.question(), r.answer(), r.requiresReview())) r.id(),
r.batchId(),
r.question(),
r.answer(),
r.requiresReview(),
r.sourceSegments() != null ? new AnnotationResultDetailResponse.SourceSegmentsDto(
r.sourceSegments().segment(),
r.sourceSegments().chunkIndex(),
r.sourceSegments().chunkTitle(),
r.sourceSegments().chunkContent()) : null,
r.questionCategory(),
r.scores() != null ? new AnnotationResultDetailResponse.ScoresDto(
r.scores().similarity(),
r.scores().confidence1(),
r.scores().confidence2(),
r.scores().hallucination(),
r.scores().trust()) : null,
r.reviewComment()))
.toList() .toList()
); );
@@ -127,7 +144,14 @@ public class AnnotationResultService {
diffContent.records().stream() diffContent.records().stream()
.map(r -> new AnnotationResultDetailResponse.DiffRecordDto( .map(r -> new AnnotationResultDetailResponse.DiffRecordDto(
r.qaId(), r.question(), r.extractAnswer(), r.qaId(), r.question(), r.extractAnswer(),
r.verifyAnswer(), r.diffReason(), r.mergedAnswer())) r.verifyAnswer(), r.diffReason(), r.mergedAnswer(),
r.questionCategory(),
r.scores() != null ? new AnnotationResultDetailResponse.ScoresDto(
r.scores().similarity(),
r.scores().confidence1(),
r.scores().confidence2(),
r.scores().hallucination(),
r.scores().trust()) : null))
.toList() .toList()
); );
} }
@@ -145,8 +169,6 @@ public class AnnotationResultService {
result.getDiffSummaryFilePath(), result.getDiffSummaryFilePath(),
qaContentDto, qaContentDto,
diffContentDto, diffContentDto,
result.getReviewComment(),
result.getReviewedAt(),
result.getCreatedAt() result.getCreatedAt()
); );
} }
@@ -173,9 +195,23 @@ public class AnnotationResultService {
List<AnnotationResultCompareResponse.QaRecord> qaRecords = qaContent.records().stream() List<AnnotationResultCompareResponse.QaRecord> qaRecords = qaContent.records().stream()
.map(qa -> new AnnotationResultCompareResponse.QaRecord( .map(qa -> new AnnotationResultCompareResponse.QaRecord(
qa.id(), qa.id(),
qa.batchId(),
qa.question(), qa.question(),
qa.answer(), qa.answer(),
qa.requiresReview() qa.requiresReview(),
qa.sourceSegments() != null ? new AnnotationResultCompareResponse.SourceSegments(
qa.sourceSegments().segment(),
qa.sourceSegments().chunkIndex(),
qa.sourceSegments().chunkTitle(),
qa.sourceSegments().chunkContent()) : null,
qa.questionCategory(),
qa.scores() != null ? new AnnotationResultCompareResponse.Scores(
qa.scores().similarity(),
qa.scores().confidence1(),
qa.scores().confidence2(),
qa.scores().hallucination(),
qa.scores().trust()) : null,
qa.reviewComment()
)).toList(); )).toList();
// 转换差异记录 // 转换差异记录
@@ -187,7 +223,14 @@ public class AnnotationResultService {
diff.extractAnswer(), diff.extractAnswer(),
diff.verifyAnswer(), diff.verifyAnswer(),
diff.diffReason(), diff.diffReason(),
diff.mergedAnswer() diff.mergedAnswer(),
diff.questionCategory(),
diff.scores() != null ? new AnnotationResultCompareResponse.Scores(
diff.scores().similarity(),
diff.scores().confidence1(),
diff.scores().confidence2(),
diff.scores().hallucination(),
diff.scores().trust()) : null
)).toList() : List.of(); )).toList() : List.of();
return new AnnotationResultCompareResponse( return new AnnotationResultCompareResponse(
@@ -220,16 +263,22 @@ public class AnnotationResultService {
// 读取当前 qa.json // 读取当前 qa.json
QaContent qaContent = loadQaContent(result); QaContent qaContent = loadQaContent(result);
// 更新 qa.json 的 answer 字段 // 更新 qa.json 的 answer 字段和 reviewComment
List<QaContent.QaRecord> updatedQaRecords = qaContent.records().stream() List<QaContent.QaRecord> updatedQaRecords = qaContent.records().stream()
.map(record -> { .map(record -> {
String mergedAnswer = request.mergedAnswers().get(record.id()); String mergedAnswer = request.mergedAnswers().get(record.id());
if (mergedAnswer != null) { String reviewComment = request.reviewComments() != null ? request.reviewComments().get(record.id()) : null;
if (mergedAnswer != null || reviewComment != null) {
return new QaContent.QaRecord( return new QaContent.QaRecord(
record.id(), record.id(),
record.batchId(),
record.question(), record.question(),
mergedAnswer, mergedAnswer != null ? mergedAnswer : record.answer(),
false false,
record.sourceSegments(),
record.questionCategory(),
record.scores(),
reviewComment != null ? reviewComment : record.reviewComment()
); );
} }
return record; return record;
@@ -247,13 +296,20 @@ public class AnnotationResultService {
); );
saveQaContent(result, updatedQaContent); saveQaContent(result, updatedQaContent);
// 更新数据库记录 // 用单条 SQL 原子完成人工审核归档,避免状态部分更新后再次被自动归档扫描到。
result.setIsDeleted(Boolean.TRUE); int updated = annotationResultMapper.markReviewedAndArchived(
result.setReviewerId(currentUser.userId()); result.getId(),
result.setReviewComment(request.reviewComment()); currentUser.companyId(),
result.setReviewedAt(LocalDateTime.now()); currentUser.userId());
if (updated == 0) {
// 记录已被其他进程归档
throw new BusinessException(ResultCode.CONFLICT, "记录已被归档");
}
result.setRequiresManualReview(false); result.setRequiresManualReview(false);
annotationResultMapper.updateById(result); result.setIsDeleted(true);
result.setReviewerId(currentUser.userId());
// 归档到历史表(人工审核后归档) // 归档到历史表(人工审核后归档)
archiveToHistory(result, currentUser, "审核通过后归档", false); archiveToHistory(result, currentUser, "审核通过后归档", false);
@@ -281,8 +337,6 @@ public class AnnotationResultService {
result.getIsDeleted(), result.getIsDeleted(),
result.getQaContentFilePath(), result.getQaContentFilePath(),
result.getDiffSummaryFilePath(), result.getDiffSummaryFilePath(),
result.getReviewComment(),
result.getReviewedAt(),
result.getCreatedAt() result.getCreatedAt()
); );
} }
@@ -392,17 +446,15 @@ public class AnnotationResultService {
// 根据归档类型设置审核人信息 // 根据归档类型设置审核人信息
if (isAutoArchive) { if (isAutoArchive) {
// 自动归档reviewer_id为NULLname和comment为"auto" // 自动归档reviewer_id为NULLname为"auto"
historyBuilder historyBuilder
.reviewerId(null) .reviewerId(null)
.reviewerName("auto") .reviewerName("auto");
.reviewerComment("auto");
} else { } else {
// 人工审核后归档:使用审核人信息 // 人工审核后归档:使用审核人信息
historyBuilder historyBuilder
.reviewerId(result.getReviewerId()) .reviewerId(currentUser.userId())
.reviewerName(currentUser.realName()) .reviewerName(currentUser.realName());
.reviewerComment(result.getReviewComment());
} }
annotationResultHistoryMapper.insert(historyBuilder.build()); annotationResultHistoryMapper.insert(historyBuilder.build());
@@ -436,7 +488,16 @@ public class AnnotationResultService {
List<QaRecord> records, List<QaRecord> records,
Metadata metadata Metadata metadata
) { ) {
private record QaRecord(String id, String question, String answer, Boolean requiresReview) { private record QaRecord(String id, Long batchId, String question, String answer,
Boolean requiresReview, SourceSegments sourceSegments,
String questionCategory, Scores scores, String reviewComment) {
}
private record SourceSegments(String segment, Integer chunkIndex, String chunkTitle, String chunkContent) {
}
private record Scores(Double similarity, Double confidence1, Double confidence2,
Double hallucination, Double trust) {
} }
private record Metadata(String createdAt, String updatedAt) { private record Metadata(String createdAt, String updatedAt) {
@@ -451,10 +512,15 @@ public class AnnotationResultService {
Metadata metadata Metadata metadata
) { ) {
private record DiffRecord(String qaId, String question, String extractAnswer, private record DiffRecord(String qaId, String question, String extractAnswer,
String verifyAnswer, String diffReason, String mergedAnswer) { String verifyAnswer, String diffReason, String mergedAnswer,
String questionCategory, Scores scores) {
}
private record Scores(Double similarity, Double confidence1, Double confidence2,
Double hallucination, Double trust) {
} }
private record Metadata(String createdAt) { private record Metadata(String createdAt) {
} }
} }
} }

View File

@@ -13,7 +13,6 @@ import com.labelsys.backend.dto.response.AnnotationTaskResponse;
import com.labelsys.backend.entity.AnnotationTask; import com.labelsys.backend.entity.AnnotationTask;
import com.labelsys.backend.entity.AnnotationTaskResource; import com.labelsys.backend.entity.AnnotationTaskResource;
import com.labelsys.backend.entity.SourceResource; import com.labelsys.backend.entity.SourceResource;
import com.labelsys.backend.enums.IndustryType;
import com.labelsys.backend.enums.TaskStatus; import com.labelsys.backend.enums.TaskStatus;
import com.labelsys.backend.enums.TaskType; import com.labelsys.backend.enums.TaskType;
import com.labelsys.backend.mapper.AnnotationTaskMapper; import com.labelsys.backend.mapper.AnnotationTaskMapper;
@@ -53,7 +52,6 @@ public class AnnotationTaskService {
.creatorId(currentUser.userId()) .creatorId(currentUser.userId())
.creatorRole(currentUser.role()) .creatorRole(currentUser.role())
.taskName(request.taskName()) .taskName(request.taskName())
.industryType(defaultIndustryType(request.industryType()))
.taskType(defaultTaskType(request.taskType())) .taskType(defaultTaskType(request.taskType()))
.taskStatus(TaskStatus.PENDING.name()) .taskStatus(TaskStatus.PENDING.name())
.isDeleted(false) .isDeleted(false)
@@ -97,10 +95,6 @@ public class AnnotationTaskService {
resources = loadAndValidateResources(currentUser, request.resourceIds()); resources = loadAndValidateResources(currentUser, request.resourceIds());
} }
if (request.industryType() != null) {
task.setIndustryType(request.industryType());
}
if (request.taskType() != null) { if (request.taskType() != null) {
task.setTaskType(request.taskType()); task.setTaskType(request.taskType());
} }
@@ -238,7 +232,6 @@ public class AnnotationTaskService {
return new AnnotationTaskResponse( return new AnnotationTaskResponse(
task.getId(), task.getId(),
task.getTaskName(), task.getTaskName(),
task.getIndustryType(),
task.getTaskType(), task.getTaskType(),
task.getTaskStatus(), task.getTaskStatus(),
resourceIds, resourceIds,
@@ -264,10 +257,6 @@ public class AnnotationTaskService {
} }
} }
private IndustryType defaultIndustryType(IndustryType industryType) {
return industryType != null ? industryType : IndustryType.TRANSPORT;
}
private TaskType defaultTaskType(TaskType taskType) { private TaskType defaultTaskType(TaskType taskType) {
return taskType != null ? taskType : TaskType.EXTRACT_QA; return taskType != null ? taskType : TaskType.EXTRACT_QA;
} }

View File

@@ -13,16 +13,14 @@
<result column="requires_manual_review" property="requiresManualReview"/> <result column="requires_manual_review" property="requiresManualReview"/>
<result column="is_deleted" property="isDeleted"/> <result column="is_deleted" property="isDeleted"/>
<result column="reviewer_id" property="reviewerId"/> <result column="reviewer_id" property="reviewerId"/>
<result column="review_comment" property="reviewComment"/>
<result column="reviewed_at" property="reviewedAt"/>
<result column="created_at" property="createdAt"/> <result column="created_at" property="createdAt"/>
<result column="updated_at" property="updatedAt"/> <result column="updated_at" property="updatedAt"/>
</resultMap> </resultMap>
<sql id="AnnotationResultColumns"> <sql id="AnnotationResultColumns">
id, company_id, creator_id, creator_role, task_id, resource_id, qa_content_file_path, id, company_id, creator_id, creator_role, task_id, resource_id, qa_content_file_path,
diff_summary_file_path, requires_manual_review, is_deleted, reviewer_id, review_comment, diff_summary_file_path, requires_manual_review, is_deleted, reviewer_id,
reviewed_at, created_at, updated_at created_at, updated_at
</sql> </sql>
<select id="findActiveByIdAndCompanyId" resultMap="AnnotationResultResultMap"> <select id="findActiveByIdAndCompanyId" resultMap="AnnotationResultResultMap">
@@ -37,12 +35,19 @@
<update id="markArchived"> <update id="markArchived">
update annotation_result update annotation_result
set is_deleted = true, set is_deleted = true,
reviewer_id = #{reviewerId}, reviewer_id = #{reviewerId}
review_comment = #{reviewComment},
reviewed_at = #{reviewedAt},
updated_at = #{reviewedAt}
where id = #{id} where id = #{id}
and company_id = #{companyId} and company_id = #{companyId}
and is_deleted = false and is_deleted = false
</update> </update>
</mapper>
<update id="markReviewedAndArchived">
update annotation_result
set is_deleted = true,
requires_manual_review = false,
reviewer_id = #{reviewerId}
where id = #{id}
and company_id = #{companyId}
and is_deleted = false
</update>
</mapper>

View File

@@ -7,7 +7,6 @@
<result column="creator_id" property="creatorId"/> <result column="creator_id" property="creatorId"/>
<result column="creator_role" property="creatorRole"/> <result column="creator_role" property="creatorRole"/>
<result column="task_name" property="taskName"/> <result column="task_name" property="taskName"/>
<result column="industry_type" property="industryType"/>
<result column="task_type" property="taskType"/> <result column="task_type" property="taskType"/>
<result column="task_status" property="taskStatus"/> <result column="task_status" property="taskStatus"/>
<result column="is_deleted" property="isDeleted"/> <result column="is_deleted" property="isDeleted"/>
@@ -19,7 +18,7 @@
</resultMap> </resultMap>
<sql id="AnnotationTaskColumns"> <sql id="AnnotationTaskColumns">
id, company_id, creator_id, creator_role, task_name, industry_type, task_type, id, company_id, creator_id, creator_role, task_name, task_type,
task_status, is_deleted, started_at, finished_at, error_message, created_at, updated_at task_status, is_deleted, started_at, finished_at, error_message, created_at, updated_at
</sql> </sql>

View File

@@ -66,12 +66,12 @@ INSERT INTO source_resource (
ON CONFLICT DO NOTHING; ON CONFLICT DO NOTHING;
INSERT INTO annotation_task ( INSERT INTO annotation_task (
id, company_id, creator_id, creator_role, task_name, industry_type, task_type, id, company_id, creator_id, creator_role, task_name, task_type,
task_status, is_deleted, started_at, finished_at, error_message task_status, is_deleted, started_at, finished_at, error_message
) VALUES ) VALUES
(701, 2, 4, 'EMPLOYEE', '多资源问答抽取任务', 'ELECTRICITY', 'EXTRACT_QA', (701, 2, 4, 'EMPLOYEE', '多资源问答抽取任务', 'EXTRACT_QA',
'PENDING', FALSE, NULL, NULL, NULL), 'PENDING', FALSE, NULL, NULL, NULL),
(702, 2, 4, 'EMPLOYEE', '图片问答抽取任务', 'TRANSPORT', 'EXTRACT_QA', (702, 2, 4, 'EMPLOYEE', '图片问答抽取任务', 'EXTRACT_QA',
'COMPLETED', FALSE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL) 'COMPLETED', FALSE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL)
ON CONFLICT DO NOTHING; ON CONFLICT DO NOTHING;
@@ -86,25 +86,25 @@ ON CONFLICT DO NOTHING;
INSERT INTO annotation_result ( INSERT INTO annotation_result (
id, company_id, creator_id, creator_role, task_id, task_name, resource_id, resource_name, id, company_id, creator_id, creator_role, task_id, task_name, resource_id, resource_name,
qa_content_file_path, diff_summary_file_path, qa_content_file_path, diff_summary_file_path,
requires_manual_review, is_deleted, reviewer_id, review_comment, reviewed_at requires_manual_review, is_deleted, reviewer_id
) VALUES ) VALUES
(801, 2, 3, 'EMPLOYEE', 701, '多资源问答抽取任务', 601, '设备巡检规范.txt', (801, 2, 3, 'EMPLOYEE', 701, '多资源问答抽取任务', 601, '设备巡检规范.txt',
'annotation-artifacts/qa/qa1.json', 'annotation-artifacts/qa/qa1.json',
'annotation-artifacts/diff/diff1.json', 'annotation-artifacts/diff/diff1.json',
TRUE, FALSE, NULL, NULL, NULL), TRUE, FALSE, NULL),
(802, 2, 3, 'EMPLOYEE', 702, '图片问答抽取任务', 602, '控制柜照片.jpg', (802, 2, 3, 'EMPLOYEE', 702, '图片问答抽取任务', 602, '控制柜照片.jpg',
'annotation-artifacts/qa/qa2.json', 'annotation-artifacts/qa/qa2.json',
'annotation-artifacts/diff/diff2.json', 'annotation-artifacts/diff/diff2.json',
FALSE, FALSE, 5, '结果可通过。', CURRENT_TIMESTAMP) FALSE, FALSE, 5)
ON CONFLICT DO NOTHING; ON CONFLICT DO NOTHING;
INSERT INTO annotation_result_history ( INSERT INTO annotation_result_history (
id, company_id, creator_id, creator_role, source_result_id, task_id, task_name, resource_id, resource_name, id, company_id, creator_id, creator_role, source_result_id, task_id, task_name, resource_id, resource_name,
qa_content_file_path, reviewer_id, reviewer_name, reviewer_comment, archive_reason, archived_by, archived_at qa_content_file_path, reviewer_id, reviewer_name, archive_reason, archived_by, archived_at
) VALUES ) VALUES
(901, 2, 3, 'EMPLOYEE', 802, 702, '图片问答抽取任务', 602, '控制柜照片.jpg', (901, 2, 3, 'EMPLOYEE', 802, 702, '图片问答抽取任务', 602, '控制柜照片.jpg',
'annotation-results/2/qa/802.json', 'annotation-results/2/qa/802.json',
5, '甲公司审核员', '结果可通过。', '审核通过后归档', 5, CURRENT_TIMESTAMP) 5, '甲公司审核员', '审核通过后归档', 5, CURRENT_TIMESTAMP)
ON CONFLICT DO NOTHING; ON CONFLICT DO NOTHING;
INSERT INTO image_bbox_annotation ( INSERT INTO image_bbox_annotation (

View File

@@ -199,7 +199,6 @@ CREATE TABLE IF NOT EXISTS annotation_task
creator_id BIGINT NOT NULL, creator_id BIGINT NOT NULL,
creator_role VARCHAR(32) NOT NULL DEFAULT 'EMPLOYEE', creator_role VARCHAR(32) NOT NULL DEFAULT 'EMPLOYEE',
task_name VARCHAR(255) NOT NULL, task_name VARCHAR(255) NOT NULL,
industry_type VARCHAR(32) NOT NULL DEFAULT 'GENERAL',
task_type VARCHAR(32) NOT NULL DEFAULT 'EXTRACT_QA', task_type VARCHAR(32) NOT NULL DEFAULT 'EXTRACT_QA',
task_status VARCHAR(32) NOT NULL DEFAULT 'PENDING', task_status VARCHAR(32) NOT NULL DEFAULT 'PENDING',
is_deleted BOOLEAN NOT NULL DEFAULT FALSE, is_deleted BOOLEAN NOT NULL DEFAULT FALSE,
@@ -218,7 +217,6 @@ COMMENT ON COLUMN annotation_task.company_id IS '所属公司ID。';
COMMENT ON COLUMN annotation_task.creator_id IS '任务创建人用户ID。'; COMMENT ON COLUMN annotation_task.creator_id IS '任务创建人用户ID。';
COMMENT ON COLUMN annotation_task.creator_role IS '任务创建人数据权限角色,默认 EMPLOYEE。'; COMMENT ON COLUMN annotation_task.creator_role IS '任务创建人数据权限角色,默认 EMPLOYEE。';
COMMENT ON COLUMN annotation_task.task_name IS '任务名称。'; COMMENT ON COLUMN annotation_task.task_name IS '任务名称。';
COMMENT ON COLUMN annotation_task.industry_type IS '行业类型简写,默认 transport可选值按业务扩展。';
COMMENT ON COLUMN annotation_task.task_type IS '任务类型,默认 EXTRACT_QA。'; COMMENT ON COLUMN annotation_task.task_type IS '任务类型,默认 EXTRACT_QA。';
COMMENT ON COLUMN annotation_task.task_status IS '任务状态,默认 PENDING可选 RUNNING、COMPLETED、FAILED。'; COMMENT ON COLUMN annotation_task.task_status IS '任务状态,默认 PENDING可选 RUNNING、COMPLETED、FAILED。';
COMMENT ON COLUMN annotation_task.is_deleted IS '任务软删除标记,默认 FALSE。'; COMMENT ON COLUMN annotation_task.is_deleted IS '任务软删除标记,默认 FALSE。';
@@ -263,8 +261,6 @@ CREATE TABLE IF NOT EXISTS annotation_result
requires_manual_review BOOLEAN NOT NULL DEFAULT FALSE, requires_manual_review BOOLEAN NOT NULL DEFAULT FALSE,
is_deleted BOOLEAN NOT NULL DEFAULT FALSE, is_deleted BOOLEAN NOT NULL DEFAULT FALSE,
reviewer_id BIGINT, reviewer_id BIGINT,
review_comment TEXT,
reviewed_at TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_annotation_result_company FOREIGN KEY (company_id) REFERENCES sys_company (id), CONSTRAINT fk_annotation_result_company FOREIGN KEY (company_id) REFERENCES sys_company (id),
@@ -286,8 +282,6 @@ COMMENT ON COLUMN annotation_result.diff_summary_file_path IS '差异摘要文
COMMENT ON COLUMN annotation_result.requires_manual_review IS '是否需要人工审核,默认 FALSE。当diff_summary_file_path不为空时为TRUE。'; COMMENT ON COLUMN annotation_result.requires_manual_review IS '是否需要人工审核,默认 FALSE。当diff_summary_file_path不为空时为TRUE。';
COMMENT ON COLUMN annotation_result.is_deleted IS '软删除标记,默认 FALSE。'; COMMENT ON COLUMN annotation_result.is_deleted IS '软删除标记,默认 FALSE。';
COMMENT ON COLUMN annotation_result.reviewer_id IS '审核人用户ID。'; COMMENT ON COLUMN annotation_result.reviewer_id IS '审核人用户ID。';
COMMENT ON COLUMN annotation_result.review_comment IS '审核意见。';
COMMENT ON COLUMN annotation_result.reviewed_at IS '审核时间。';
COMMENT ON COLUMN annotation_result.created_at IS '创建时间。'; COMMENT ON COLUMN annotation_result.created_at IS '创建时间。';
COMMENT ON COLUMN annotation_result.updated_at IS '更新时间。'; COMMENT ON COLUMN annotation_result.updated_at IS '更新时间。';
COMMENT ON COLUMN annotation_result.task_name IS '任务名称(冗余字段)。'; COMMENT ON COLUMN annotation_result.task_name IS '任务名称(冗余字段)。';
@@ -307,7 +301,6 @@ CREATE TABLE IF NOT EXISTS annotation_result_history
qa_content_file_path VARCHAR(512) NOT NULL, qa_content_file_path VARCHAR(512) NOT NULL,
reviewer_id BIGINT, reviewer_id BIGINT,
reviewer_name VARCHAR(128), reviewer_name VARCHAR(128),
reviewer_comment TEXT,
archive_reason VARCHAR(256), archive_reason VARCHAR(256),
archived_by BIGINT, archived_by BIGINT,
archived_at TIMESTAMP, archived_at TIMESTAMP,
@@ -336,7 +329,6 @@ COMMENT ON COLUMN annotation_result_history.archived_at IS '归档时间。';
COMMENT ON COLUMN annotation_result_history.created_at IS '创建时间。'; COMMENT ON COLUMN annotation_result_history.created_at IS '创建时间。';
COMMENT ON COLUMN annotation_result_history.reviewer_id IS '审核人用户ID。自动归档时为NULL。'; COMMENT ON COLUMN annotation_result_history.reviewer_id IS '审核人用户ID。自动归档时为NULL。';
COMMENT ON COLUMN annotation_result_history.reviewer_name IS '审核人姓名。自动归档时为"auto"。'; COMMENT ON COLUMN annotation_result_history.reviewer_name IS '审核人姓名。自动归档时为"auto"。';
COMMENT ON COLUMN annotation_result_history.reviewer_comment IS '审核意见。自动归档时为"auto"。';
COMMENT ON COLUMN annotation_result_history.task_name IS '任务名称(冗余字段)。'; COMMENT ON COLUMN annotation_result_history.task_name IS '任务名称(冗余字段)。';
COMMENT ON COLUMN annotation_result_history.resource_name IS '资源名称(冗余字段)。'; COMMENT ON COLUMN annotation_result_history.resource_name IS '资源名称(冗余字段)。';