Install coconut-pytorch
mainInstall the package using pip:
$ pip install coconut-pytorchrepository·main·Indexed 41 days ago
https://github.com/lucidrains/coconut-pytorchA PyTorch implementation of the Coconut architecture, enabling Large Language Models to reason within a continuous latent space. Version 0.0.32 features recurrent latent reasoning, multi-stream hypothesis support, and a specialized Transformer backbone with value residual mixing. It includes the Coconut class for training and generation, as well as utility functions for Min-P filtering and Gumbel sampling.
Install the package using pip:
$ pip install coconut-pytorchThe Coconut class implements the architecture proposed in the paper "Training Large Language Models to Reason in a Continuous Latent Space".
Initialize the model by specifying the number of reasoning steps, the number of latents per step, and a dictionary defining the transformer architecture parameters (num_tokens, dim, and depth).
Pass a prompt and an answer tensor to the model instance to compute the loss. The model supports standard PyTorch backpropagation via loss.backward().
After training, use the .generate() method to produce an answer from a given prompt by specifying max_length.
import torch
from coconut_pytorch import Coconut
model = Coconut(
num_reasoning_steps = 3,
num_latents_per_step = 1,
transformer = dict(
num_tokens = 256,
dim = 512,
depth = 6
)
)
prompt = torch.randint(0, 256, (2, 1024))
answer = torch.randint(0, 256, (2, 64))
# Training step
loss = model(prompt, answer)
loss.backward()
# Generation step
answer = model.generate(prompt, max_length = 64) # (2, 64)When num_hypothesis > 1 is set in the Coconut class, the model implements a multi-stream reasoning process:
to_streams.synthesize_hypothesis_per_step is True, the streams interact via a synthesis layer during each step.hyp_diff_loss can be applied to encourage the different hypothesis streams to represent different latent states (using cosine similarity).merge_streams before the final answer generation.The Coconut class is the primary interface for the library.
__call__(prompt, answer)Computes the loss for a given prompt and target answer.
prompt: Tensor of shape (batch, prompt_length) containing token indices.answer: Tensor of shape (batch, answer_length) containing target token indices.generate(prompt, max_length)Generates an answer sequence from the provided prompt.
prompt: Tensor of shape (batch, prompt_length).max_length: Integer specifying the maximum number of tokens to generate.(batch, max_length) containing the generated token indices.# Example of the API usage
model = Coconut(num_reasoning_steps=3, num_latents_per_step=1, transformer=dict(num_tokens=256, dim=512, depth=6))
loss = model(prompt, answer)
answer = model.generate(prompt, max_length=64)The Transformer class is the backbone of the Coconut model. It supports multiple residual streams and a specialized attention mechanism that allows for value residual mixing.
Key parameters:
num_tokens: Vocabulary size.dim: Model dimension.depth: Number of layers.num_residual_streams: Number of parallel residual streams (uses hyper-connections to expand/reduce).accept_value_residual: If True, enables the Attention mechanism to mix in a value_residual from the previous layer, which is critical for the Coconut reasoning mechanism.Inputs can be a single Tensor of integer tokens [b n] or a list of Tensors (e.g., combining discrete tokens and continuous embeddings).
from coconut_pytorch.coconut import Transformer
import torch
model = Transformer(
num_tokens=5000,
dim=512,
depth=6,
num_residual_streams=4,
accept_value_residual=True
)
# Input can be integer tokens
x = torch.randint(0, 5000, (2, 10))
logits = model(x)The generate method performs autoregressive generation following the latent reasoning phase. It handles the transition from the prompt to the latent reasoning tokens and finally to the answer tokens.
Arguments:
prompt: The input sequence (Tensor).max_length: Maximum number of answer tokens to generate.filter_fn: A function to filter logits (defaults to min_p_filter).temperature: Sampling temperature.**forward_kwargs: Additional arguments passed to the model's forward pass.# Generate an answer from a prompt
output_tokens = model.generate(
prompt,
max_length=20,
temperature=0.8
)The Coconut class implements a model architecture that performs recurrent latent reasoning. It uses a Transformer backbone to process a prompt, then enters a reasoning phase where it iteratively updates latent tokens (thoughts) before generating an answer.
Key features include:
num_reasoning_steps.num_hypothesis > 1, the model can maintain multiple independent latent streams (hypotheses) that are merged at the end of the reasoning phase.begin_of_thought and end_of_thought tokens to demarcate the reasoning phase.begin_thought_loss (to teach the model when to start thinking) and hyp_diff_loss (to encourage diversity among multiple hypotheses).from coconut_pytorch.multi_stream_coconut import Coconut, Transformer
# Define transformer configuration
transformer_config = {
'num_tokens': 50000,
'dim': 512,
'depth': 12,
'num_residual_streams': 4
}
# Initialize Coconut model
model = Coconut(
num_reasoning_steps=5,
transformer=transformer_config,
num_latents_per_step=1,
num_hypothesis=3, # Enables multiple latent streams
learn_begin_of_thought=True,
hyp_diff_loss_weight=0.1
)
# Forward pass with prompt and answer
# prompt: Tensor of shape [batch, seq_len]
# answer: Tensor of shape [batch, seq_len]
loss, (loss_breakdown, prompt_logits, latent_tokens, answer_logits, cached_kv) = model(prompt, answer=answer)
# Backward pass
loss.backward()The Attention class implements causal attention with an optional learned_value_residual_mixing mechanism. This allows the model to interpolate between the current attention output and a provided value_residual.
When accept_value_residual=True is passed to the Attention constructor (or the Transformer), the forward method accepts a value_residual argument. This is used during the Coconut reasoning steps to pass information through the layers via the residual stream.
# Inside the Attention.forward call:
# out, (cached_kv, orig_v) = self.forward(
# x,
# value_residual=value_residual,
# ...
# )The Transformer class is the core engine used by Coconut. It supports multiple residual streams via hyper-connections.
Key parameters:
num_tokens: Vocabulary size.dim: Embedding dimension.depth: Number of layers.dim_head: Dimension of each attention head.heads: Number of attention heads.ff_mult: Multiplier for the feedforward dimension.num_residual_streams: Number of parallel residual streams (used for hyper-connections).from coconut_pytorch.multi_stream_coconut import Transformer
transformer = Transformer(
num_tokens=50000,
dim=512,
depth=12,
heads=8,
num_residual_streams=4
)The gumbel_sample function performs sampling from a distribution using the Gumbel-max trick, which is useful for differentiable-like discrete sampling.
Args:
t: Input logits.temperature: Sampling temperature.dim: Dimension to sample over.keepdim: Whether to keep the dimension.Returns: The index of the sampled token.
from coconut_pytorch.coconut import gumbel_sample
import torch
logits = torch.randn(1, 100)
sampled_idx = gumbel_sample(logits, temperature=1.0)The Coconut class is a wrapper around a Transformer that implements recurrent latent reasoning. It uses special <bot> (begin of thought) and <eot> (end of thought) tokens to facilitate reasoning steps in a continuous latent space.
Key features:
num_reasoning_steps) where the last hidden state of one step is passed as input to the next, while keeping the prompt's KV cache constant.num_latents_per_step to extend the paper's implementation.<bot> token via learn_begin_of_thought and uses gradient checkpointing to save memory during long reasoning chains..generate() method for autoregressive decoding after the reasoning phase.from coconut_pytorch.coconut import Coconut, Transformer
import torch
# Define transformer configuration
transformer_config = {
'num_tokens': 5000,
'dim': 512,
'depth': 6,
}
# Initialize Coconut wrapper
model = Coconut(
num_reasoning_steps=4,
transformer=transformer_config,
num_latents_per_step=1,
learn_begin_of_thought=True,
checkpoint=True
)
# Example forward pass with prompt and answer
prompt = torch.randint(0, 5000, (2, 10))
answer = torch.randint(0, 5000, (2, 15))
total_loss, (loss_breakdown, prompt_logits, latent_tokens, answer_logits, cached_kv) = model(
prompt=prompt,
answer=answer,
return_loss=True
)The .generate() method performs the full Coconut reasoning cycle followed by autoregressive token sampling.
Parameters:
prompt: The input token sequence.max_length: Number of tokens to generate after reasoning.filter_fn: A function to filter logits (defaults to min_p_filter).temperature: Sampling temperature.**forward_kwargs: Additional arguments passed to the model's forward pass.Returns the sampled token sequence.
# Assuming 'model' is an initialized Coconut instance
prompt = torch.randint(0, 5000, (1, 10))
generated_tokens = model.generate(
prompt,
max_length=20,
temperature=0.8,
filter_fn=min_p_filter
)