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:135(prefix: /labelstudio/)→install/kubernetes/virtual.yaml:143(host: labelstudio.kubeflow.svc.cluster.local)。原文档把前缀写作/lablestudio/,系笔误,实际为/labelstudio/。
用户互通(cookie)
CubeStudio 用户登录时会把用户名写入 cookie,因此 LabelStudio 侧能直接拿到当前用户名信息。
- LabelStudio 侧代码:
label_studio/users/views.py的user_login函数(label-studio 源码仓库)。
项目分组过滤
打开标注任务组列表时,LabelStudio 后端会请求 CubeStudio 的 /my/project 接口,拿到当前用户所属的项目组,再据此过滤可见的标注任务组。
- LabelStudio 侧代码:
label_studio/projects/api.py的get_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:1119(postgresql+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_predict见 AIHub 算法应用开发。
NLP / chat 类:后端调用大模型
NLP 和 chat 相关的自动化标注在 myapp/views/view_labelstudio.py 中实现。
后端类 Labelstudio_View_Base(route_base = '/proxy/labelstudio')对外暴露统一的 /<field>/<model_type>/{health,setup,predict} 接口,predict 按 field=='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,另含temperature、top_p、stop、max_tokens、presence_penalty、frequency_penalty等(view_labelstudio.py:608-622)。
自定义自动化标注接口
要为新的标注类型编写自动化标注后端,做法是:把 job-template/job/yolo26/labelstudio.py 复制到你的接口代码旁,引入其中的 LabelStudio_ML_Backend 类,并在你的 API 中对外提供三个接口:
/health和/setup:仅用于检查接口是否启动。参考job-template/job/yolo26/server.py中的labelstudio_setup/labelstudio_health函数。/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_token、hostname、project,用于后续下载素材时鉴权。labelstudio_download_image(image_path, save_dir='result', ...)/labelstudio_download_audio(...):把 LabelStudio 里的图片/音频下载到本地再推理(命中hostname时走/static/直链下载)。
推理接口(/predict)输入
/predict 接收的参数包含:tasks、project、label_config、force_reload、try_fetch、params、model_version。
tasks:当前要标注的数据 source,JSON 格式(如task['data']['image']为图片路径)。
project:目前无用。label_config:你的标注项目「标签接口」中 Code 的值,字符串格式(XML),后端会从中解析出可用标签集合(server.py:365-375用ET.fromstring解析<Label value="...">)。
force_reload、try_fetch:布尔值;model_version:字符串,表示使用哪个版本的模型。
已核实:上述参数名与默认值与
view_labelstudio.py各nlp_*函数签名一致:force_reload=False, try_fetch=True, params={}, model_version=None。
推理接口(/predict)输出
技巧:先在 LabelStudio 上人肉标注一条数据并提交,查看该数据的 source,里面就是标注结果(result)应有的格式。

接口按下面的 JSON 返回,其中 result 即上图的格式:
{
"results": [
{
"result": "<result,即上图格式>",
"score": "0-1 之间的浮点数",
"model_version": "xxxx"
}
],
"model_version": "xxx"
}
已核实:返回结构与
server.py:406-416(labelstudio_predict)一致——外层results列表中每项含result/score/model_version,顶层另有model_version。
相关文档
- 使用侧:数据标注功能与操作流程
- aihub 应用如何写
labelstudio_predict:AIHub 算法应用开发 - YOLO 系列任务模板(含 yolo26 server):多媒体/CV/语音任务模板
- 平台级 logo/水印替换:更换 Logo 与水印
- istio 流量分流原理:流量代理与网关