1 points par GN⁺ 2024-05-27 | 1 commentaires | Partager sur WhatsApp
  • mistral-finetune est une base de code légère pour fine-tuner les modèles Mistral de manière économe en mémoire et performante ; le dépôt est actuellement archivé et n’est plus activement maintenu
  • La méthode d’entraînement repose sur LoRA, qui fige la plupart des poids et n’entraîne que 1 à 2 % de poids supplémentaires sous forme de perturbations matricielles de bas rang
  • Pour une efficacité maximale, l’utilisation de GPU A100 ou H100 est recommandée ; le code est optimisé pour l’entraînement multi-GPU sur un seul nœud, mais les petits modèles comme les 7B peuvent aussi fonctionner sur un seul GPU
  • Les modèles pris en charge incluent 7B, Mixtral 8x7B, Mixtral 8x22B, Mistral-Nemo 12B et Mistral Large v2 123B Instruct ; Mistral-Nemo et Large v2 ont chacun des contraintes liées à la longueur de séquence et au taux d’apprentissage
  • Les données doivent respecter le format jsonl et un schéma strict ; avant l’entraînement, il est important de valider le format avec utils.validate_data et d’effectuer une estimation du temps d’entraînement

État et objectif du projet

  • Le dépôt mistral-finetune est archivé et n’est plus activement maintenu
  • S’il existe une demande de la communauté ou si cela peut apporter de la valeur à l’écosystème du fine-tuning, une nouvelle bibliothèque ou une mise à jour majeure pourrait voir le jour à l’avenir
  • L’objectif est de fournir un point d’entrée simple et guidé pour fine-tuner les modèles Mistral
  • Cette base de code est particulièrement prescriptive sur le format des données et ne vise pas à être un outil généraliste couvrant plusieurs architectures de modèles ou types de matériel
  • Pour une approche plus générale, des projets comme torchtune peuvent servir de référence

Méthode de fine-tuning et recommandations matérielles

  • mistral-finetune repose sur LoRA
    • La plupart des poids du modèle sont figés
    • Seuls 1 à 2 % de poids supplémentaires, sous forme de perturbations matricielles de bas rang, sont entraînés
  • Pour une efficacité maximale, l’utilisation de GPU A100 ou H100 est recommandée
  • Le code est optimisé pour les environnements d’entraînement multi-GPU sur un seul nœud
  • Les petits modèles comme les 7B peuvent suffire avec un seul GPU

Mises à jour récentes des modèles compatibles

  • Depuis le 13 août 2024, Mistral Large v2 est compatible avec mistral-finetune
    • Il faut télécharger le checkpoint 123B Instruct et définir model_id_or_path sur le répertoire de ce checkpoint
    • La grande taille du modèle nécessite beaucoup plus de mémoire pour le fine-tuning
    • Pour l’instant, seq_len doit être défini à 8192 ou moins
    • Un taux d’apprentissage plus faible que pour les autres modèles est recommandé ; dans la plupart des cas, lr=1e-6 est indiqué comme fonctionnant bien
  • Depuis le 19 juillet 2024, Mistral Nemo est compatible avec mistral-finetune
    • Il faut télécharger le modèle 12B Base ou Instruct et définir model_id_or_path sur le répertoire du checkpoint
    • Une version de mistral-common prenant en charge Tekkenizer est nécessaire ; il faut installer la version >=1.3.1 avec pip install --upgrade mistral-common
    • En raison de la grande taille du vocabulaire, les besoins mémoire en pic de la CE loss augmentent, ce qui nécessite actuellement davantage de mémoire
    • Pour l’instant, seq_len doit être défini à 16384 ou moins
    • L’utilisation des mêmes hyperparamètres que pour 7B v3 est recommandée

Installation et téléchargement des modèles

  • La procédure de démarrage consiste à cloner le dépôt et installer les dépendances
  • Le fine-tuning des modèles Mistral officiels est recommandé, et le README fournit les liens de téléchargement et checksums suivants
  • Avant le fine-tuning, 8x7B Base V1 et 8x7B Instruct V1 doivent utiliser le tokenizer v3 et étendre la taille du vocabulaire à 32768
  • Le chemin du dossier du modèle téléchargé doit être indiqué comme chemin absolu dans model_id_or_path du YAML d’entraînement

Exigences de format des données

  • Tous les fichiers de données doivent être au format jsonl
  • Les données de préentraînement stockent le texte brut dans la clé "text"
  • Les données d’instruction stockent une liste de conversations dans la clé "messages"
    • Chaque entrée contient les clés "content" et "role"
    • "role" vaut l’un de "user", "assistant" ou "system"
    • La loss n’est calculée que lorsque "role" == "assistant"
    • Il est possible d’exclure un message assistant de l’entraînement en définissant "weight": 0 sur ce message
  • Les données d’appel de fonction stockent aussi une liste de conversations dans la clé "messages"
    • Chaque entrée contient la clé "role" et soit "content", soit "tool_calls"
    • "role" vaut l’un de "user", "assistant", "system" ou "tool"
    • La loss n’est calculée que lorsque "role" == "assistant"
    • Les champs "id" et "tool_call_id" de "tool_calls" doivent être des chaînes aléatoires d’exactement 9 caractères
    • Le README recommande de les générer automatiquement dans le script de préparation des données

Validation des données et exemple de workflow

  • Avant de lancer l’entraînement, il faut valider le format des données et estimer le temps d’entraînement avec utils.validate_data
  • L’exemple d’instruction utilise une partie de Ultachat_200k
    • Les données parquet sont chargées avec Pandas
    • Elles sont séparées en 95 % pour l’entraînement et 5 % pour l’évaluation
    • Elles sont enregistrées en jsonl
    • Les chemins sont indiqués dans data.instruct_data et data.eval_instruct_data de example/7B.yaml
  • Lors de la validation, certaines conversations peuvent être détectées comme se terminant par le rôle user
    • Comme seuls les messages assistant sont entraînés, le dernier message user devient un élément inutile à traiter
    • Les données peuvent être corrigées avec utils.reformat_data.py
  • Après correction, une nouvelle validation affiche un résumé incluant le nombre de tokens de données, le nombre de tokens d’entraînement, le nombre d’epochs, max_steps et le temps estimé
  • Dans l’exemple du README, max_steps=500 parcourt le dataset environ 5 fois ; pour une configuration prenant environ 30 minutes sur un cluster 8xH100, max_steps=300 est recommandé

Exemple de fine-tuning pour l’appel de fonction

  • L’exemple d’appel de fonction utilise le Glaive function calling dataset
  • Les données sont chargées avec Pandas, divisées en 95 % pour l’entraînement et 5 % pour l’évaluation, puis enregistrées en jsonl
  • Le dataset d’origine ne suit pas le format d’appel de fonction requis et doit donc être reformaté
    • "from" doit être remplacé par "user"
    • Les caractères "\n" inutiles doivent être supprimés
  • utils.reformat_data_glaive.py permet de mettre la plupart des échantillons au bon format
  • Comme il est impossible d’écrire un script de reformatage fonctionnant pour tous les types de datasets, les datasets qui ne respectent pas le format requis peuvent nécessiter un script de reformatage dédié
  • utils.validate_data --create_corrected permet de supprimer les erreurs restantes et de créer un dataset .corrected

Exécution de l’entraînement et exemples de résultats

  • Après validation des données, l’entraînement peut être lancé
  • Pour un entraînement plus rapide, une configuration avec max_steps défini à 300 est recommandée
  • run_dir doit être défini comme dossier d’expérience ; en option, wandb.project peut être défini pour utiliser le logging Weights & Biases
  • L’entraînement s’exécute avec torchrun, et --nproc-per-node doit être défini au nombre de GPU disponibles
  • L’entraînement UltraChat prend environ 30 minutes sur un nœud 8xH100, et les poids obtenus peuvent produire un score MT Bench d’environ 6,3
  • L’entraînement Glaive prend environ 1 heure sur un nœud 8xH100, et les poids obtenus sont présentés comme fonctionnant bien pour l’appel de fonction

Principaux paramètres d’entraînement

  • model_id_or_path : modèle préentraîné à partir duquel démarrer l’entraînement, ou chemin vers un répertoire de modèle local
  • run_dir : répertoire où enregistrer les checkpoints et les métriques
  • seq_len : longueur de séquence d’entraînement ; les échantillons sont packés à la longueur seq_len pour plus d’efficacité
  • batch_size : nombre d’exemples d’entraînement par GPU
    • La taille effective totale du batch en tokens est num_gpus x batch_size x seq_len
  • max_steps : nombre total d’itérations d’entraînement
    • Le nombre total de tokens vus pendant l’entraînement est max_steps x num_gpus x batch_size x seq_len
  • optim.lr : taux d’apprentissage initial de l’optimiseur
  • optim.weight_decay : weight decay ; le README recommande de le maintenir à 0,1
  • optim.pct_start : proportion de la phase de warm-up de OneCycleLR de PyTorch
  • lora.rank : taille de l’adapter LoRA ; une valeur inférieure ou égale à 64 est recommandée
  • seed : graine aléatoire pour la reproductibilité de l’initialisation, du mélange des données et de l’échantillonnage
  • data.instruct_data : chemin vers les données d’entraînement d’instruction
    • Il peut s’agir d’un fichier jsonl unique, d’un répertoire de fichiers jsonl ou de plusieurs sources de données avec pondération
  • data.data : chemin optionnel vers des données de préentraînement supplémentaires
  • data.eval_instruct_data : chemin optionnel vers des données d’instruction d’évaluation
  • eval_freq, no_eval, ckpt_freq : contrôlent la fréquence d’évaluation, l’évaluation intermédiaire et l’enregistrement des checkpoints
  • save_adapters : détermine s’il faut enregistrer uniquement les checkpoints LoRA ou fusionner LoRA dans le modèle de base et enregistrer le modèle complet
    • save_adapters=False nécessite suffisamment de mémoire CPU et GPU pour enregistrer le modèle complet dans un seul processus, ce qui n’est généralement possible qu’avec les modèles 7B

Inférence et Weights & Biases

  • Pour l’inférence avec le modèle entraîné, l’utilisation de mistral-inference est recommandée
  • Il peut être installé avec pip install mistral_inference
  • Lors de l’exécution de mistral-chat, le chemin vers le lora.safetensors enregistré peut être indiqué via --lora_path pour utiliser les poids LoRA
  • La prise en charge de Weights and Biases est incluse afin de surveiller les métriques d’entraînement et les expériences
    • Installation avec pip install wandb
    • Il est recommandé de fournir la clé API via la variable d’environnement WANDB_API_KEY
    • Pour des raisons de sécurité, la clé API n’est pas lue depuis la configuration YAML
    • La loss d’entraînement, la loss d’évaluation, le taux d’apprentissage, etc., sont enregistrés et visualisés dans le tableau de bord du projet wandb
  • Pour plus de détails d’utilisation, consulter la documentation Weights and Biases

Extension des modèles et FAQ

  • Seuls les modèles Mistral compatibles avec le tokenizer v3 peuvent être fine-tunés
  • Les modèles compatibles doivent avoir une taille de vocabulaire de 32768, et non 32000
  • Les anciens modèles avec un vocabulaire de taille 32000 peuvent être étendus à 32768 avec utils.extend_model_vocab
  • Le fine-tuning des modèles MoE présente une variance de performance plus importante
    • Il est suggéré d’exécuter plusieurs fois le même fine-tuning MoE avec des seeds différentes et de choisir le meilleur résultat
    • Cette forte variance n’a pas été observée sur les modèles denses
  • Le nombre de tokens utilisés pour l’entraînement peut être vérifié en fournissant le fichier YAML d’entraînement à utils.validate_data.py
  • En cas d’erreur CUDA out-of-memory, il est possible de réduire la taille de batch par GPU
    • La taille de batch est seq_len x batch_size
    • Il est suggéré de définir batch_size à 1 et de réduire seq_len
  • La bibliothèque est distribuée sous licence Apache 2.0
  • Cette bibliothèque ou ces modèles ne doivent pas être utilisés d’une manière qui enfreint, détourne ou viole des droits, y compris les droits de propriété intellectuelle de tiers

1 commentaires

 
GN⁺ 2024-05-27
Avis sur Hacker News
  • Avec des modèles qui progressent aussi vite, le fine-tuning a-t-il encore de la valeur ? Je serais curieux de voir des cas d’usage concrets.
    Par exemple, l’an dernier Bloomberg a entraîné sur des données financières un LLM du niveau de GPT-3.5, mais peu après, GPT-4-8k l’a dépassé sur presque toutes les tâches financières.
    Au final, nous nous sommes concentrés sur des données d’évaluation de haute qualité et sur une architecture permettant de passer facilement à de nouveaux modèles.

    • Oui. Nous avons des données humaines non anglophones, annotées dans un format conçu pour une étude spécifique liée à la santé.
      Les LLM n’ont jamais vu ce type d’annotations, les LLM non anglophones ne sont pas non plus la priorité absolue des entreprises, et pour des raisons de confidentialité des données nous ne pouvons utiliser que des modèles offline-first.
      Dans cette situation, le fine-tuning d’un modèle de langage généraliste convient très bien.
    • Si vous devez générer en grand volume des sorties dans un format précis, le fine-tuning peut être utile.
      En fine-tunant le modèle sur des messages structurés dans ce format, il le produira automatiquement, ce qui permet d’économiser beaucoup de tokens qui serviraient sinon à décrire le format de sortie dans chaque prompt.
    • Et si ce sont des données internes d’entreprise que GPT-4 n’a jamais vues ?
    • Sur les tâches classiques de traitement automatique du langage naturel, les LLM restent loin derrière des pipelines de TALN dédiés, comme l’étiquetage morphosyntaxique ou l’étiquetage de caractéristiques.
      Cela dit, le fine-tuning comble assez bien l’écart entre les deux.
      C’est un domaine restreint, mais c’est aussi le cas de la plupart de la programmation. Si l’objectif est de rendre un LLM généraliste plus orienté vers vos propres données, le fine-tuning a probablement peu de rapport.
      Mais si vous essayez de résoudre un problème très spécifique tout en restant ambigu, et qu’un LLM n’en résout qu’une partie, le fine-tuning est probablement la meilleure option.
    • Les appels de fonctions peuvent aussi être une raison.
      Si votre app contient beaucoup de fonctions personnalisées qui interagissent avec des outils, vous pouvez préférer le fine-tuning à l’utilisation de tokens de contexte.
  • Quel GPU faudrait-il pour faire ça ? J’ai un portable avec une 3060 Ti, un i9 et 16 Go de RAM.
    Je n’ai pas de quotas AWS ou GCP et j’ai entendu parler de Paperspace, mais je prévois d’utiliser une partie des modèles Mistral dans un projet client en cours, donc j’aimerais commencer rapidement le fine-tuning de Mistral.

    • Si votre budget n’est pas totalement nul, je recommande fortement de passer à un PC desktop gaming.
      Un GPU gaming peut dissiper 300 W de chaleur sans problème, alors qu’un GPU de portable fondrait dans ces conditions et sera probablement limité autour de 100 W.
      L’évacuation de la chaleur est directement proportionnelle à la vitesse.
      En plus, avec un desktop, vous pouvez passer à un GPU plus rapide ou utiliser plusieurs GPU.
      Attention toutefois : les configurations multi-GPU en particulier sont bruyantes et dégagent assez de chaleur pour réchauffer rapidement une pièce.
      Si, dans les prochaines années, vous ne prévoyez pas de faire tourner vos GPU à pleine charge plus de 10 % du temps, le cloud sera probablement moins cher.
    • Vous pouvez consulter ce site : https://www.hardware-corner.net/llm-database/Mistral/
      Il récapitule les exigences matérielles par modèle, et permet de filtrer les modèles disponibles en sélectionnant la VRAM et la mémoire système.
    • Chez Hetzner, vous pouvez utiliser un serveur GPU à 184 € par mois.
      Dans notre entreprise, nous avons fine-tuné Mistral et Llama 3 avec les RTX4000 qu’ils proposent.
      Avec seulement 20 Go de RAM, c’est un peu limité, mais pour de plus grands nombres de tokens en entrée, réduire le niveau de quantification a aidé.
      Ils proposent maintenant aussi de la location à l’heure.
    • Essayez openpipe.
      Nous l’utilisons actuellement dans l’entreprise et nous avons obtenu de très bons résultats.
  • Il est très intéressant de voir quels outils deviendront le standard de facto pour chaque cas d’usage courant des LLM.
    L’écosystème est tellement fragmenté qu’on a l’impression de n’avoir même jamais entendu parler de la plupart des outils.
    Il y a quelques jours, j’ai découvert Olive de Microsoft, et c’était totalement nouveau pour moi.

  • Maintenant que beaucoup de LLM open source ont déjà atteint un niveau « utilisable », l’important est de faciliter le développement autour d’eux.
    En particulier, les personnes qui sont à la fois utilisatrices et développeuses doivent pouvoir exploiter des données privées, plus précisément des données qui ne figurent pas dans le préentraînement du modèle.
    Le dépôt indique qu’il est optimisé pour de grands modèles et nécessite des A100/H100, mais j’ai tout de même l’impression que cela pourrait être encore plus utile pour les petits modèles que pour les grands.
    On peut prolonger « si vous le construisez, ils viendront » en « si vous fournissez les outils, ils construiront ».

    • « Si vous fournissez les outils, ils construiront » ne vaut que lorsque l’incitation à apprendre cette technologie laisse entrevoir des bénéfices futurs.
  • La partie sur les poids est intéressante.
    Le SFTTrainer de HuggingFace permet, si on le souhaite, de n’entraîner que la partie complétion, mais même si cela semble naturel pour les humains, il est généralement préférable d’entraîner un LLM à prédire toute l’entrée.
    Avec cette approche, on obtient le meilleur des deux mondes.

  • Peut-on l’optimiser pour entraîner de plus grandes variantes de modèles avec deux 3090 ou deux 4090 ?

  • Comment pourrais-je entraîner mon modèle de conversations WhatsApp ?

    • Il faudrait être plus clair sur ce que vous voulez dire.
      Voulez-vous entraîner un modèle sur vos propres messages WhatsApp ? Quel est l’objectif ? Cela dépend si vous voulez qu’il écrive comme vous, ou si vous voulez faire de la question-réponse basée sur du RAG.