From 09acd566c48ffdd995d10a7ff6aa58e69656900d Mon Sep 17 00:00:00 2001 From: Quarto GHA Workflow Runner Date: Thu, 7 Nov 2024 15:17:23 +0000 Subject: [PATCH] Built site for gh-pages --- .nojekyll | 2 +- II-Developpements/1_Anatomie_LLM.html | 6 ++- .../2_Classification_accords_entreprise.html | 16 ++++---- search.json | 4 +- sitemap.xml | 38 +++++++++---------- 5 files changed, 35 insertions(+), 31 deletions(-) diff --git a/.nojekyll b/.nojekyll index 73acaf6..a8880f9 100644 --- a/.nojekyll +++ b/.nojekyll @@ -1 +1 @@ -7947852f \ No newline at end of file +4257870f \ No newline at end of file diff --git a/II-Developpements/1_Anatomie_LLM.html b/II-Developpements/1_Anatomie_LLM.html index b19d4cb..57e1efc 100644 --- a/II-Developpements/1_Anatomie_LLM.html +++ b/II-Developpements/1_Anatomie_LLM.html @@ -573,7 +573,11 @@
DPO, KTO
  • Explication théorique
  • Guide pratique / Implémentation HugginFace
  • -

    Liens des papiers originaux : - DPO - KTO

    +

    Liens des papiers originaux :

    + diff --git a/IV-Exemples/2_Classification_accords_entreprise.html b/IV-Exemples/2_Classification_accords_entreprise.html index ea618ef..3d4344e 100644 --- a/IV-Exemples/2_Classification_accords_entreprise.html +++ b/IV-Exemples/2_Classification_accords_entreprise.html @@ -347,7 +347,7 @@

    Récupération

    Les données sont disponibles sur Légifrance. Le stock des textes est également publié par le FTP de la DILA et les thématiques déclarées sont à la fois dans les métadonnées XML publié conjointement avec les textes, ou retrouvables sur Légifrance.

    Pour des raisons pratiques, nous travaillerons avec une photographie du stock au 1er semestre 2024 et sur un échantillon des 1000 textes d’accords, convertis au format parquet.

    Ces données comportent le numéro de dossier de l’accord, identifiant unique, puis le texte et les thématiques déclarées, et enfin suivies des thématiques une à une :

    -
    +
    @@ -416,7 +416,7 @@

    Lecture de données

    Nous allons dans cet exemple, extraire 10 textes pour des raisons de rapidité :

    -
    +
    import json
     import numpy as np
     import pandas as pd
    @@ -445,7 +445,7 @@ 

    Lecture de données

    Vectoriser nos textes avec ChromaDB

    Pour vectoriser nos textes, nous utilisons ChromaDB qui s’intègre avec Langchain. Nous allons découper en morceau des 3000 caractères à chaque saut à ligne, ce qui correspond à un paragraphe. Les morceaux de textes, ici paragraphes, sont stockés dans une boutique de vecteur avec le numéro de dossier et le numéro de paragraphe en métadonnées.

    -
    +
    text_splitter = CharacterTextSplitter(
         separator="\n\n",
         chunk_size=3000,
    @@ -472,7 +472,7 @@ 

    Vector

    Interroger un LLM en mode API

    Pour interroger le LLM, nous construisons une classe qui permet de générer les requêtes et de traiter les réponses :

    -
    +
    MODEL="llama3.1"
     
     
    @@ -493,7 +493,7 @@ 

    Interroger u llm = LocalOllamaLLM(api_url="http://127.0.0.1:11434")

    Nous définissons également un prompt de base, améliorable par la suite, et une chaîne LangChain entre le prompt et le LLM :

    -
    +
    system_prompt = (
         " Répondez à la question posée "
         " Utilisez le contexte (sélection des meilleurs paragraphes liés à la question) donné pour répondre à la question "
    @@ -510,7 +510,7 @@ 

    Interroger u question_answer_chain = create_stuff_documents_chain(llm, prompt)

    Nous définissons une fonction pour effectuer le RAG, avec à la fois la recherche de similarité par rapport à la question, et la soumission augmentée pour une réponse du LLM :

    -
    +
    def search_and_invoke_llm(vector_store,index,query,k=5):
         if k==0:
             print(f"bug with {index}")
    @@ -535,7 +535,7 @@ 

    Interroger u

    Automatiser la classification sur l’ensemble des thématiques

    Nous automatisons ici la classification sous forme de classification binaire pour chaque thématique, en posant une question “oui ou non” et en inférant oui si la réponse commence par oui, non sinon.

    -
    +
    THEMATIQUES={
         "accord_methode_penibilite":"Accords de méthode (pénibilité)",
     "accord_methode_pse":"Accords de méthode (PSE)",
    @@ -626,7 +626,7 @@ 

    Evaluation

    Nous évaluons les performances de cette solution simple, en affichant la matrice de confusion et les différentes métriques, pour chaque thématique :

    -
    +
    import numpy as np
     from sklearn.metrics import confusion_matrix
     from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, classification_report
    diff --git a/search.json b/search.json
    index 4099a6e..3efc4bd 100644
    --- a/search.json
    +++ b/search.json
    @@ -303,7 +303,7 @@
         "href": "II-Developpements/1_Anatomie_LLM.html",
         "title": "PARTIE II. Développements autour des LLMs (pour les data scientists)",
         "section": "",
    -    "text": "Les LLMs reposent sur un développement en deux voire trois étapes.\n\nLe pré-entraînement consiste à entraîner le modèle, en partant de zéro, de façon auto-supervisée, et sur un corpus d’entraînement gigantesque. L’objectif de ce pré-entraînement dépend du type de modèle utilisé (cf. paragraphe suivant), mais la plupart apprennent à prédire le token suivant, à partir d’une suite de tokens. C’est ce qui les rend particulièrement efficaces pour de la génération de texte.\nL’instruction-tuning permet d’adapter le modèle pré-entraîné à une plus grande diversité de tâches. Dans de nombreux cas (chatbot, résumé de texte, etc.), la prédiction du token suivant n’est pas la bonne stratégie. L’étape d’instruction-tuning permet ainsi, grâce à un entraînement supervisé, de créer une version « chat » du modèle. Pour donner un exemple connu de tous, ChatGPT est la version instruction-tunée de GPT-4.\nLe fine-tuning (optionnel) peut être utilisé pour adapter le modèle à une tâche et à des données spécifiques. Les LLMs étant des outils multitâches, souvent multilingues et multidomaines, leurs performances peuvent être dégradées lorsqu’il y a des exigences précises et spécifiques. Le fine-tuning est une nouvelle phase d’entraînement supervisé, nécessitant moins de données et de puissance de calcul, qui permet de spécialiser le modèle.\n\nPar leur taille et les exigences techniques qu’ils impliquent, seules quelques entreprises spécialisées ont les moyens de pré-entraîner et d’instruction-tuner des LLMs. Le fine-tuning, en revanche, peut être abordable pour beaucoup plus d’acteurs, pour peu qu’ils répondent à certaines exigences techniques (cf. partie sur le fine-tuning).\nPour donner des ordres de grandeur, la petite version du dernier modèle de Meta, Llama-3 8B, a été pré-entraîné et instruction-tuné sur un corpus de 15 trillions de tokens. Ces deux phases d’entraînement ont nécessité 1,3 millions d’heures GPU, réparties sur plusieurs milliers de GPU H100.\n\nArticle résumant la dualité pré-entraînement/fine-tuning\n\n\n\n\n\nIntroduite en 2017 dans le papier Attention Is All You Need, l’architecture Transformer a révolutionné le domaine du TAL. Par rapport aux RNN, les Transformers permettent un traitement efficace des séquences en parallèle, conduisant à un temps de calcul beaucoup plus court (tant lors de l’entraînement qu’en inférence), tandis que les RNN, par construction, ne peuvent traiter une séquence que séquentiellement, c’est-à-dire token par token. En outre, le mécanisme d’auto-attention, présenté ci-dessous, permet de capturer efficacement les dépendances distantes en atténuant le problème de la disparition et de l’explosion des gradients.\n\nL’auto-attention est le mécanisme central des Transformers. Elle est utilisée pour pondérer, lors de l’examen d’un token en particulier, l’importance, relative à ce token, de chaque autre token de la séquence. Concrètement, trois vecteurs (qui représentent chacun la séquence d’entrée dans un rôle différent) sont déduits de la séquence d’entrée \\(X\\) : les requêtes (\\(Q\\)), les clés (\\(K\\)) et les valeurs (\\(V\\)), par des transformations linéaires comme exprimées dans l’équation suivantes. Les matrices \\(W_Q\\), \\(W_K\\) et \\(W_V\\) sont des paramètres entraînables du modèle. \\[Q = X \\cdot W_Q \\qquad K = X \\cdot W_K \\qquad V = X \\cdot W_V \\]\nLes scores d’attention sont ensuite calculés selon l’équation suivante. \\[\\text{Attention}(Q, K, V) = \\text{softmax} \\left( \\frac{QK^{T}}{\\sqrt{d}} \\right) V\\]\nPour chaque token d’entrée \\(X_i\\), le résultat \\(\\text{Attention}(Q, K, V)_i\\) est une combinaison de tous les autres éléments de la séquence, pondérés selon leur pertinence par rapport à \\(X_i\\).\nL’auto-attention telle que présentée ci-dessus n’est cependant pas directement utilisée dans l’architecture Transformer. A la place, une extension, appelée attention multi-têtes, permet au modèle de capturer plusieurs aspects des relations et des dépendances entre les éléments de la séquence d’entrée. Cela est fait en transformant la séquence d’entrée en plusieurs têtes, i.e. en plusieurs vecteurs de requêtes, de clés et de valeurs, et en appliquant un mécanisme d’auto-attention sur chacune de ces têtes. Les vecteurs d’attention de chaque tête sont ensuite concaténés et réduits linéairement à la taille d’entrée d’origine. Le calcul de l’attention multi-têtes est détaillé dans l’équation suivante.\n\\[\\text{MultiHeadAttention}(Q, K, V) = \\text{Concat}(\\text{head}_1 , \\cdots, \\text{head}_h)W^O\\]\noù \\(\\text{head}_i = \\text{Attention}(X \\cdot W_Q^i, X \\cdot W_K^i, X \\cdot W_V^i)\\) pour \\(i = 1, \\cdot, h\\) avec \\(h\\) le nombre de têtes d’attention. Chaque tête d’attention peut donc se spécialiser dans un aspect spécifique des données, et le modèle peut apprendre à combiner ces différents aspects pour une meilleure représentation. La combinaison de ce mécanisme d’attention multi-têtes, de couches de normalisation et de couches à action directes (FNN) forme un bloc Transformer.\nPlusieurs blocs (6 dans l’implémentation originale) forment ensuite l’encodeur (qui a accès à la séquence d’entrée dans son intégralité) et le décodeur (qui a accès à la représention encodée de la séquence d’entrée, et à la séquence de sortie générée jusqu’alors). La combinaison de ces deux éléments composent le Transformer encodeur-décodeur original.\n\nPapier original ‘Attention Is All You Need’\nExplication illustrée et très détaillée\n\n\n\n\nLes LLMs basés sur des architectures Transformers appartiennent à l’une des 3 catégories suivantes :\n\nModèle « encoder-only » : Ils sont basés uniquement sur la partie encodeur des Transformers. Leur pré-entraînement est souvent basé sur la reconstruction de phrases : à chaque étape, le modèle a accès à une phrase entière, sauf certains mots qui ont été masqués, et apprend à retrouver ces mots masqués. Ces modèles sont adaptés pour des tâches de classification, de reconnaissance d’entités nommées (NER), de réponses aux questions, etc. Ils ont aujourd’hui perdu en popularité, mais leurs représentants les plus connus (BERT, RoBERTa, DistilBERT, CamemBERT, etc.) sont encore très utilisés, et restent un choix intéressant selon la tâche, grâce à leur compréhension fine du langage et à leur petite taille.\nModèle « decoder-only » : Ils sont basés uniquement sur la partie décodeur des Transformers. Ces modèles sont aujourd’hui la norme, et l’immense majorité des LLMs actuels utilisent cette architecture. Leur pré-entraînement est basé sur la prédiction du prochain token : à chaque étape, le modèle a accès au début d’une phrase, et apprend à prédire le token suivant. Pour cette raison, ces modèles sont également qualifiés d’« autorégressifs ». Les modèles GPT (2, 3, 4), Llama (2, 3), Mistral, Gemini, etc. sont tous des decoder-only.\nModèle « encoder-decoder » : Ils utilisent les deux blocs des Transformers. L’encodeur a ainsi accès à l’intégralité de la séquence d’entrée, alors que le décodeur a accès à la représentation cachée de l’entrée et aux tokens générés jusqu’alors. Les modèles les plus connus sont par exemple BART et T5.\n\nhttps://medium.com/artificial-corner/discovering-llm-structures-decoder-only-encoder-only-or-decoder-encoder-5036b0e9e88\n\n\n\nLes architectures Mixture of Experts ne sont pas spécifiques aux LLMs, mais elles ont été adaptées avec succès sur des modèles comme Mixtral 8x7B, Mixtral 8x22B ou GPT-4 (supposition). Le principe est de remplacer chaque réseau à propagation directe (présent dans chaque bloc de l’architecture Transformer) par un ensemble de réseaux « experts ». Au moment de passer dans cette partie du réseau, un routeur envoie vers un de ces experts uniquement. L’intérêt est double : un seul expert étant utilisé à la fois, le temps d’inférence est naturellement nettement plus court. Par ailleurs, chaque réseau expert est entraîné et donc spécialisé différement des autres : pour un même nombre de paramètres, les performances sont donc supposées être meilleures qu’avec une architecture classique. En revanche, si tous les poids du modèles ne sont pas utilisés systématiquement, c’est uniquement à l’inférence et à chaque couche du réseau que l’expert est choisi : il est donc tout de même nécessaire de charger l’intégralité des poids du modèle en mémoire, ce qui peut être très coûteux en VRAM. Pour une explication plus technique, l’article suivant détaille très bien les MoE en prenant l’exemple de Mixtral.\n\nExplication détaillée des MoE (exemple de Mixtral) : https://huggingface.co/blog/moe\n\n\n\nLe principal inconvénient architectural des Transformers est leur complexité quadratique par rapport à la taille de l’entrée (qui vient du calcul quadratique de l’attention). Mamba est une architecture récente (Décembre 2023) qui s’affranchit du mécanisme d’attention, au profit de briques SSM (Structured State Space Models). L’intérêt principal de cette architecture est sa complexité linéaire par rapport à la taille de l’entrée.\nJamba est une nouvelle architecture hybride, à mi-chemin entre le Transformer et Mamba. Cela semble permettre un niveau de performance élevé, une gestion des contextes très longs, un temps d’inférence nettement plus court, et des exigences mémoires bien moindres.\nLiens des papiers originaux :\n\nMamba\nJamba\n\n\n\n\n\nLes LLM sont des réseaux de neurones de taille importante et font l’objet d’entraînement avec des ressources colossales (e.g: quelques dizaines de milliers de GPUs dernier modèle pendant 3 mois pour GPT-4). L’entraînement permet d’apprendre un jeu de données particulier, en réglant l’ensemble des poids du modèles (e.g: Mixtral 8x22B est une architecture à 141 milliards de poids; 175 milliards pour GPT-3). Les LLM sont entraînés à répondre à plusieurs tâches génériques et ne sont pas forcément pertinent pour des cas d’utilisation particulier.\nPour répondre à ce besoin, plusieurs méthodes relevant du principe de fine-tuning sont possibles. Le fine-tuning consiste à reprendre un modèle déjà entraîné et à l’adapter sur un jeu de données particulier sur une ou plusieurs tâches spécifiques. En général, il s’agit de modifier une partie ou l’ensemble des poids pour que le modèle soit plus précis pour les tâches voulues. Le fine-tuning garde en grande partie les bénéfices de l’entraînement initial, i.e les connaissances antérieures déjà apprises. Repartir d’un modèle déjà entraîné pourra réduire le temps d’entraînement requis pour le fine-tuning, en fonction de la similarité entre la nouvelle tâche souhaitée et son jeu de données et les entraînements précédents.\nPour des petits modèles de langages, il est possible de ré-entraîner en modifiant l’ensemble des poids. Pour des modèles plus grands, modifier l’ensemble des poids peut s’avérer couteux en temps et en GPUs. Plusieurs approches permettent de ré-entraîner à moindre coût :\n\nréentrainer seulement un sous-ensemble de poids\nmodifier la tête de modélisation de la langue (lm_head) pour certains modèles, soit en réentrainant depuis les poids entraînés, soit en réinitialisant ces poids.\ngarder l’intégralité du modèle et rajouter des poids à entraîner puis utiliser l’approximation de bas rang avec LORA (Low-Rank Adaptation) pour l’entraînement et l’inférence.\nutiliser des versions quantisées, i.e. des modèles où les poids ont été tronqués à une précision inférieure (possibilité de combiner avec la technique précédente, sous le nom de qLORA).\n\n\n\n\n\n\nImplémentation HuggingFace\n\n\n\n\nPEFT = Parameter-Efficient Fine-Tuning | LoRA = Low-Rank Adaptation | QLoRA = Quantized Low-Rank Adaptation | DoRA = Weight-Decomposed Low-Rank Adaptation\nRé-entraîner entièrement un LLM est très coûteux en termes d’infrastructure et de données, et n’est donc pas à la portée de n’importe quelle organisation. Des méthodes « efficaces » ont été créées pour rendre le fine-tuning facilement accessible, dont la plus connue et la plus populaire est LoRA (Low-Rank Adaptation). Son fonctionnement repose sur deux éléments :\n\nL’adaptation : Les poids du modèle pré-entraîné sont gelés pendant l’entraînement. Ce sont des poids supplémentaires (ceux de l’adapteur) qui vont être entraînés. Cela permet de garder l’entièreté du modèle pré-entraîné tel quel, et de rajouter uniquement la partie spécifique à chaque tâche. Entre autres, il est ainsi possible, avec un seul modèle de base, d’héberger plusieurs modèles spécialisés à moindre coût. Le papier LoRA Land explique d’ailleurs comment faire tenir 25 versions de Mistral 7B fine-tunés avec LoRA sur un seul GPU A100.\nLe rang faible : Les poids additionnels peuvent être choisis de beaucoup de manières. Avec LoRA, certaines couches du modèle (les couches d’attention ou les couches linéaires par exemple) sont sélectionnées, et les poids de ces couches sont exprimés comme une multiplication de deux matrices de rangs faibles, ce qui réduit grandement le nombre de poids à entraîner (la valeur de ce rang étant un hyperparamètre de l’entraînement). En fonction de la valeur de ce rang et des couches sélectionnées, il est ainsi possible d’entraîner uniquement 1 ou 2 % du nombre de paramètres global du modèle pré-entraîné, sans que cela n’affecte trop les performances du fine-tuning.\n\n\nD’autres approches de PEFT (Parameter-Efficient Fine-Tuning) ont vu le jour, dont la plupart s’inspirent de LoRA. Parmi les plus connues, QLoRA permet d’appliquer LoRA sur des modèles quantifiés, et DoRA propose un raffinement de l’adapteur de LoRA.\n\nGuide théorique très clair sur le PEFT (principe, avantages, etc.) avec un focus sur LoRA\nGuide pratique / Implémentation HugginFace\n\nLiens des papiers originaux : - LoRA - QLoRA - DoRA\nEntraînement avec qLORA en pratique :\nEn plus de la librairie transformers et datasets, les librairies peft, bitsandbytes et trl permettent de simplifier l’entraînement avec qLORA\n(inspiré du notebook suivant )\n%%capture\n%pip install -U bitsandbytes\n%pip install -U transformers\n%pip install -U peft\n%pip install -U trl\n%pip install -U sentencepiece\n%pip install -U protobuf\n\nfrom transformers import AutoModelForCausalLM, AutoTokenizer,TrainingArguments\nfrom peft import LoraConfig, prepare_model_for_kbit_training, get_peft_model\nfrom datasets import load_dataset\nimport torch\nfrom trl import SFTTrainer\n\nbase_model = \"teknium/OpenHermes-2.5-Mistral-7B\"\nnew_model = \"Mistral-7b-instruct-teletravail\"\n\npath_to_training_file=\"Dataset_public_accords_teletravail_Dares_train.parquet\"\npath_to_test_file=\"Dataset_public_accords_teletravail_Dares_test.parquet\"\n\n\ndataset=load_dataset(\"parquet\", data_files={'train': path_to_training_file, 'test': path_to_test_file})\n\nbnb_config = BitsAndBytesConfig(\n    load_in_4bit= True,\n    bnb_4bit_quant_type= \"nf4\",\n    bnb_4bit_compute_dtype= torch.bfloat16,\n    bnb_4bit_use_double_quant= False,\n)\n\nmodel = AutoModelForCausalLM.from_pretrained(\n        base_model,\n        quantization_config=bnb_config,\n        torch_dtype=torch.bfloat16,\n        device_map=\"auto\",\n        trust_remote_code=True,\n)\nmodel.config.use_cache = False # silence the warnings. Please re-enable for inference!\nmodel.config.pretraining_tp = 1\nmodel.gradient_checkpointing_enable()\n\n# Load tokenizer\ntokenizer = AutoTokenizer.from_pretrained(base_model, trust_remote_code=True)\ntokenizer.padding_side = 'right'\ntokenizer.pad_token = tokenizer.eos_token\ntokenizer.add_eos_token = True\ntokenizer.add_bos_token, tokenizer.add_eos_token\n\n\nmodel = prepare_model_for_kbit_training(model)\npeft_config = LoraConfig(\n    lora_alpha=16,\n    lora_dropout=0.1,\n    r=64,\n    bias=\"none\",\n    task_type=\"CAUSAL_LM\",\n    target_modules=[\"q_proj\", \"k_proj\", \"v_proj\", \"o_proj\",\"gate_proj\"]\n)\nmodel = get_peft_model(model, peft_config)\n\ntraining_arguments = TrainingArguments(\n    output_dir=\"./results\",\n    num_train_epochs=1,\n    per_device_train_batch_size=4,\n    gradient_accumulation_steps=1,\n    optim=\"paged_adamw_32bit\",\n    save_steps=25,\n    logging_steps=25,\n    learning_rate=2e-4,\n    weight_decay=0.001,\n    fp16=False,\n    bf16=False,\n    max_grad_norm=0.3,\n    max_steps=-1,\n    warmup_ratio=0.03,\n    group_by_length=True,\n    lr_scheduler_type=\"constant\",\n)\n\ntrainer = SFTTrainer(\n    model=model,\n    train_dataset=dataset[\"train\"],\n    peft_config=peft_config,\n    max_seq_length= None,\n    dataset_text_field=\"text\",\n    tokenizer=tokenizer,\n    args=training_arguments,\n    packing= False,\n)\n\ntrainer.train()\n\ntrainer.model.save_pretrained(new_model)\n\n\n\n\nLe fine-tuning supervisé est très efficace dans de nombreux cas, mais il présente notamment l’inconvénient de nécessiter une quantité importante de données. La constitution d’une base de questions-réponses attendues par exemple peut se réveler coûteuse. Un autre moyen d’améliorer un modèle est d’utiliser de l’apprentissage par renforcement. La première version utilisée pour ré-entraîner un LLM est le RLHF (Reinforcement Learning from Human Feedback), qui consiste à récolter des retours d’utilisateurs humains (typiquement, entre deux réponses générées par un LLM, l’utilisateur va dire laquelle il préfère), puis à mettre à jour les poids du modèle, par un algorithme d’apprentissage par renforcement, de telle sorte que la réponse préférée par l’utilisateur ait plus de chances d’être générée. Cette approche s’est révélée particulièrement effiace pour « aligner » le modèle aux préférences humaines, en termes de biais, de toxicité, de style, etc.\nBien que la constitution d’une base de retours humains soit moins coûteuse que celle d’une base de questions/réponses, elle reste coûteuse. Une solution aujourd’hui très populaire est de remplacer ces retours humains par des retours générés artificiellement, ce qui donne une approche appelée RLAIF (Reinforcement Learning from Artificial Intelligence Feedback). Typiquement, un LLM plus performant (par exemple GPT-4) va être utilisé pour déterminer la meilleure réponse entre deux ou plusieurs choix, selon des critères donnés. Ce sont ensuite ces retours qui vont être utilisés pour améliorer le modèle grâce à l’algorithme d’apprentissage par renforcement.\nRLHF = Reinforcement Learning from Human Feedback | RLAIF = Reinforcement Learning from Artificial Intelligence Feedback\n\nIntroduction au RLHF\n\n\n\nLe premier algorithme de Reinforcement Learning utilisé dans le cadre des LLM était la PPO (Proximal Policy Optimization). Cet algorithme classique consiste à entraîner un modèle de récompense fondé sur les retours humains, puis à entraîner le LLM à optimiser cette récompense. La politique du modèle est donc mise à jour itérativement pour maximiser cette récompense. Le principal inconvénient de la PPO, que la DPO pallie, est le besoin d’entraîner un modèle de récompense, en plus du LLM lui-même.\n\nExplication théorique\nImplémentation HuggingFace\n\nhttps://medium.com/@oleglatypov/a-comprehensive-guide-to-proximal-policy-optimization-ppo-in-ai-82edab5db200\n\n\n\nL’algorithme de DPO (Direct Preference Optimization) permet de mettre à jour les poids du LLM en fonctions des retours humains directement, sans passer par un modèle de récompense : la politique que le LLM apprend maximise directement la satisfaction humaine. Une variation de cet algorithme est celui de KTO (Kahneman-Tversky Optimization), dont le fonctionnement général reste similaire.\n\nExplication théorique\nGuide pratique / Implémentation HugginFace\n\nLiens des papiers originaux : - DPO - KTO",
    +    "text": "Les LLMs reposent sur un développement en deux voire trois étapes.\n\nLe pré-entraînement consiste à entraîner le modèle, en partant de zéro, de façon auto-supervisée, et sur un corpus d’entraînement gigantesque. L’objectif de ce pré-entraînement dépend du type de modèle utilisé (cf. paragraphe suivant), mais la plupart apprennent à prédire le token suivant, à partir d’une suite de tokens. C’est ce qui les rend particulièrement efficaces pour de la génération de texte.\nL’instruction-tuning permet d’adapter le modèle pré-entraîné à une plus grande diversité de tâches. Dans de nombreux cas (chatbot, résumé de texte, etc.), la prédiction du token suivant n’est pas la bonne stratégie. L’étape d’instruction-tuning permet ainsi, grâce à un entraînement supervisé, de créer une version « chat » du modèle. Pour donner un exemple connu de tous, ChatGPT est la version instruction-tunée de GPT-4.\nLe fine-tuning (optionnel) peut être utilisé pour adapter le modèle à une tâche et à des données spécifiques. Les LLMs étant des outils multitâches, souvent multilingues et multidomaines, leurs performances peuvent être dégradées lorsqu’il y a des exigences précises et spécifiques. Le fine-tuning est une nouvelle phase d’entraînement supervisé, nécessitant moins de données et de puissance de calcul, qui permet de spécialiser le modèle.\n\nPar leur taille et les exigences techniques qu’ils impliquent, seules quelques entreprises spécialisées ont les moyens de pré-entraîner et d’instruction-tuner des LLMs. Le fine-tuning, en revanche, peut être abordable pour beaucoup plus d’acteurs, pour peu qu’ils répondent à certaines exigences techniques (cf. partie sur le fine-tuning).\nPour donner des ordres de grandeur, la petite version du dernier modèle de Meta, Llama-3 8B, a été pré-entraîné et instruction-tuné sur un corpus de 15 trillions de tokens. Ces deux phases d’entraînement ont nécessité 1,3 millions d’heures GPU, réparties sur plusieurs milliers de GPU H100.\n\nArticle résumant la dualité pré-entraînement/fine-tuning\n\n\n\n\n\nIntroduite en 2017 dans le papier Attention Is All You Need, l’architecture Transformer a révolutionné le domaine du TAL. Par rapport aux RNN, les Transformers permettent un traitement efficace des séquences en parallèle, conduisant à un temps de calcul beaucoup plus court (tant lors de l’entraînement qu’en inférence), tandis que les RNN, par construction, ne peuvent traiter une séquence que séquentiellement, c’est-à-dire token par token. En outre, le mécanisme d’auto-attention, présenté ci-dessous, permet de capturer efficacement les dépendances distantes en atténuant le problème de la disparition et de l’explosion des gradients.\n\nL’auto-attention est le mécanisme central des Transformers. Elle est utilisée pour pondérer, lors de l’examen d’un token en particulier, l’importance, relative à ce token, de chaque autre token de la séquence. Concrètement, trois vecteurs (qui représentent chacun la séquence d’entrée dans un rôle différent) sont déduits de la séquence d’entrée \\(X\\) : les requêtes (\\(Q\\)), les clés (\\(K\\)) et les valeurs (\\(V\\)), par des transformations linéaires comme exprimées dans l’équation suivantes. Les matrices \\(W_Q\\), \\(W_K\\) et \\(W_V\\) sont des paramètres entraînables du modèle. \\[Q = X \\cdot W_Q \\qquad K = X \\cdot W_K \\qquad V = X \\cdot W_V \\]\nLes scores d’attention sont ensuite calculés selon l’équation suivante. \\[\\text{Attention}(Q, K, V) = \\text{softmax} \\left( \\frac{QK^{T}}{\\sqrt{d}} \\right) V\\]\nPour chaque token d’entrée \\(X_i\\), le résultat \\(\\text{Attention}(Q, K, V)_i\\) est une combinaison de tous les autres éléments de la séquence, pondérés selon leur pertinence par rapport à \\(X_i\\).\nL’auto-attention telle que présentée ci-dessus n’est cependant pas directement utilisée dans l’architecture Transformer. A la place, une extension, appelée attention multi-têtes, permet au modèle de capturer plusieurs aspects des relations et des dépendances entre les éléments de la séquence d’entrée. Cela est fait en transformant la séquence d’entrée en plusieurs têtes, i.e. en plusieurs vecteurs de requêtes, de clés et de valeurs, et en appliquant un mécanisme d’auto-attention sur chacune de ces têtes. Les vecteurs d’attention de chaque tête sont ensuite concaténés et réduits linéairement à la taille d’entrée d’origine. Le calcul de l’attention multi-têtes est détaillé dans l’équation suivante.\n\\[\\text{MultiHeadAttention}(Q, K, V) = \\text{Concat}(\\text{head}_1 , \\cdots, \\text{head}_h)W^O\\]\noù \\(\\text{head}_i = \\text{Attention}(X \\cdot W_Q^i, X \\cdot W_K^i, X \\cdot W_V^i)\\) pour \\(i = 1, \\cdot, h\\) avec \\(h\\) le nombre de têtes d’attention. Chaque tête d’attention peut donc se spécialiser dans un aspect spécifique des données, et le modèle peut apprendre à combiner ces différents aspects pour une meilleure représentation. La combinaison de ce mécanisme d’attention multi-têtes, de couches de normalisation et de couches à action directes (FNN) forme un bloc Transformer.\nPlusieurs blocs (6 dans l’implémentation originale) forment ensuite l’encodeur (qui a accès à la séquence d’entrée dans son intégralité) et le décodeur (qui a accès à la représention encodée de la séquence d’entrée, et à la séquence de sortie générée jusqu’alors). La combinaison de ces deux éléments composent le Transformer encodeur-décodeur original.\n\nPapier original ‘Attention Is All You Need’\nExplication illustrée et très détaillée\n\n\n\n\nLes LLMs basés sur des architectures Transformers appartiennent à l’une des 3 catégories suivantes :\n\nModèle « encoder-only » : Ils sont basés uniquement sur la partie encodeur des Transformers. Leur pré-entraînement est souvent basé sur la reconstruction de phrases : à chaque étape, le modèle a accès à une phrase entière, sauf certains mots qui ont été masqués, et apprend à retrouver ces mots masqués. Ces modèles sont adaptés pour des tâches de classification, de reconnaissance d’entités nommées (NER), de réponses aux questions, etc. Ils ont aujourd’hui perdu en popularité, mais leurs représentants les plus connus (BERT, RoBERTa, DistilBERT, CamemBERT, etc.) sont encore très utilisés, et restent un choix intéressant selon la tâche, grâce à leur compréhension fine du langage et à leur petite taille.\nModèle « decoder-only » : Ils sont basés uniquement sur la partie décodeur des Transformers. Ces modèles sont aujourd’hui la norme, et l’immense majorité des LLMs actuels utilisent cette architecture. Leur pré-entraînement est basé sur la prédiction du prochain token : à chaque étape, le modèle a accès au début d’une phrase, et apprend à prédire le token suivant. Pour cette raison, ces modèles sont également qualifiés d’« autorégressifs ». Les modèles GPT (2, 3, 4), Llama (2, 3), Mistral, Gemini, etc. sont tous des decoder-only.\nModèle « encoder-decoder » : Ils utilisent les deux blocs des Transformers. L’encodeur a ainsi accès à l’intégralité de la séquence d’entrée, alors que le décodeur a accès à la représentation cachée de l’entrée et aux tokens générés jusqu’alors. Les modèles les plus connus sont par exemple BART et T5.\n\nhttps://medium.com/artificial-corner/discovering-llm-structures-decoder-only-encoder-only-or-decoder-encoder-5036b0e9e88\n\n\n\nLes architectures Mixture of Experts ne sont pas spécifiques aux LLMs, mais elles ont été adaptées avec succès sur des modèles comme Mixtral 8x7B, Mixtral 8x22B ou GPT-4 (supposition). Le principe est de remplacer chaque réseau à propagation directe (présent dans chaque bloc de l’architecture Transformer) par un ensemble de réseaux « experts ». Au moment de passer dans cette partie du réseau, un routeur envoie vers un de ces experts uniquement. L’intérêt est double : un seul expert étant utilisé à la fois, le temps d’inférence est naturellement nettement plus court. Par ailleurs, chaque réseau expert est entraîné et donc spécialisé différement des autres : pour un même nombre de paramètres, les performances sont donc supposées être meilleures qu’avec une architecture classique. En revanche, si tous les poids du modèles ne sont pas utilisés systématiquement, c’est uniquement à l’inférence et à chaque couche du réseau que l’expert est choisi : il est donc tout de même nécessaire de charger l’intégralité des poids du modèle en mémoire, ce qui peut être très coûteux en VRAM. Pour une explication plus technique, l’article suivant détaille très bien les MoE en prenant l’exemple de Mixtral.\n\nExplication détaillée des MoE (exemple de Mixtral) : https://huggingface.co/blog/moe\n\n\n\nLe principal inconvénient architectural des Transformers est leur complexité quadratique par rapport à la taille de l’entrée (qui vient du calcul quadratique de l’attention). Mamba est une architecture récente (Décembre 2023) qui s’affranchit du mécanisme d’attention, au profit de briques SSM (Structured State Space Models). L’intérêt principal de cette architecture est sa complexité linéaire par rapport à la taille de l’entrée.\nJamba est une nouvelle architecture hybride, à mi-chemin entre le Transformer et Mamba. Cela semble permettre un niveau de performance élevé, une gestion des contextes très longs, un temps d’inférence nettement plus court, et des exigences mémoires bien moindres.\nLiens des papiers originaux :\n\nMamba\nJamba\n\n\n\n\n\nLes LLM sont des réseaux de neurones de taille importante et font l’objet d’entraînement avec des ressources colossales (e.g: quelques dizaines de milliers de GPUs dernier modèle pendant 3 mois pour GPT-4). L’entraînement permet d’apprendre un jeu de données particulier, en réglant l’ensemble des poids du modèles (e.g: Mixtral 8x22B est une architecture à 141 milliards de poids; 175 milliards pour GPT-3). Les LLM sont entraînés à répondre à plusieurs tâches génériques et ne sont pas forcément pertinent pour des cas d’utilisation particulier.\nPour répondre à ce besoin, plusieurs méthodes relevant du principe de fine-tuning sont possibles. Le fine-tuning consiste à reprendre un modèle déjà entraîné et à l’adapter sur un jeu de données particulier sur une ou plusieurs tâches spécifiques. En général, il s’agit de modifier une partie ou l’ensemble des poids pour que le modèle soit plus précis pour les tâches voulues. Le fine-tuning garde en grande partie les bénéfices de l’entraînement initial, i.e les connaissances antérieures déjà apprises. Repartir d’un modèle déjà entraîné pourra réduire le temps d’entraînement requis pour le fine-tuning, en fonction de la similarité entre la nouvelle tâche souhaitée et son jeu de données et les entraînements précédents.\nPour des petits modèles de langages, il est possible de ré-entraîner en modifiant l’ensemble des poids. Pour des modèles plus grands, modifier l’ensemble des poids peut s’avérer couteux en temps et en GPUs. Plusieurs approches permettent de ré-entraîner à moindre coût :\n\nréentrainer seulement un sous-ensemble de poids\nmodifier la tête de modélisation de la langue (lm_head) pour certains modèles, soit en réentrainant depuis les poids entraînés, soit en réinitialisant ces poids.\ngarder l’intégralité du modèle et rajouter des poids à entraîner puis utiliser l’approximation de bas rang avec LORA (Low-Rank Adaptation) pour l’entraînement et l’inférence.\nutiliser des versions quantisées, i.e. des modèles où les poids ont été tronqués à une précision inférieure (possibilité de combiner avec la technique précédente, sous le nom de qLORA).\n\n\n\n\n\n\nImplémentation HuggingFace\n\n\n\n\nPEFT = Parameter-Efficient Fine-Tuning | LoRA = Low-Rank Adaptation | QLoRA = Quantized Low-Rank Adaptation | DoRA = Weight-Decomposed Low-Rank Adaptation\nRé-entraîner entièrement un LLM est très coûteux en termes d’infrastructure et de données, et n’est donc pas à la portée de n’importe quelle organisation. Des méthodes « efficaces » ont été créées pour rendre le fine-tuning facilement accessible, dont la plus connue et la plus populaire est LoRA (Low-Rank Adaptation). Son fonctionnement repose sur deux éléments :\n\nL’adaptation : Les poids du modèle pré-entraîné sont gelés pendant l’entraînement. Ce sont des poids supplémentaires (ceux de l’adapteur) qui vont être entraînés. Cela permet de garder l’entièreté du modèle pré-entraîné tel quel, et de rajouter uniquement la partie spécifique à chaque tâche. Entre autres, il est ainsi possible, avec un seul modèle de base, d’héberger plusieurs modèles spécialisés à moindre coût. Le papier LoRA Land explique d’ailleurs comment faire tenir 25 versions de Mistral 7B fine-tunés avec LoRA sur un seul GPU A100.\nLe rang faible : Les poids additionnels peuvent être choisis de beaucoup de manières. Avec LoRA, certaines couches du modèle (les couches d’attention ou les couches linéaires par exemple) sont sélectionnées, et les poids de ces couches sont exprimés comme une multiplication de deux matrices de rangs faibles, ce qui réduit grandement le nombre de poids à entraîner (la valeur de ce rang étant un hyperparamètre de l’entraînement). En fonction de la valeur de ce rang et des couches sélectionnées, il est ainsi possible d’entraîner uniquement 1 ou 2 % du nombre de paramètres global du modèle pré-entraîné, sans que cela n’affecte trop les performances du fine-tuning.\n\n\nD’autres approches de PEFT (Parameter-Efficient Fine-Tuning) ont vu le jour, dont la plupart s’inspirent de LoRA. Parmi les plus connues, QLoRA permet d’appliquer LoRA sur des modèles quantifiés, et DoRA propose un raffinement de l’adapteur de LoRA.\n\nGuide théorique très clair sur le PEFT (principe, avantages, etc.) avec un focus sur LoRA\nGuide pratique / Implémentation HugginFace\n\nLiens des papiers originaux : - LoRA - QLoRA - DoRA\nEntraînement avec qLORA en pratique :\nEn plus de la librairie transformers et datasets, les librairies peft, bitsandbytes et trl permettent de simplifier l’entraînement avec qLORA\n(inspiré du notebook suivant )\n%%capture\n%pip install -U bitsandbytes\n%pip install -U transformers\n%pip install -U peft\n%pip install -U trl\n%pip install -U sentencepiece\n%pip install -U protobuf\n\nfrom transformers import AutoModelForCausalLM, AutoTokenizer,TrainingArguments\nfrom peft import LoraConfig, prepare_model_for_kbit_training, get_peft_model\nfrom datasets import load_dataset\nimport torch\nfrom trl import SFTTrainer\n\nbase_model = \"teknium/OpenHermes-2.5-Mistral-7B\"\nnew_model = \"Mistral-7b-instruct-teletravail\"\n\npath_to_training_file=\"Dataset_public_accords_teletravail_Dares_train.parquet\"\npath_to_test_file=\"Dataset_public_accords_teletravail_Dares_test.parquet\"\n\n\ndataset=load_dataset(\"parquet\", data_files={'train': path_to_training_file, 'test': path_to_test_file})\n\nbnb_config = BitsAndBytesConfig(\n    load_in_4bit= True,\n    bnb_4bit_quant_type= \"nf4\",\n    bnb_4bit_compute_dtype= torch.bfloat16,\n    bnb_4bit_use_double_quant= False,\n)\n\nmodel = AutoModelForCausalLM.from_pretrained(\n        base_model,\n        quantization_config=bnb_config,\n        torch_dtype=torch.bfloat16,\n        device_map=\"auto\",\n        trust_remote_code=True,\n)\nmodel.config.use_cache = False # silence the warnings. Please re-enable for inference!\nmodel.config.pretraining_tp = 1\nmodel.gradient_checkpointing_enable()\n\n# Load tokenizer\ntokenizer = AutoTokenizer.from_pretrained(base_model, trust_remote_code=True)\ntokenizer.padding_side = 'right'\ntokenizer.pad_token = tokenizer.eos_token\ntokenizer.add_eos_token = True\ntokenizer.add_bos_token, tokenizer.add_eos_token\n\n\nmodel = prepare_model_for_kbit_training(model)\npeft_config = LoraConfig(\n    lora_alpha=16,\n    lora_dropout=0.1,\n    r=64,\n    bias=\"none\",\n    task_type=\"CAUSAL_LM\",\n    target_modules=[\"q_proj\", \"k_proj\", \"v_proj\", \"o_proj\",\"gate_proj\"]\n)\nmodel = get_peft_model(model, peft_config)\n\ntraining_arguments = TrainingArguments(\n    output_dir=\"./results\",\n    num_train_epochs=1,\n    per_device_train_batch_size=4,\n    gradient_accumulation_steps=1,\n    optim=\"paged_adamw_32bit\",\n    save_steps=25,\n    logging_steps=25,\n    learning_rate=2e-4,\n    weight_decay=0.001,\n    fp16=False,\n    bf16=False,\n    max_grad_norm=0.3,\n    max_steps=-1,\n    warmup_ratio=0.03,\n    group_by_length=True,\n    lr_scheduler_type=\"constant\",\n)\n\ntrainer = SFTTrainer(\n    model=model,\n    train_dataset=dataset[\"train\"],\n    peft_config=peft_config,\n    max_seq_length= None,\n    dataset_text_field=\"text\",\n    tokenizer=tokenizer,\n    args=training_arguments,\n    packing= False,\n)\n\ntrainer.train()\n\ntrainer.model.save_pretrained(new_model)\n\n\n\n\nLe fine-tuning supervisé est très efficace dans de nombreux cas, mais il présente notamment l’inconvénient de nécessiter une quantité importante de données. La constitution d’une base de questions-réponses attendues par exemple peut se réveler coûteuse. Un autre moyen d’améliorer un modèle est d’utiliser de l’apprentissage par renforcement. La première version utilisée pour ré-entraîner un LLM est le RLHF (Reinforcement Learning from Human Feedback), qui consiste à récolter des retours d’utilisateurs humains (typiquement, entre deux réponses générées par un LLM, l’utilisateur va dire laquelle il préfère), puis à mettre à jour les poids du modèle, par un algorithme d’apprentissage par renforcement, de telle sorte que la réponse préférée par l’utilisateur ait plus de chances d’être générée. Cette approche s’est révélée particulièrement effiace pour « aligner » le modèle aux préférences humaines, en termes de biais, de toxicité, de style, etc.\nBien que la constitution d’une base de retours humains soit moins coûteuse que celle d’une base de questions/réponses, elle reste coûteuse. Une solution aujourd’hui très populaire est de remplacer ces retours humains par des retours générés artificiellement, ce qui donne une approche appelée RLAIF (Reinforcement Learning from Artificial Intelligence Feedback). Typiquement, un LLM plus performant (par exemple GPT-4) va être utilisé pour déterminer la meilleure réponse entre deux ou plusieurs choix, selon des critères donnés. Ce sont ensuite ces retours qui vont être utilisés pour améliorer le modèle grâce à l’algorithme d’apprentissage par renforcement.\nRLHF = Reinforcement Learning from Human Feedback | RLAIF = Reinforcement Learning from Artificial Intelligence Feedback\n\nIntroduction au RLHF\n\n\n\nLe premier algorithme de Reinforcement Learning utilisé dans le cadre des LLM était la PPO (Proximal Policy Optimization). Cet algorithme classique consiste à entraîner un modèle de récompense fondé sur les retours humains, puis à entraîner le LLM à optimiser cette récompense. La politique du modèle est donc mise à jour itérativement pour maximiser cette récompense. Le principal inconvénient de la PPO, que la DPO pallie, est le besoin d’entraîner un modèle de récompense, en plus du LLM lui-même.\n\nExplication théorique\nImplémentation HuggingFace\n\nhttps://medium.com/@oleglatypov/a-comprehensive-guide-to-proximal-policy-optimization-ppo-in-ai-82edab5db200\n\n\n\nL’algorithme de DPO (Direct Preference Optimization) permet de mettre à jour les poids du LLM en fonctions des retours humains directement, sans passer par un modèle de récompense : la politique que le LLM apprend maximise directement la satisfaction humaine. Une variation de cet algorithme est celui de KTO (Kahneman-Tversky Optimization), dont le fonctionnement général reste similaire.\n\nExplication théorique\nGuide pratique / Implémentation HugginFace\n\nLiens des papiers originaux :\n\nDPO\nKTO",
         "crumbs": [
           "II-Développements",
           "Anatomie et conception d'un modèle de langage"
    @@ -314,7 +314,7 @@
         "href": "II-Developpements/1_Anatomie_LLM.html#anatomie-et-conception-dun-llm",
         "title": "PARTIE II. Développements autour des LLMs (pour les data scientists)",
         "section": "",
    -    "text": "Les LLMs reposent sur un développement en deux voire trois étapes.\n\nLe pré-entraînement consiste à entraîner le modèle, en partant de zéro, de façon auto-supervisée, et sur un corpus d’entraînement gigantesque. L’objectif de ce pré-entraînement dépend du type de modèle utilisé (cf. paragraphe suivant), mais la plupart apprennent à prédire le token suivant, à partir d’une suite de tokens. C’est ce qui les rend particulièrement efficaces pour de la génération de texte.\nL’instruction-tuning permet d’adapter le modèle pré-entraîné à une plus grande diversité de tâches. Dans de nombreux cas (chatbot, résumé de texte, etc.), la prédiction du token suivant n’est pas la bonne stratégie. L’étape d’instruction-tuning permet ainsi, grâce à un entraînement supervisé, de créer une version « chat » du modèle. Pour donner un exemple connu de tous, ChatGPT est la version instruction-tunée de GPT-4.\nLe fine-tuning (optionnel) peut être utilisé pour adapter le modèle à une tâche et à des données spécifiques. Les LLMs étant des outils multitâches, souvent multilingues et multidomaines, leurs performances peuvent être dégradées lorsqu’il y a des exigences précises et spécifiques. Le fine-tuning est une nouvelle phase d’entraînement supervisé, nécessitant moins de données et de puissance de calcul, qui permet de spécialiser le modèle.\n\nPar leur taille et les exigences techniques qu’ils impliquent, seules quelques entreprises spécialisées ont les moyens de pré-entraîner et d’instruction-tuner des LLMs. Le fine-tuning, en revanche, peut être abordable pour beaucoup plus d’acteurs, pour peu qu’ils répondent à certaines exigences techniques (cf. partie sur le fine-tuning).\nPour donner des ordres de grandeur, la petite version du dernier modèle de Meta, Llama-3 8B, a été pré-entraîné et instruction-tuné sur un corpus de 15 trillions de tokens. Ces deux phases d’entraînement ont nécessité 1,3 millions d’heures GPU, réparties sur plusieurs milliers de GPU H100.\n\nArticle résumant la dualité pré-entraînement/fine-tuning\n\n\n\n\n\nIntroduite en 2017 dans le papier Attention Is All You Need, l’architecture Transformer a révolutionné le domaine du TAL. Par rapport aux RNN, les Transformers permettent un traitement efficace des séquences en parallèle, conduisant à un temps de calcul beaucoup plus court (tant lors de l’entraînement qu’en inférence), tandis que les RNN, par construction, ne peuvent traiter une séquence que séquentiellement, c’est-à-dire token par token. En outre, le mécanisme d’auto-attention, présenté ci-dessous, permet de capturer efficacement les dépendances distantes en atténuant le problème de la disparition et de l’explosion des gradients.\n\nL’auto-attention est le mécanisme central des Transformers. Elle est utilisée pour pondérer, lors de l’examen d’un token en particulier, l’importance, relative à ce token, de chaque autre token de la séquence. Concrètement, trois vecteurs (qui représentent chacun la séquence d’entrée dans un rôle différent) sont déduits de la séquence d’entrée \\(X\\) : les requêtes (\\(Q\\)), les clés (\\(K\\)) et les valeurs (\\(V\\)), par des transformations linéaires comme exprimées dans l’équation suivantes. Les matrices \\(W_Q\\), \\(W_K\\) et \\(W_V\\) sont des paramètres entraînables du modèle. \\[Q = X \\cdot W_Q \\qquad K = X \\cdot W_K \\qquad V = X \\cdot W_V \\]\nLes scores d’attention sont ensuite calculés selon l’équation suivante. \\[\\text{Attention}(Q, K, V) = \\text{softmax} \\left( \\frac{QK^{T}}{\\sqrt{d}} \\right) V\\]\nPour chaque token d’entrée \\(X_i\\), le résultat \\(\\text{Attention}(Q, K, V)_i\\) est une combinaison de tous les autres éléments de la séquence, pondérés selon leur pertinence par rapport à \\(X_i\\).\nL’auto-attention telle que présentée ci-dessus n’est cependant pas directement utilisée dans l’architecture Transformer. A la place, une extension, appelée attention multi-têtes, permet au modèle de capturer plusieurs aspects des relations et des dépendances entre les éléments de la séquence d’entrée. Cela est fait en transformant la séquence d’entrée en plusieurs têtes, i.e. en plusieurs vecteurs de requêtes, de clés et de valeurs, et en appliquant un mécanisme d’auto-attention sur chacune de ces têtes. Les vecteurs d’attention de chaque tête sont ensuite concaténés et réduits linéairement à la taille d’entrée d’origine. Le calcul de l’attention multi-têtes est détaillé dans l’équation suivante.\n\\[\\text{MultiHeadAttention}(Q, K, V) = \\text{Concat}(\\text{head}_1 , \\cdots, \\text{head}_h)W^O\\]\noù \\(\\text{head}_i = \\text{Attention}(X \\cdot W_Q^i, X \\cdot W_K^i, X \\cdot W_V^i)\\) pour \\(i = 1, \\cdot, h\\) avec \\(h\\) le nombre de têtes d’attention. Chaque tête d’attention peut donc se spécialiser dans un aspect spécifique des données, et le modèle peut apprendre à combiner ces différents aspects pour une meilleure représentation. La combinaison de ce mécanisme d’attention multi-têtes, de couches de normalisation et de couches à action directes (FNN) forme un bloc Transformer.\nPlusieurs blocs (6 dans l’implémentation originale) forment ensuite l’encodeur (qui a accès à la séquence d’entrée dans son intégralité) et le décodeur (qui a accès à la représention encodée de la séquence d’entrée, et à la séquence de sortie générée jusqu’alors). La combinaison de ces deux éléments composent le Transformer encodeur-décodeur original.\n\nPapier original ‘Attention Is All You Need’\nExplication illustrée et très détaillée\n\n\n\n\nLes LLMs basés sur des architectures Transformers appartiennent à l’une des 3 catégories suivantes :\n\nModèle « encoder-only » : Ils sont basés uniquement sur la partie encodeur des Transformers. Leur pré-entraînement est souvent basé sur la reconstruction de phrases : à chaque étape, le modèle a accès à une phrase entière, sauf certains mots qui ont été masqués, et apprend à retrouver ces mots masqués. Ces modèles sont adaptés pour des tâches de classification, de reconnaissance d’entités nommées (NER), de réponses aux questions, etc. Ils ont aujourd’hui perdu en popularité, mais leurs représentants les plus connus (BERT, RoBERTa, DistilBERT, CamemBERT, etc.) sont encore très utilisés, et restent un choix intéressant selon la tâche, grâce à leur compréhension fine du langage et à leur petite taille.\nModèle « decoder-only » : Ils sont basés uniquement sur la partie décodeur des Transformers. Ces modèles sont aujourd’hui la norme, et l’immense majorité des LLMs actuels utilisent cette architecture. Leur pré-entraînement est basé sur la prédiction du prochain token : à chaque étape, le modèle a accès au début d’une phrase, et apprend à prédire le token suivant. Pour cette raison, ces modèles sont également qualifiés d’« autorégressifs ». Les modèles GPT (2, 3, 4), Llama (2, 3), Mistral, Gemini, etc. sont tous des decoder-only.\nModèle « encoder-decoder » : Ils utilisent les deux blocs des Transformers. L’encodeur a ainsi accès à l’intégralité de la séquence d’entrée, alors que le décodeur a accès à la représentation cachée de l’entrée et aux tokens générés jusqu’alors. Les modèles les plus connus sont par exemple BART et T5.\n\nhttps://medium.com/artificial-corner/discovering-llm-structures-decoder-only-encoder-only-or-decoder-encoder-5036b0e9e88\n\n\n\nLes architectures Mixture of Experts ne sont pas spécifiques aux LLMs, mais elles ont été adaptées avec succès sur des modèles comme Mixtral 8x7B, Mixtral 8x22B ou GPT-4 (supposition). Le principe est de remplacer chaque réseau à propagation directe (présent dans chaque bloc de l’architecture Transformer) par un ensemble de réseaux « experts ». Au moment de passer dans cette partie du réseau, un routeur envoie vers un de ces experts uniquement. L’intérêt est double : un seul expert étant utilisé à la fois, le temps d’inférence est naturellement nettement plus court. Par ailleurs, chaque réseau expert est entraîné et donc spécialisé différement des autres : pour un même nombre de paramètres, les performances sont donc supposées être meilleures qu’avec une architecture classique. En revanche, si tous les poids du modèles ne sont pas utilisés systématiquement, c’est uniquement à l’inférence et à chaque couche du réseau que l’expert est choisi : il est donc tout de même nécessaire de charger l’intégralité des poids du modèle en mémoire, ce qui peut être très coûteux en VRAM. Pour une explication plus technique, l’article suivant détaille très bien les MoE en prenant l’exemple de Mixtral.\n\nExplication détaillée des MoE (exemple de Mixtral) : https://huggingface.co/blog/moe\n\n\n\nLe principal inconvénient architectural des Transformers est leur complexité quadratique par rapport à la taille de l’entrée (qui vient du calcul quadratique de l’attention). Mamba est une architecture récente (Décembre 2023) qui s’affranchit du mécanisme d’attention, au profit de briques SSM (Structured State Space Models). L’intérêt principal de cette architecture est sa complexité linéaire par rapport à la taille de l’entrée.\nJamba est une nouvelle architecture hybride, à mi-chemin entre le Transformer et Mamba. Cela semble permettre un niveau de performance élevé, une gestion des contextes très longs, un temps d’inférence nettement plus court, et des exigences mémoires bien moindres.\nLiens des papiers originaux :\n\nMamba\nJamba\n\n\n\n\n\nLes LLM sont des réseaux de neurones de taille importante et font l’objet d’entraînement avec des ressources colossales (e.g: quelques dizaines de milliers de GPUs dernier modèle pendant 3 mois pour GPT-4). L’entraînement permet d’apprendre un jeu de données particulier, en réglant l’ensemble des poids du modèles (e.g: Mixtral 8x22B est une architecture à 141 milliards de poids; 175 milliards pour GPT-3). Les LLM sont entraînés à répondre à plusieurs tâches génériques et ne sont pas forcément pertinent pour des cas d’utilisation particulier.\nPour répondre à ce besoin, plusieurs méthodes relevant du principe de fine-tuning sont possibles. Le fine-tuning consiste à reprendre un modèle déjà entraîné et à l’adapter sur un jeu de données particulier sur une ou plusieurs tâches spécifiques. En général, il s’agit de modifier une partie ou l’ensemble des poids pour que le modèle soit plus précis pour les tâches voulues. Le fine-tuning garde en grande partie les bénéfices de l’entraînement initial, i.e les connaissances antérieures déjà apprises. Repartir d’un modèle déjà entraîné pourra réduire le temps d’entraînement requis pour le fine-tuning, en fonction de la similarité entre la nouvelle tâche souhaitée et son jeu de données et les entraînements précédents.\nPour des petits modèles de langages, il est possible de ré-entraîner en modifiant l’ensemble des poids. Pour des modèles plus grands, modifier l’ensemble des poids peut s’avérer couteux en temps et en GPUs. Plusieurs approches permettent de ré-entraîner à moindre coût :\n\nréentrainer seulement un sous-ensemble de poids\nmodifier la tête de modélisation de la langue (lm_head) pour certains modèles, soit en réentrainant depuis les poids entraînés, soit en réinitialisant ces poids.\ngarder l’intégralité du modèle et rajouter des poids à entraîner puis utiliser l’approximation de bas rang avec LORA (Low-Rank Adaptation) pour l’entraînement et l’inférence.\nutiliser des versions quantisées, i.e. des modèles où les poids ont été tronqués à une précision inférieure (possibilité de combiner avec la technique précédente, sous le nom de qLORA).\n\n\n\n\n\n\nImplémentation HuggingFace\n\n\n\n\nPEFT = Parameter-Efficient Fine-Tuning | LoRA = Low-Rank Adaptation | QLoRA = Quantized Low-Rank Adaptation | DoRA = Weight-Decomposed Low-Rank Adaptation\nRé-entraîner entièrement un LLM est très coûteux en termes d’infrastructure et de données, et n’est donc pas à la portée de n’importe quelle organisation. Des méthodes « efficaces » ont été créées pour rendre le fine-tuning facilement accessible, dont la plus connue et la plus populaire est LoRA (Low-Rank Adaptation). Son fonctionnement repose sur deux éléments :\n\nL’adaptation : Les poids du modèle pré-entraîné sont gelés pendant l’entraînement. Ce sont des poids supplémentaires (ceux de l’adapteur) qui vont être entraînés. Cela permet de garder l’entièreté du modèle pré-entraîné tel quel, et de rajouter uniquement la partie spécifique à chaque tâche. Entre autres, il est ainsi possible, avec un seul modèle de base, d’héberger plusieurs modèles spécialisés à moindre coût. Le papier LoRA Land explique d’ailleurs comment faire tenir 25 versions de Mistral 7B fine-tunés avec LoRA sur un seul GPU A100.\nLe rang faible : Les poids additionnels peuvent être choisis de beaucoup de manières. Avec LoRA, certaines couches du modèle (les couches d’attention ou les couches linéaires par exemple) sont sélectionnées, et les poids de ces couches sont exprimés comme une multiplication de deux matrices de rangs faibles, ce qui réduit grandement le nombre de poids à entraîner (la valeur de ce rang étant un hyperparamètre de l’entraînement). En fonction de la valeur de ce rang et des couches sélectionnées, il est ainsi possible d’entraîner uniquement 1 ou 2 % du nombre de paramètres global du modèle pré-entraîné, sans que cela n’affecte trop les performances du fine-tuning.\n\n\nD’autres approches de PEFT (Parameter-Efficient Fine-Tuning) ont vu le jour, dont la plupart s’inspirent de LoRA. Parmi les plus connues, QLoRA permet d’appliquer LoRA sur des modèles quantifiés, et DoRA propose un raffinement de l’adapteur de LoRA.\n\nGuide théorique très clair sur le PEFT (principe, avantages, etc.) avec un focus sur LoRA\nGuide pratique / Implémentation HugginFace\n\nLiens des papiers originaux : - LoRA - QLoRA - DoRA\nEntraînement avec qLORA en pratique :\nEn plus de la librairie transformers et datasets, les librairies peft, bitsandbytes et trl permettent de simplifier l’entraînement avec qLORA\n(inspiré du notebook suivant )\n%%capture\n%pip install -U bitsandbytes\n%pip install -U transformers\n%pip install -U peft\n%pip install -U trl\n%pip install -U sentencepiece\n%pip install -U protobuf\n\nfrom transformers import AutoModelForCausalLM, AutoTokenizer,TrainingArguments\nfrom peft import LoraConfig, prepare_model_for_kbit_training, get_peft_model\nfrom datasets import load_dataset\nimport torch\nfrom trl import SFTTrainer\n\nbase_model = \"teknium/OpenHermes-2.5-Mistral-7B\"\nnew_model = \"Mistral-7b-instruct-teletravail\"\n\npath_to_training_file=\"Dataset_public_accords_teletravail_Dares_train.parquet\"\npath_to_test_file=\"Dataset_public_accords_teletravail_Dares_test.parquet\"\n\n\ndataset=load_dataset(\"parquet\", data_files={'train': path_to_training_file, 'test': path_to_test_file})\n\nbnb_config = BitsAndBytesConfig(\n    load_in_4bit= True,\n    bnb_4bit_quant_type= \"nf4\",\n    bnb_4bit_compute_dtype= torch.bfloat16,\n    bnb_4bit_use_double_quant= False,\n)\n\nmodel = AutoModelForCausalLM.from_pretrained(\n        base_model,\n        quantization_config=bnb_config,\n        torch_dtype=torch.bfloat16,\n        device_map=\"auto\",\n        trust_remote_code=True,\n)\nmodel.config.use_cache = False # silence the warnings. Please re-enable for inference!\nmodel.config.pretraining_tp = 1\nmodel.gradient_checkpointing_enable()\n\n# Load tokenizer\ntokenizer = AutoTokenizer.from_pretrained(base_model, trust_remote_code=True)\ntokenizer.padding_side = 'right'\ntokenizer.pad_token = tokenizer.eos_token\ntokenizer.add_eos_token = True\ntokenizer.add_bos_token, tokenizer.add_eos_token\n\n\nmodel = prepare_model_for_kbit_training(model)\npeft_config = LoraConfig(\n    lora_alpha=16,\n    lora_dropout=0.1,\n    r=64,\n    bias=\"none\",\n    task_type=\"CAUSAL_LM\",\n    target_modules=[\"q_proj\", \"k_proj\", \"v_proj\", \"o_proj\",\"gate_proj\"]\n)\nmodel = get_peft_model(model, peft_config)\n\ntraining_arguments = TrainingArguments(\n    output_dir=\"./results\",\n    num_train_epochs=1,\n    per_device_train_batch_size=4,\n    gradient_accumulation_steps=1,\n    optim=\"paged_adamw_32bit\",\n    save_steps=25,\n    logging_steps=25,\n    learning_rate=2e-4,\n    weight_decay=0.001,\n    fp16=False,\n    bf16=False,\n    max_grad_norm=0.3,\n    max_steps=-1,\n    warmup_ratio=0.03,\n    group_by_length=True,\n    lr_scheduler_type=\"constant\",\n)\n\ntrainer = SFTTrainer(\n    model=model,\n    train_dataset=dataset[\"train\"],\n    peft_config=peft_config,\n    max_seq_length= None,\n    dataset_text_field=\"text\",\n    tokenizer=tokenizer,\n    args=training_arguments,\n    packing= False,\n)\n\ntrainer.train()\n\ntrainer.model.save_pretrained(new_model)\n\n\n\n\nLe fine-tuning supervisé est très efficace dans de nombreux cas, mais il présente notamment l’inconvénient de nécessiter une quantité importante de données. La constitution d’une base de questions-réponses attendues par exemple peut se réveler coûteuse. Un autre moyen d’améliorer un modèle est d’utiliser de l’apprentissage par renforcement. La première version utilisée pour ré-entraîner un LLM est le RLHF (Reinforcement Learning from Human Feedback), qui consiste à récolter des retours d’utilisateurs humains (typiquement, entre deux réponses générées par un LLM, l’utilisateur va dire laquelle il préfère), puis à mettre à jour les poids du modèle, par un algorithme d’apprentissage par renforcement, de telle sorte que la réponse préférée par l’utilisateur ait plus de chances d’être générée. Cette approche s’est révélée particulièrement effiace pour « aligner » le modèle aux préférences humaines, en termes de biais, de toxicité, de style, etc.\nBien que la constitution d’une base de retours humains soit moins coûteuse que celle d’une base de questions/réponses, elle reste coûteuse. Une solution aujourd’hui très populaire est de remplacer ces retours humains par des retours générés artificiellement, ce qui donne une approche appelée RLAIF (Reinforcement Learning from Artificial Intelligence Feedback). Typiquement, un LLM plus performant (par exemple GPT-4) va être utilisé pour déterminer la meilleure réponse entre deux ou plusieurs choix, selon des critères donnés. Ce sont ensuite ces retours qui vont être utilisés pour améliorer le modèle grâce à l’algorithme d’apprentissage par renforcement.\nRLHF = Reinforcement Learning from Human Feedback | RLAIF = Reinforcement Learning from Artificial Intelligence Feedback\n\nIntroduction au RLHF\n\n\n\nLe premier algorithme de Reinforcement Learning utilisé dans le cadre des LLM était la PPO (Proximal Policy Optimization). Cet algorithme classique consiste à entraîner un modèle de récompense fondé sur les retours humains, puis à entraîner le LLM à optimiser cette récompense. La politique du modèle est donc mise à jour itérativement pour maximiser cette récompense. Le principal inconvénient de la PPO, que la DPO pallie, est le besoin d’entraîner un modèle de récompense, en plus du LLM lui-même.\n\nExplication théorique\nImplémentation HuggingFace\n\nhttps://medium.com/@oleglatypov/a-comprehensive-guide-to-proximal-policy-optimization-ppo-in-ai-82edab5db200\n\n\n\nL’algorithme de DPO (Direct Preference Optimization) permet de mettre à jour les poids du LLM en fonctions des retours humains directement, sans passer par un modèle de récompense : la politique que le LLM apprend maximise directement la satisfaction humaine. Une variation de cet algorithme est celui de KTO (Kahneman-Tversky Optimization), dont le fonctionnement général reste similaire.\n\nExplication théorique\nGuide pratique / Implémentation HugginFace\n\nLiens des papiers originaux : - DPO - KTO",
    +    "text": "Les LLMs reposent sur un développement en deux voire trois étapes.\n\nLe pré-entraînement consiste à entraîner le modèle, en partant de zéro, de façon auto-supervisée, et sur un corpus d’entraînement gigantesque. L’objectif de ce pré-entraînement dépend du type de modèle utilisé (cf. paragraphe suivant), mais la plupart apprennent à prédire le token suivant, à partir d’une suite de tokens. C’est ce qui les rend particulièrement efficaces pour de la génération de texte.\nL’instruction-tuning permet d’adapter le modèle pré-entraîné à une plus grande diversité de tâches. Dans de nombreux cas (chatbot, résumé de texte, etc.), la prédiction du token suivant n’est pas la bonne stratégie. L’étape d’instruction-tuning permet ainsi, grâce à un entraînement supervisé, de créer une version « chat » du modèle. Pour donner un exemple connu de tous, ChatGPT est la version instruction-tunée de GPT-4.\nLe fine-tuning (optionnel) peut être utilisé pour adapter le modèle à une tâche et à des données spécifiques. Les LLMs étant des outils multitâches, souvent multilingues et multidomaines, leurs performances peuvent être dégradées lorsqu’il y a des exigences précises et spécifiques. Le fine-tuning est une nouvelle phase d’entraînement supervisé, nécessitant moins de données et de puissance de calcul, qui permet de spécialiser le modèle.\n\nPar leur taille et les exigences techniques qu’ils impliquent, seules quelques entreprises spécialisées ont les moyens de pré-entraîner et d’instruction-tuner des LLMs. Le fine-tuning, en revanche, peut être abordable pour beaucoup plus d’acteurs, pour peu qu’ils répondent à certaines exigences techniques (cf. partie sur le fine-tuning).\nPour donner des ordres de grandeur, la petite version du dernier modèle de Meta, Llama-3 8B, a été pré-entraîné et instruction-tuné sur un corpus de 15 trillions de tokens. Ces deux phases d’entraînement ont nécessité 1,3 millions d’heures GPU, réparties sur plusieurs milliers de GPU H100.\n\nArticle résumant la dualité pré-entraînement/fine-tuning\n\n\n\n\n\nIntroduite en 2017 dans le papier Attention Is All You Need, l’architecture Transformer a révolutionné le domaine du TAL. Par rapport aux RNN, les Transformers permettent un traitement efficace des séquences en parallèle, conduisant à un temps de calcul beaucoup plus court (tant lors de l’entraînement qu’en inférence), tandis que les RNN, par construction, ne peuvent traiter une séquence que séquentiellement, c’est-à-dire token par token. En outre, le mécanisme d’auto-attention, présenté ci-dessous, permet de capturer efficacement les dépendances distantes en atténuant le problème de la disparition et de l’explosion des gradients.\n\nL’auto-attention est le mécanisme central des Transformers. Elle est utilisée pour pondérer, lors de l’examen d’un token en particulier, l’importance, relative à ce token, de chaque autre token de la séquence. Concrètement, trois vecteurs (qui représentent chacun la séquence d’entrée dans un rôle différent) sont déduits de la séquence d’entrée \\(X\\) : les requêtes (\\(Q\\)), les clés (\\(K\\)) et les valeurs (\\(V\\)), par des transformations linéaires comme exprimées dans l’équation suivantes. Les matrices \\(W_Q\\), \\(W_K\\) et \\(W_V\\) sont des paramètres entraînables du modèle. \\[Q = X \\cdot W_Q \\qquad K = X \\cdot W_K \\qquad V = X \\cdot W_V \\]\nLes scores d’attention sont ensuite calculés selon l’équation suivante. \\[\\text{Attention}(Q, K, V) = \\text{softmax} \\left( \\frac{QK^{T}}{\\sqrt{d}} \\right) V\\]\nPour chaque token d’entrée \\(X_i\\), le résultat \\(\\text{Attention}(Q, K, V)_i\\) est une combinaison de tous les autres éléments de la séquence, pondérés selon leur pertinence par rapport à \\(X_i\\).\nL’auto-attention telle que présentée ci-dessus n’est cependant pas directement utilisée dans l’architecture Transformer. A la place, une extension, appelée attention multi-têtes, permet au modèle de capturer plusieurs aspects des relations et des dépendances entre les éléments de la séquence d’entrée. Cela est fait en transformant la séquence d’entrée en plusieurs têtes, i.e. en plusieurs vecteurs de requêtes, de clés et de valeurs, et en appliquant un mécanisme d’auto-attention sur chacune de ces têtes. Les vecteurs d’attention de chaque tête sont ensuite concaténés et réduits linéairement à la taille d’entrée d’origine. Le calcul de l’attention multi-têtes est détaillé dans l’équation suivante.\n\\[\\text{MultiHeadAttention}(Q, K, V) = \\text{Concat}(\\text{head}_1 , \\cdots, \\text{head}_h)W^O\\]\noù \\(\\text{head}_i = \\text{Attention}(X \\cdot W_Q^i, X \\cdot W_K^i, X \\cdot W_V^i)\\) pour \\(i = 1, \\cdot, h\\) avec \\(h\\) le nombre de têtes d’attention. Chaque tête d’attention peut donc se spécialiser dans un aspect spécifique des données, et le modèle peut apprendre à combiner ces différents aspects pour une meilleure représentation. La combinaison de ce mécanisme d’attention multi-têtes, de couches de normalisation et de couches à action directes (FNN) forme un bloc Transformer.\nPlusieurs blocs (6 dans l’implémentation originale) forment ensuite l’encodeur (qui a accès à la séquence d’entrée dans son intégralité) et le décodeur (qui a accès à la représention encodée de la séquence d’entrée, et à la séquence de sortie générée jusqu’alors). La combinaison de ces deux éléments composent le Transformer encodeur-décodeur original.\n\nPapier original ‘Attention Is All You Need’\nExplication illustrée et très détaillée\n\n\n\n\nLes LLMs basés sur des architectures Transformers appartiennent à l’une des 3 catégories suivantes :\n\nModèle « encoder-only » : Ils sont basés uniquement sur la partie encodeur des Transformers. Leur pré-entraînement est souvent basé sur la reconstruction de phrases : à chaque étape, le modèle a accès à une phrase entière, sauf certains mots qui ont été masqués, et apprend à retrouver ces mots masqués. Ces modèles sont adaptés pour des tâches de classification, de reconnaissance d’entités nommées (NER), de réponses aux questions, etc. Ils ont aujourd’hui perdu en popularité, mais leurs représentants les plus connus (BERT, RoBERTa, DistilBERT, CamemBERT, etc.) sont encore très utilisés, et restent un choix intéressant selon la tâche, grâce à leur compréhension fine du langage et à leur petite taille.\nModèle « decoder-only » : Ils sont basés uniquement sur la partie décodeur des Transformers. Ces modèles sont aujourd’hui la norme, et l’immense majorité des LLMs actuels utilisent cette architecture. Leur pré-entraînement est basé sur la prédiction du prochain token : à chaque étape, le modèle a accès au début d’une phrase, et apprend à prédire le token suivant. Pour cette raison, ces modèles sont également qualifiés d’« autorégressifs ». Les modèles GPT (2, 3, 4), Llama (2, 3), Mistral, Gemini, etc. sont tous des decoder-only.\nModèle « encoder-decoder » : Ils utilisent les deux blocs des Transformers. L’encodeur a ainsi accès à l’intégralité de la séquence d’entrée, alors que le décodeur a accès à la représentation cachée de l’entrée et aux tokens générés jusqu’alors. Les modèles les plus connus sont par exemple BART et T5.\n\nhttps://medium.com/artificial-corner/discovering-llm-structures-decoder-only-encoder-only-or-decoder-encoder-5036b0e9e88\n\n\n\nLes architectures Mixture of Experts ne sont pas spécifiques aux LLMs, mais elles ont été adaptées avec succès sur des modèles comme Mixtral 8x7B, Mixtral 8x22B ou GPT-4 (supposition). Le principe est de remplacer chaque réseau à propagation directe (présent dans chaque bloc de l’architecture Transformer) par un ensemble de réseaux « experts ». Au moment de passer dans cette partie du réseau, un routeur envoie vers un de ces experts uniquement. L’intérêt est double : un seul expert étant utilisé à la fois, le temps d’inférence est naturellement nettement plus court. Par ailleurs, chaque réseau expert est entraîné et donc spécialisé différement des autres : pour un même nombre de paramètres, les performances sont donc supposées être meilleures qu’avec une architecture classique. En revanche, si tous les poids du modèles ne sont pas utilisés systématiquement, c’est uniquement à l’inférence et à chaque couche du réseau que l’expert est choisi : il est donc tout de même nécessaire de charger l’intégralité des poids du modèle en mémoire, ce qui peut être très coûteux en VRAM. Pour une explication plus technique, l’article suivant détaille très bien les MoE en prenant l’exemple de Mixtral.\n\nExplication détaillée des MoE (exemple de Mixtral) : https://huggingface.co/blog/moe\n\n\n\nLe principal inconvénient architectural des Transformers est leur complexité quadratique par rapport à la taille de l’entrée (qui vient du calcul quadratique de l’attention). Mamba est une architecture récente (Décembre 2023) qui s’affranchit du mécanisme d’attention, au profit de briques SSM (Structured State Space Models). L’intérêt principal de cette architecture est sa complexité linéaire par rapport à la taille de l’entrée.\nJamba est une nouvelle architecture hybride, à mi-chemin entre le Transformer et Mamba. Cela semble permettre un niveau de performance élevé, une gestion des contextes très longs, un temps d’inférence nettement plus court, et des exigences mémoires bien moindres.\nLiens des papiers originaux :\n\nMamba\nJamba\n\n\n\n\n\nLes LLM sont des réseaux de neurones de taille importante et font l’objet d’entraînement avec des ressources colossales (e.g: quelques dizaines de milliers de GPUs dernier modèle pendant 3 mois pour GPT-4). L’entraînement permet d’apprendre un jeu de données particulier, en réglant l’ensemble des poids du modèles (e.g: Mixtral 8x22B est une architecture à 141 milliards de poids; 175 milliards pour GPT-3). Les LLM sont entraînés à répondre à plusieurs tâches génériques et ne sont pas forcément pertinent pour des cas d’utilisation particulier.\nPour répondre à ce besoin, plusieurs méthodes relevant du principe de fine-tuning sont possibles. Le fine-tuning consiste à reprendre un modèle déjà entraîné et à l’adapter sur un jeu de données particulier sur une ou plusieurs tâches spécifiques. En général, il s’agit de modifier une partie ou l’ensemble des poids pour que le modèle soit plus précis pour les tâches voulues. Le fine-tuning garde en grande partie les bénéfices de l’entraînement initial, i.e les connaissances antérieures déjà apprises. Repartir d’un modèle déjà entraîné pourra réduire le temps d’entraînement requis pour le fine-tuning, en fonction de la similarité entre la nouvelle tâche souhaitée et son jeu de données et les entraînements précédents.\nPour des petits modèles de langages, il est possible de ré-entraîner en modifiant l’ensemble des poids. Pour des modèles plus grands, modifier l’ensemble des poids peut s’avérer couteux en temps et en GPUs. Plusieurs approches permettent de ré-entraîner à moindre coût :\n\nréentrainer seulement un sous-ensemble de poids\nmodifier la tête de modélisation de la langue (lm_head) pour certains modèles, soit en réentrainant depuis les poids entraînés, soit en réinitialisant ces poids.\ngarder l’intégralité du modèle et rajouter des poids à entraîner puis utiliser l’approximation de bas rang avec LORA (Low-Rank Adaptation) pour l’entraînement et l’inférence.\nutiliser des versions quantisées, i.e. des modèles où les poids ont été tronqués à une précision inférieure (possibilité de combiner avec la technique précédente, sous le nom de qLORA).\n\n\n\n\n\n\nImplémentation HuggingFace\n\n\n\n\nPEFT = Parameter-Efficient Fine-Tuning | LoRA = Low-Rank Adaptation | QLoRA = Quantized Low-Rank Adaptation | DoRA = Weight-Decomposed Low-Rank Adaptation\nRé-entraîner entièrement un LLM est très coûteux en termes d’infrastructure et de données, et n’est donc pas à la portée de n’importe quelle organisation. Des méthodes « efficaces » ont été créées pour rendre le fine-tuning facilement accessible, dont la plus connue et la plus populaire est LoRA (Low-Rank Adaptation). Son fonctionnement repose sur deux éléments :\n\nL’adaptation : Les poids du modèle pré-entraîné sont gelés pendant l’entraînement. Ce sont des poids supplémentaires (ceux de l’adapteur) qui vont être entraînés. Cela permet de garder l’entièreté du modèle pré-entraîné tel quel, et de rajouter uniquement la partie spécifique à chaque tâche. Entre autres, il est ainsi possible, avec un seul modèle de base, d’héberger plusieurs modèles spécialisés à moindre coût. Le papier LoRA Land explique d’ailleurs comment faire tenir 25 versions de Mistral 7B fine-tunés avec LoRA sur un seul GPU A100.\nLe rang faible : Les poids additionnels peuvent être choisis de beaucoup de manières. Avec LoRA, certaines couches du modèle (les couches d’attention ou les couches linéaires par exemple) sont sélectionnées, et les poids de ces couches sont exprimés comme une multiplication de deux matrices de rangs faibles, ce qui réduit grandement le nombre de poids à entraîner (la valeur de ce rang étant un hyperparamètre de l’entraînement). En fonction de la valeur de ce rang et des couches sélectionnées, il est ainsi possible d’entraîner uniquement 1 ou 2 % du nombre de paramètres global du modèle pré-entraîné, sans que cela n’affecte trop les performances du fine-tuning.\n\n\nD’autres approches de PEFT (Parameter-Efficient Fine-Tuning) ont vu le jour, dont la plupart s’inspirent de LoRA. Parmi les plus connues, QLoRA permet d’appliquer LoRA sur des modèles quantifiés, et DoRA propose un raffinement de l’adapteur de LoRA.\n\nGuide théorique très clair sur le PEFT (principe, avantages, etc.) avec un focus sur LoRA\nGuide pratique / Implémentation HugginFace\n\nLiens des papiers originaux : - LoRA - QLoRA - DoRA\nEntraînement avec qLORA en pratique :\nEn plus de la librairie transformers et datasets, les librairies peft, bitsandbytes et trl permettent de simplifier l’entraînement avec qLORA\n(inspiré du notebook suivant )\n%%capture\n%pip install -U bitsandbytes\n%pip install -U transformers\n%pip install -U peft\n%pip install -U trl\n%pip install -U sentencepiece\n%pip install -U protobuf\n\nfrom transformers import AutoModelForCausalLM, AutoTokenizer,TrainingArguments\nfrom peft import LoraConfig, prepare_model_for_kbit_training, get_peft_model\nfrom datasets import load_dataset\nimport torch\nfrom trl import SFTTrainer\n\nbase_model = \"teknium/OpenHermes-2.5-Mistral-7B\"\nnew_model = \"Mistral-7b-instruct-teletravail\"\n\npath_to_training_file=\"Dataset_public_accords_teletravail_Dares_train.parquet\"\npath_to_test_file=\"Dataset_public_accords_teletravail_Dares_test.parquet\"\n\n\ndataset=load_dataset(\"parquet\", data_files={'train': path_to_training_file, 'test': path_to_test_file})\n\nbnb_config = BitsAndBytesConfig(\n    load_in_4bit= True,\n    bnb_4bit_quant_type= \"nf4\",\n    bnb_4bit_compute_dtype= torch.bfloat16,\n    bnb_4bit_use_double_quant= False,\n)\n\nmodel = AutoModelForCausalLM.from_pretrained(\n        base_model,\n        quantization_config=bnb_config,\n        torch_dtype=torch.bfloat16,\n        device_map=\"auto\",\n        trust_remote_code=True,\n)\nmodel.config.use_cache = False # silence the warnings. Please re-enable for inference!\nmodel.config.pretraining_tp = 1\nmodel.gradient_checkpointing_enable()\n\n# Load tokenizer\ntokenizer = AutoTokenizer.from_pretrained(base_model, trust_remote_code=True)\ntokenizer.padding_side = 'right'\ntokenizer.pad_token = tokenizer.eos_token\ntokenizer.add_eos_token = True\ntokenizer.add_bos_token, tokenizer.add_eos_token\n\n\nmodel = prepare_model_for_kbit_training(model)\npeft_config = LoraConfig(\n    lora_alpha=16,\n    lora_dropout=0.1,\n    r=64,\n    bias=\"none\",\n    task_type=\"CAUSAL_LM\",\n    target_modules=[\"q_proj\", \"k_proj\", \"v_proj\", \"o_proj\",\"gate_proj\"]\n)\nmodel = get_peft_model(model, peft_config)\n\ntraining_arguments = TrainingArguments(\n    output_dir=\"./results\",\n    num_train_epochs=1,\n    per_device_train_batch_size=4,\n    gradient_accumulation_steps=1,\n    optim=\"paged_adamw_32bit\",\n    save_steps=25,\n    logging_steps=25,\n    learning_rate=2e-4,\n    weight_decay=0.001,\n    fp16=False,\n    bf16=False,\n    max_grad_norm=0.3,\n    max_steps=-1,\n    warmup_ratio=0.03,\n    group_by_length=True,\n    lr_scheduler_type=\"constant\",\n)\n\ntrainer = SFTTrainer(\n    model=model,\n    train_dataset=dataset[\"train\"],\n    peft_config=peft_config,\n    max_seq_length= None,\n    dataset_text_field=\"text\",\n    tokenizer=tokenizer,\n    args=training_arguments,\n    packing= False,\n)\n\ntrainer.train()\n\ntrainer.model.save_pretrained(new_model)\n\n\n\n\nLe fine-tuning supervisé est très efficace dans de nombreux cas, mais il présente notamment l’inconvénient de nécessiter une quantité importante de données. La constitution d’une base de questions-réponses attendues par exemple peut se réveler coûteuse. Un autre moyen d’améliorer un modèle est d’utiliser de l’apprentissage par renforcement. La première version utilisée pour ré-entraîner un LLM est le RLHF (Reinforcement Learning from Human Feedback), qui consiste à récolter des retours d’utilisateurs humains (typiquement, entre deux réponses générées par un LLM, l’utilisateur va dire laquelle il préfère), puis à mettre à jour les poids du modèle, par un algorithme d’apprentissage par renforcement, de telle sorte que la réponse préférée par l’utilisateur ait plus de chances d’être générée. Cette approche s’est révélée particulièrement effiace pour « aligner » le modèle aux préférences humaines, en termes de biais, de toxicité, de style, etc.\nBien que la constitution d’une base de retours humains soit moins coûteuse que celle d’une base de questions/réponses, elle reste coûteuse. Une solution aujourd’hui très populaire est de remplacer ces retours humains par des retours générés artificiellement, ce qui donne une approche appelée RLAIF (Reinforcement Learning from Artificial Intelligence Feedback). Typiquement, un LLM plus performant (par exemple GPT-4) va être utilisé pour déterminer la meilleure réponse entre deux ou plusieurs choix, selon des critères donnés. Ce sont ensuite ces retours qui vont être utilisés pour améliorer le modèle grâce à l’algorithme d’apprentissage par renforcement.\nRLHF = Reinforcement Learning from Human Feedback | RLAIF = Reinforcement Learning from Artificial Intelligence Feedback\n\nIntroduction au RLHF\n\n\n\nLe premier algorithme de Reinforcement Learning utilisé dans le cadre des LLM était la PPO (Proximal Policy Optimization). Cet algorithme classique consiste à entraîner un modèle de récompense fondé sur les retours humains, puis à entraîner le LLM à optimiser cette récompense. La politique du modèle est donc mise à jour itérativement pour maximiser cette récompense. Le principal inconvénient de la PPO, que la DPO pallie, est le besoin d’entraîner un modèle de récompense, en plus du LLM lui-même.\n\nExplication théorique\nImplémentation HuggingFace\n\nhttps://medium.com/@oleglatypov/a-comprehensive-guide-to-proximal-policy-optimization-ppo-in-ai-82edab5db200\n\n\n\nL’algorithme de DPO (Direct Preference Optimization) permet de mettre à jour les poids du LLM en fonctions des retours humains directement, sans passer par un modèle de récompense : la politique que le LLM apprend maximise directement la satisfaction humaine. Une variation de cet algorithme est celui de KTO (Kahneman-Tversky Optimization), dont le fonctionnement général reste similaire.\n\nExplication théorique\nGuide pratique / Implémentation HugginFace\n\nLiens des papiers originaux :\n\nDPO\nKTO",
         "crumbs": [
           "II-Développements",
           "Anatomie et conception d'un modèle de langage"
    diff --git a/sitemap.xml b/sitemap.xml
    index a454313..8bc209f 100644
    --- a/sitemap.xml
    +++ b/sitemap.xml
    @@ -2,78 +2,78 @@
     
       
         https://etalab.github.io/programme10pourcent-kallm/IV-Exemples/2_Classification_accords_entreprise.html
    -    2024-11-07T14:56:51.172Z
    +    2024-11-07T15:17:00.886Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/I-Accompagnement/4_Impacts.html
    -    2024-11-07T14:56:51.168Z
    +    2024-11-07T15:17:00.886Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/I-Accompagnement/2_Deja_Fait_Admin.html
    -    2024-11-07T14:56:51.168Z
    +    2024-11-07T15:17:00.886Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/II-Developpements/4_Evaluations.html
    -    2024-11-07T14:56:51.168Z
    +    2024-11-07T15:17:00.886Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/II-Developpements/0_Introduction.html
    -    2024-11-07T14:56:51.168Z
    +    2024-11-07T15:17:00.886Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/II-Developpements/3_RAG.html
    -    2024-11-07T14:56:51.168Z
    +    2024-11-07T15:17:00.886Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/notebooks/10p_RAG_OLLAMA.html
    -    2024-11-07T14:56:51.184Z
    +    2024-11-07T15:17:00.902Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/III-Deploiements/1_Socle_minimal.html
    -    2024-11-07T14:56:51.172Z
    +    2024-11-07T15:17:00.886Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/III-Deploiements/3_Socle_Production.html
    -    2024-11-07T14:56:51.172Z
    +    2024-11-07T15:17:00.886Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/Reste_a_faire.html
    -    2024-11-07T14:56:51.172Z
    +    2024-11-07T15:17:00.886Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/III-Deploiements/2_Socle_avance.html
    -    2024-11-07T14:56:51.172Z
    +    2024-11-07T15:17:00.886Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/III-Deploiements/4_Infras_administrations.html
    -    2024-11-07T14:56:51.172Z
    +    2024-11-07T15:17:00.886Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/Bibliographie.html
    -    2024-11-07T14:56:51.168Z
    +    2024-11-07T15:17:00.886Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/notebooks/autres/parse_llama31_results.html
    -    2024-11-07T14:56:51.184Z
    +    2024-11-07T15:17:00.902Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/II-Developpements/1_Anatomie_LLM.html
    -    2024-11-07T14:56:51.168Z
    +    2024-11-07T15:17:00.886Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/II-Developpements/2_Utilisation_LLM.html
    -    2024-11-07T14:56:51.168Z
    +    2024-11-07T15:17:00.886Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/index.html
    -    2024-11-07T14:56:51.184Z
    +    2024-11-07T15:17:00.902Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/I-Accompagnement/1_cas_usage.html
    -    2024-11-07T14:56:51.168Z
    +    2024-11-07T15:17:00.886Z
       
       
         https://etalab.github.io/programme10pourcent-kallm/I-Accompagnement/3_Acculturation.html
    -    2024-11-07T14:56:51.168Z
    +    2024-11-07T15:17:00.886Z