MAATRIX / Блог / Label Studio: разметка данных на своём сервере

Label Studio: разметка данных на своём сервере

MAATRIX

Если вы дообучаете модель под свою задачу — классифицируете обращения клиентов, извлекаете сущности из договоров, учите модель распознавать дефекты на фото — рано или поздно упрётесь не в архитектуру и не в GPU, а в качество размеченных данных. И вот тут встаёт неудобный вопрос: кому вы отдаёте на разметку внутренние документы, переписку с клиентами или фотографии производства. Label Studio на собственном сервере снимает этот вопрос — разметка происходит там же, где хранятся исходные данные, а не на чужой инфраструктуре.

Зачем вообще нужна разметка и что делает Label Studio

Модель не умеет угадывать разметку сама, если вы не используете совсем самообучающиеся подходы. Классификатор тональности отзывов нужно сначала показать на сотнях или тысячах примеров, где человек уже проставил метку «позитив/негатив/нейтрально». Модель для извлечения именованных сущностей (NER) — на текстах, где вручную выделены границы имён, адресов, сумм, дат. Модель для детекции объектов на фото — на изображениях с нарисованными рамками вокруг нужных объектов. Без этого набора «вопрос-правильный ответ» дообучение (fine-tuning) или обучение с нуля просто не на чём делать — модель либо не выучит нужный паттерн, либо выучит его криво.

Label Studio — открытый инструмент (open source, лицензия Apache 2.0 для community-редакции), который даёт разметчикам-людям удобный веб-интерфейс для этой работы и одновременно даёт вам как владельцу проекта единое место для управления процессом. Поддерживаются разные типы данных — текст, изображения, аудио, видео, временные ряды — и разные типы разметки под них: классификация целого документа, выделение span'ов текста для NER, bounding box и полигоны на изображениях, транскрипция и разметка сегментов в аудио, разметка временных интервалов в видео. Один и тот же инструмент закрывает почти весь спектр задач подготовки датасета, что удобно, если в компании несколько ML-проектов одновременно.

Технически это Django-приложение с фронтендом на React, которое ставится через Docker-образ heartexlabs/label-studio, хранит метаданные проектов и задач в базе (SQLite для маленьких инсталляций, PostgreSQL — для рабочих), а сами файлы с данными — на диске сервера или во внешнем хранилище типа S3.

Почему это тот случай, когда стоит хостить самому

Тут ключевая причина не в цене и не в кастомизации — а в том, ЧТО именно вы отправляете на разметку. Возьмём типичный пример: у компании есть внутренние документы (договоры, служебная переписка, финансовые отчёты), и нужно обучить модель извлекать из них структурированные данные. Чтобы это сделать, документы нужно сначала разметить — то есть показать людям-разметчикам. Если вы используете облачный SaaS-сервис разметки, эти документы физически загружаются на серверы третьей стороны, обрабатываются её сотрудниками или подрядчиками, и весь дальнейший контроль над копией этих данных вы теряете — она осталась у чужого провайдера со своей политикой хранения, доступа и удаления.

То же самое с персональными данными клиентов (переписка службы поддержки, медицинские записи, финансовые транзакции) — их передача на разметку через чужой облачный сервис создаёт прямой риск утечки третьей стороне: это ещё одна точка, где данные покидают периметр компании, ещё один набор логов, бэкапов и учётных записей сотрудников подрядчика с доступом к содержимому. Для коммерчески чувствительной информации (продукты до релиза, внутренние метрики, переговоры) добавляется риск, что содержимое ваших данных станет частью обучающей выборки самого SaaS-провайдера — это прямо прописано в условиях некоторых бесплатных и freemium-сервисов разметки.

Самостоятельный хостинг убирает эту точку риска: данные никогда не покидают вашу инфраструктуру. Разметчики заходят в веб-интерфейс Label Studio на вашем сервере и работают с данными, которые физически лежат на диске этого же сервера (или в вашем собственном S3-совместимом хранилище — см. S3-совместимое хранилище у себя), результат сохраняется там же. Дополнительно стоит контролировать доступ самих разметчиков (VPN или ограничение по IP, если это внешние подрядчики) и шифрование диска — но это управляемые риски, в отличие от риска "что происходит с данными внутри чужой инфраструктуры", который вы в принципе не можете проконтролировать.

Честно: самостоятельный хостинг не решает проблему полностью — если разметчик снимет данные на телефон, это от него не защищает. Но он убирает системный риск передачи данных чужой организации, а это самая частая причина утечек при использовании облачных SaaS-инструментов разметки.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть ИИ на сервере

Разворачиваем Label Studio на сервере

Проще всего — через Docker Compose. Минимальный рабочий docker-compose.yml с PostgreSQL в качестве бэкенда (для продакшена так надёжнее, чем встроенный SQLite):

version: "3.8"

services:
  db:
    image: postgres:16
    restart: unless-stopped
    environment:
      POSTGRES_DB: labelstudio
      POSTGRES_USER: labelstudio
      POSTGRES_PASSWORD: change_me_strong_password
    volumes:
      - pgdata:/var/lib/postgresql/data

  label-studio:
    image: heartexlabs/label-studio:latest
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:8080"
    depends_on:
      - db
    environment:
      DJANGO_DB: default
      POSTGRE_NAME: labelstudio
      POSTGRE_USER: labelstudio
      POSTGRE_PASSWORD: change_me_strong_password
      POSTGRE_HOST: db
      POSTGRE_PORT: 5432
      LABEL_STUDIO_HOST: https://label.example.com
      LABEL_STUDIO_USERNAME: admin@example.com
      LABEL_STUDIO_PASSWORD: change_me_admin_password
      LABEL_STUDIO_LOCAL_FILES_SERVING_ENABLED: "true"
      LABEL_STUDIO_LOCAL_FILES_DOCUMENT_ROOT: /label-studio/data/local-files
    volumes:
      - ls_data:/label-studio/data
      - ./local-files:/label-studio/data/local-files

volumes:
  pgdata:
  ls_data:

Порт 8080 сознательно проброшен только на 127.0.0.1 — наружу сервис отдаётся через nginx как reverse proxy с TLS. Базовый серверный блок:

server {
    listen 443 ssl;
    server_name label.example.com;

    ssl_certificate     /etc/letsencrypt/live/label.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/label.example.com/privkey.pem;

    client_max_body_size 200m;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 300s;
    }
}

client_max_body_size увеличен, потому что при загрузке через интерфейс аудио- и видеофайлы бывают заметно тяжелее стандартных 1 МБ. После docker compose up -d первый вход — по LABEL_STUDIO_USERNAME/LABEL_STUDIO_PASSWORD, дальше заводятся остальные учётные записи.

Ориентировочно: команде из 5-10 разметчиков без тяжёлого видео обычно хватает VPS на 2 vCPU и 4 ГБ RAM. Реальные цифры зависят от объёма файлов и параллельной нагрузки — это отправная точка, а не гарантия.

Шаблоны разметки под конкретную задачу

Сила Label Studio — в конфигурируемом интерфейсе разметки. Он описывается XML-подобной разметкой (Label Studio Config), и под каждый тип задачи есть готовый шаблон, который можно взять как есть или доработать. Например, классификация текста:

<View>
  <Text name="text" value="$text"/>
  <Choices name="sentiment" toName="text" choice="single">
    <Choice value="Позитив"/>
    <Choice value="Негатив"/>
    <Choice value="Нейтрально"/>
  </Choices>
</View>

Извлечение именованных сущностей — разметчик выделяет фрагмент текста мышью и присваивает ему метку:

<View>
  <Labels name="label" toName="text">
    <Label value="Имя" background="#ff6666"/>
    <Label value="Организация" background="#66ff66"/>
    <Label value="Дата" background="#6666ff"/>
  </Labels>
  <Text name="text" value="$text"/>
</View>

Разметка объектов на изображении (bounding box):

<View>
  <Image name="image" value="$image"/>
  <RectangleLabels name="label" toName="image">
    <Label value="Дефект" background="red"/>
    <Label value="Норма" background="green"/>
  </RectangleLabels>
</View>

Для аудио — сегментация с транскрипцией, для видео — разметка временных интервалов, всё по тому же принципу «взять шаблон из галереи, поправить список меток под свою задачу». Это удобно тем, что не нужно писать отдельный UI под каждый ML-проект — меняется только конфиг, а инфраструктура (хранение, экспорт, управление пользователями) общая для всех проектов на одном сервере.

Отдельная полезная возможность — подключение ML-backend'а как источника предразметки: если уже есть черновая модель, которая предсказывает метки с приемлемой, но не идеальной точностью, её можно подключить как отдельный сервис (репозиторий label-studio-ml-backend), и тогда разметчики не размечают с нуля, а проверяют и правят предложенные моделью варианты — это заметно ускоряет работу на больших объёмах.

Совместная работа нескольких разметчиков

В интерфейсе заводятся отдельные учётные записи под каждого разметчика, задачи внутри проекта распределяются между ними (вручную или через встроенное автоматическое распределение), и можно настроить, чтобы одна и та же задача размечалась несколькими людьми независимо — это нужно для расчёта согласованности разметки (inter-annotator agreement) и выявления спорных случаев. Честно: часть возможностей продвинутых воркфлоу ревью (многоступенчатое утверждение, отдельная роль "ревьюер" с блокировкой финального экспорта до подтверждения) в community-версии скромнее, чем в платной Enterprise-редакции — если команда крупная, стоит заранее свериться с документацией, что именно доступно бесплатно.

Для среднего размера команды типичный рабочий процесс такой: один человек (тимлид или ML-инженер) заводит проект и шаблон разметки, разметчики выполняют задачи, и периодически (не после каждой задачи, а пакетами) кто-то просматривает выборку размеченного и решает, нужно ли поправить инструкцию или отдельные примеры. Задачи, размеченные с явными расхождениями между разметчиками, стоит разбирать отдельно — обычно расхождение указывает либо на неоднозначный пример в данных, либо на нечёткую инструкцию, а не на то, что кто-то из разметчиков "плохо работает".

Экспорт результата для обучения модели

Когда разметка готова (или готова её часть — экспортировать можно в любой момент, не дожидаясь стопроцентного покрытия датасета), результат выгружается в форматах, которые понимают стандартные библиотеки для обучения. Из интерфейса или через API доступны, в частности:

ФорматДля чего
JSON / JSON-MINуниверсальный, можно распарсить под любой пайплайн
CSV / TSVпростая табличная разметка (классификация)
CONLL2003стандарт для NER-задач
COCOдетекция объектов на изображениях
Pascal VOC (XML)детекция объектов, альтернативный стандарт
YOLOразметка под YOLO-совместимые детекторы
ASR manifestтранскрипция аудио
Bratразметка сущностей и отношений в тексте

Экспорт также доступен через REST API Label Studio, что удобно, если разметка — часть автоматизированного пайплайна: сервер по расписанию забирает свежую порцию размеченных задач и добавляет их в обучающую выборку, не дожидаясь ручной выгрузки. Если дальше данные идут в дообучение модели на своём железе, конвейер логично продолжить статьёй про LoRA-файнтюнинг своей модели на VPS — экспортированный из Label Studio датасет как раз и становится входом для такого дообучения.

Инструкция для разметчиков важнее выбора инструмента

Здесь стоит сказать прямо то, что часто недооценивают: выбор конкретного инструмента разметки влияет на итоговое качество датасета меньше, чем качество написанной для разметчиков инструкции. Можно развернуть идеально настроенный Label Studio с продуманными шаблонами — и всё равно получить противоречивый датасет, если разметчикам не объяснили чётко, что считается "позитивным отзывом", где проходит граница сущности "Организация" в тексте со сложной структурой, как размечать пограничные и спорные случаи.

Практический совет, который экономит недели переразметки: до того как разметчики начнут массово работать, соберите 20-30 примеров и явно пропишите на них "правильно / неправильно" с объяснением почему. Не абстрактное "размечайте по смыслу", а конкретные примеры: вот этот текст — позитивный отзыв, а вот этот похожий, но с сарказмом — на самом деле негативный, и вот почему. Проведите короткий пилотный раунд на 50-100 задачах несколькими разметчиками параллельно, сравните расхождения — если согласованность низкая, проблема почти всегда в инструкции, а не в разметчиках, и её нужно переписать до того, как весь датасет будет размечен по нечёткому критерию.

Второй момент — контроль согласованности не разовая процедура, а процесс на всём протяжении разметки. Полезно периодически подмешивать в очередь уже размеченные ранее задачи повторно (не говоря разметчику, что это повтор) и сверять, совпадает ли новая метка со старой у одного и того же человека — это ловит как "усталость" разметчика на однообразной задаче, так и постепенный дрейф понимания инструкции. Небольшая инвестиция времени в качество инструкций и в такой контроль обычно окупается сильнее, чем поиск более продвинутого инструмента разметки или более быстрого сервера под него — модель, обученная на чистом и согласованном датасете, почти всегда выигрывает у модели с более сложной архитектурой, но обученной на шумной разметке. Мифы вокруг того, что "чем сложнее модель, тем меньше важны данные", разобраны отдельно в статье про обучение модели на чужих данных — там же честно про границы того, что вообще можно и что рискованно использовать для обучения.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть ИИ на сервере

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Обязательно ли использовать PostgreSQL вместо встроенной SQLite?

Для пробы и небольшого проекта SQLite достаточно, но при росте числа задач и пользователей PostgreSQL даёт предсказуемее производительность и меньше блокировок при параллельной записи — на продакшене стоит сразу поднимать с ним.

Можно ли подключить свою модель, чтобы она подсказывала разметку?

Да, через отдельный ML-backend сервис (label-studio-ml-backend), который отдаёт предсказания как предразметку — разметчик их проверяет и правит, а не создаёт с нуля.

Нужен ли для Label Studio GPU-сервер?

Самому инструменту — нет, это обычное веб-приложение. GPU нужен отдельно, если подключаете ML-backend с моделью для предразметки или обучаете модель на экспортированных данных — см. сервер для машинного обучения.

Как защитить инструмент, если разметчики — внешние подрядчики?

VPN или ограничение доступа по IP на уровне nginx/firewall в дополнение к аутентификации внутри Label Studio, плюс отдельная учётная запись на каждого человека.

Что делать, если данных для разметки — терабайты видео или аудио?

Держать такой объём на локальном диске сервера неудобно — логичнее подключить своё S3-совместимое хранилище как источник данных, тогда Label Studio обращается к файлам по ссылкам, а не хранит копию у себя.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →