Aller au contenu principal

ADR-0172 : Labellisation des données et affinage des modèles : Label Studio et LLaMA-Factory dans le catalogue

  • Statut : accepté
  • Date : 2026-11-02
  • Portée : catalogue du Navin Manager (navin-manager/catalog/services/label-studio.yaml, navin-manager/catalog/services/llama-factory.yaml), registre des consoles, composants gérés
  • Documents liés : ADR-0101 (politique de licences), ADR-0168 (moteurs d'inférence vLLM et Ollama), ADR-0171 (installation durcie), navin-manager/docs/fr/labeling-finetuning.md (guide)

Contexte​

La plateforme sert des modèles (vLLM derrière LiteLLM) et les évalue (Opik, promptfoo, Ragas, garak), mais n'offrait ni la labellisation des données, ni la validation humaine des sorties des modèles, ni l'affinage des modèles publics et privés. Le client demande deux services, avec leur licence : Label Studio (Apache-2.0) pour la labellisation de textes, d'images, de sons et de vidéos, la validation humaine et la préparation des jeux de données ; LLaMA-Factory (Apache-2.0) pour l'affinage (SFT, LoRA, QLoRA, DPO) et la gestion des entraînements. Ils s'installent comme les autres services du catalogue : hors ligne, durcis selon l'ADR-0171, documentés en français et en anglais.

Décision​

  1. Label Studio 1.23.2, édition Community, méthode podman. Image officielle heartexlabs/label-studio épinglée par empreinte, deux composants comme le docker-compose.yml du projet : app (uwsgi) et nginx (fichiers statiques, relais vers l'application, médias). Pas de méthode python : label-studio start du paquet PyPI lance le serveur de développement de Django, et le paquet ne contient ni la configuration nginx ni l'entrée uwsgi de l'image.
  2. État dans les services de la plateforme. Base PostgreSQL de la liaison database, jamais SQLite ; médias et exports dans le compartiment S3 de la liaison s3 (SeaweedFS par défaut), servis par nginx grâce à X-Accel-Redirect. Le point d'accès S3 de l'installation est le seul point d'accès interne de confiance (S3_ENDPOINT) ; la protection contre la falsification de requêtes côté serveur reste active pour les points d'accès saisis dans un projet, les imports par URL et les webhooks.
  3. Sécurité de Label Studio. Réseau isolé du service, --cap-drop ALL, utilisateur 1001 de l'image. Inscription sur invitation (LABEL_STUDIO_DISABLE_SIGNUP_WITHOUT_LINK), compte administrateur et clé secrète générés à l'installation et gardés dans le coffre, cookies sécurisés et origine CSRF derrière la passerelle HTTPS (public_url), télémétrie, rapports Sentry (DSN par défaut de l'image) et vérification de version coupés, fichiers locaux désactivés, autorités internes de confiance pour la base et le stockage (trusted_ca_pem). Le mode replicated partage la base, le compartiment et la clé : n'importe quelle réplique sert n'importe quel utilisateur, et seule la première application crée le premier compte.
  4. LLaMA-Factory 0.9.5, méthode podman. Pile PyTorch et CUDA de l'image officielle hiyouga/llamafactory, épinglée par empreinte. Une interface LLaMA Board (Gradio) par hôte GPU, GPU par CDI (nvidia.com/gpu), réseau isolé, --cap-drop ALL, hors ligne (HF_HUB_OFFLINE, TRANSFORMERS_OFFLINE, HF_DATASETS_OFFLINE), sans lien de partage public, sans statistiques Gradio, sans serveur MCP de Gradio, sans W&B. Modèles, jeux de données, configurations, entraînements et exports restent dans /var/lib/navin/llama-factory de l'hôte.
  5. Entraînements pilotés par le Manager. Commandes download_model (cache Hugging Face, miroir interne), train et export (configurations YAML relues du dossier configs, lancées en arrière-plan avec leur journal), runs, run_log, env, gpu_status. Un paramètre n'entre jamais dans le texte d'un script : il est passé en argument, et son motif refuse les caractères du shell et les chemins.
  6. Mise en service d'un modèle affiné. L'export fusionne l'adaptateur dans son modèle de base ; le dossier exporté est importé dans models/local d'un hôte vLLM (model_source: local), que LiteLLM enregistre par sa liaison. Les agents n'appellent jamais LLaMA-Factory.
  7. Console sans authentification. LLaMA Board n'a pas d'authentification : sa console est déclarée sans authentification et avec des ressources externes (polices Google de Gradio) ; les contrôles des consoles ne l'ouvrent en production qu'à travers la passerelle authentifiante.
  8. Licences. Apache-2.0 pour les deux (ADR-0101). Les bibliothèques CUDA de l'image LLaMA-Factory relèvent de LEX-011 comme celles de vLLM ; les poids affinés gardent la licence de leur modèle de base (LEX-012).

Alternatives écartées​

  • Label Studio avec SQLite : un seul serveur, aucune réplique, état sur l'hôte, contraire à la haute disponibilité et à la sauvegarde de la plateforme.
  • Stockage local des médias de Label Studio : il faudrait un volume partagé entre les hôtes ; le compartiment S3 de la plateforme le remplace.
  • Entraînement multi nœud de LLaMA-Factory (torchrun entre hôtes) : NCCL demande le réseau de l'hôte et des ports dynamiques ; écarté tant que le besoin n'est pas démontré (ADR-0171).
  • Méthode python pour LLaMA-Factory : la pile PyTorch, CUDA, flash-attn et DeepSpeed dépend du pilote et de la version de CUDA ; l'image officielle la fige.
  • Label Studio Enterprise (rôles, SSO, relecture) : licence commerciale, hors de la politique de licences.

Conséquences​

Le catalogue compte 51 services. Label Studio demande PostgreSQL et un stockage S3 (SeaweedFS de la plateforme par défaut). LLaMA-Factory demande un hôte GPU NVIDIA (pilote, NVIDIA Container Toolkit et spécification CDI), 16 Go de mémoire au moins et de l'espace disque pour les modèles. L'édition Community de Label Studio n'a pas de rôles : l'accès se contrôle par l'invitation et la passerelle.

Complément du 2 novembre 2026 (LLM et VLM, QLoRA, DPO) : LLaMA-Factory affine aussi les modèles de vision (Qwen3-VL, par exemple) sur des jeux sharegpt à images ou vidéos, que Label Studio prépare comme les préférences du DPO (comparaison Pairwise). L'image officielle n'embarque pas bitsandbytes, nécessaire à QLoRA : la commande install_qlora installe bitsandbytes 0.50.2 (MIT), roue vérifiée par son sha256 épinglé, dans un dossier de l'hôte monté en lecture seule dans l'interface (PYTHONPATH), depuis le dossier wheels de l'hôte ou l'index Python du service. L'image reste celle de l'éditeur, épinglée par son empreinte : aucune image n'est reconstruite. Le paramètre vision de vLLM déclare le VLM servi à LiteLLM (supports_vision).

Complément du 2 novembre 2026 (service par vLLM ou Ollama) : les commandes publish_to_vllm et publish_to_ollama de LLaMA-Factory copient un export fusionné dans les poids importés de vLLM (model_source: local) ou dans le dossier d'import d'Ollama du même hôte, sans jamais écraser un dossier ; la nouvelle commande import_safetensors d'Ollama fait de ce dossier un modèle sur chaque instance, publié dans LiteLLM par litellm_models. Les noms sont des arguments positionnels ou des variables d'environnement, jamais une partie d'un script, et leur motif refuse les chemins.

Preuves​

navin-manager/server/tests/test_catalog_labeling_finetuning.py, navin-manager/server/tests/test_catalog.py, navin-manager/server/tests/test_consoles.py, navin-manager/server/tests/test_console_credentials.py, services/control-plane/tests/test_functional_catalog_coverage.py, services/control-plane/tests/test_platform_components.py, navin-manager/server/tests/test_catalog_inference.py.