适配QA问答对数据结构
This commit is contained in:
5
pom.xml
5
pom.xml
@@ -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>
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
@@ -9,7 +9,7 @@ public record MergeReviewResultRequest(
|
|||||||
@Schema(description = "合并后的答案映射,key为qa记录ID,value为合并后的答案")
|
@Schema(description = "合并后的答案映射,key为qa记录ID,value为合并后的答案")
|
||||||
Map<String, String> mergedAnswers,
|
Map<String, String> mergedAnswers,
|
||||||
|
|
||||||
@Schema(description = "审核备注")
|
@Schema(description = "每条QA记录的审核评论映射,key为qa记录ID,value为审核评论")
|
||||||
String reviewComment
|
Map<String, String> reviewComments
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -37,5 +37,4 @@ public class AnnotationResultHistory {
|
|||||||
// 新增审核人相关字段
|
// 新增审核人相关字段
|
||||||
private Long reviewerId;
|
private Long reviewerId;
|
||||||
private String reviewerName;
|
private String reviewerName;
|
||||||
private String reviewerComment;
|
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,5 @@ 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);
|
|
||||||
}
|
}
|
||||||
@@ -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,8 +208,7 @@ 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 内容
|
// 从对象存储读取 qa.json 内容
|
||||||
@@ -177,22 +231,64 @@ public class AnnotationResultArchiveService {
|
|||||||
.archivedAt(archivedAt)
|
.archivedAt(archivedAt)
|
||||||
.reviewerId(null)
|
.reviewerId(null)
|
||||||
.reviewerName("auto")
|
.reviewerName("auto")
|
||||||
.reviewerComment("auto")
|
|
||||||
.build();
|
.build();
|
||||||
annotationResultHistoryMapper.insert(history);
|
annotationResultHistoryMapper.insert(history);
|
||||||
|
|
||||||
int updated = annotationResultMapper.markArchived(
|
int updated = annotationResultMapper.markArchived(
|
||||||
result.getId(),
|
result.getId(),
|
||||||
result.getCompanyId(),
|
result.getCompanyId(),
|
||||||
reviewerId,
|
reviewerId);
|
||||||
reviewComment,
|
|
||||||
archivedAt);
|
|
||||||
if (updated == 0) {
|
if (updated == 0) {
|
||||||
return null;
|
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 +335,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 +347,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 +367,5 @@ public class AnnotationResultArchiveService {
|
|||||||
throw new BusinessException(ResultCode.ERROR, "加载文件内容失败");
|
throw new BusinessException(ResultCode.ERROR, "加载文件内容失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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,11 +296,18 @@ public class AnnotationResultService {
|
|||||||
);
|
);
|
||||||
saveQaContent(result, updatedQaContent);
|
saveQaContent(result, updatedQaContent);
|
||||||
|
|
||||||
// 更新数据库记录
|
// 更新数据库记录(使用 markArchived 保证幂等性,防止并发重复归档)
|
||||||
result.setIsDeleted(Boolean.TRUE);
|
int updated = annotationResultMapper.markArchived(
|
||||||
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, "记录已被归档");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新 requires_manual_review 字段
|
||||||
result.setRequiresManualReview(false);
|
result.setRequiresManualReview(false);
|
||||||
annotationResultMapper.updateById(result);
|
annotationResultMapper.updateById(result);
|
||||||
|
|
||||||
@@ -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为NULL,name和comment为"auto"
|
// 自动归档:reviewer_id为NULL,name为"auto"
|
||||||
historyBuilder
|
historyBuilder
|
||||||
.reviewerId(null)
|
.reviewerId(null)
|
||||||
.reviewerName("auto")
|
.reviewerName("auto");
|
||||||
.reviewerComment("auto");
|
|
||||||
} else {
|
} else {
|
||||||
// 人工审核后归档:使用审核人信息
|
// 人工审核后归档:使用审核人信息
|
||||||
historyBuilder
|
historyBuilder
|
||||||
.reviewerId(result.getReviewerId())
|
.reviewerId(result.getReviewerId())
|
||||||
.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,7 +512,12 @@ 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) {
|
||||||
|
|||||||
@@ -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,10 +35,7 @@
|
|||||||
<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
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
|||||||
@@ -263,8 +263,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 +284,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 +303,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 +331,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 '资源名称(冗余字段)。';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user