Accéder au contenu principal

Tutoriel Tinker : Optimisation des modèles d'apprentissage automatique à grande échelle avec Thinking Machines Lab

Guide pratique pour la mise en œuvre de LoRA via Tinker AI afin de former Qwen3-8B sur des données financières Chain-of-Thought (CoT), en optimisant la généralisation.
Actualisé 5 déc. 2025  · 15 min lire

Le réglage fin des grands modèles linguistiques implique généralement de gérer une infrastructure GPU distribuée, de gérer les pannes de cluster et de déboguer des scripts d'entraînement complexes. Tinker est là pour résoudre ce problème.

Publié par le Thinking Machines Lab de Mira Murati le 1er octobre 2025, Tinker est une API de formation qui gère toute la complexité de l'infrastructure tout en vous offrant un contrôle total sur vos algorithmes et vos données. Il permet d'écrire des scripts Python simples avec quatre fonctions principales, et Tinker les exécute sur des GPU distribués pour une large gamme de modèles open source tels que Llama 70B ou Qwen 235B.

La plateforme utilise l'ajustement Low-Rank Adaptation (LoRA) pour réduire les coûts et prend en charge toutes les méthodes, de l'apprentissage supervisé à l'apprentissage par renforcement. Les équipes de recherche de Princeton, Stanford et Berkeley l'utilisent déjà dans le cadre de leurs travaux.

Dans ce tutoriel, je vous guiderai à travers l'installation de Tinker, la compréhension de son API et le réglage d'un modèle complet de questions-réponses financières à l'aide du modèle de base Qwen3-8B. Si vous souhaitez approfondir vos connaissances en matière de réglage fin à travers des exercices pratiques, je vous recommande de consulter ce cours sur le réglage fin avec Llama 3.

Qu'est-ce que Tinker ?

Thinking Machines Lab a développé Tinker pour les personnes qui souhaitent personnaliser la manière dont les modèles apprennent sans devenir des experts en infrastructure.

Qui utilise Tinker ?

La plateforme s'adresse à trois groupes : 

  • Des chercheurs explorent une nouvelle méthode de formation
  • Développeurs créant des produits d'IA nécessitant un comportement personnalisé
  • Les constructeurs qui souhaitent obtenir des résultats de qualité industrielle sans disposer des ressources d'une grande entreprise. 

Chaque groupe partage un besoin commun : ils savent ce qu'ils souhaitent que leur modèle accomplisse, mais les interfaces de réglage standard ne leur offrent pas suffisamment de contrôle.

Par exemple, les équipes universitaires pourraient l'utiliser pour tester de nouveaux algorithmes. Un laboratoire de chimie pourrait souhaiter former des modèles sur des modèles de raisonnement spécifiques à un domaine qui ne correspondent pas aux modèles classiques d'ajustement des instructions. Une start-up développant un bot conseiller financier pourrait utiliser ce modèle pour suivre des formats de sortie et des chaînes de raisonnement spécifiques. 

Tous ces cas d'utilisation ont en commun le fait qu'ils nécessitent de modifier le processus d'entraînement lui-même, et non pas simplement d'échanger des ensembles de données.

Qu'est-ce qui distingue Tinker ?

La plupart des plateformes sont optimisées pour l'un des deux aspects suivants : la facilité d'utilisation ou la flexibilité. L'approche de Tinker consiste à considérer que ces deux éléments ne sont pas nécessairement en conflit. La plateforme vous offre un accès de base à la formation grâce à quatre opérations principales, mais gère tout le reste automatiquement :

  • Contrôle de la boucle de formation : Veuillez rédiger vos propres fonctions de perte, stratégies d'accumulation de gradients ou modèles d'échantillonnage.
  • Mises à jour du modèle : Veuillez préciser comment les pondérations doivent évoluer au cours de l'optimisation.
  • Évaluation : Générez des résultats ou calculez des probabilités à tout moment pendant la formation.
  • Gestion de l'État : Enregistrez et reprenez votre formation tout en conservant un contrôle total sur les éléments qui sont conservés.

Tinker met à disposition ces fonctionnalités via quatre primitives API que vous découvrirez dans la section pratique.

Cela fonctionne car la complexité de la formation provient principalement de l'infrastructure, et non des algorithmes eux-mêmes. Il est très simple d'exécuter une boucle d'entraînement personnalisée sur votre ordinateur portable. Il est difficile de l'exécuter sur 100 GPU avec récupération après panne et planification des ressources. Tinker se charge de la deuxième partie, vous pouvez donc vous concentrer sur la première.

Où Tinker s'intègre

L'écosystème des outils d'IA se divise globalement en trois couches : les fournisseurs de services informatiques dans le cloud qui fournissent des GPU bruts, les plateformes gérées qui exécutent des flux de travail prédéfinis et les frameworks qui facilitent la création de systèmes d'entraînement à partir de zéro. Tinker se situe entre les plateformes gérées et les cadres. Vous bénéficiez d'un contrôle accru par rapport à des plateformes telles que Hugging Face AutoTrain, tout en nécessitant moins de travail d'infrastructure que la configuration d'un cluster personnalisé sur Google Cloud Platform (GCP).

Tarifs et crédits Tinker

Tinker utilise une tarification transparente par jeton qui varie en fonction de la taille du modèle et du type d'opération. La formation de Qwen3-8B coûte 0,40 $ par million de jetons. La bonne nouvelle : les nouveaux utilisateurs reçoivent 150 $ de crédits lorsqu'ils sont retirés de la liste d'attente, ce qui couvre largement plusieurs essais de formation comme celui présenté dans ce tutoriel.

Tarification Tinker

Source : Laboratoire des machines pensantes

Exemple de Tinker : Ajustement de Qwen3-8B pour les questions financières

Dans cette section, je vais vous guider dans la création d'un workflow complet de réglage fin à l'aide de l'API de Tinker. Nous affinerons Qwen3-8B sur des données de questions-réponses financières à l'aide de LoRA, en apprenant les quatre primitives API de base tout en observant les meilleures pratiques de production en action.

Pour obtenir un aperçu plus détaillé du modèle, veuillez consulter cet article consacré à Qwen3.

Remarque importante: Tinker est actuellement en version bêta et l'accès se fait sur liste d'attente. Si vous disposez d'un accès, vous pouvez suivre et exécuter le code. Si vous êtes sur la liste d'attente, vous pouvez tout de même lire cet article pour comprendre à quel point le processus de réglage est simple avec Tinker. Une fois que vous aurez accès, vous serez prêt à commencer immédiatement.

Résultats de la formation et sélection des points de contrôle

Examinons d'abord les résultats de la formation. Comprendre ce qui s'est produit vous aide à repérer ces schémas lorsque vous effectuez vos propres tâches de réglage.

Nous avons affiné Qwen3-8B sur l'ensemble de données FinCoT, un ensemble de données de raisonnement financier en chaîne de pensée, en utilisant LoRA avec un rang de 32. Après avoir filtré les séquences ne dépassant pas 10 000 tokens, nous avons obtenu 7 244 exemples d'entraînement et 500 exemples de validation avec lesquels travailler. 

La formation s'est déroulée sur 904 itérations réparties sur quatre époques, ce qui a pris environ trois heures, tandis que Tinker s'est chargé de toute la coordination distribuée des GPU. 

Une époque correspond à un passage complet de l'ensemble des données d'entraînement. Étant donné qu'il y avait 226 lots par époque (7 244 exemples divisés par une taille de lot de 32), les quatre époques ont totalisé 904 itérations.

Analyse des résultats de la formation

Le graphique suivant suit un cursus de trois indicateurs : la perte d'entraînement (en bleu), la perte de validation (en rouge) et le taux d'apprentissage (en vert).

Progrès de la formation des bricoleurs

La formation initiale (itérations 0 à 400) semble satisfaisante : les pertes de formation et de validation diminuent fortement, passant de plus de 1,4 à moins de 0,8 et restant à environ 0,1 l'une de l'autre. 

Cette période démontre que le modèle apprend efficacement des modèles généralisables dans les données. Le taux d'apprentissage (ligne verte) augmente progressivement au cours des 200 premières itérations, à mesure que la phase de préchauffage stabilise l'entraînement. 

Vers les itérations 400 à 600, la situation évolue. La perte d'entraînement continue de diminuer, mais la perte de validation se stabilise autour de 0,75-0,8, creusant l'écart à 0,13 à mesure que le modèle commence à surajuster. Entre les itérations 600 et 900, la divergence devient évidente : la perte d'entraînement chute à 0,39 tandis que la perte de validation augmente à 0,8, ce qui indique que le modèle est passé de l'apprentissage de modèles de raisonnement à la mémorisation d'exemples. 

Ce modèle est courant lors du réglage fin des modèles de raisonnement. Si vous souhaitez en savoir plus sur le développement des capacités de raisonnement au cours de la formation, nous vous invitons à consulter ce tutoriel sur le réglage fin de DeepSeek R1, qui explore des dynamiques similaires.

Le modèle enregistré au point de contrôle 400 offre la meilleure généralisation, avec une perte d'entraînement de 0,68, une perte de validation de 0,73 et un écart minime de seulement 0,05. Malgré une perte d'entraînement plus élevée que le point de contrôle final, il gère mieux les nouvelles questions. La perte d'entraînement la plus faible produit rarement le meilleur modèle, c'est pourquoi les mesures de validation sont importantes.

Nous vérifierons cela ultérieurement en comparant le modèle au point de contrôle 400 avec le modèle de base à l'aide d'un juge LLM. Pour l'instant, examinons étape par étape la création de ce flux de travail de réglage fin.

Étape 1 : Veuillez installer Tinker et configurer votre environnement.

Remarque: Les étapes suivantes décomposent un script d'environ 300 lignes. Les explications étant intégrées dans des morceaux de code, nous vous recommandons d'ouvrir le script complet dans un nouvel onglet afin de suivre le déroulement complet.

Vous aurez besoin de Python 3.11 ou d'une version ultérieure, ainsi que d'une connexion Internet stable. Étant donné que Tinker gère la formation GPU sur ses serveurs, il est plus important de disposer d'une bonne connexion Internet que d'un ordinateur puissant.

Veuillez commencer par vous connecter à la console Tinker et créer une clé API. Veuillez enregistrer cette clé dans un fichier .env situé dans le répertoire de votre projet :

TINKER_API_KEY=your_key_here

Une fois configurée, la console Tinker devient votre plateforme centrale pour surveiller les entraînements et gérer les points de contrôle.

Entraînements de Tinker

La console Tinker assure le cursus de toutes vos séances d'entraînement avec des informations clés : identifiants uniques, modèle de base, classement LoRA et heures des dernières requêtes. Vous pouvez rechercher, filtrer et gérer plusieurs expériences à partir de cette interface.

Veuillez installer les paquets requis. Tinker dépend de certains composants qui ne s'installent pas automatiquement. Veuillez donc les spécifier explicitement :

pip install tinker transformers torch datasets python-dotenv numpy

Les paquets transformers et torch fournissent les opérations de tokenisation et de tenseur utilisées en interne par Tinker. La bibliothèque datasets gère le chargement des données d'entraînement depuis Hugging Face.

Veuillez maintenant configurer vos importations et une fonction d'aide à la réessai. Lorsque vous vous entraînez sur des serveurs distants, il est possible que vous rencontriez des erreurs de connexion temporaires qui ne signifient pas nécessairement qu'il y ait un problème. Votre tâche de formation fonctionne toujours correctement sur l'infrastructure de Tinker. Ce wrapper de réessai gère automatiquement ces échecs transitoires :

import time
import numpy as np
from dotenv import load_dotenv
from datasets import load_dataset
import tinker
from tinker import types

def with_retry(future, max_attempts=3, delay=5):
    """Simple retry logic for API futures"""
    for attempt in range(max_attempts):
        try:
            return future.result()
        except Exception as e:
            if attempt == max_attempts - 1:
                raise
            time.sleep(delay)

Cette fonction récupère un objet futur (un objet représentant une opération qui n'est pas encore terminée) à partir de l'API de Tinker et tente d'obtenir le résultat jusqu'à trois fois, en attendant cinq secondes entre chaque tentative. La plupart des défaillances temporaires se résolvent dans ce délai.

Étape 2 : Veuillez initialiser le ServiceClient et charger l'ensemble de données.

Le site ServiceClient constitue votre point d'entrée vers Tinker. Il identifie les modèles disponibles et gère l'authentification :

load_dotenv()
service_client = tinker.ServiceClient()

Vous n'aurez pas besoin de l'utiliser fréquemment après cette configuration initiale. Il est principalement destiné à créer des clients d'entraînement et d'échantillonnage pour des modèles spécifiques.

Il est maintenant temps de charger l'ensemble de données FinCoT.  Il contient des questions financières accompagnées de raisonnements étape par étape et de réponses finales. Contrairement aux simples ensembles de données de questions-réponses, FinCoT enseigne au modèle à présenter son travail avant de fournir des réponses, une compétence importante pour les applications de conseil financier où les utilisateurs doivent comprendre le raisonnement qui sous-tend les recommandations.

dataset = load_dataset("TheFinAI/FinCoT")

Ensemble de données Tinker

L'ensemble de données comprend une division SFT (ajustement fin supervisé) avec des chaînes de raisonnement complètes et une division RL pour l'apprentissage par renforcement. Veuillez utiliser la division SFT pour l'entraînement et un échantillon de la division RL pour la validation afin de garantir que le modèle s'applique à différents exemples.

train_data_raw = dataset["SFT"]  # 7,686 examples with reasoning chains
val_data_raw = dataset["RL"].shuffle(seed=42).select(range(500))  # 500 validation examples

print(f"Loaded {len(train_data_raw)} training examples")
print(f"Loaded {len(val_data_raw)} validation examples")

Étape 3 : Veuillez créer votre client de formation LoRA.

Veuillez maintenant créer un client d'entraînement LoRA pour Qwen3-8B :

training_client = service_client.create_lora_training_client(
    base_model="Qwen/Qwen3-8B",
    rank=32
)

Analysons ce qui se passe ici :

  • Qwen/Qwen3-8B : Il s'agit d'un modèle comportant 8 milliards de paramètres, suffisamment puissant pour des tâches réelles, mais néanmoins efficace à former. C'est un excellent endroit pour apprendre. Vous pouvez consulter tous les modèles disponibles dans la gamme de modèles Tinker.
  • LoRA (adaptation de rang faible) : Au lieu de mettre à jour les 8 milliards de paramètres, LoRA forme de petites couches « adaptatrices » qui modifient le comportement du modèle de base. Considérez cela comme l'ajout d'objectifs personnalisés à un appareil photo plutôt que comme la reconstruction complète de l'appareil. Le modèle de base reste figé sur les serveurs de Tinker ; vous ne faites qu'entraîner ces petits adaptateurs.
  • rang=32 : Ceci détermine le nombre de paramètres entraînables contenus dans vos adaptateurs LoRA. Un rang de 32 convient parfaitement aux ensembles de données comprenant entre 5 000 et 10 000 exemples. Les ensembles de données plus volumineux peuvent nécessiter rank=64 ou rank=128 pour une plus grande capacité d'adaptation.

Pour approfondir vos connaissances sur le fonctionnement mathématique de LoRA et sur la manière d'ajuster les paramètres de rang, veuillez consulter le guide d'introduction à LoRA de Tinker ou le guide complet de DataCamp sur la maîtrise de l'adaptation de rang faible.

Les modèles linguistiques ne fonctionnent pas directement avec les mots. Ils fonctionnent avec des « jetons », qui représentent des fragments de texte. Un tokeniseur divise le texte en ces éléments. Par exemple, « financier » pourrait devenir un seul mot, tandis que « compréhension » pourrait être divisé en « compréhension » et « ». 

Le tokeniseur convertit le texte en chiffres (identifiants de jetons) que le modèle peut traiter. En obtenant le tokenizer auprès du client de formation, vous vous assurez d'utiliser exactement la même tokenisation que celle attendue par Qwen3-8B.

tokenizer = training_client.get_tokenizer()

Étape 4 : Transformez les données au format Tinker

Tinker requiert vos données d'entraînement dans un format appelé types.Datum. Ce format sépare les données d'entrée du modèle de la configuration de la fonction de perte, vous permettant ainsi de contrôler avec précision les jetons qui contribuent à l'entraînement.

Lors du réglage des modèles linguistiques, il est généralement souhaitable que le modèle apprenne à générer de bonnes réponses, plutôt que de mémoriser les questions. Pour ce faire, il convient d'attribuer des pondérations différentes aux différentes parties de l'entrée :

  • Jetons d'invite (la question) : Poids = 0,0 (n'en tirez pas de leçons)
  • Jetons d'achèvement (la réponse) : Poids = 1,0 (tirer des enseignements de ces éléments)

Construisons la fonction de transformation des données étape par étape. Commencez par la signature de la fonction :

def prepare_datum(example, max_length=10000):

Veuillez formater la conversation en utilisant le modèle de chat de Qwen3.

Différents modèles prévoient différents formats pour les conversations à plusieurs tours. Qwen3 utilise des jetons spéciaux tels que <|im_start|> et <|im_end|> pour marquer les limites des messages. Divisez chaque message en deux parties : les « observations » (en-têtes de rôle) et les « actions » (contenu réel) :

   # Qwen3 chat format - split into observation and action parts
    user_ob = "<|im_start|>user\n"
    user_ac = f"{example['Question']}<|im_end|>"
    
    assistant_ob = "\n<|im_start|>assistant\n"
    # Include both reasoning process AND final answer
    assistant_ac = f"{example['Reasoning_process']}\n\nFinal Answer: {example['Final_response']}<|im_end|>"

L'ensemble de données FinCoT fournit un raisonnement structuré, nous concaténons donc les champs Reasoning_process et Final_response. Cela enseigne au modèle à présenter son travail avant de répondre.

Veuillez tokeniser chaque partie séparément. 

Afin de déterminer où les pondérations doivent s'appliquer, chaque partie du message doit être tokenisée séparément.

   # Tokenize each part separately to track weight boundaries
    user_ob_tokens = tokenizer.encode(user_ob, add_special_tokens=False)
    user_ac_tokens = tokenizer.encode(user_ac, add_special_tokens=False)
    assistant_ob_tokens = tokenizer.encode(assistant_ob, add_special_tokens=False)
    assistant_ac_tokens = tokenizer.encode(assistant_ac, add_special_tokens=False)
    
    # Combine all tokens
    all_tokens = user_ob_tokens + user_ac_tokens + assistant_ob_tokens + assistant_ac_tokens

Veuillez filtrer les séquences trop longues.

Certains exemples de FinCoT comprennent des chaînes de raisonnement extrêmement détaillées qui dépassent la fenêtre contextuelle confortable de Qwen3-8B. Bien que le modèle prenne techniquement en charge 32 768 jetons, les séquences très longues peuvent entraîner une instabilité de l'entraînement :

   # Check if sequence exceeds max length
    if len(all_tokens) > max_length:
        return None  # Skip this example

Le filtrage des exemples contenant plus de 10 000 tokens ne supprime que 5 à 6 % des données, tout en améliorant considérablement la fiabilité de la formation.

Attribuer des pondérations pour contrôler ce que le modèle apprend à partir de

Définissez les pondérations sur 0,0 pour la question (afin que le modèle n'apprenne pas à prédire les questions) et sur 1,0 pour la réponse (afin qu'il apprenne à générer de bonnes réponses) :

   # Weights: only train on assistant's answer (action part)
    weights = np.array(
        [0.0] * len(user_ob_tokens) +
        [0.0] * len(user_ac_tokens) +
        [0.0] * len(assistant_ob_tokens) +
        [1.0] * len(assistant_ac_tokens)
    )

Jetons de décalage et pondérations pour la prédiction du jeton suivant

Les modèles linguistiques prédisent le prochain token dans une séquence. Lorsque le modèle identifie les jetons 0 à 9, il devrait prédire le jeton 10. Vos cibles sont donc toujours les entrées décalées d'une position vers l'avant :

   # CRITICAL: Shift tokens AND weights for next-token prediction
    input_tokens_model = all_tokens[:-1]
    target_tokens = all_tokens[1:]
    weights_shifted = weights[1:]

Il est important de noter que vous devez déplacer les poids en même temps que les jetons. Si vous ne modifiez pas les poids, le calcul de la perte sera incorrect : le modèle serait entraîné à prédire le premier jeton de réponse, mais le poids à cette position resterait égal à 0,0 à partir de l'invite. Ce problème d'alignement peut empêcher le modèle d'apprendre correctement.

Veuillez renvoyer les données formatées.

Enfin, la fonction prepare_datum() renvoie les données formatées, prêtes à être traitées.

   return types.Datum(
        model_input=types.ModelInput.from_ints(tokens=input_tokens_model),
        loss_fn_inputs=dict(weights=weights_shifted, target_tokens=target_tokens),
    )

En appliquant la fonction définie aux sous-ensembles bruts d'entraînement et de validation, nous pouvons désormais traiter l'ensemble complet des données :

# Process and filter training data
training_data_raw = [prepare_datum(example) for example in train_data_raw]
training_data = [d for d in training_data_raw if d is not None]
skipped = len(train_data_raw) - len(training_data)

print(f"Processed {len(training_data)} examples (skipped {skipped} too-long sequences)")
# Output: Processed 7,244 examples (skipped 442 too-long sequences)

# Process validation data
val_data_raw_processed = [prepare_datum(example) for example in val_data_raw]
val_data = [d for d in val_data_raw_processed if d is not None]

print(f"Validation set: {len(val_data)} examples")

Étape 5 : Entraîner le modèle à l'aide de la boucle d'entraînement

La boucle de formation utilise deux des primitives API principales de Tinker : forward_backward et optim_step. Construisons-le étape par étape avec un suivi de validation afin de détecter rapidement tout surajustement.

Définir une fonction de perte de validation

Tout d'abord, définissez une fonction de perte de validation. Contrairement à la perte d'entraînement, la perte de validation vous indique dans quelle mesure votre modèle généralise correctement à des données non observées. Ceci est essentiel pour détecter le surajustement.

def compute_validation_loss(val_data, batch_size=100):
    """Compute loss on validation set (forward only, no backward)"""
    batch_indices = np.random.choice(
        len(val_data), size=min(batch_size, len(val_data)), replace=False
    )
    batch = [val_data[i] for i in batch_indices]
    
    # Forward pass only (no backward!)
    fwd_future = training_client.forward(batch, loss_fn="cross_entropy")
    fwd_result = with_retry(fwd_future)
    
    # Calculate per-token loss
    loss_sum = fwd_result.metrics["loss:sum"]
    total_completion_tokens = sum(
        np.sum(np.array(val_data[i].loss_fn_inputs["weights"].data) > 0)
        for i in batch_indices
    )
    return loss_sum / total_completion_tokens if total_completion_tokens > 0 else 0

La méthode d'évaluation sans gradient ( forward() ) calcule la perte sans calculer les gradients, ce qui la rend efficace pour l'évaluation lorsque vous avez uniquement besoin de mesurer les performances, sans mettre à jour les poids. Le calcul de la perte de validation ajoute une surcharge minimale (il s'agit simplement d'un passage en avant, sans calcul de gradient), mais fournit une alerte précoce lorsque l'écart entre la perte d'entraînement et la perte de validation dépasse 0,2, indiquant que votre modèle mémorise plutôt qu'il n'apprend.

Configurer les paramètres de formation

Il est nécessaire de définir le nombre d'époques ainsi que le taux d'apprentissage. LoRA nécessite des taux d'apprentissage nettement plus élevés que le réglage fin complet, généralement 10 à 20 fois plus importants.

# Training configuration
n_samples = len(training_data)  # 7,244
n_epochs = 4  # More epochs for smaller dataset
batch_size = 32

# Calculate optimal LR for Qwen3-8B with LoRA
# Formula: base_lr * lora_multiplier * (2000 / hidden_size) ** exponent
# For Qwen: base=5e-5, multiplier=10, hidden_size=4096, exponent=0.0775
learning_rate = 5e-5 * 10.0 * (2000 / 4096) ** 0.0775  # ≈ 4.7e-4

La formule tient compte de la taille du modèle (Qwen3-8B a une taille cachée de 4 096) et utilise des exposants déterminés empiriquement qui varient selon la famille de modèles, comme indiqué dans le livre de recettes Tinker. Pour les modèles Qwen, l'exposant est de 0,0775, tandis que les modèles Llama utilisent 0,781. Dans notre cas, cela produit un taux d'apprentissage d'environ 4,7e-4, assurant une convergence stable sans explosion du gradient.

Configurer le préchauffage du taux d'apprentissage

Commencer avec un taux d'apprentissage maximal peut entraîner des explosions de gradient au début de l'entraînement, lorsque le modèle ne s'est pas encore adapté à la tâche. Le réchauffement augmente progressivement le taux d'apprentissage de près de zéro à la valeur cible au cours des 200 premières itérations. Ceci est clairement illustré dans la visualisation de l'entraînement présentée précédemment, où le taux d'apprentissage (ligne verte) augmente progressivement au cours des 200 premières itérations.

# Warmup configuration
warmup_steps = 200

# Calculate iterations from epochs
num_iterations = n_epochs * (n_samples // batch_size)  # 4 * 226 = 904
checkpoint_interval = 200
validation_interval = 50

Veuillez démarrer la boucle d'entraînement.

Après avoir initialisé les listes pour suivre les pertes, nous pouvons commencer la boucle d'entraînement :

losses = []
per_token_losses = []
val_losses = []

for iteration in range(num_iterations):
    # Sample random batch
    batch_indices = np.random.choice(len(training_data), size=batch_size, replace=False)
    batch = [training_data[i] for i in batch_indices]
    
    # Apply learning rate warmup
    if iteration < warmup_steps:
        current_lr = learning_rate * (iteration + 1) / warmup_steps
    else:
        current_lr = learning_rate

La logique de préchauffage augmente progressivement le taux d'apprentissage au cours des 200 premières itérations, ce qui permet d'éviter une instabilité précoce.

Appeler les primitives de formation de base de Tinker

À chaque itération, les primitives de base de Tinker sont appelées comme suit :

   # API Primitive 1: forward_backward - compute gradients
    fwdbwd_future = training_client.forward_backward(batch, loss_fn="cross_entropy")

    # API Primitive 2: optim_step - update parameters
    optim_future = training_client.optim_step(types.AdamParams(learning_rate=current_lr))

    # Wait for results with retry logic
    fwdbwd_result = with_retry(fwdbwd_future)
    optim_result = with_retry(optim_future)

forward_backward calcule les gradients en déterminant l'erreur des prédictions du modèle et la direction dans laquelle chaque paramètre doit être ajusté. Il utilise la perte de cross-entropie, qui mesure dans quelle mesure la distribution de probabilité prédite par le modèle correspond aux tokens suivants réels. L' optim_step e met à jour les paramètres du modèle en fonction de ces gradients à l'aide de l'optimiseur Adam.

Veuillez noter que les deux méthodes renvoient immédiatement des objets « futurs ». Cela permet à Tinker de traiter plusieurs opérations simultanément, ce qui accélère le processus. L'appel de with_retry(future) attend que cette opération spécifique soit terminée.

Cursus et afficher les indicateurs de perte

Nous calculons les pertes totales et par jeton et les ajoutons aux listes respectives :

   # Track loss
    loss_sum = fwdbwd_result.metrics["loss:sum"]
    total_completion_tokens = sum(
        np.sum(np.array(training_data[i].loss_fn_inputs["weights"].data) > 0)
        for i in batch_indices
    )
    per_token_loss = loss_sum / total_completion_tokens

    losses.append(loss_sum)
    per_token_losses.append(per_token_loss)

    if iteration % 10 == 0:
        warmup_indicator = "🔥" if iteration < warmup_steps else ""
        print(f"{warmup_indicator} Iteration {iteration} | Train: {per_token_loss:.4f} | LR: {current_lr:.6f}")

La perte par jeton normalise la perte en fonction du nombre de jetons de réponse, ce qui facilite l'interprétation pour différentes tailles de lots. Un bon cycle d'entraînement commence généralement avec une perte par jeton comprise entre 1,2 et 1,5, puis diminue pour passer sous la barre des 0,8 au point de contrôle 400. Si votre perte commence au-dessus de 2,0 ou ne diminue pas après 50 itérations, veuillez vérifier la préparation de vos données et le taux d'apprentissage.

Intégrer des contrôles de validation et des points de contrôle périodiques

En enregistrant les poids toutes les 200 itérations, vous créez des instantanés que vous pouvez comparer. Comme vous avez pu le constater dans les résultats de l'entraînement précédents, le point de contrôle 400 présente une meilleure généralisation que le point de contrôle final, malgré une perte d'entraînement plus élevée. Veuillez toujours enregistrer plusieurs points de contrôle et les évaluer sur des données conservées. Les points de contrôle restent actifs sur les serveurs de Tinker une fois votre script terminé.

   # Compute validation loss periodically
    if iteration % validation_interval == 0:
        val_loss = compute_validation_loss(val_data)
        val_losses.append((iteration, val_loss))
        gap = val_loss - per_token_loss
        print(f"  📊 Iteration {iteration} | Train: {per_token_loss:.4f} | Val: {val_loss:.4f} | Gap: {gap:+.4f}")

    # Checkpoint every 200 iterations
    if iteration > 0 and iteration % checkpoint_interval == 0:
        training_client.save_weights_for_sampler(name=f"fincot-checkpoint-{iteration}")

Points de contrôle Tinker

Tinker classe les points de contrôle en deux catégories : les points de contrôle complets (pour reprendre l'entraînement en cas d'interruption) et les poids d'échantillonnage (points de contrôle légers pour l'inférence). Veuillez noter que le point de contrôle 400 apparaît dans les deux formats, ce qui facilite la poursuite de l'entraînement et le déploiement du modèle.

Si votre session d'entraînement est interrompue, vous pouvez la reprendre à partir de n'importe quel point de contrôle enregistré en utilisant les poids d'état complet, ce qui vous permet de poursuivre l'entraînement sans avoir à recommencer depuis le début.

Pour obtenir une référence API complète sur ces méthodes, veuillez consulter la documentation relative à la formation et à l'échantillonnage de Tinker.

Étape 6 : Veuillez enregistrer votre modèle optimisé.

Une fois la formation terminée, veuillez enregistrer les poids du modèle final :

sampling_client = training_client.save_weights_and_get_sampling_client(
    name="financial-qa-qwen3-8b-lora"
)

Les poids sont enregistrés sur les serveurs de Tinker, et non sur votre ordinateur. Les adaptateurs LoRA ne nécessitent généralement que quelques dizaines de mégaoctets. Tinker peut éventuellement les exporter pour une utilisation avec des fournisseurs d'inférence externes si vous souhaitez déployer le modèle en dehors de leur infrastructure.

Étape 7 : Veuillez tester le modèle à l'aide d'exemples de questions.

Enfin, veuillez tester votre modèle ajusté à l'aide de la primitive API sample. Tout d'abord, veuillez configurer les paramètres d'échantillonnage :

sampling_params = types.SamplingParams(
    max_tokens=200,
    temperature=0.7,
    top_p=0.9,
    stop_sequences=["<|im_end|>"]
)

Veuillez permettre l'explication de ces paramètres :

  • max_tokens: Longueur maximale de la réponse générée (200 jetons correspondent à environ 150 mots).
  • temperature: Contrôle le caractère aléatoire de la génération. Des valeurs plus faibles (0,1-0,5) rendent le résultat plus ciblé et déterministe ; des valeurs plus élevées (0,7-1,0) permettent une plus grande créativité. Une valeur de 0,7 permet d'équilibrer cohérence et diversité.
  • top_p (échantillonnage du noyau) : Ne prend en compte que l'ensemble le plus petit de jetons dont la probabilité cumulative dépasse cette valeur. 0,9 signifie « ne prendre en compte que les jetons qui représentent ensemble 90 % de la masse de probabilité ». Cela empêche le modèle de sélectionner des tokens peu probables.
  • stop_sequences: Indique au modèle d'arrêter la génération lorsqu'il atteint cette séquence. <|im_end|> est le marqueur de fin de séquence.

Générer des réponses pour les questions du test :

questions = [
    "What are the main risks associated with investing in stocks?",
    "How does diversification help reduce portfolio risk?"
]

for question in questions:
    model_input = types.ModelInput.from_ints(tokenizer.encode(question))

    response = with_retry(
        sampling_client.sample(
            prompt=model_input,
            num_samples=1,
            sampling_params=sampling_params
        )
    )

    answer = tokenizer.decode(response.sequences[0].tokens)
    print(f"Q: {question}")
    print(f"A: {answer}\n")

Voici deux exemples de résultats obtenus à partir du modèle optimisé (tronqués à des fins d'illustration) :

Q: What are the main risks associated with investing in stocks?
A: Investing in stocks carries several key risks. Market risk represents the potential for stock prices to decline due to economic downturns or market volatility. Company-specific risk arises from poor management decisions, competitive pressures, or operational failures that affect individual stocks. Liquidity risk occurs when you cannot sell shares quickly without significantly impacting the price. Additionally, investors face inflation risk, where returns may not keep pace with rising prices...

Q: How does diversification help reduce portfolio risk?
A: Diversification reduces portfolio risk by spreading investments across different asset classes, sectors, and geographic regions. When you hold multiple uncorrelated assets, losses in one investment can be offset by gains in others. For example, if technology stocks decline but healthcare stocks rise, a diversified portfolio experiences less volatility than one concentrated in technology alone. The key principle is that different assets respond differently to market conditions...

L'objet de réponse contient une liste d'sequences s, car il est possible de demander plusieurs échantillons par invite. Veuillez accéder aux jetons via sequences[0].tokens et les décoder en texte à l'aide du même tokenizer.

Vous avez maintenant démontré avec succès les quatre primitives API principales :

  1. forward_backward: Calculez les gradients à partir de vos données d'entraînement.
  2. optim_step: Mettre à jour les paramètres du modèle à l'aide de l'optimiseur Adam
  3. save_weights_and_get_sampling_client: Conservez votre modèle optimisé
  4. sample: Générer des prédictions à partir du modèle ajusté

Ce même modèle de flux de travail s'étend à des paradigmes de formation plus avancés. Pour l'apprentissage par renforcement ou l'optimisation des préférences, vous utiliseriez les mêmes primitives, mais avec des fonctions de perte et des formats de données différents. Si vous souhaitez aligner les modèles sur les préférences humaines, veuillez vous renseigner sur les techniques de réglage fin des préférences, qui reposent sur les mêmes principes. Le livre de recettes Tinker fournit des exemples pour ces scénarios avancés.

Cependant, comment savoir si ces ajustements ont réellement amélioré les performances ? Plutôt que de vous fier à des impressions subjectives, il est nécessaire de procéder à une évaluation rigoureuse. Dans la section suivante, vous découvrirez les résultats d'une évaluation LLM-as-judge qui compare le modèle optimisé au modèle de base Qwen3-8B sur 10 questions financières diverses.

Évaluation du modèle affiné à l'aide d'un juge LLM

Afin de mesurer objectivement les performances, nous avons utilisé LLM-as-judge : GPT-4o a évalué Checkpoint-400 par rapport à la base Qwen3-8B sur 10 questions financières diverses, en notant chaque réponse en fonction de son exactitude, de sa clarté, de son exhaustivité et de sa terminologie financière.

Le modèle optimisé a obtenu une note de 8,5/10, contre 6,5 pour le modèle de base, remportant ainsi les 10 comparaisons. Les verdicts révèlent pourquoi : il fournit des explications complètes avec un raisonnement structuré et assuré, tandis que la base se contente de « je pense » et « peut-être », laissant les pensées incomplètes.

Cela confirme les performances supérieures du checkpoint-400 dans des conditions réelles. La perte d'entraînement plus faible à l'itération 900 nous aurait permis d'obtenir une mémorisation, et non un raisonnement.

Veuillez consulter le script de comparaison et les résultats détaillés afin de réaliser des évaluations similaires sur vos modèles.

Conclusion

Vous avez constaté comment Tinker simplifie le réglage fin sans compromettre le contrôle. Quatre primitives API principales, forward_backward, optim_step, save_weights_and_get_sampling_client et sample, vous fournissent les éléments de base pour créer des workflows de formation personnalisés, tandis que Tinker gère l'infrastructure distribuée.

Le modèle financier Q&A que nous avons élaboré illustre les meilleures pratiques de production : le suivi de la validation a permis de détecter rapidement le surapprentissage, le checkpoint-400 a surpassé le modèle final en se concentrant sur la généralisation, et l'évaluation LLM-as-judge a confirmé une amélioration de 2 points par rapport au modèle de base. Ces modèles s'appliquent que vous ajustiez des modèles à 8 milliards ou à 70 milliards de paramètres.

La plateforme est actuellement en version bêta avec accès sur liste d'attente, mais les concepts que vous avez appris s'appliquent directement une fois que vous y avez accès. Les entraînements que j'ai effectués pour ce tutoriel (y compris ceux qui ont échoué et ceux qui étaient expérimentaux) ont coûté 150 crédits de départ. Avec les crédits initiaux, vous pouvez donc suivre ce tutoriel 6 fois et effectuer des expériences supplémentaires, ce qui vous laisse beaucoup de temps pour apprendre et itérer sur vos propres projets de réglage fin.

Quelle est la prochaine étape ? Nous vous recommandons d'affiner vos données spécifiques à votre domaine, d'expérimenter différents rangs LoRA et taux d'apprentissage, ou d'explorer des paradigmes d'entraînement avancés tels que l'apprentissage par renforcement à partir des commentaires humains. Le livre de recettes Tinker fournit des exemples pour ces scénarios. Commencez dès maintenant à réfléchir à votre cas d'utilisation : quel comportement souhaitez-vous que votre modèle apprenne ?

Si vous souhaitez développer des compétences plus étendues dans la formation et le réglage des derniers modèles d'IA pour la production, nous vous invitons à consulter le cursus Ingénieur IA associé pour les développeurs.


Bex Tuychiev's photo
Author
Bex Tuychiev
LinkedIn

Je suis un créateur de contenu en science des données avec plus de 2 ans d'expérience et l'un des plus grands followings sur Medium. J'aime écrire des articles détaillés sur l'IA et la ML dans un style un peu sarcastıc, car il faut bien faire quelque chose pour les rendre un peu moins ennuyeux. J'ai produit plus de 130 articles et un cours DataCamp, et un autre est en cours d'élaboration. Mon contenu a été vu par plus de 5 millions de personnes, dont 20 000 sont devenues des adeptes sur Medium et LinkedIn. 

Sujets

Cours d'ingénierie en intelligence artificielle

Cursus

Développer des applications d'IA

21 h
Apprenez à créer des applications alimentées par l'IA avec les derniers outils de développement d'IA, notamment l'API OpenAI, Hugging Face et LangChain.
Afficher les détailsRight Arrow
Commencer le cours
Voir plusRight Arrow
Contenus associés

blog

Comprendre les TPU et les GPU dans l'IA : Un guide complet

L'essor du développement de l'intelligence artificielle (IA) a entraîné une augmentation notable de la demande en matière de calcul, d'où la nécessité de disposer de solutions matérielles robustes. Les unités de traitement graphique (GPU) et les unités de traitement tensoriel (TPU) sont devenues des technologies essentielles pour répondre à ces demandes.
Kurtis Pykes 's photo

Kurtis Pykes

9 min

blog

Types d'agents d'intelligence artificielle : Comprendre leurs rôles, leurs structures et leurs applications

Découvrez les principaux types d'agents d'intelligence artificielle, comment ils interagissent avec les environnements et comment ils sont utilisés dans les différents secteurs d'activité. Comprendre les agents réflexes simples, les agents basés sur un modèle, les agents basés sur un but, les agents basés sur l'utilité, les agents d'apprentissage, etc.
Vinod Chugani's photo

Vinod Chugani

14 min

blog

Architecture de l'entrepôt de données : Tendances, outils et techniques

Apprenez l'essentiel de l'architecture d'un entrepôt de données, des composants clés aux meilleures pratiques, pour construire un système de données évolutif et efficace !
Kurtis Pykes 's photo

Kurtis Pykes

15 min

cursor ai code editor

Tutoriel

Cursor AI : Un guide avec 10 exemples pratiques

Apprenez à installer Cursor AI sur Windows, macOS et Linux, et découvrez comment l'utiliser à travers 10 cas d'utilisation différents.

Tutoriel

Normalisation vs. Standardisation: comment faire la différence

Découvrez les principales différences, les applications et la mise en œuvre de la normalisation et de la standardisation dans le prétraitement des données pour l’apprentissage automatique.
Samuel Shaibu's photo

Samuel Shaibu

Voir plusVoir plus