## 1. 核心范式定义
在 Label Studio 中,机器学习模型(ML Backend)主要通过两种模式辅助人工标注。理解两者的区别是技术集成的基础。
### 1.1 预标注 (Pre-labeling)
- **定义**:**“模型先行,人工校对”**。
- **工作流**:任务加载时,模型一次性处理原始数据,生成预测结果并渲染在界面上。
- **交互逻辑**:单向通信(Server -> Client)。模型在后台运行,不响应用户的实时操作。
- **适用模型**:传统静态模型(如 YOLO, ResNet, BERT, BiLSTM-CRF)。
- **典型场景**:
- 图像:自动框出所有车辆。
- 文本:自动对全篇文档进行情感分类。
### 1.2 交互式标注 (Interactive Labeling)
- **定义**:**“人工引导,模型响应”**。
- **工作流**:用户在界面上进行原子操作(如点击、划选、输入提示),模型实时接收这些操作作为“条件(Context)”,动态计算并返回结果。
- **交互逻辑**:双向循环通信(Client <-> Server)。
- **适用模型**:支持 Prompt/Input Point 的模型(如 Segment Anything Model, LLM, Smart Regex)。
- **典型场景**:
- 图像:点击猫的头部,自动生成猫的像素级掩码(SAM)。
- 文本:输入“把这段话改成敬语”,自动替换原文(LLM)。
### 1.3 两种模式对比

---
## 2. 技术实现原理
### 工作流程可视化
**预标注工作流程:**

**交互式标注工作流程:**

### 2.1 架构差异:ML Backend 接收数据的不同
后端 `predict` 函数接收到的 JSON 数据结构决定了当前是预标注还是交互模式。
#### 模式 A:预标注请求包
Label Studio 仅发送原始数据。
```json
{
"tasks": [
{
"data": {
"image": "http://s3-bucket/data/123.jpg",
"text": "The quick brown fox..."
}
}
]
}
```
#### 模式 B:交互式请求包
Label Studio 发送原始数据 + **用户上下文 (Context)**。
- **触发条件**:XML 配置中开启 `smart="true"`。
- **数据特征**:包含 `context` 字段,记录了用户的点击坐标、选区或文本输入。
```json
{
"tasks": [{ "data": { ... } }],
"context": {
"result": [
{
"type": "keypointlabels", // 用户操作类型:点击关键点
"value": { "x": 50, "y": 50 } // 用户操作内容:坐标
}
]
}
}
```
### 2.2 ML Backend 数据处理架构

---
## 3. 图像模态 (Computer Vision)
### 模态技术概览

图像任务是交互式标注最成熟的领域,主要表现为从“目标检测”向“语义分割”的进化。
### 3.1 图像预标注
- **模型**:YOLO, Faster-RCNN。
- **行为**:模型读取图片,返回一组矩形框坐标 `[x, y, width, height]`。
- **XML 配置**:
```xml
<RectangleLabels name="label" toName="image">
<Label value="Car" />
</RectangleLabels>
```
### 3.2 图像交互式标注 (以 SAM 为例)
- **模型**:Segment Anything Model (SAM)。
- **行为**:
1. **输入层**:用户使用 **关键点 (KeyPoint)** 或 **矩形框 (Rectangle)** 作为提示(Prompt)。
2. **输出层**:模型返回 **画笔掩码 (Brush/Mask)**。
- **核心逻辑**:ML Backend 必须解析 `context` 中的点坐标,将其作为 Prompts 喂给 SAM Predictor,生成的 Mask 转为 RLE 格式返回。
- **XML 配置 (分离输入输出)**:
```xml
<View>
<!-- 图像对象 -->
<Image name="image" value="$image" />
<!-- 输出层:承载模型生成的 Mask -->
<BrushLabels name="mask_output" toName="image">
<Label value="Object" predictionMode="true"/>
</BrushLabels>
<!-- 输入层:用户点击交互 (smart="true") -->
<KeyPointLabels name="user_input" toName="image" smart="true">
<Label value="Positive" />
<Label value="Negative" />
</KeyPointLabels>
</View>
```
---
## 4. 文本模态 (NLP)
文本交互式标注主要依赖大语言模型 (LLM) 或规则传播算法,分为“基于选区”和“基于对话”两种路径。
### 4.1 文本预标注
- **模型**:BERT, Scikit-learn Classifier。
- **行为**:返回分类标签或实体索引 `start/end`。
### 4.2 文本交互式标注
#### 路径 A:智能选区传播 (Smart Selection)
- **场景**:快速实体抽取(NER)。
- **原理**:用户手动标注一个词(如“Apple”),模型通过正则或 Embedding 相似度,自动选中全文中所有的“Apple”或相似实体。
- **实现**:后端解析 `context` 中的选区文本,执行搜索算法,返回所有匹配项的 `start/end` 索引。
#### 路径 B:生成式对话 / LLM 辅助 (Generative AI)
- **场景**:文本摘要、纠错、风格迁移、RLHF。
- **原理**:利用 LLM 的指令遵循能力。
- **实现**:
1. 用户在 `<TextArea>` 中输入指令(Prompt)。
2. 后端提取指令与原文,拼接发给 OpenAI/DeepSeek。
3. 模型返回生成的文本,填入另一个 `<TextArea>` 供人工修改。
- **XML 配置 (LLM 交互模式)**:
```xml
<View>
<Text name="source_text" value="$text" />
<!-- 用户输入指令 -->
<TextArea name="user_prompt" toName="source_text"
editable="true" placeholder="输入指令,如:翻译成中文" />
<!-- 模型返回结果 -->
<TextArea name="llm_result" toName="source_text" editable="true" />
</View>
```
> *注:在 ML Backend 中,需监听 `user_prompt` 的变化,将结果写入 `llm_result`。*
---
## 5. 开发速查表:如何适配任意模型
### 模型适配决策流程

要将任意模型封装进 Label Studio,请遵循以下决策流程:
| 决策步骤 | 预标注 (Pre-labeling) | 交互式标注 (Interactive) |
| :-------------- | :--------------------------- | :----------------------------------------- |
| **1. 适用场景** | 批量处理,对延迟不敏感 | 精细处理,要求低延迟 (<1s) |
| **2. XML 属性** | 无特殊要求 | 必须在输入标签加 `smart="true"` |
| **3. 后端入口** | `predict(tasks)` | `predict(tasks, context)` |
| **4. 核心参数** | 仅使用 `tasks['data']` | 必须解析 `context['result']` 里的用户操作 |
| **5. 坐标转换** | 需将像素转为 0-100% 相对坐标 | 同左,且需处理输入点的相对坐标 |
| **6. 返回格式** | 标准 JSON 列表 | 标准 JSON 列表(通常只包含当前交互的结果) |
### 后端代码逻辑模版 (Python)
```python
class MyModel(LabelStudioMLBase):
def predict(self, tasks, context=None, **kwargs):
"""
统一处理入口
"""
# 1. 交互模式:如果有 context,说明用户正在操作
if context and 'result' in context:
user_action = context['result'][-1] # 获取最后一次操作
prompt_data = user_action['value'] # 获取点击坐标或输入文本
# 调用交互式模型 (如 SAM 或 ChatGPT)
result = self.interactive_model_inference(prompt_data, tasks[0])
return result
# 2. 预标注模式:没有 context,说明是任务刚加载
else:
# 调用静态模型 (如 YOLO 或 BERT)
results = []
for task in tasks:
res = self.static_model_inference(task['data'])
results.append(res)
return results
```
---
## 6. 总结
- **预标注**解决的是“从 0 到 1”的问题,通过静态模型减少手动输入的总量。
- **交互式标注**解决的是“从 1 到 100”的精度问题,利用 SAM 或 LLM 的推理能力,让模型充当增强型工具。
- **核心区别**在于 **ML Backend 是否处理 `context` 参数**。任何能接受外部条件输入的模型,理论上都可以封装为交互式后端。