Merge remote-tracking branch 'origin/main'

This commit is contained in:
jiang 2024-11-25 18:10:34 +08:00
commit 14ae1e1fb3
18 changed files with 694 additions and 313 deletions

View File

@ -6,13 +6,17 @@ 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>";
final static String template = "<View><Image name=\"image\" value=\"$image\"/><RectangleLabels name=\"label\" toName=\"image\">.*?</RectangleLabels></View>";
/**
* 替换 View 中的 Label 标签内容
* @param labels 要替换的 labels 列表
* @return 替换后的字符串
*/
public static String rectangleImageLabels(List<String> labels) {
public static String rectangleImageLabels(String labelsStr) {
if ( labelsStr.isEmpty()) {
return "";
}
// 使用 split 分割字符串并转换为 List
List<String> labels = Arrays.asList(labelsStr.split(","));
if (labels == null || labels.isEmpty()){
return "";
}
@ -48,11 +52,11 @@ public class OnlineAnnotateUtil {
* </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);
}
// 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

@ -1,83 +0,0 @@
package com.bonus.ai.client;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
@Component
public class OnlineAnnotationFallbackFactory implements FallbackFactory<OnlineAnnotationService> {
private static final Logger log = LoggerFactory.getLogger(OnlineAnnotationFallbackFactory.class);
@Override
public OnlineAnnotationService create(Throwable throwable) {
log.error("系统服务调用失败:{}", throwable.getMessage());
return new OnlineAnnotationService() {
@Override
public String createProject(ProjectParam projectParam, String authorization) {
return null;
}
@Override
public String getProjectById(String id, String authorization) {
return "";
}
@Override
public boolean deleteProjectById(String id, String authorization) {
return false;
}
@Override
public String updateProject(ProjectParam projectParam, String authorization) {
return "";
}
@Override
public String createTask(TaskParam task, String authorization) {
return null;
}
@Override
public String getTaskById(String id, String authorization) {
return "";
}
@Override
public boolean deleteTaskById(String id, String authorization) {
return false;
}
@Override
public String updateTask(TaskParam task, String authorization) {
return "";
}
@Override
public String createAnnotation(AnnotationParam annotationParam, String authorization) {
return "";
}
@Override
public String getAnnotationById(String id, String authorization) {
return "";
}
@Override
public boolean deleteAnnotationById(String id, String authorization) {
return false;
}
@Override
public String updateAnnotation(AnnotationParam annotationParam, String authorization) {
return "";
}
};
}
}

View File

@ -1,72 +0,0 @@
package com.bonus.ai.client;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
@FeignClient(name = "onlineAnnotationService")
public interface OnlineAnnotationService {
/**
* project <------> 人工智能数据中心的标注任务
* project 增删改查
*/
@PostMapping("/api/projects/")
public String createProject(@RequestBody ProjectParam projectParam, @RequestHeader(AIConstants.AUTHORIZATION_HEADER) String authorization);
@GetMapping("/api/projects/{id}/")
public String getProjectById(@PathVariable("id") String id, @RequestHeader(AIConstants.AUTHORIZATION_HEADER) String authorization);
@DeleteMapping("/api/projects/{id}/")
public boolean deleteProjectById(@PathVariable("id") String id, @RequestHeader(AIConstants.AUTHORIZATION_HEADER) String authorization);
@PatchMapping("/api/projects/")
public String updateProject(@RequestBody ProjectParam projectParam, @RequestHeader(AIConstants.AUTHORIZATION_HEADER) String authorization);
/**
* task <------> 人工智能数据中心的具体的标注文件
* task 增删改查
*/
@PostMapping("/api/tasks/")
public String createTask(@RequestBody TaskParam task, @RequestHeader(AIConstants.AUTHORIZATION_HEADER) String authorization);
@GetMapping("/api/tasks/{id}/")
public String getTaskById(@PathVariable("id") String id, @RequestHeader(AIConstants.AUTHORIZATION_HEADER) String authorization);
@DeleteMapping("/api/tasks/{id}/")
public boolean deleteTaskById(@PathVariable("id") String id, @RequestHeader(AIConstants.AUTHORIZATION_HEADER) String authorization);
@PatchMapping("/api/tasks/")
public String updateTask(@RequestBody TaskParam task, @RequestHeader(AIConstants.AUTHORIZATION_HEADER) String authorization);
/**
* annotation <------> 人工智能数据中心的标注结果
* annotation 增删改查
*/
@PostMapping("/api/tasks/{id}/annotations/")
public String createAnnotation(@RequestBody AnnotationParam annotationParam, @RequestHeader(AIConstants.AUTHORIZATION_HEADER) String authorization);
@GetMapping("/api/annotations/{id}")
public String getAnnotationById(@PathVariable("id") String id, @RequestHeader(AIConstants.AUTHORIZATION_HEADER) String authorization);
@DeleteMapping("/api/annotations/{id}")
public boolean deleteAnnotationById(@PathVariable("id") String id, @RequestHeader(AIConstants.AUTHORIZATION_HEADER) String authorization);
@PatchMapping("/api/tasks/{id}/annotations/")
public String updateAnnotation(@RequestBody AnnotationParam annotationParam, @RequestHeader(AIConstants.AUTHORIZATION_HEADER) String authorization);
/**
* 导出指定project的所有标注结果
*/
// @GetMapping("/api/project/{id}/export")
// public String exportAnnotationByProjectId(@PathVariable("id") String id, @RequestHeader(AIConstants.AUTHORIZATION_HEADER) String authorization);
//
// @GetMapping("/api/annotations/{id}")
// public String exportAnnotationByTaskIds(@PathVariable("id") String id, @RequestHeader(AIConstants.AUTHORIZATION_HEADER) String authorization);
}

View File

@ -0,0 +1,159 @@
package com.bonus.ai.client;
import com.bonus.ai.config.OnlineAnnotateConfig;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.stereotype.Service;
import java.io.IOException;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.annotation.Resource;
@Slf4j
@Service
public class OnlineAnnotationServiceOkHttp {
private static final OkHttpClient client = new OkHttpClient();
private static final ObjectMapper objectMapper = new ObjectMapper(); // 用于JSON序列化和反序列化
//private static final String BASE_URL = "http://127.0.0.1:8080/api/projects/"; // 替换为实际URL
@Resource
private OnlineAnnotateConfig onlineAnnotateConfig;
/**
* project <------> 人工智能数据中心的标注任务
* project 增删改查
*/
// Create project
public ProjectParam createProject(ProjectInputParam projectParam) throws IOException {
String url = onlineAnnotateConfig.getUrl()+ "/projects/";
String json = objectMapper.writeValueAsString(projectParam);
RequestBody body = RequestBody.create(json, MediaType.parse("application/json"));
log.error("Request JSON: " + json);
Request request = new Request.Builder()
.url(url)
.post(body)
.addHeader("Authorization", onlineAnnotateConfig.getApikey())
.build();
String response = executeRequest(request);
return ProjectParam.fromJson(response);
}
// Get project by ID
public ProjectParam getProjectById(String id) throws IOException {
String url = onlineAnnotateConfig.getUrl()+ "/projects/" + id + "/";
Request request = new Request.Builder()
.url(url)
.get()
.addHeader("Authorization", onlineAnnotateConfig.getApikey())
.build();
String response = executeRequest(request);
return ProjectParam.fromJson(response);
}
// Delete project by ID
public boolean deleteProjectById(String id) throws IOException {
String url = onlineAnnotateConfig.getUrl()+ "/projects/" + id + "/";
Request request = new Request.Builder()
.url(url)
.delete()
.addHeader("Authorization", onlineAnnotateConfig.getApikey())
.build();
String response = executeRequest(request);
return response != null && !response.isEmpty();
}
// Update project
public ProjectParam updateProject(ProjectInputParam projectParam) throws IOException {
String url = onlineAnnotateConfig.getUrl()+ "/projects/"+ projectParam.getId() + "/";
String json = objectMapper.writeValueAsString(projectParam);
RequestBody body = RequestBody.create(json, MediaType.parse("application/json"));
Request request = new Request.Builder()
.url(url)
.patch(body)
.addHeader("Authorization", onlineAnnotateConfig.getApikey())
.build();
String response = executeRequest(request);
return ProjectParam.fromJson(response);
}
/**
* task <------> 人工智能数据中心的具体的标注文件
* task 增删改查
*/
public TaskParam createTask(TaskParam taskParam) throws IOException {
String url = onlineAnnotateConfig.getUrl()+ "/tasks/";
String json = objectMapper.writeValueAsString(taskParam);
RequestBody body = RequestBody.create(json, MediaType.parse("application/json"));
log.error("Request JSON: " + json);
Request request = new Request.Builder()
.url(url)
.post(body)
.addHeader("Authorization", onlineAnnotateConfig.getApikey())
.build();
String response = executeRequest(request);
return TaskParam.fromJson(response);
}
public TaskParam getTaskById(String id) throws IOException {
String url = onlineAnnotateConfig.getUrl()+ "/tasks/" + id + "/";
Request request = new Request.Builder()
.url(url)
.get()
.addHeader("Authorization", onlineAnnotateConfig.getApikey())
.build();
String response = executeRequest(request);
return TaskParam.fromJson(response);
}
public boolean deleteTaskById(String id) throws IOException {
String url = onlineAnnotateConfig.getUrl()+ "/tasks/" + id + "/";
Request request = new Request.Builder()
.url(url)
.delete()
.addHeader("Authorization", onlineAnnotateConfig.getApikey())
.build();
String response = executeRequest(request);
return response != null && !response.isEmpty();
}
public TaskParam updateTask(TaskParam taskParam) throws IOException {
String url = onlineAnnotateConfig.getUrl()+ "/tasks/"+ taskParam.getId() + "/";
String json = objectMapper.writeValueAsString(taskParam);
RequestBody body = RequestBody.create(json, MediaType.parse("application/json"));
Request request = new Request.Builder()
.url(url)
.patch(body)
.addHeader("Authorization", onlineAnnotateConfig.getApikey())
.build();
String response = executeRequest(request);
return TaskParam.fromJson(response);
}
// Execute the request
private String executeRequest(Request request) throws IOException {
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
return response.body() != null ? response.body().string() : null;
}
}
}

View File

@ -0,0 +1,124 @@
package com.bonus.ai.client;
//public class ParsedLabelConfig {
//}
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class ParsedLabelConfig {
@JsonProperty("label")
private Label label;
@Data
public static class Label {
@JsonProperty("type")
private String type;
@JsonProperty("to_name")
private List<String> toName;
@JsonProperty("inputs")
private List<Input> inputs;
@JsonProperty("labels")
private List<String> labels;
@JsonProperty("labels_attrs")
private Map<String, LabelAttributes> labelsAttrs;
}
@Data
public static class Input {
@JsonProperty("type")
private String type;
@JsonProperty("value")
private String value;
@JsonProperty("valueType")
private String valueType; // 注意JSON 中为 `null` Java 中用 `String` 表示
}
@Data
public static class LabelAttributes {
@JsonProperty("value")
private String value;
@JsonProperty("background")
private String background;
}
/**
* JSON 字符串解析为实体类对象
*/
public static ParsedLabelConfig fromJson(String json) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(json, ParsedLabelConfig.class);
}
/**
* 将实体类对象转换为 JSON 字符串
*/
public String toJson() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(this);
}
public static void main(String[] args) throws JsonProcessingException {
String json = "{\n" +
" \"parsed_label_config\": {\n" +
" \"label\": {\n" +
" \"type\": \"RectangleLabels\",\n" +
" \"to_name\": [\"image\"],\n" +
" \"inputs\": [\n" +
" {\n" +
" \"type\": \"Image\",\n" +
" \"value\": \"image\",\n" +
" \"valueType\": null\n" +
" }\n" +
" ],\n" +
" \"labels\": [\"person\", \"cat\"],\n" +
" \"labels_attrs\": {\n" +
" \"person\": {\n" +
" \"value\": \"person\",\n" +
" \"background\": \"#FFA39E\"\n" +
" },\n" +
" \"cat\": {\n" +
" \"value\": \"cat\",\n" +
" \"background\": \"#D4380D\"\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
// ParsedLabelConfig record = ParsedLabelConfig.fromJson(json);
//
// System.out.println(record);
// 提取 "parsed_label_config" 部分
ObjectMapper mapper = new ObjectMapper();
String parsedLabelConfigJson = mapper.readTree(json).get("parsed_label_config").toString();
// JSON 转为实体类
ParsedLabelConfig parsedLabelConfig = ParsedLabelConfig.fromJson(parsedLabelConfigJson);
System.out.println("实体类内容:");
System.out.println(parsedLabelConfig);
// 实体类转为 JSON
String jsonOutput = parsedLabelConfig.toJson();
System.out.println("\n转换回 JSON");
System.out.println(jsonOutput);
}
}

View File

@ -0,0 +1,34 @@
package com.bonus.ai.client;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class ProjectInputParam {
private Long id;
private String title;
private String description;
@JsonProperty("label_config")
private String labelConfig;
@JsonProperty("expert_instruction")
private String expertInstruction = "labels";
@JsonProperty("show_instruction")
private boolean showInstruction = true;
@JsonProperty("show_skip_button")
private boolean showSkipButton = true;
@JsonProperty("enable_empty_annotation")
private boolean enableEmptyAnnotation = true;
@JsonProperty("show_annotation_history")
private boolean showAnnotationHistory = true;
private int organization = 1;
private String color = "color";
@JsonProperty("maximum_annotations")
private int maximumAnnotations = 1;
}

View File

@ -1,6 +1,8 @@
package com.bonus.ai.client;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonRawValue;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
@ -11,25 +13,29 @@ import java.util.Map;
@Data
public class ProjectParam {
private int id;
private Long id = 0L;
@JsonProperty("title")
private String title;
@JsonProperty("description")
private String description;
@JsonProperty("label_config")
@JsonRawValue(true)
private String labelConfig;
@JsonProperty("expert_instruction")
private String expertInstruction;
private String expertInstruction = "labels";
@JsonProperty("show_instruction")
private boolean showInstruction;
private boolean showInstruction = true;
@JsonProperty("show_skip_button")
private boolean showSkipButton;
private boolean showSkipButton = true;
@JsonProperty("enable_empty_annotation")
private boolean enableEmptyAnnotation;
private boolean enableEmptyAnnotation = true;
@JsonProperty("show_annotation_history")
private boolean showAnnotationHistory;
private int organization;
private String color;
private boolean showAnnotationHistory = true;
private int organization = 1;
private String color = "color";
@JsonProperty("maximum_annotations")
private int maximumAnnotations;
private int maximumAnnotations = 1;
@JsonProperty("is_published")
private boolean isPublished;
@JsonProperty("model_version")
@ -95,13 +101,13 @@ public class ProjectParam {
// Getters and Setters for all fields
@Data
public static class CreatedBy {
private int id;
private int id = 1;
@JsonProperty("first_name")
private String firstName;
private String firstName = "";
@JsonProperty("last_name")
private String lastName;
private String email;
private String avatar;
private String lastName = "";
private String email = "wang272160587@gmail.com";
private String avatar = null;
// Getters and Setters
}
@ -117,91 +123,166 @@ public class ProjectParam {
@Data
public static class ParsedLabelConfig {
private Map<String, LabelConfig> label;
// Getters and Setters
}
@JsonProperty("label")
private com.bonus.ai.client.ParsedLabelConfig.Label label;
@Data
public static class LabelConfig {
private String type;
@JsonProperty("to_name")
private List<String> toName;
private List<Input> inputs;
private List<String> labels;
@JsonProperty("labels_attrs")
private Map<String, LabelAttributes> labelsAttrs;
@Data
public static class Label {
@JsonProperty("type")
private String type;
// Getters and Setters
}
@JsonProperty("to_name")
private List<String> toName;
@Data
public static class Input {
private String type;
private String value;
private String valueType;
@JsonProperty("inputs")
private List<com.bonus.ai.client.ParsedLabelConfig.Input> inputs;
// Getters and Setters
}
@JsonProperty("labels")
private List<String> labels;
@Data
public static class LabelAttributes {
private String value;
private String background;
@JsonProperty("labels_attrs")
private Map<String, com.bonus.ai.client.ParsedLabelConfig.LabelAttributes> labelsAttrs;
}
@Data
public static class Input {
@JsonProperty("type")
private String type;
@JsonProperty("value")
private String value;
@JsonProperty("valueType")
private String valueType; // 注意JSON 中为 `null` Java 中用 `String` 表示
}
@Data
public static class LabelAttributes {
@JsonProperty("value")
private String value;
@JsonProperty("background")
private String background;
}
// Getters and Setters
}
public static ProjectParam fromJson(String json) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(json, ProjectParam.class);
return new ObjectMapper().readValue(json, ProjectParam.class);
}
public String toJson() throws JsonProcessingException {
public String toJson() throws Exception {
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(this);
}
public static void main(String[] args) throws JsonProcessingException {
String json = "{\n" +
" \"data\": {\n" +
" \"image\": \"https://example.com/image.jpg\",\n" +
" \"text\": \"Hello, AI!\"\n" +
" },\n" +
" \"id\": 1,\n" +
" \"meta\": {\n" +
" \"key\": \"value\"\n" +
" },\n" +
" \"created_at\": \"2024-06-18T23:45:46Z\",\n" +
" \"updated_at\": \"2024-06-18T23:45:46Z\",\n" +
" \"is_labeled\": false,\n" +
" \"overlap\": 1,\n" +
" \"inner_id\": 1,\n" +
" \"total_annotations\": 0,\n" +
" \"cancelled_annotations\": 0,\n" +
" \"total_predictions\": 0,\n" +
" \"comment_count\": 0,\n" +
" \"unresolved_comment_count\": 0,\n" +
" \"last_comment_updated_at\": \"2024-01-15T09:30:00Z\",\n" +
" \"project\": 1,\n" +
" \"updated_by\": [\n" +
" {\n" +
" \"user_id\": 1\n" +
" }\n" +
" ],\n" +
" \"file_upload\": \"42d46c4c-my-pic.jpeg\",\n" +
" \"comment_authors\": [\n" +
" 1\n" +
" ]\n" +
"}";
String json = "{\"id\":16,\"title\":\"taskName\",\"description\":\"description\",\"label_config\":\"<View>\\n <Image name=\\\"image\\\" value=\\\"$image\\\"/>\\n <RectangleLabels name=\\\"label\\\" toName=\\\"image\\\">\\n <Label value=\\\"person\\\" background=\\\"#FFA39E\\\"/>\\n <Label value=\\\"cat\\\" background=\\\"#D4380D\\\"/>\\n </RectangleLabels>\\n</View>\",\"expert_instruction\":\"labels\",\"show_instruction\":true,\"show_skip_button\":true,\"enable_empty_annotation\":true,\"show_annotation_history\":true,\"organization\":1,\"color\":\"color\",\"maximum_annotations\":1,\"is_published\":false,\"model_version\":\"\",\"is_draft\":false,\"created_by\":{\"id\":1,\"first_name\":\"\",\"last_name\":\"\",\"email\":\"wang272160587@gmail.com\",\"avatar\":null},\"created_at\":\"2024-11-25T01:27:36.414342Z\",\"min_annotations_to_start_training\":0,\"start_training_on_annotation_update\":false,\"show_collab_predictions\":true,\"num_tasks_with_annotations\":null,\"task_number\":null,\"useful_annotation_number\":null,\"ground_truth_number\":null,\"skipped_annotations_number\":null,\"total_annotations_number\":null,\"total_predictions_number\":null,\"sampling\":\"Sequential sampling\",\"show_ground_truth_first\":false,\"show_overlap_first\":false,\"overlap_cohort_percentage\":100,\"task_data_login\":null,\"task_data_password\":null,\"control_weights\":{\"label\":{\"overall\":1.0,\"type\":\"RectangleLabels\",\"labels\":{\"person\":1.0,\"cat\":1.0}}},\"parsed_label_config\":{\"label\":{\"type\":\"RectangleLabels\",\"to_name\":[\"image\"],\"inputs\":[{\"type\":\"Image\",\"value\":\"image\",\"valueType\":null}],\"labels\":[\"person\",\"cat\"],\"labels_attrs\":{\"person\":{\"value\":\"person\",\"background\":\"#FFA39E\"},\"cat\":{\"value\":\"cat\",\"background\":\"#D4380D\"}}}},\"evaluate_predictions_automatically\":false,\"config_has_control_tags\":true,\"skip_queue\":\"REQUEUE_FOR_OTHERS\",\"reveal_preannotations_interactively\":false,\"pinned_at\":null,\"finished_task_number\":null,\"queue_total\":0,\"queue_done\":0}";
// String json = "{\"id\":16,\"title\":\"taskName\",\"description\":\"description\",\"label_config\":\"<View>\\n <Image name=\\\"image\\\" value=\\\"$image\\\"/>\\n <RectangleLabels name=\\\"label\\\" toName=\\\"image\\\">\\n <Label value=\\\"person\\\" background=\\\"#FFA39E\\\"/>\\n <Label value=\\\"cat\\\" background=\\\"#D4380D\\\"/>\\n </RectangleLabels>\\n</View>\",\"expert_instruction\":\"labels\",\"show_instruction\":true,\"show_skip_button\":true,\"enable_empty_annotation\":true,\"show_annotation_history\":true,\"organization\":1,\"color\":\"color\",\"maximum_annotations\":1,\"is_published\":false}";
// String json = "{\n" +
// " \"id\": 11,\n" +
// " \"title\": \"测试项目\",\n" +
// " \"description\": \"My Second project\",\n" +
// " \"label_config\": \"<View>\\n <Image name=\\\"image\\\" value=\\\"$image\\\"/>\\n <RectangleLabels name=\\\"label\\\" toName=\\\"image\\\">\\n <Label value=\\\"person\\\" background=\\\"#FFA39E\\\"/>\\n <Label value=\\\"cat\\\" background=\\\"#D4380D\\\"/>\\n </RectangleLabels>\\n</View>\",\n" +
// " \"expert_instruction\": \"Label all cats\",\n" +
// " \"show_instruction\": true,\n" +
// " \"show_skip_button\": true,\n" +
// " \"enable_empty_annotation\": true,\n" +
// " \"show_annotation_history\": true,\n" +
// " \"organization\": 1,\n" +
// " \"color\": \"color\",\n" +
// " \"maximum_annotations\": 1,\n" +
// " \"is_published\": false,\n" +
// " \"model_version\": \"\",\n" +
// " \"is_draft\": false,\n" +
// " \"created_by\": {\n" +
// " \"id\": 1,\n" +
// " \"first_name\": \"\",\n" +
// " \"last_name\": \"\",\n" +
// " \"email\": \"wang272160587@gmail.com\",\n" +
// " \"avatar\": null\n" +
// " },\n" +
// " \"created_at\": \"2024-11-25T00:36:17.622117Z\",\n" +
// " \"min_annotations_to_start_training\": 0,\n" +
// " \"start_training_on_annotation_update\": false,\n" +
// " \"show_collab_predictions\": true,\n" +
// " \"num_tasks_with_annotations\": null,\n" +
// " \"task_number\": null,\n" +
// " \"useful_annotation_number\": null,\n" +
// " \"ground_truth_number\": null,\n" +
// " \"skipped_annotations_number\": null,\n" +
// " \"total_annotations_number\": null,\n" +
// " \"total_predictions_number\": null,\n" +
// " \"sampling\": \"Sequential sampling\",\n" +
// " \"show_ground_truth_first\": false,\n" +
// " \"show_overlap_first\": false,\n" +
// " \"overlap_cohort_percentage\": 100,\n" +
// " \"task_data_login\": null,\n" +
// " \"task_data_password\": null,\n" +
// " \"control_weights\": {\n" +
// " \"label\": {\n" +
// " \"overall\": 1.0,\n" +
// " \"type\": \"RectangleLabels\",\n" +
// " \"labels\": {\n" +
// " \"person\": 1.0,\n" +
// " \"cat\": 1.0\n" +
// " }\n" +
// " }\n" +
// " },\n" +
// " \"parsed_label_config\": {\n" +
// " \"label\": {\n" +
// " \"type\": \"RectangleLabels\",\n" +
// " \"to_name\": [\n" +
// " \"image\"\n" +
// " ],\n" +
// " \"inputs\": [\n" +
// " {\n" +
// " \"type\": \"Image\",\n" +
// " \"value\": \"image\",\n" +
// " \"valueType\": null\n" +
// " }\n" +
// " ],\n" +
// " \"labels\": [\n" +
// " \"person\",\n" +
// " \"cat\"\n" +
// " ],\n" +
// " \"labels_attrs\": {\n" +
// " \"person\": {\n" +
// " \"value\": \"person\",\n" +
// " \"background\": \"#FFA39E\"\n" +
// " },\n" +
// " \"cat\": {\n" +
// " \"value\": \"cat\",\n" +
// " \"background\": \"#D4380D\"\n" +
// " }\n" +
// " }\n" +
// " }\n" +
// " },\n" +
// " \"evaluate_predictions_automatically\": false,\n" +
// " \"config_has_control_tags\": true,\n" +
// " \"skip_queue\": \"REQUEUE_FOR_OTHERS\",\n" +
// " \"reveal_preannotations_interactively\": true,\n" +
// " \"pinned_at\": null,\n" +
// " \"finished_task_number\": null,\n" +
// " \"queue_total\": 0,\n" +
// " \"queue_done\": 0\n" +
// "}";
System.out.println(json);
TaskParam record = TaskParam.fromJson(json);
System.out.println("Create At: " + record.getData());
ProjectParam record = ProjectParam.fromJson(json);
System.out.println("Create At: " + record.getCreatedAt());
System.out.println("Image URL: " + record.getData().getImage());
}
// public static void main(String[] args) throws Exception {
// String json = "{\"id\":16,\"title\":\"taskName\",\"description\":\"description\",\"label_config\":\"<View>\\n <Image name=\\\"image\\\" value=\\\"$image\\\"/>\\n <RectangleLabels name=\\\"label\\\" toName=\\\"image\\\">\\n <Label value=\\\"person\\\" background=\\\"#FFA39E\\\"/>\\n <Label value=\\\"cat\\\" background=\\\"#D4380D\\\"/>\\n </RectangleLabels>\\n</View>\",\"expert_instruction\":\"labels\",\"show_instruction\":true,\"show_skip_button\":true,\"enable_empty_annotation\":true,\"show_annotation_history\":true,\"organization\":1,\"color\":\"color\",\"maximum_annotations\":1,\"is_published\":false}";
//
// ObjectMapper objectMapper = new ObjectMapper();
// ProjectParam projectParam = objectMapper.readValue(json, ProjectParam.class);
//
// System.out.println(projectParam);
// }
}

View File

@ -1,5 +1,6 @@
package com.bonus.ai.controller.dataset;
import com.bonus.ai.client.AnnotationParam;
import com.bonus.ai.domain.dataset.AnnotationSubTaskEntity;
import com.bonus.ai.domain.dataset.AnnotationTaskEntity;
import com.bonus.ai.service.DataSetBasicFileService;
@ -39,7 +40,8 @@ public class AnnotationTaskController extends BaseController {
@PostMapping("/edit")
public AjaxResult edit(@Validated @RequestBody AnnotationTaskEntity task) {
return AjaxResult.success();
int status = annotationTaskService.updateTask(task);
return status == 1 ? AjaxResult.success() : AjaxResult.error("更新任务失败");
}
/**
@ -72,7 +74,8 @@ public class AnnotationTaskController extends BaseController {
*/
@GetMapping(value = "/{taskId}")
public AjaxResult getInfo(@PathVariable Long taskId) {
return AjaxResult.success(new AnnotationTaskEntity());
AnnotationTaskEntity taskEntity = annotationTaskService.getTaskInfo(taskId);
return AjaxResult.success(taskEntity);
}

View File

@ -12,6 +12,8 @@ public class AnnotationTaskAnnotatorEntity {
private Long reviewerId; // 审核人员
private Long taskId; // 任务ID
private Long fileId; // 文件ID
private String fileUrl; // 文件URL
private Long labelStudioTaskId; //label studio 里对应的任务id
private String description; // 描述
private String annotationStatus; // 标注状态
private String annotationResult; // 标注结果 (JSON串)

View File

@ -1,5 +1,6 @@
package com.bonus.ai.domain.dataset;
import com.bonus.ai.client.ProjectParam;
import com.bonus.ai.domain.enums.AnnotationFileStatus;
import com.bonus.ai.domain.enums.AnnotationTaskStatus;
import com.bonus.common.core.web.domain.BaseEntity;
@ -32,10 +33,11 @@ public class AnnotationTaskEntity extends BaseEntity {
/**标签集合,标签之间用逗号分隔*/
private String labels;
/**在线标注工具里关联的项目id*/
Long projectId;
/**在线标注工具里关联的项目id 和label studio里 项目详情*/
Long labelStudioProjectId;
ProjectParam projectParam;
AnnotationTaskStatus annotateTaskStatus;
private String annotateTaskStatus;
/**删除标志0代表存在 1代表删除 */
private String delFlag;

View File

@ -54,5 +54,6 @@ public interface AnnotationTaskMapper
int deleteAnnotator(Long taskId);
AnnotationTaskEntity selectAnnotationTaskListUUID(Long taskId);
//这个接口不需要可以扩展selectAnnotationTaskList
// AnnotationTaskEntity selectAnnotationTaskListUUID(Long taskId);
}

View File

@ -1,5 +1,6 @@
package com.bonus.ai.mapper;
import com.bonus.ai.domain.DataSetBasicFileEntity;
import com.bonus.ai.domain.dataset.DatasetFile;
import org.apache.ibatis.annotations.Param;
@ -46,7 +47,7 @@ public interface DatasetFileMapper {
* @param datasetId 数据集ID
* @return 文件映射列表
*/
List<DatasetFile> selectFilesByDatasetId(Long datasetId);
List<DataSetBasicFileEntity> selectFilesByDatasetId(Long datasetId);
/**
* 更新是否已标注状态

View File

@ -1,28 +1,37 @@
package com.bonus.ai.service.Impl.dataset;
import com.alibaba.fastjson.JSON;
import com.bonus.ai.client.OnlineAnnotationService;
import com.bonus.ai.client.ProjectParam;
import com.bonus.ai.client.*;
import com.bonus.ai.config.OnlineAnnotateConfig;
import com.bonus.ai.domain.DataSetBasicFileEntity;
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 com.bonus.common.core.utils.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
@Slf4j
@Service
public class AnnotationTaskServiceImpl implements AnnotationTaskService {
private static final int THREAD_POOL_SIZE = 10;
@Resource
OnlineAnnotationService onlineAnnotationService;
OnlineAnnotationServiceOkHttp onlineAnnotationService;
// OnlineAnnotationService onlineAnnotationService;
@Resource
private OnlineAnnotateConfig onlineAnnotateConfig;
@ -39,34 +48,66 @@ public class AnnotationTaskServiceImpl implements AnnotationTaskService {
@Autowired
private AnnotationTaskAnnotatorEntity annotationTaskAnnotatorEntity;
private final ThreadPoolTaskExecutor executorService = SpringUtils.getBean(ThreadPoolTaskExecutor.class);
public void callWithOkHttp() throws Exception {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://127.0.0.1:8080/api/projects")
.addHeader("Authorization", "Token bb0859020874c95809212f7b9616d15bbdbb2422")
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
}
/**
* 创建标注任务
*/
@Override
public int createTask(AnnotationTaskEntity task) {
public int createTask(AnnotationTaskEntity task){
int status =0;
// TODO 调用label studio 接口获取其project id
ProjectParam lSProject = new ProjectParam();
//调用label studio 接口获取其project id
ProjectInputParam lSProject= new ProjectInputParam();
lSProject.setTitle(task.getTaskName());
lSProject.setDescription(task.getTaskDesc());
//需要将标签转换为json格式
lSProject.setLabelConfig(task.getLabels());
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);
String labelConfig = OnlineAnnotateUtil.rectangleImageLabels(task.getLabels());
lSProject.setLabelConfig(labelConfig);
String project = "";
Long projectId = 0L;
try {
ProjectParam projectParams = onlineAnnotationService.createProject(lSProject);
if (projectParams != null) {
projectId = Long.valueOf(projectParams.getId());
task.setLabelStudioProjectId(projectId);
}
}catch (Exception e){
e.printStackTrace();
}
//需要生成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<DataSetBasicFileEntity> datafile = datasetFileMapper.selectFilesByDatasetId(task.getDatasetId());
//根据标注任务file list 和标注人信息自动分配
List<AnnotationTaskAnnotatorEntity> annotationTaskAnnotatorEntities = AverageUtil.distributeFiles(datafile, task);
// for (AnnotationTaskAnnotatorEntity entity : annotationTaskAnnotatorEntities) {
// //TODO 每个文件都需要创建label studio的 task id 与之唯一对应
// executorService.execute(()->{
// TaskParam taskParam = new TaskParam();
// taskParam.setProject(projectId);
// try {
// onlineAnnotationService.createTask(taskParam);
// }catch(Exception e){
// e.printStackTrace();
// }
// });
//entity.setLabelStudioTaskId(0);
// }
// 获取project id以后调用AnnotationTaskMapper 和AnnotationTaskAnnotatorMapper 插入数据集
if(status == 1){
status = annotationTaskMapper.insertAnnotTaskannotator(annotationTaskAnnotatorEntities);
@ -93,6 +134,30 @@ public class AnnotationTaskServiceImpl implements AnnotationTaskService {
*/
@Override
public int updateTask(AnnotationTaskEntity task){
//将信息也同步更新到label studio studio 对应的project
AnnotationTaskEntity newTask = new AnnotationTaskEntity();
newTask.setTaskId(task.getTaskId());
//处理与label studio 相关的更新
List<AnnotationTaskEntity> resultTasks = annotationTaskMapper.selectAnnotationTaskList(newTask);
if (!resultTasks.isEmpty()) {
Long project = resultTasks.get(0).getLabelStudioProjectId();
//调用label studio 接口获取其project id
ProjectInputParam lSProject= new ProjectInputParam();
lSProject.setTitle(task.getTaskName());
lSProject.setDescription(task.getTaskDesc());
//需要将标签转换为json格式
String labelConfig = OnlineAnnotateUtil.rectangleImageLabels(task.getLabels());
lSProject.setLabelConfig(labelConfig);
lSProject.setId(project);
try {
ProjectParam projectParam = onlineAnnotationService.updateProject(lSProject);
}catch(Exception e){
e.printStackTrace();
}
//删除对应的标注任务文件关联关系表信息
}
return 0;
}
@ -105,16 +170,22 @@ public class AnnotationTaskServiceImpl implements AnnotationTaskService {
@Override
public int deleteTaskById(Long taskId) {
//删除任务需要删除两个个表 对应两个个表删除状态修改成1
AnnotationTaskEntity task = new AnnotationTaskEntity();
task.setTaskId(taskId);
int status = 0;
try{
//删除主表任务信息
status = annotationTaskMapper.deleteTaskById(taskId);
//删除团队成员表信息
status = annotationTaskMapper.deleteAnnotator(taskId);
//查询对应的uuid
AnnotationTaskEntity task = annotationTaskMapper.selectAnnotationTaskListUUID(taskId);
//删除对应的标注任务文件关联关系表信息
onlineAnnotationService.deleteProjectById(task.getTaskUuid(), onlineAnnotateConfig.getApikey());
// //删除主表任务信息
// status = annotationTaskMapper.deleteTaskById(taskId);
// //删除团队成员表信息
// status = annotationTaskMapper.deleteAnnotator(taskId);
// //查询对应的label studio project id , 删除这个标注任务对应的label studio project
List<AnnotationTaskEntity> resultTask = annotationTaskMapper.selectAnnotationTaskList(task);
if (!resultTask.isEmpty()){
Long project = resultTask.get(0).getLabelStudioProjectId();
//删除对应的标注任务文件关联关系表信息
onlineAnnotationService.deleteProjectById(String.valueOf(project));
}
}catch (Exception e){
e.printStackTrace();
}
@ -129,6 +200,22 @@ public class AnnotationTaskServiceImpl implements AnnotationTaskService {
@Override
public AnnotationTaskEntity getTaskInfo(Long taskId) {
AnnotationTaskEntity task = new AnnotationTaskEntity();
task.setTaskId(taskId);
try {
//查询对应的label studio project id , 从label studio这个标注任务对应的label studio project
List<AnnotationTaskEntity> resultTasks = annotationTaskMapper.selectAnnotationTaskList(task);
if (!resultTasks.isEmpty()) {
Long project = resultTasks.get(0).getLabelStudioProjectId();
//删除对应的标注任务文件关联关系表信息
ProjectParam projectParam = onlineAnnotationService.getProjectById(String.valueOf(project));
AnnotationTaskEntity resultTask = resultTasks.get(0);
resultTask.setProjectParam(projectParam);
}
} catch (Exception e){
e.printStackTrace();
}
return null;
}

View File

@ -4,6 +4,8 @@ import com.bonus.ai.domain.dataset.AnnotationSubTaskEntity;
import com.bonus.ai.domain.dataset.AnnotationTaskEntity;
import com.bonus.ai.domain.dataset.DataSetEntity;
import java.io.IOException;
public interface AnnotationTaskService {
/**创建标注任务*/
int createTask(AnnotationTaskEntity task);

View File

@ -1,5 +1,6 @@
package com.bonus.ai.utils;
import com.bonus.ai.domain.DataSetBasicFileEntity;
import com.bonus.ai.domain.dataset.AnnotationTaskAnnotatorEntity;
import com.bonus.ai.domain.dataset.AnnotationTaskEntity;
import com.bonus.ai.domain.dataset.DatasetFile;
@ -15,28 +16,33 @@ public class AverageUtil {
* @param taskEntity 标注任务实体
* @return 分配结果包含标注者和审核者的文件分配
*/
public static List<AnnotationTaskAnnotatorEntity> distributeFiles(List<DatasetFile> files, AnnotationTaskEntity taskEntity) {
public static List<AnnotationTaskAnnotatorEntity> distributeFiles(List<DataSetBasicFileEntity> 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() 方法
//这里需要将基础文件的url也获取并赋值
entity.setFileUrl(files.get(i).getFileUrl() );
annotatorEntities.add(entity);
}
// 平分文件给审核者
for (int i = 0; i < files.size(); i++) {
for (int i = 0; i < annotatorEntities.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);
annotatorEntities.get(i).setReviewerId(reviewerId);
// AnnotationTaskAnnotatorEntity entity = new AnnotationTaskAnnotatorEntity();
// entity.setAnnotatorId(reviewerId); // 设置审核者 ID
// entity.setFileId(files.get(i).getFileId()); // 假设 DatasetFile getId() 方法
// annotatorEntities.add(entity);
}
return annotatorEntities;

View File

@ -14,7 +14,8 @@
<result column="annotation_scene" property="annotateScene" jdbcType="CHAR"/>
<result column="annotation_type" property="annotateType" jdbcType="CHAR"/>
<result column="labels" property="labels" jdbcType="VARCHAR"/>
<result column="is_annotation_team" property="isStartTeam" jdbcType="CHAR"/>
<result column="label_studio_project_id" property="labelStudioProjectId" jdbcType="BIGINT"/>
<result column="isStartTeam" property="isStartTeam" jdbcType="CHAR"/>
<result column="annotation_status" property="annotateTaskStatus" jdbcType="CHAR"/>
<result column="del_flag" property="delFlag" jdbcType="CHAR"/>
<result column="create_by" property="createBy" jdbcType="VARCHAR"/>
@ -23,6 +24,7 @@
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="selectTaskDetailVo">
select distinct t.task_id, t.task_uuid, t.task_name, t.description, t.annotation_scene, t.annotation_type,
FROM ai_annotation_task t
@ -43,14 +45,17 @@
<!-- TODO 根据审核人id查询所有需要审核文件列表-->
<!-- 查询标注任务列表 -->
<select id="selectAnnotationTaskList" parameterType="com.bonus.ai.domain.dataset.AnnotationTaskEntity" resultType="com.bonus.ai.domain.dataset.AnnotationTaskEntity">
SELECT task_id , dataset_id , task_name , task_uuidd, description, annotation_scene, annotation_type ,
<!-- 根据条件查询标注任务列表 -->
<select id="selectAnnotationTaskList" parameterType="com.bonus.ai.domain.dataset.AnnotationTaskEntity" resultMap="BaseResultMap">
SELECT task_id , dataset_id , task_name , task_uuid, description, annotation_scene, annotation_type ,
labels, is_annotation_team AS isStartTeam, annotation_status,
project_id, del_flag, create_by , create_time,
label_studio_project_id, del_flag, create_by , create_time,
update_by , update_time
FROM ai_annotation_task
WHERE del_flag = '0'
<if test="taskId != null">
AND task_id = #{taskId}
</if>
<if test="datasetId != null">
AND dataset_id = #{datasetId}
</if>
@ -67,9 +72,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>
<!-- <select id="selectAnnotationTaskListUUID" resultType="com.bonus.ai.domain.dataset.AnnotationTaskEntity">-->
<!-- SELECT label_studio_project_id, task_id, task_uuid FROM ai_annotation_task where del_flag = 0-->
<!-- </select>-->
<!-- 插入标注任务 -->
<insert id="insertAnnotationTask" parameterType="com.bonus.ai.domain.dataset.AnnotationTaskEntity">
@ -84,7 +89,7 @@
<if test="labels != null">labels,</if>
<if test="isStartTeam != null">is_annotation_team,</if>
<if test="annotateTaskStatus != null">annotation_status,</if>
<if test="projectId != null">project_id,</if>
<if test="labelStudioProjectId != null">label_studio_project_id,</if>
<if test="delFlag != null">del_flag,</if>
<if test="createBy != null">create_by,</if>
create_time,
@ -101,7 +106,7 @@
<if test="labels != null">#{labels},</if>
<if test="isStartTeam != null">#{isStartTeam},</if>
<if test="annotateTaskStatus != null">#{annotateTaskStatus},</if>
<if test="projectId != null">#{projectId},</if>
<if test="labelStudioProjectId != null">#{labelStudioProjectId},</if>
<if test="delFlag != null">#{delFlag},</if>
<if test="createBy != null">#{createBy},</if>
sysdate(),
@ -113,6 +118,18 @@
INSERT INTO ai_annotation_task_annotator_map
<trim prefix="(" suffix=")" suffixOverrides=",">
task_id
<if test="fileId != null">
, file_id
</if>
<if test="fileUrl != null">
, file_url
</if>
<if test="fileUrl != null">
, file_url
</if>
<if test="labelStudioTaskId != null">
, label_studio_task_id
</if>
<if test="annotatorId != null">
, annotator_id
</if>
@ -134,6 +151,15 @@
</trim>
<trim prefix="VALUES (" suffix=")" suffixOverrides=",">
#{taskId}
<if test="fileId != null">
, #{fileId}
</if>
<if test="fileUrl != null">
, #{fileUrl}
</if>
<if test="labelStudioTaskId != null">
, #{labelStudioTaskId}
</if>
<if test="annotatorId != null">
, #{annotatorId}
</if>
@ -169,7 +195,7 @@
<if test="labels != null">labels = #{labels},</if>
<if test="isStartTeam != null">is_annotation_team = #{isStartTeam},</if>
<if test="annotateTaskStatus != null">annotation_status = #{annotateTaskStatus},</if>
<if test="projectId != null">project_id = #{projectId},</if>
<if test="labelStudioProjectId != null">label_studio_project_id = #{labelStudioProjectId},</if>
<if test="delFlag != null">del_flag = #{delFlag},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
update_time = sysdate(),

View File

@ -42,10 +42,11 @@
<!-- </delete>-->
<!-- 根据数据集ID查询文件列表 -->
<select id="selectFilesByDatasetId" resultType="com.bonus.ai.domain.dataset.DatasetFile">
SELECT file_id AS fileId, dataset_id AS datasetId
FROM ai_dataset_file_map
WHERE dataset_id = #{datasetId}
<select id="selectFilesByDatasetId" parameterType="Long" resultType="com.bonus.ai.domain.DataSetBasicFileEntity">
SELECT bf.file_id AS fileId, bf.file_url AS fileUrl
FROM ai_dataset_file_map df
WHERE df.dataset_id = #{datasetId}
left join ai_basic_file bf on bf.file_id = df.file_id
</select>
<!-- 更新是否已标注状态 -->

View File

@ -4,21 +4,22 @@
drop table if exists ai_annotation_task;
create table ai_annotation_task
(
task_id bigint(20) not null auto_increment comment '任务id',
dataset_id bigint(20) not null comment '数据集id',
task_name varchar(64) comment '任务名称',
task_uuid varchar(64) comment '任务唯一标识id',
description varchar(500) default '' comment '描述',
annotation_scene char(1) comment '标注场景(对应数据集的数据类型)',
annotation_type char(2) comment '标注类型(不同数据类型有不同的标注类型,如图片:图像分类,物体检测等)',
labels varchar(200) comment '允许的标签集',
task_id bigint(20) not null auto_increment comment '任务id',
dataset_id bigint(20) not null comment '数据集id',
task_name varchar(64) comment '任务名称',
task_uuid varchar(64) comment '任务唯一标识id',
description varchar(500) default '' comment '描述',
annotation_scene char(1) comment '标注场景(对应数据集的数据类型)',
annotation_type char(2) comment '标注类型(不同数据类型有不同的标注类型,如图片:图像分类,物体检测等)',
labels varchar(200) comment '允许的标签集',
is_annotation_team char(1) comment '标注团队id0未启用,1启用团队',
annotation_status char(1) default '0' comment '0未标注1正在标注2已标注3正在审核4已审核',
del_flag char(1) default '0' comment '是否删除(0代表存在,1代表删除)',
create_by varchar(64) default '' comment '创建者',
update_by varchar(64) default '' comment '更新者',
update_time datetime default null comment '更新时间',
create_time datetime default null comment '创建时间',
annotation_status char(1) default '0' comment '0未标注1正在标注2已标注3正在审核4已审核',
label_studio_project_id bigint(20) comment "label studio 对应的projectId"
del_flag char(1) default '0' comment '是否删除(0代表存在,1代表删除)',
create_by varchar(64) default '' comment '创建者',
update_by varchar(64) default '' comment '更新者',
update_time datetime default null comment '更新时间',
create_time datetime default null comment '创建时间',
primary key (task_id)
)engine=innodb comment = '标注任务';
@ -32,6 +33,8 @@ create table ai_annotation_task_annotator_map
reviewer_id bigint(20) not null comment '审核人员',
task_id bigint(20) not null comment '任务id',
file_id bigint(20) not null comment '文件id',
file_url varchar(200) default '' comment '文件网络路径',
label_studio_task_id bigint(20) comment "label studio 对应的taskId"
description varchar(500) default '' comment '描述',
annotation_status char(1) comment '0未标注1正在标注2已标注3正在审核4 审核驳回5已审核',
annotation_result text comment '标注结果(json串)',