Merge remote-tracking branch 'origin/main'

This commit is contained in:
jiang 2024-11-25 10:57:12 +08:00
commit 4e0d660338
10 changed files with 205 additions and 25 deletions

View File

@ -1,21 +1,24 @@
package com.bonus.ai.client;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class OnlineAnnotateUtil {
final static String template = "<View><RectangleLabels name=\"label\" toName=\"image\">.*?</RectangleLabels></View>";
/**
* 替换 View 中的 Label 标签内容
* @param template 原始字符串模板
* @param labels 要替换的 labels 列表
* @return 替换后的字符串
*/
public static String rectangleImageLabels(String template, List<String> labels) {
public static String rectangleImageLabels(List<String> labels) {
if (labels == null || labels.isEmpty()){
return "";
}
// 构建新的 Label 标签内容
StringBuilder labelBuilder = new StringBuilder();
String[] colors = {"#FFA39E", "#D4380D", "#36CFC9", "#FF85C0", "#FFD666"}; // 颜色数组
String[] colors = {"blue", "green", "orange", "purge"}; // 颜色数组
int colorIndex = 0;
for (String label : labels) {
@ -36,5 +39,20 @@ public class OnlineAnnotateUtil {
);
}
/**
* <View>
* <Image name="image" value="$image" zoom="true" rotateControl="true" />
* <RectangleLabels name="label" toName="image">
* <Label value="Person" background="blue"/>
* <Label value="Car" background="green"/>
* </RectangleLabels>
* </View>
*/
public static void main(String[] args) {
// List<String> labels = Arrays.asList("label1", "label2", "label3");
List<String> labels = Stream.of("label1", "label2", "label3")
.collect(Collectors.toList());
String result = rectangleImageLabels(labels);
System.out.println(result);
}
}

View File

@ -2,8 +2,6 @@ package com.bonus.ai.controller;
import com.bonus.ai.domain.DataSetBasicFileEntity;
import com.bonus.ai.service.DataSetBasicFileService;
import com.bonus.common.core.constant.HttpStatus;
import com.bonus.common.core.utils.Base64Utils;
import com.bonus.common.core.utils.poi.ExcelUtil;
import com.bonus.common.core.web.controller.BaseController;
import com.bonus.common.core.web.domain.AjaxResult;

View File

@ -28,7 +28,8 @@ public class AnnotationTaskController extends BaseController {
*/
@PostMapping("/create")
public AjaxResult add(@Validated @RequestBody AnnotationTaskEntity task) {
return AjaxResult.success();
int status = annotationTaskService.createTask(task);
return status == 1 ? AjaxResult.success() : AjaxResult.error("创建任务失败");
}
/**修改任务
@ -37,6 +38,7 @@ public class AnnotationTaskController extends BaseController {
*/
@PostMapping("/edit")
public AjaxResult edit(@Validated @RequestBody AnnotationTaskEntity task) {
return AjaxResult.success();
}
@ -47,6 +49,7 @@ public class AnnotationTaskController extends BaseController {
*/
@PostMapping("/delete/{taskId}")
public AjaxResult remove(@PathVariable Long taskId) {
annotationTaskService.deleteTaskById(taskId);
return AjaxResult.success();
}

View File

@ -1,10 +1,12 @@
package com.bonus.ai.domain.dataset;
import lombok.Data;
import org.springframework.stereotype.Component;
import java.util.Date;
@Data
public class AnnotationTaskAnnotatorMap {
@Component
public class AnnotationTaskAnnotatorEntity {
private Long annotatorId; // 标注人员
private Long reviewerId; // 审核人员
@ -22,4 +24,4 @@ public class AnnotationTaskAnnotatorMap {
private String updateBy; // 更新者
private Date updateTime; // 更新时间
private Date createTime; // 创建时间
}
}

View File

@ -4,10 +4,13 @@ import com.bonus.ai.domain.enums.AnnotationFileStatus;
import com.bonus.ai.domain.enums.AnnotationTaskStatus;
import com.bonus.common.core.web.domain.BaseEntity;
import lombok.Data;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.List;
@Data
@Component
public class AnnotationTaskEntity extends BaseEntity {
/**任务名称*/

View File

@ -1,5 +1,6 @@
package com.bonus.ai.mapper;
import com.bonus.ai.domain.dataset.AnnotationTaskAnnotatorEntity;
import com.bonus.ai.domain.dataset.AnnotationTaskEntity;
import java.util.List;
@ -38,7 +39,7 @@ public interface AnnotationTaskMapper
* @param taskId 任务ID
* @return 标注任务实体
*/
AnnotationTaskEntity selectAnnotationTaskById(Long taskId);
// AnnotationTaskEntity selectAnnotationTaskById(Long taskId);
/**
* 查询标注任务列表
@ -46,4 +47,12 @@ public interface AnnotationTaskMapper
* @return 标注任务列表
*/
List<AnnotationTaskEntity> selectAnnotationTaskList(AnnotationTaskEntity annotationTask);
}
int insertAnnotTaskannotator(List<AnnotationTaskAnnotatorEntity> annotationTaskAnnotatorEntities);
int deleteTaskById(Long taskId);
int deleteAnnotator(Long taskId);
AnnotationTaskEntity selectAnnotationTaskListUUID(Long taskId);
}

View File

@ -1,19 +1,20 @@
package com.bonus.ai.service.Impl.dataset;
import com.bonus.ai.client.OnlineAnnotateUtil;
import com.alibaba.fastjson.JSON;
import com.bonus.ai.client.OnlineAnnotationService;
import com.bonus.ai.client.ProjectParam;
import com.bonus.ai.client.TaskParam;
import com.bonus.ai.config.MinioConfig;
import com.bonus.ai.config.OnlineAnnotateConfig;
import com.bonus.ai.domain.dataset.AnnotationSubTaskEntity;
import com.bonus.ai.domain.dataset.AnnotationTaskEntity;
import com.bonus.ai.domain.dataset.DataSetEntity;
import com.bonus.ai.domain.dataset.*;
import com.bonus.ai.mapper.AnnotationTaskMapper;
import com.bonus.ai.mapper.DatasetFileMapper;
import com.bonus.ai.service.dataset.AnnotationTaskService;
import com.bonus.ai.utils.AverageUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;
@Slf4j
@Service
@ -26,21 +27,51 @@ public class AnnotationTaskServiceImpl implements AnnotationTaskService {
@Resource
private OnlineAnnotateConfig onlineAnnotateConfig;
@Resource
private AnnotationTaskMapper annotationTaskMapper;
@Resource
private DatasetFileMapper datasetFileMapper;
@Autowired
private AnnotationTaskEntity annotationTaskEntity;
@Autowired
private AnnotationTaskAnnotatorEntity annotationTaskAnnotatorEntity;
/**
* 创建标注任务
*/
@Override
public int createTask(AnnotationTaskEntity task) {
int status =0;
// TODO 调用label studio 接口获取其project id
ProjectParam lSProject = new ProjectParam();
lSProject.setTitle(task.getTaskName());
lSProject.setDescription(task.getTaskDesc());
//需要将标签转换为json格式
lSProject.setLabelConfig(task.getLabels());
onlineAnnotationService.createProject(lSProject, onlineAnnotateConfig.getApikey());
String project = onlineAnnotationService.createProject(lSProject, onlineAnnotateConfig.getApikey());
List<ProjectParam> projectParams = JSON.parseArray(project, ProjectParam.class);
if (projectParams.size() > 0) {
Long projectId = Long.valueOf(projectParams.get(0).getId());
task.setProjectId(projectId);
for(ProjectParam projectParam: projectParams){
//需要生成32位uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
task.setTaskUuid(uuid);
status= annotationTaskMapper.insertAnnotationTask(task);
}
}
//通过数据集id 从数据集和文件关联关系表获取文件信息
List<DatasetFile> datafile = datasetFileMapper.selectFilesByDatasetId(task.getDatasetId());
//TODO 根据标注任务file list 和标注人信息自动分配
List<AnnotationTaskAnnotatorEntity> annotationTaskAnnotatorEntities = AverageUtil.distributeFiles(datafile, task);
// 获取project id以后调用AnnotationTaskMapper 和AnnotationTaskAnnotatorMapper 插入数据集
return 0;
if(status == 1){
status = annotationTaskMapper.insertAnnotTaskannotator(annotationTaskAnnotatorEntities);
}
return status;
}
@ -73,7 +104,21 @@ public class AnnotationTaskServiceImpl implements AnnotationTaskService {
*/
@Override
public int deleteTaskById(Long taskId) {
return 0;
//删除任务需要删除两个个表 对应两个个表删除状态修改成1
int status = 0;
try{
//删除主表任务信息
status = annotationTaskMapper.deleteTaskById(taskId);
//删除团队成员表信息
status = annotationTaskMapper.deleteAnnotator(taskId);
//查询对应的uuid
AnnotationTaskEntity task = annotationTaskMapper.selectAnnotationTaskListUUID(taskId);
//删除对应的标注任务文件关联关系表信息
onlineAnnotationService.deleteProjectById(task.getTaskUuid(), onlineAnnotateConfig.getApikey());
}catch (Exception e){
e.printStackTrace();
}
return status;
}
/**

View File

@ -0,0 +1,45 @@
package com.bonus.ai.utils;
import com.bonus.ai.domain.dataset.AnnotationTaskAnnotatorEntity;
import com.bonus.ai.domain.dataset.AnnotationTaskEntity;
import com.bonus.ai.domain.dataset.DatasetFile;
import java.util.ArrayList;
import java.util.List;
public class AverageUtil {
/**
* 将文件集合分别平分到 annotators reviewers
* @param files 文件集合
* @param taskEntity 标注任务实体
* @return 分配结果包含标注者和审核者的文件分配
*/
public static List<AnnotationTaskAnnotatorEntity> distributeFiles(List<DatasetFile> files, AnnotationTaskEntity taskEntity) {
List<AnnotationTaskAnnotatorEntity> annotatorEntities = new ArrayList<>();
List<Long> annotators = taskEntity.getAnnotators(); // 获取标注者列表
List<Long> reviewers = taskEntity.getReviewers(); // 获取审核者列表
// 平分文件给标注者
for (int i = 0; i < files.size(); i++) {
Long annotatorId = annotators.get(i % annotators.size()); // 轮流分配给标注者
AnnotationTaskAnnotatorEntity entity = new AnnotationTaskAnnotatorEntity();
entity.setAnnotatorId(annotatorId); // 设置标注者 ID
entity.setFileId(files.get(i).getFileId()); // 假设 DatasetFile getId() 方法
annotatorEntities.add(entity);
}
// 平分文件给审核者
for (int i = 0; i < files.size(); i++) {
Long reviewerId = reviewers.get(i % reviewers.size()); // 轮流分配给审核者
AnnotationTaskAnnotatorEntity entity = new AnnotationTaskAnnotatorEntity();
entity.setAnnotatorId(reviewerId); // 设置审核者 ID
entity.setFileId(files.get(i).getFileId()); // 假设 DatasetFile getId() 方法
annotatorEntities.add(entity);
}
return annotatorEntities;
}
}

View File

@ -28,6 +28,16 @@
FROM ai_annotation_task t
left join ai_annotation_task_annotator_map a on t.task_id = a.task_id
</sql>
<update id="deleteTaskById">
UPDATE ai_annotation_task
SET del_flag = '1'
WHERE task_id = #{taskId}
</update>
<update id="deleteAnnotator">
UPDATE ai_annotation_task_annotator_map
SET del_flag = '1'
WHERE task_id = #{taskId}
</update>
<!-- TODO 根据标注人id查询所有标注文件列表-->
@ -57,6 +67,9 @@
AND annotation_status = #{annotateTaskStatus}
</if>
</select>
<select id="selectAnnotationTaskListUUID" resultType="com.bonus.ai.domain.dataset.AnnotationTaskEntity">
SELECT task_uuid FROM ai_annotation_task where del_flag = 0
</select>
<!-- 插入标注任务 -->
<insert id="insertAnnotationTask" parameterType="com.bonus.ai.domain.dataset.AnnotationTaskEntity">
@ -96,6 +109,51 @@
<if test="updateTime != null">#{updateTime},</if>
</trim>
</insert>
<insert id="insertAnnotTaskannotator">
INSERT INTO ai_annotation_task_annotator_map
<trim prefix="(" suffix=")" suffixOverrides=",">
task_id
<if test="annotatorId != null">
, annotator_id
</if>
<if test="reviewerId != null">
, reviewer_id
</if>
<if test="description != null and description != ''">
, description
</if>
<if test="annotationStatus != null">
, annotation_status
</if>
<if test="annotationResult != null">
, annotation_result
</if>
<if test="annotationResource != null">
, annotation_resource
</if>
</trim>
<trim prefix="VALUES (" suffix=")" suffixOverrides=",">
#{taskId}
<if test="annotatorId != null">
, #{annotatorId}
</if>
<if test="reviewerId != null">
, #{reviewerId}
</if>
<if test="description != null and description != ''">
, #{description}
</if>
<if test="annotationStatus != null">
, #{annotationStatus}
</if>
<if test="annotationResult != null">
, #{annotationResult}
</if>
<if test="annotationResource != null">
, #{annotationResource}
</if>
</trim>
</insert>
<!-- 根据任务ID更新标注任务 -->

View File

@ -27,13 +27,12 @@
</delete>
<!-- 删除数据集文件映射关系 -->
<delete id="deleteDatasetFiles" parameterType="String">
delete from ai_dataset_file_map
where dataset_id in
<update id="deleteDatasetFiles">
update FROM ai_dataset_file_map
<foreach collection="array" item="datasetId" open="(" separator="," close=")">
#{datasetId}
</foreach>
</delete>
</update>
<!-- <delete id="deleteDatasetFiles">-->
<!-- DELETE FROM ai_dataset_file_map-->