Le framework Coconut (Chain of Continuous Thought) introduit une approche novatrice pour le raisonnement des grands modèles de langage (LLM). Contrairement aux méthodes Chain-of-Thought (CoT) classiques qui s'appuient sur des étapes intermédiaires en langage naturel, Coconut effecteu son raisonnement dans un espace latent continu. Ce paradigme viserait à atténuer les pertes d'information dues à la discrétisation en texte et à permettre des processus de raisonnement plus fluides.
Principe Fondamental : Les Jetons Latents
Le mécanisme central repose sur des jetons latents (latent tokens). Ces vecteurs continus, générés par le modèle, ne correspondent pas à des mots du vocabulaire. Ils servent de véhicules pour transporter l'état interne du raisonnement à travers les couches du réseau. L'architecture implémente une boucle de rétroaction bidirectionnelle où les états latents calculés lors d'une passe influencent les représentations en entrée des passes suivantes, créant ainsi un processus d'itération sur la pensée.
Implémentation Technique
L'implémentation encapsule cette logique dans une classe Python qui enveloppe un modèle causal de base. L'initialisation configure les identifiants spéciaux pour délimiter et insérer les séquences de raisonnement latent.
class ModèleCoconut(nn.Module):
def __init__(self, modèle_de_base, id_jeton_latent, id_début_latent, id_fin_latent):
super().__init__()
self.modèle = modèle_de_base
self.id_latent = id_jeton_latent
self.id_début = id_début_latent
self.id_fin = id_fin_latent
self.couche_embed = self.modèle.get_input_embeddings()
La passe avant (forward) est le cœur de l'opération. Elle identifie les positions des jetons latents dans la séquence d'entrée et remplace leur représentation par la sortie de la couche cachée précédente, matérialisant ainsi la boucle de rétroaction continue.
def forward(self, ids_entrée, masque_attention, **kwargs):
embeds = self.couche_embed(ids_entrée)
positions_latentes = (ids_entrée == self.id_latent).nonzero(as_tuple=True)
# Simulation de la boucle de rétroaction
états_cachés_précédents = None
for tour in range(nb_tours_raisonnement):
sorties = self.modèle(inputs_embeds=embeds, attention_mask=masque_attention)
nouveaux_états = sorties.last_hidden_state
# Mise à jour conditionnelle des embeddings pour les jetons latents
if tour < nb_tours_raisonnement - 1:
for lot, idx in zip(*positions_latentes):
# On injecte l'état précédent dans l'embedding du jeton latent actuel
embeds[lot, idx] = nouveaux_états[lot, idx - 1]
return sorties
La phase de génération (generate) initie le processus avec la méthode forward pour obtenir la représentation latente complète, puis procède à la décodage de la réponse finale en utilisent le modèle de base de manière itérative jusqu'à produire un jeton de fin de séquence.
Démarrage et Préparation des Données
Pour l'expérimentation, l'environnement se prépare en installant les dépendances Python requises. Les jeux de données, comme GSM8K, nécessitent un prétraitement spécifique pour injecter les marqueurs de début et de fin de raisonnement latent autour des séquences de pensée.
pip install torch transformers
# Prétraitement d'exemple pour une tâche arithmétique
python scripts/prétraiter_données.py --ensemble gsm8k --config configs/coconut_gsm.json
L'entraînement s'effectue via un script de lancement qui charge la configuration et le jeu de données prétraité. Les hyperparamètres critiques incluent le nombre d'étapes de raisonnement latent et la température de la rétroaction.
python entraîner.py --config configs/entraînement_coconut.yaml