Label Studio Enterprise 2.7.0 深度解析:外部分类法、标签分布图表与用户软删除
【免费下载链接】label-studioLabel Studio is a multi-type data labeling and annotation tool with standardized output format项目地址: https://gitcode.com/GitHub_Trending/la/label-studio
本文以 Label Studio Enterprise 2.7.0(2023 年 11 月 21 日发布,对应 Helm Chart 1.2.9)为核心,系统讲解该版本引入的三大关键能力——通过Taxonomy标签apiUrl参数加载外部分类法(External taxonomy)、项目仪表盘上的标签组分布图表与拖拽排序、以及面向管理员的安全用户软删除(Soft delete users)。读者将掌握外部分类法 JSON 数据格式与懒加载原理、软删除的底层实现与身份掩码机制,并完整了解该版本的安全修复与 Bug 修复清单。
该版本的官方发布说明位于仓库 docs/source/guide/release_notes/onprem/2.7.0.md,其核心亮点可概括为三句话:分类法不必再内联写在标注配置里,可从外部 JSON 远程加载;标签组在项目仪表盘中以环图直观呈现且支持拖拽排序;被删除的用户以“软删除”方式保留数据完整性并自动掩码身份信息。
版本概览
| 维度 | 说明 |
|---|---|
| 版本号 | Label Studio Enterprise 2.7.0 |
| 发布日期 | 2023 年 11 月 21 日 |
| Helm Chart 版本 | 1.2.9 |
| 核心亮点 | External taxonomy、Group visibility in label distribution charts、Soft delete users |
本版本包含三类变更:
- 新功能(New Features):外部分类法加载、标签分布图表中的标签组可见性与仪表盘拖拽排序、用户软删除;
- 增强(Enhancements):支持 AWS Signature Version 4 查询参数、仪表盘 “Submitted Annotations” 指标新增 tooltip;
- 安全与修复(Security & Bug fixes):修复 SSRF DNS rebinding、两处 XSS 漏洞(含 CVE-2023-47115)以及十余项功能 Bug。
下文将按照“新功能 → 增强 → 安全 → Bug 修复”的顺序逐一展开,并深入对应源码进行印证。
新功能一:外部分类法(External Taxonomy)
从内联Choice到外部 JSON 的转变
在 2.7.0 之前,构建层级分类法(Taxonomy)只能通过标注配置中的Choice标签手工内联定义。对于拥有成百上千个节点的大型分类法,这种方式的维护成本极高:分类法更新意味着修改标注配置、重新保存项目,且大规模内联选择项还会拖慢标注器的加载与交互性能。
2.7.0 引入了Taxonomy标签上的apiUrl参数,允许标注配置从一个外部 JSON 格式文件或远程 API加载分类法。官方在发布说明中将其收益归纳为三点:
- 性能(Performance):大型分类法场景下获得显著性能提升——分类法按需懒加载,不再随配置整体注入前端;
- 可用性与标准化(Usability and standardization):JSON 格式配合任意编辑器管理,分类法更易于组织、更新和版本化;
- 安全(Security):分类法内容可以安全地存放在 Label Studio 之外,敏感的分类数据不必进入项目配置或标注界面源码。
标签配置示例
使用apiUrl的外部分类法标注配置形如:
<View> <Taxonomy name="taxonomy" toName="text" apiUrl="https://example.com/taxonomy.json" leafsOnly="false" showFullPath="true" pathSeparator=" / "> </Taxonomy> <Text name="text" value="$text" /> </View>其中apiUrl指向的 JSON 数据源即外部分类法的根。该用法同样适用于 audio、image、HTML、paragraphs、text、time series、video 等多种数据类型(参见 docs/source/tags/taxonomy.md)。
外部分类法 JSON 数据格式
前端Taxonomy组件期望apiUrl返回如下结构的 JSON(顶层可以是items数组,也兼容直接返回数组的旧格式):
{ "items": [ { "value": "Online", "alias": "online", "hint": "内容可通过互联网访问", "children": [ { "value": "UGC", "alias": "ugc", "isLeaf": true }, { "value": "Paywall", "alias": "paywall", "children": [ { "value": "NY Times", "alias": "nytimes", "isLeaf": true }, { "value": "The Wall Street Journal", "alias": "wsj", "isLeaf": true } ]} ] }, { "value": "Offline", "alias": "offline", "isLeaf": true } ] }从 web/libs/editor/src/tags/control/Taxonomy/Taxonomy.jsx 的实现可以看出,每个节点支持的字段包括:
value:节点显示名称(必填);alias:节点别名,用于在结果中标识路径;缺省时回退为value;children:子节点数组,用于构建层级;isLeaf:是否叶子节点,用于控制是否可继续展开/选中;hint、color、hotkey:提示信息、颜色与快捷键等可选展示属性。
加载时组件会将原始 JSON 递归转换为内部格式(label/path/depth/isLeaf等),其中path记录了从根到当前节点的完整路径([...parents, alias ?? value]),这正是“选择叶子节点时同时保存其所有祖先”这一分类法结果格式的基础。
源码级原理解析:懒加载与认证
Taxonomy的apiUrl行为在源码中由几个关键环节构成(文件均为 web/libs/editor/src/tags/control/Taxonomy/Taxonomy.jsx):
- 属性模型:
TagAttrs中定义了apiurl: types.maybeNull(types.string)(第 98 行),并通过!!self.apiurl判断是否为“由 API 加载的分类法”(isLoadedByApi)。 - URL 解析与预签名:
updateValue(第 564-573 行)首先通过parseValue(self.apiurl, store.task.dataObj)解析apiUrl——这意味着apiUrl支持从任务数据中插值,例如apiUrl="https://example.com/taxonomy/{{taxonomy_id}}.json";随后尝试通过presignUrlForProject对 URL 进行预签名(若项目配置了云存储,可支持私有资源)。 - 懒加载与分页语义:
loadItems(第 400-468 行)是核心加载逻辑。它对每个非叶子节点的展开请求追加path查询参数(如?path=Online&path=Paywall),实现逐级按需加载,这是大型分类法性能提升的关键。响应同样按{ items: [...] }或裸数组格式递归转换。 - HTTP Basic 认证:如果
apiUrl中携带用户名密码(https://user:pass@host/taxonomy.json),组件会自动提取并构造Authorization: Basic ...请求头(第 421-430 行),方便对受保护的数据源做简单认证。 - 错误处理:加载失败时会通过
messages.ERR_LOADING_HTTP生成错误提示并写入标注错误列表,标注器可看到明确的apiUrl加载失败信息。
与外部分类法配套的相关参数
在外部分类法场景下,Taxonomy标签的以下参数同样值得关注(完整参数清单见 docs/source/tags/taxonomy.md 及标签源码注释):
leafsOnly:是否只允许标注器选择叶子节点(默认false);showFullPath:是否在结果中展示选中项的完整路径(默认false);pathSeparator:完整路径的层级分隔符(默认" / ",需确保分类数据中不包含该分隔符,避免路径解析歧义);maxUsages:每个任务/区域内同一选项的最大可选中次数;allowAddLabels:仅新版 Taxonomy UI 可用,是否允许标注器新增自定义标签;外部分类法(设置了apiUrl)时该参数被忽略——外部分类法应在其源头统一管理;legacy(已废弃):启用旧版 Taxonomy UI 时apiUrl不可用,两者互斥。
新功能二:标签分布图表中的标签组可见性与拖拽排序
当标注配置包含多个标签组(label groups)时,2.7.0 在项目仪表盘(Project Dashboard)中新增了Summary 视图,以**环图(donut chart)**展示标签组分布情况。该视图帮助项目管理员直观掌握各组标签的使用进度,快速定位“哪一类标签覆盖不足、需要补充任务数据”的区域。
同时,仪表盘上的 KPI 指标卡与图表现在支持拖拽排序(drag-and-drop reordering),管理员可以按自己的工作习惯调整仪表盘布局。发布说明中给出了仪表盘标签组分布截图与拖拽演示动图,但该动图素材位于外部发布站点(/images/releases/...),并未随本开源仓库分发,本文不额外引用。
配套增强方面,2.7.0 还改进了项目仪表盘上Submitted Annotations(已提交标注)指标:当鼠标悬停该指标时会显示 tooltip,补充说明其中包含的跳过(skipped)与空标注(empty annotations)的细分信息,帮助管理员理解指标口径、判断数据质量。
新功能三:用户软删除(Soft Delete Users)
软删除 vs 停用(Deactivate)
此前,管理员移除用户只能通过停用账户(deactivating)实现。这带来一个实际问题:“不会再回来的用户”(如离职员工)与“暂时不活跃的用户”(如自由标注者)无法区分,停用操作语义过于笼统。
2.7.0 起,管理员可以通过应用界面或 API删除(delete)用户。删除采用“软删除(soft delete)”语义:用户记录本身被保留以保证数据完整性(历史标注、任务分配等引用关系不中断),但其在系统中的可见身份被掩码处理,并退出所有活动上下文。
底层实现:组织成员关系的deleted_at
从源码看,软删除的主体是组织成员关系OrganizationMember,其核心实现在 label_studio/organizations/models.py:
- 模型新增
deleted_at时间戳字段,is_deleted属性即bool(self.deleted_at)(第 66-67 行); soft_delete()方法(第 77-91 行)在事务内完成:置deleted_at = now();将用户的active_organization切换到下一个未被删除的组织;若用户已无任何有效组织,则删除其头像并将avatar置空;最后清理该用户在该组织项目上的任务锁(task locks),避免残留锁导致任务分配异常。
此外,label_studio/users/migrations/0007_user_is_deleted.py 中为用户模型增加了is_deleted布尔字段(db_index=True、默认False),用于系统层面标记“按删除对待的用户”。
身份掩码:序列化层的隐私保护
软删除后,用户在其他成员与 API 响应中的身份会被自动掩码。见 label_studio/users/serializers.py 中is_user_deleted()与to_representation()的实现逻辑:
is_user_deleted()(第 11-66 行)通过组织成员关系的deleted_at判断用户是否处于删除状态,并利用deleted_user_ids/is_deleted_cache等上下文缓存避免重复查询;- 对已删除用户,序列化时(第 119-130 行)做如下掩码替换:
username→deleted-{uid}、email→deleted-{uid}-user@example.com、first_name→Deleted、last_name→User {uid}。
也就是说,历史标注记录中“由谁完成”的信息会保留为可区分的占位身份,而真实姓名、邮箱等 PII 不会泄露给其他成员。仓库中的相关测试(如 label_studio/tasks/tests/test_deleted_user_task_serialization.py)专门验证了注解、草稿与数据导出中已删除用户用户名的掩码行为。
管理 API 说明
软删除通过组织成员详情接口OrganizationMemberDetailAPI的DELETE方法触发(label_studio/organizations/api.py 第 272-318 行),关键约束如下:
- 仅允许删除当前活跃组织下的成员(否则返回 403 “You can delete members only for your current active organization”);
- 不能软删除自己(返回 405 “User cannot soft delete self”);
- 已删除的成员再次删除返回 404 “Member not found”;
- 权限要求为
organizations_change(组织管理权限)。
增强功能(Enhancements)
- AWS Signature Version 4 查询参数支持:本版本为相关云存储/对象存储同步场景增加了对 AWS SigV4 风格查询参数(签名头与查询串)的支持,提升与 AWS 生态服务的兼容性。
- Submitted Annotations 指标 tooltip:如前述,仪表盘指标悬停提示补充了跳过与空标注的细分信息。
安全修复(Security)
2.7.0 共修复三处安全问题:
- SSRF DNS rebinding 问题:修复了服务端请求伪造(SSRF)类攻击面中的 DNS rebinding 绕过,降低恶意 DNS 重绑定导致的内部网络探测风险;
- 错误页 XSS 漏洞:修复了特定错误页面上的跨站脚本(XSS)注入点;
- 头像文件扩展名 XSS 漏洞(CVE-2023-47115):修复了与用户头像文件扩展名校验相关的 XSS 漏洞,对应 GitHub Advisory GHSA-q68h-xwq5-mm7x。该问题提示头像上传处理必须严格校验文件扩展名与内容类型。
Bug 修复清单
本版本修复的 Bug 涵盖标注配置、编辑器性能、仪表盘统计、存储同步、Webhook 与 API 行为等多个方面,逐条梳理如下:
- 修复设置项目标注配置时验证错误显示不正确的问题;
- 修复图像分割(Image Segmentation)场景下的缩放性能问题;
- 修复标注员绩效仪表盘中一致性(agreements)数据错误的问题;
- 修复与 Azure Blob 存储同步时出现的运行时错误;
- 修复通过源存储创建的任务不触发 Webhook 的问题;
- 修复在禁用上下文滚动时仍执行不必要代码的问题;
- 修复离开页面前草稿标注未保存的问题;
- 修复
PATCH api/tasks/<id>返回错误的问题; - 修复复制项目时错误地包含一个未复制任何标注的标注计数的问题;
- 修复一致性 groundtruth API 调用占用过多资源的问题。
升级与部署说明
本版本以 Helm Chart 1.2.9 发布,适用于 Label Studio Enterprise 2.7.0 的 on-premise 部署(对应 Kubernetes/Helm 部署形态)。升级时建议关注:
- 软删除用户涉及数据迁移(
users与organizations相关迁移,如 label_studio/users/migrations/0007_user_is_deleted.py),请按常规迁移流程执行; - 若使用了
apiUrl外部分类法,请确保目标 JSON 数据源可被标注器浏览器端访问,且 URL 允许附加path查询参数; - 安全修复建议在升级后尽快验证头像上传与错误页展示行为,确认补丁已生效。
综上,Label Studio Enterprise 2.7.0 的核心价值在于:将大型分类法的管理从标注配置中解放出来(外部 JSON + 懒加载)、让标签组维度的进度可见(分布环图与拖拽布局)、并以软删除机制补齐了用户生命周期管理中的“删除”语义,同时通过 SSRF 与 XSS 修复提升了整体安全基线。读者可结合 docs/source/tags/taxonomy.md(Taxonomy 标签完整参数)、web/libs/editor/src/tags/control/Taxonomy/Taxonomy.jsx(外部加载实现)以及 label_studio/organizations/models.py(软删除实现)在仓库中进一步深入。
【免费下载链接】label-studioLabel Studio is a multi-type data labeling and annotation tool with standardized output format项目地址: https://gitcode.com/GitHub_Trending/la/label-studio
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考