LabelStudio 标注平台二次开发

要给 LabelStudio 接入自动化标注接口、编译/换 logo/打包 LabelStudio 镜像、打通 CubeStudio 用户与项目组、或理解标注平台与 aihub/大模型如何联动时读这篇

06-二次开发 / 数据标注
labelstudiolabel-studio标注平台数据标注自动化标注auto-labelingML Backend机器学习后端predictsetuphealth换logocookie共享单点登录SSO项目组过滤

LabelStudio 标注平台二次开发

CubeStudio 的数据标注能力基于开源 LabelStudio 二次开发而来。LabelStudio 本身是一个独立的项目(Django 后端 + React 前端),CubeStudio 通过 镜像定制 + istio 流量分流 + cookie 共享 + 自动化标注接口 把它无缝集成进平台。

说明:LabelStudio 的源码(label_studio/web/Dockerfile.cubestudio 等)位于 独立的 label-studio fork 仓库,不在 cube-studio-enterprise 主仓内。本文涉及 label_studio/... 的文件路径均指那个源码仓库;与本仓相关的部分(istio 路由、NLP 自动化标注后端、项目组过滤接口、k8s 部署清单)已逐一核对并在文中标明 文件:行号

面向使用者的操作流程见 数据标注功能与操作流程

代码结构

LabelStudio 源码仓库目录约定:

  • label_studio/:Django 框架的后端代码
  • web/:React 框架的前端代码
  • 其他目录可忽略

源码内容提示:

  • 配置文件:label_studio/core/settings/label_studio.py + label_studio/core/settings/base.py
  • 用户登录视图:label_studio/users/views.py

启动与本地调试

参考源码仓库的 docker-compose.yaml,它会启动三个服务:前端 nginx 打包镜像、后端 app、PostgreSQL 数据库。

后端 app 容器的启动命令是 sleep(即不自动起服务),所以流程是:先 docker-compose up -d 起容器,再手动进入 app 容器内操作。

容器内:

  • 前端构建:第一次构建需要科学上网,执行 cd /label-studio/web/ && sh build.sh;之后的构建只需执行最后一步 yarn run build:dev
  • 启动后端./deploy/docker-entrypoint.sh label-studio-uwsgi

浏览器访问以下地址完成用户登录(会自动登录 admin 用户并跳转到标注任务项目管理界面):

http://xx.xx/user/login/?username=admin@tencent.com

裸启动 Django 调试(不走 uwsgi)的命令参考:

export LOG_LEVEL=INFO
export DEBUG=1
export JSON_LOG=0
python3 label_studio/manage.py migrate
python3 label_studio/manage.py collectstatic
python3 label_studio/manage.py runserver 0.0.0.0:8080

构建与打包镜像

  • 后端:不需要构建。
  • 前端:见上文,docker-compose 启动后在容器内 yarn run build:dev
  • 打包镜像:参考源码仓库的 Dockerfile.cubestudio
docker build --network=host \
  -t ccr.ccs.tencentyun.com/cube-studio/label-studio:1.13.2-amd64 \
  --build-arg TARGETARCH=amd64 \
  -f Dockerfile.cubestudio .

注意:上面的镜像 tag 1.13.2-amd64 是 LabelStudio 源码仓库构建脚本里的示例版本。本仓 k8s 部署清单中实际拉取的镜像 tag 为 ccr.ccs.tencentyun.com/cube-studio/label-studio:20260701(注释标 heartexlabs/label-studio:1.10.1),见 install/kubernetes/labelstudio/labelstudio.yaml:40,89,151。部署到平台时请以 labelstudio.yaml 中的 tag 为准。

更换 logo

替换 label_studio/dev/ 下的图片,然后执行:

sh label_studio/dev/build.sh

平台级(CubeStudio 前端)的 logo / 水印替换是另一回事,见 更换 Logo 与水印

用户与权限互通

LabelStudio 的用户项目分组与 CubeStudio 打通,核心机制是「同 IP 端口 + istio 分流 + cookie 共享」。

流量分流(istio)

LabelStudio 和 CubeStudio 部署在同一个 IP/端口下,由 istio 的 VirtualService 按路径前缀分流:

  • /labelstudio/ 前缀的流量被分流到 LabelStudio 的 pod;
  • 其余默认流量进入 CubeStudio 前端 pod。

由于二者属于同一 IP 的服务,浏览器 cookie 天然共享

已核实:istio 路由配置见 install/kubernetes/virtual.yaml:135prefix: /labelstudio/)→ install/kubernetes/virtual.yaml:143host: labelstudio.kubeflow.svc.cluster.local)。原文档把前缀写作 /lablestudio/,系笔误,实际为 /labelstudio/

用户互通(cookie)

CubeStudio 用户登录时会把用户名写入 cookie,因此 LabelStudio 侧能直接拿到当前用户名信息。

  • LabelStudio 侧代码:label_studio/users/views.pyuser_login 函数(label-studio 源码仓库)。

项目分组过滤

打开标注任务组列表时,LabelStudio 后端会请求 CubeStudio 的 /my/project 接口,拿到当前用户所属的项目组,再据此过滤可见的标注任务组。

  • LabelStudio 侧代码:label_studio/projects/api.pyget_queryset 函数(label-studio 源码仓库)。
  • CubeStudio 侧接口:/my/project,见 myapp/views/view_team.py:641@expose_api ... url="/my/project",返回「我有权限的项目组」)。

补充(本仓实现):CubeStudio 后端另提供 /proxy/labelstudio/projects 接口(myapp/views/view_labelstudio.py:648),直接连 LABEL_STUDIO_DAT 指向的 PostgreSQL,按当前用户所属项目组 ID 过滤 project 表(workspace 字段存的是 CubeStudio 项目组 ID 字符串),供任务模板下拉等场景使用。LABEL_STUDIO_DAT 默认值见 myapp/config.py:1119postgresql+psycopg2://postgres:postgres@postgresql.kubeflow:5432/labelstudio)。

自动化标注

每种标注类型都需要单独编写自动化标注接口。平台自带示例的实现分两类:

  • 视觉、语音类:由对应的 aihub 应用提供自动化标注(每个应用实现 labelstudio_predict 函数)。
  • NLP / chat 类:由 CubeStudio 后端 myapp/views/view_labelstudio.py 实现,内部调用大模型(OpenAI 兼容)接口完成。

视觉 / 语音类:对应的 aihub 应用

下列每个 aihub 应用的 labelstudio_predict 函数提供对应标注类型的自动化标注(路径均已核对存在):

标注类型 aihub 应用 app.py 路径
目标识别 DAMOYOLO-高性能通用检测模型-S aihub/modelscope/cv-tinynas-object-detection-damoyolo/app.py
视觉-视频目标跟踪 YOLO 多目标跟踪模型 aihub/deep-learning/yolo-object-track/app.py
视觉-图像分类 ViT 图像分类-中文-日常物品 aihub/modelscope/cv-vit-base-image-classification-dailylife-labels/app.py
视觉-关键点检测 106 点人脸关键点-通用领域-2D aihub/modelscope/cv-mobilenet-face-2d-keypoints-alignment/app.py
视觉-目标边界识别(实例分割) CascadeMaskRCNN-SwinB 图像实例分割 aihub/modelscope/cv-swin-b-image-instance-segmentation-coco/app.py
视觉-目标遮罩识别(语义分割) Segformer-B0 实时语义分割 aihub/modelscope/cv-segformer-b0-image-semantic-segmentation-coco-stuff164k/app.py
视觉-光学字符识别(OCR) ocr 识别 aihub/deep-learning/paddleocr/app.py
视觉-图片描述 mPLUG 图像描述模型-中文-base aihub/modelscope/mplug-image-captioning-coco-base-zh/app.py
audio-语音识别 Paraformer 语音识别-中文-通用-16k-离线-large-pytorch aihub/modelscope/speech-paraformer-large-asr-nat-zh-cn-16k-common-vocab8404-pytorch/app.py
audio-说话人分隔 CAM++ 说话人日志-对话场景角色区分-通用 aihub/modelscope/speech-campplus-speaker-diarization-common/app.py
audio-多说话人语音识别 CAM++ 说话人日志-对话场景角色区分-通用 aihub/modelscope/speech-campplus-speaker-diarization-common/app.py

已核实:上述全部 app.py 路径在本仓存在;以 cv-tinynas-object-detection-damoyolo/app.py:144 为例,确有 def labelstudio_predict(self, tasks, project, label_config, force_reload=False, try_fetch=True, params={}, model_version=None, **kwargs)。aihub 应用如何实现 labelstudio_predictAIHub 算法应用开发

NLP / chat 类:后端调用大模型

NLP 和 chat 相关的自动化标注在 myapp/views/view_labelstudio.py 中实现。

后端类 Labelstudio_View_Baseroute_base = '/proxy/labelstudio')对外暴露统一的 /<field>/<model_type>/{health,setup,predict} 接口,predictfield=='nlp' 分发到不同子类型处理(view_labelstudio.py:72-93):

model_type 处理函数
classification nlp_classification
summary nlp_summary
translaton nlp_translaton(代码中即此拼写)
ner nlp_ner
faq nlp_faq
rank nlp_rank
intent nlp_intent
chat nlp_chat

这些函数都通过 self.chatgpt(prompt) 调用大模型(view_labelstudio.py:603),相关配置(myapp/config.py):

  • CHATGPT_CHAT_URL:大模型 OpenAI 兼容接口地址,默认 https://api.openai.com/v1(代码默认值;config.py:1380 示例配的是 ['https://lonlie.plus7.plus/v1'],可为列表随机选)。请求时会自动补 /chat/completions
  • CHATGPT_TOKEN:鉴权 token,写入 Authorization: Bearer 头(同时写 api-key 头兼容微软接口),见 config.py:1379
  • CHATGPT_ARGS:模型参数字典,model 默认 gpt-5-mini,另含 temperaturetop_pstopmax_tokenspresence_penaltyfrequency_penalty 等(view_labelstudio.py:608-622)。

自定义自动化标注接口

要为新的标注类型编写自动化标注后端,做法是:把 job-template/job/yolo26/labelstudio.py 复制到你的接口代码旁,引入其中的 LabelStudio_ML_Backend 类,并在你的 API 中对外提供三个接口:

  1. /health/setup:仅用于检查接口是否启动。参考 job-template/job/yolo26/server.py 中的 labelstudio_setup / labelstudio_health 函数。
  2. /predict:提供真正的自动化标注。

注意(路由前缀):原文档把接口写作 /health/setup/predict。在 job-template/job/yolo26/server.py 中,三个接口的实际注册路径带 /labelstudio/ 前缀@app.get("/labelstudio/health")server.py:427)、@app.post("/labelstudio/setup")server.py:421)、@app.post("/labelstudio/predict")server.py:350)。而 CubeStudio 内置 NLP 后端则用 /proxy/labelstudio/<field>/<model_type>/{health,setup,predict}view_labelstudio.py:47,51,72)。接入时请以你实际部署的服务实现为准。

LabelStudio_ML_Backend 类(job-template/job/yolo26/labelstudio.py)的职责:

  • labelstudio_health(**kwargs):返回 {}
  • labelstudio_setup(**kwargs):保存标注平台发来的元数据 access_tokenhostnameproject,用于后续下载素材时鉴权。
  • labelstudio_download_image(image_path, save_dir='result', ...) / labelstudio_download_audio(...):把 LabelStudio 里的图片/音频下载到本地再推理(命中 hostname 时走 /static/ 直链下载)。

推理接口(/predict)输入

/predict 接收的参数包含:tasksprojectlabel_configforce_reloadtry_fetchparamsmodel_version

  • tasks:当前要标注的数据 source,JSON 格式(如 task['data']['image'] 为图片路径)。

    task 数据格式示意

  • project:目前无用。

  • label_config:你的标注项目「标签接口」中 Code 的值,字符串格式(XML),后端会从中解析出可用标签集合(server.py:365-375ET.fromstring 解析 <Label value="...">)。

    label_config 示意

  • force_reloadtry_fetch:布尔值;model_version:字符串,表示使用哪个版本的模型。

已核实:上述参数名与默认值与 view_labelstudio.pynlp_* 函数签名一致:force_reload=False, try_fetch=True, params={}, model_version=None

推理接口(/predict)输出

技巧:先在 LabelStudio 上人肉标注一条数据并提交,查看该数据的 source,里面就是标注结果(result)应有的格式。

标注结果 source 格式示意

接口按下面的 JSON 返回,其中 result 即上图的格式:

{
    "results": [
        {
            "result": "<result,即上图格式>",
            "score": "0-1 之间的浮点数",
            "model_version": "xxxx"
        }
    ],
    "model_version": "xxx"
}

已核实:返回结构与 server.py:406-416labelstudio_predict)一致——外层 results 列表中每项含 result / score / model_version,顶层另有 model_version

相关文档

最后更新 2026-07-04完整文档以官方仓库为准:GitHub Wiki