You've already forked DataMate
- 在前端页面中新增标注类型列并使用Tag组件展示 - 添加AnnotationTypeMap常量用于标注类型的映射 - 修改接口定义支持labelingType字段的传递 - 更新后端项目创建和更新逻辑以存储标注类型 - 添加标注类型配置键常量统一管理 - 扩展数据传输对象支持标注类型属性 - 实现模板标注类型的继承逻辑
557 lines
15 KiB
TypeScript
557 lines
15 KiB
TypeScript
import { StickyNote } from "lucide-react";
|
|
import {AnnotationTaskStatus, AnnotationType, Classification, DataType, TemplateType} from "./annotation.model";
|
|
import {
|
|
CheckCircleOutlined,
|
|
ClockCircleOutlined,
|
|
CloseCircleOutlined,
|
|
} from "@ant-design/icons";
|
|
|
|
type AnnotationTaskStatistics = {
|
|
accuracy?: number | string;
|
|
averageTime?: number | string;
|
|
reviewCount?: number | string;
|
|
};
|
|
|
|
type AnnotationTaskPayload = {
|
|
id?: string;
|
|
labelingProjId?: string;
|
|
labelingProjectId?: string;
|
|
projId?: string;
|
|
labeling_project_id?: string;
|
|
name?: string;
|
|
description?: string;
|
|
datasetId?: string;
|
|
datasetName?: string;
|
|
dataset_name?: string;
|
|
labelingType?: string;
|
|
labeling_type?: string;
|
|
template?: {
|
|
labelingType?: string;
|
|
labeling_type?: string;
|
|
};
|
|
totalCount?: number;
|
|
total_count?: number;
|
|
annotatedCount?: number;
|
|
annotated_count?: number;
|
|
inProgressCount?: number;
|
|
in_progress_count?: number;
|
|
segmentationEnabled?: boolean;
|
|
segmentation_enabled?: boolean;
|
|
createdAt?: string;
|
|
created_at?: string;
|
|
updatedAt?: string;
|
|
updated_at?: string;
|
|
status?: string;
|
|
statistics?: AnnotationTaskStatistics;
|
|
[key: string]: unknown;
|
|
};
|
|
|
|
export type AnnotationTaskListItem = {
|
|
id?: string;
|
|
labelingProjId?: string;
|
|
projId?: string;
|
|
name?: string;
|
|
description?: string;
|
|
datasetId?: string;
|
|
datasetName?: string;
|
|
labelingType?: string;
|
|
totalCount?: number;
|
|
annotatedCount?: number;
|
|
inProgressCount?: number;
|
|
segmentationEnabled?: boolean;
|
|
createdAt?: string;
|
|
updatedAt?: string;
|
|
icon?: JSX.Element;
|
|
iconColor?: string;
|
|
status?: {
|
|
label: string;
|
|
color: string;
|
|
};
|
|
statistics?: { label: string; value: string | number }[];
|
|
[key: string]: unknown;
|
|
};
|
|
|
|
export const AnnotationTaskStatusMap = {
|
|
[AnnotationTaskStatus.ACTIVE]: {
|
|
label: "活跃",
|
|
value: AnnotationTaskStatus.ACTIVE,
|
|
color: "#409f17ff",
|
|
icon: <CheckCircleOutlined />,
|
|
},
|
|
[AnnotationTaskStatus.PROCESSING]: {
|
|
label: "处理中",
|
|
value: AnnotationTaskStatus.PROCESSING,
|
|
color: "#2673e5",
|
|
icon: <ClockCircleOutlined />,
|
|
},
|
|
[AnnotationTaskStatus.INACTIVE]: {
|
|
label: "未激活",
|
|
value: AnnotationTaskStatus.INACTIVE,
|
|
color: "#4f4444ff",
|
|
icon: <CloseCircleOutlined />,
|
|
},
|
|
};
|
|
|
|
export function mapAnnotationTask(task: AnnotationTaskPayload): AnnotationTaskListItem {
|
|
// Normalize labeling project id from possible backend field names
|
|
const labelingProjId = task?.labelingProjId || task?.labelingProjectId || task?.projId || task?.labeling_project_id || "";
|
|
const segmentationEnabled = task?.segmentationEnabled ?? task?.segmentation_enabled ?? false;
|
|
const inProgressCount = task?.inProgressCount ?? task?.in_progress_count ?? 0;
|
|
const labelingType =
|
|
task?.labelingType ||
|
|
task?.labeling_type ||
|
|
task?.template?.labelingType ||
|
|
task?.template?.labeling_type;
|
|
|
|
const statsArray = task?.statistics
|
|
? [
|
|
{ label: "准确率", value: task.statistics.accuracy ?? "-" },
|
|
{ label: "平均时长", value: task.statistics.averageTime ?? "-" },
|
|
{ label: "待复核", value: task.statistics.reviewCount ?? "-" },
|
|
]
|
|
: [];
|
|
|
|
return {
|
|
...task,
|
|
id: task.id,
|
|
// provide consistent field for components
|
|
labelingProjId,
|
|
projId: labelingProjId,
|
|
segmentationEnabled,
|
|
inProgressCount,
|
|
labelingType,
|
|
name: task.name,
|
|
description: task.description || "",
|
|
datasetName: task.datasetName || task.dataset_name || "-",
|
|
totalCount: task.totalCount ?? task.total_count ?? 0,
|
|
annotatedCount: task.annotatedCount ?? task.annotated_count ?? 0,
|
|
createdAt: task.createdAt || task.created_at || "-",
|
|
updatedAt: task.updatedAt || task.updated_at || "-",
|
|
icon: <StickyNote />,
|
|
iconColor: "bg-blue-100",
|
|
status: {
|
|
label:
|
|
task.status === "completed"
|
|
? "已完成"
|
|
: task.status === "processing"
|
|
? "进行中"
|
|
: task.status === "skipped"
|
|
? "已跳过"
|
|
: "待开始",
|
|
color: "bg-blue-100",
|
|
},
|
|
statistics: statsArray,
|
|
};
|
|
}
|
|
|
|
export const DataTypeMap = {
|
|
[DataType.TEXT]: {
|
|
label: "文本",
|
|
value: DataType.TEXT
|
|
},
|
|
[DataType.IMAGE]: {
|
|
label: "图片",
|
|
value: DataType.IMAGE
|
|
},
|
|
[DataType.AUDIO]: {
|
|
label: "音频",
|
|
value: DataType.AUDIO
|
|
},
|
|
[DataType.VIDEO]: {
|
|
label: "视频",
|
|
value: DataType.VIDEO
|
|
},
|
|
[DataType.PDF]: {
|
|
label: "PDF文档",
|
|
value: DataType.PDF
|
|
},
|
|
[DataType.TIMESERIES]: {
|
|
label: "时间序列",
|
|
value: DataType.TIMESERIES
|
|
},
|
|
[DataType.CHAT]: {
|
|
label: "聊天数据",
|
|
value: DataType.CHAT
|
|
},
|
|
[DataType.HTML]: {
|
|
label: "HTML文档",
|
|
value: DataType.HTML
|
|
},
|
|
[DataType.TABLE]: {
|
|
label: "表格数据",
|
|
value: DataType.TABLE
|
|
},
|
|
}
|
|
|
|
export const ClassificationMap = {
|
|
[Classification.AUDIO_SPEECH]: {
|
|
label: "音频/语音处理",
|
|
value: Classification.AUDIO_SPEECH
|
|
},
|
|
[Classification.CHAT]: {
|
|
label: "聊天评估",
|
|
value: Classification.CHAT
|
|
},
|
|
[Classification.COMPUTER_VISION]: {
|
|
label: "计算机视觉",
|
|
value: Classification.COMPUTER_VISION
|
|
},
|
|
[Classification.CONVERSATIONAL_AI]: {
|
|
label: "对话AI",
|
|
value: Classification.CONVERSATIONAL_AI
|
|
},
|
|
[Classification.GENERATIVE_AI]: {
|
|
label: "生成式AI",
|
|
value: Classification.GENERATIVE_AI
|
|
},
|
|
[Classification.NLP]: {
|
|
label: "自然语言处理",
|
|
value: Classification.NLP
|
|
},
|
|
[Classification.RANKING_SCORING]: {
|
|
label: "排名与评分",
|
|
value: Classification.RANKING_SCORING
|
|
},
|
|
[Classification.STRUCTURED_DATA]: {
|
|
label: "结构化数据解析",
|
|
value: Classification.STRUCTURED_DATA
|
|
},
|
|
[Classification.TIME_SERIES]: {
|
|
label: "时间序列分析",
|
|
value: Classification.TIME_SERIES
|
|
},
|
|
[Classification.VIDEO]: {
|
|
label: "视频处理",
|
|
value: Classification.VIDEO
|
|
},
|
|
[Classification.COMMUNITY]: {
|
|
label: "社区贡献",
|
|
value: Classification.COMMUNITY
|
|
},
|
|
[Classification.CUSTOM]: {
|
|
label: "自定义",
|
|
value: Classification.CUSTOM
|
|
},
|
|
}
|
|
|
|
export const AnnotationTypeMap = {
|
|
// ===== 音频/语音处理 =====
|
|
[AnnotationType.ASR_SEGMENTS]: {
|
|
label: "语音识别(分段)",
|
|
value: AnnotationType.ASR_SEGMENTS
|
|
},
|
|
[AnnotationType.ASR]: {
|
|
label: "语音识别",
|
|
value: AnnotationType.ASR
|
|
},
|
|
[AnnotationType.CONVERSATION_ANALYSIS]: {
|
|
label: "对话分析",
|
|
value: AnnotationType.CONVERSATION_ANALYSIS
|
|
},
|
|
[AnnotationType.INTENT_CLASSIFICATION]: {
|
|
label: "意图分类",
|
|
value: AnnotationType.INTENT_CLASSIFICATION
|
|
},
|
|
[AnnotationType.SIGNAL_QUALITY]: {
|
|
label: "信号质量检测",
|
|
value: AnnotationType.SIGNAL_QUALITY
|
|
},
|
|
[AnnotationType.SOUND_EVENT_DETECTION]: {
|
|
label: "声音事件检测",
|
|
value: AnnotationType.SOUND_EVENT_DETECTION
|
|
},
|
|
[AnnotationType.SPEAKER_SEGMENTATION]: {
|
|
label: "说话人分割",
|
|
value: AnnotationType.SPEAKER_SEGMENTATION
|
|
},
|
|
[AnnotationType.SPEECH_TRANSCRIPTION]: {
|
|
label: "语音转录",
|
|
value: AnnotationType.SPEECH_TRANSCRIPTION
|
|
},
|
|
|
|
// ===== 聊天评估 =====
|
|
[AnnotationType.AGENT_FINE_TUNE]: {
|
|
label: "Agent微调(无LLM)",
|
|
value: AnnotationType.AGENT_FINE_TUNE
|
|
},
|
|
[AnnotationType.AGENT_FINE_TUNE_LLM]: {
|
|
label: "Agent微调(有LLM)",
|
|
value: AnnotationType.AGENT_FINE_TUNE_LLM
|
|
},
|
|
[AnnotationType.RED_TEAMING]: {
|
|
label: "红队测试",
|
|
value: AnnotationType.RED_TEAMING
|
|
},
|
|
[AnnotationType.RLHF_EVALUATION]: {
|
|
label: "RLHF对话评估",
|
|
value: AnnotationType.RLHF_EVALUATION
|
|
},
|
|
[AnnotationType.CHATBOT_EVALUATION]: {
|
|
label: "聊天机器人评估",
|
|
value: AnnotationType.CHATBOT_EVALUATION
|
|
},
|
|
|
|
// ===== 计算机视觉 =====
|
|
[AnnotationType.IMAGE_CAPTIONING]: {
|
|
label: "图像描述",
|
|
value: AnnotationType.IMAGE_CAPTIONING
|
|
},
|
|
[AnnotationType.IMAGE_CLASSIFICATION]: {
|
|
label: "图像分类",
|
|
value: AnnotationType.IMAGE_CLASSIFICATION
|
|
},
|
|
[AnnotationType.INVENTORY_TRACKING]: {
|
|
label: "库存追踪",
|
|
value: AnnotationType.INVENTORY_TRACKING
|
|
},
|
|
[AnnotationType.KEYPOINT_LABELING]: {
|
|
label: "关键点标注",
|
|
value: AnnotationType.KEYPOINT_LABELING
|
|
},
|
|
[AnnotationType.MEDICAL_IMAGE_CLASSIFICATION]: {
|
|
label: "医学图像分类",
|
|
value: AnnotationType.MEDICAL_IMAGE_CLASSIFICATION
|
|
},
|
|
[AnnotationType.MULTIPAGE_DOCUMENT]: {
|
|
label: "多页文档标注",
|
|
value: AnnotationType.MULTIPAGE_DOCUMENT
|
|
},
|
|
[AnnotationType.OBJECT_DETECTION]: {
|
|
label: "目标检测",
|
|
value: AnnotationType.OBJECT_DETECTION
|
|
},
|
|
[AnnotationType.OCR]: {
|
|
label: "OCR识别",
|
|
value: AnnotationType.OCR
|
|
},
|
|
[AnnotationType.PDF_OCR]: {
|
|
label: "PDF OCR标注",
|
|
value: AnnotationType.PDF_OCR
|
|
},
|
|
[AnnotationType.SEMANTIC_SEGMENTATION_MASK]: {
|
|
label: "语义分割(掩码)",
|
|
value: AnnotationType.SEMANTIC_SEGMENTATION_MASK
|
|
},
|
|
[AnnotationType.SEMANTIC_SEGMENTATION_POLYGON]: {
|
|
label: "语义分割(多边形)",
|
|
value: AnnotationType.SEMANTIC_SEGMENTATION_POLYGON
|
|
},
|
|
[AnnotationType.VISUAL_GENOME]: {
|
|
label: "Visual Genome",
|
|
value: AnnotationType.VISUAL_GENOME
|
|
},
|
|
[AnnotationType.VQA]: {
|
|
label: "视觉问答",
|
|
value: AnnotationType.VQA
|
|
},
|
|
|
|
// ===== 对话AI =====
|
|
[AnnotationType.COREFERENCE_RESOLUTION]: {
|
|
label: "共指消解",
|
|
value: AnnotationType.COREFERENCE_RESOLUTION
|
|
},
|
|
[AnnotationType.SLOT_FILLING]: {
|
|
label: "槽填充",
|
|
value: AnnotationType.SLOT_FILLING
|
|
},
|
|
[AnnotationType.RESPONSE_GENERATION]: {
|
|
label: "响应生成",
|
|
value: AnnotationType.RESPONSE_GENERATION
|
|
},
|
|
[AnnotationType.RESPONSE_SELECTION]: {
|
|
label: "响应选择",
|
|
value: AnnotationType.RESPONSE_SELECTION
|
|
},
|
|
|
|
// ===== 生成式AI =====
|
|
[AnnotationType.CHATBOT_ASSESSMENT]: {
|
|
label: "聊天机器人评估",
|
|
value: AnnotationType.CHATBOT_ASSESSMENT
|
|
},
|
|
[AnnotationType.RLHF_PREFERENCE]: {
|
|
label: "RLHF人类偏好",
|
|
value: AnnotationType.RLHF_PREFERENCE
|
|
},
|
|
[AnnotationType.LLM_RANKING]: {
|
|
label: "LLM排名",
|
|
value: AnnotationType.LLM_RANKING
|
|
},
|
|
[AnnotationType.LLM_GRADING]: {
|
|
label: "LLM响应评分",
|
|
value: AnnotationType.LLM_GRADING
|
|
},
|
|
[AnnotationType.SFT]: {
|
|
label: "监督微调",
|
|
value: AnnotationType.SFT
|
|
},
|
|
[AnnotationType.VISUAL_RANKING]: {
|
|
label: "视觉排名",
|
|
value: AnnotationType.VISUAL_RANKING
|
|
},
|
|
|
|
// ===== 自然语言处理 =====
|
|
[AnnotationType.CONTENT_MODERATION]: {
|
|
label: "内容审核",
|
|
value: AnnotationType.CONTENT_MODERATION
|
|
},
|
|
[AnnotationType.MACHINE_TRANSLATION]: {
|
|
label: "机器翻译",
|
|
value: AnnotationType.MACHINE_TRANSLATION
|
|
},
|
|
[AnnotationType.NER]: {
|
|
label: "命名实体识别",
|
|
value: AnnotationType.NER
|
|
},
|
|
[AnnotationType.QUESTION_ANSWERING]: {
|
|
label: "问答",
|
|
value: AnnotationType.QUESTION_ANSWERING
|
|
},
|
|
[AnnotationType.RELATION_EXTRACTION]: {
|
|
label: "关系抽取",
|
|
value: AnnotationType.RELATION_EXTRACTION
|
|
},
|
|
[AnnotationType.TAXONOMY]: {
|
|
label: "层级分类",
|
|
value: AnnotationType.TAXONOMY
|
|
},
|
|
[AnnotationType.TEXT_CLASSIFICATION]: {
|
|
label: "文本分类",
|
|
value: AnnotationType.TEXT_CLASSIFICATION
|
|
},
|
|
[AnnotationType.TEXT_SUMMARIZATION]: {
|
|
label: "文本摘要",
|
|
value: AnnotationType.TEXT_SUMMARIZATION
|
|
},
|
|
|
|
// ===== 排名与评分 =====
|
|
[AnnotationType.ASR_HYPOTHESES]: {
|
|
label: "ASR假设选择",
|
|
value: AnnotationType.ASR_HYPOTHESES
|
|
},
|
|
[AnnotationType.IMAGE_RETRIEVAL]: {
|
|
label: "图像检索",
|
|
value: AnnotationType.IMAGE_RETRIEVAL
|
|
},
|
|
[AnnotationType.DOCUMENT_RETRIEVAL]: {
|
|
label: "文档检索",
|
|
value: AnnotationType.DOCUMENT_RETRIEVAL
|
|
},
|
|
[AnnotationType.PAIRWISE_CLASSIFICATION]: {
|
|
label: "成对分类",
|
|
value: AnnotationType.PAIRWISE_CLASSIFICATION
|
|
},
|
|
[AnnotationType.PAIRWISE_REGRESSION]: {
|
|
label: "成对回归",
|
|
value: AnnotationType.PAIRWISE_REGRESSION
|
|
},
|
|
[AnnotationType.SERP_RANKING]: {
|
|
label: "搜索排名",
|
|
value: AnnotationType.SERP_RANKING
|
|
},
|
|
[AnnotationType.TEXT_TO_IMAGE]: {
|
|
label: "文本生成图像",
|
|
value: AnnotationType.TEXT_TO_IMAGE
|
|
},
|
|
|
|
// ===== 结构化数据解析 =====
|
|
[AnnotationType.FREEFORM_METADATA]: {
|
|
label: "自由格式元数据",
|
|
value: AnnotationType.FREEFORM_METADATA
|
|
},
|
|
[AnnotationType.HTML_ENTITY_RECOGNITION]: {
|
|
label: "HTML实体识别",
|
|
value: AnnotationType.HTML_ENTITY_RECOGNITION
|
|
},
|
|
[AnnotationType.PDF_CLASSIFICATION]: {
|
|
label: "PDF分类",
|
|
value: AnnotationType.PDF_CLASSIFICATION
|
|
},
|
|
[AnnotationType.TABULAR_DATA]: {
|
|
label: "表格数据标注",
|
|
value: AnnotationType.TABULAR_DATA
|
|
},
|
|
|
|
// ===== 时间序列分析 =====
|
|
[AnnotationType.ACTIVITY_RECOGNITION]: {
|
|
label: "活动识别",
|
|
value: AnnotationType.ACTIVITY_RECOGNITION
|
|
},
|
|
[AnnotationType.CHANGE_POINT_DETECTION]: {
|
|
label: "变点检测",
|
|
value: AnnotationType.CHANGE_POINT_DETECTION
|
|
},
|
|
[AnnotationType.ANOMALY_DETECTION]: {
|
|
label: "异常检测",
|
|
value: AnnotationType.ANOMALY_DETECTION
|
|
},
|
|
[AnnotationType.TIMESERIES_SIGNAL_QUALITY]: {
|
|
label: "时序信号质量",
|
|
value: AnnotationType.TIMESERIES_SIGNAL_QUALITY
|
|
},
|
|
[AnnotationType.TIMESERIES_FORECASTING]: {
|
|
label: "时序预测",
|
|
value: AnnotationType.TIMESERIES_FORECASTING
|
|
},
|
|
|
|
// ===== 视频处理 =====
|
|
[AnnotationType.VIDEO_CLASSIFICATION]: {
|
|
label: "视频分类",
|
|
value: AnnotationType.VIDEO_CLASSIFICATION
|
|
},
|
|
[AnnotationType.VIDEO_FRAME_CLASSIFICATION]: {
|
|
label: "视频帧分类",
|
|
value: AnnotationType.VIDEO_FRAME_CLASSIFICATION
|
|
},
|
|
[AnnotationType.VIDEO_OBJECT_TRACKING]: {
|
|
label: "视频目标追踪",
|
|
value: AnnotationType.VIDEO_OBJECT_TRACKING
|
|
},
|
|
[AnnotationType.VIDEO_TIMELINE_SEGMENTATION]: {
|
|
label: "视频时间线分割",
|
|
value: AnnotationType.VIDEO_TIMELINE_SEGMENTATION
|
|
},
|
|
|
|
// ===== 社区贡献 =====
|
|
[AnnotationType.MAMMOGRAM_CLASSIFICATION]: {
|
|
label: "乳房X光分类",
|
|
value: AnnotationType.MAMMOGRAM_CLASSIFICATION
|
|
},
|
|
[AnnotationType.HTML_NER_TAGGING]: {
|
|
label: "HTML NER标注",
|
|
value: AnnotationType.HTML_NER_TAGGING
|
|
},
|
|
[AnnotationType.INVOICE_NER_BIO]: {
|
|
label: "发票NER(BIO)",
|
|
value: AnnotationType.INVOICE_NER_BIO
|
|
},
|
|
[AnnotationType.OCR_INVOICE_PRE_NER]: {
|
|
label: "OCR发票预NER",
|
|
value: AnnotationType.OCR_INVOICE_PRE_NER
|
|
},
|
|
[AnnotationType.TWITTER_SENTIMENT]: {
|
|
label: "Twitter情感分析",
|
|
value: AnnotationType.TWITTER_SENTIMENT
|
|
},
|
|
|
|
// ===== 通用/遗留类型 =====
|
|
[AnnotationType.CLASSIFICATION]: {
|
|
label: "通用分类",
|
|
value: AnnotationType.CLASSIFICATION
|
|
},
|
|
[AnnotationType.SEGMENTATION]: {
|
|
label: "通用分割",
|
|
value: AnnotationType.SEGMENTATION
|
|
},
|
|
}
|
|
|
|
export const TemplateTypeMap = {
|
|
[TemplateType.SYSTEM]: {
|
|
label: "系统内置",
|
|
value: TemplateType.SYSTEM
|
|
},
|
|
[TemplateType.CUSTOM]: {
|
|
label: "自定义",
|
|
value: TemplateType.CUSTOM
|
|
},
|
|
}
|