# RWKV

## Aperçu

Le modèle RWKV (version 4) a été proposé dans [ce dépôt](https://github.com/BlinkDL/RWKV-LM)

Elle propose une modification de l’attention du Transformer traditionnel pour la rendre linéaire. De cette façon, le modèle peut être utilisé comme un réseau récurrent : transmettre les entrées des horodatages 0 et 1 ensemble est équivalent à transmettre d’abord les entrées de l’horodatage 0, puis les entrées de l’horodatage 1 accompagnées de l’état de l’horodatage 0 (voir l’exemple ci-dessous).

Cela peut être plus efficace qu'un Transformer classique et peut traiter des phrases de n'importe quelle longueur (même si le modèle utilise une longueur de contexte fixe pour l'entraînement).

Ce modèle a été contribué par [sgugger](https://huggingface.co/sgugger). Le code d'origine peut être trouvé [ici](https://github.com/BlinkDL/RWKV-LM).

## Exemple d'utilisation

```python
import torch

from transformers import AutoTokenizer, RwkvModel

model = RwkvModel.from_pretrained("sgugger/rwkv-430M-pile", device_map="auto")
tokenizer = AutoTokenizer.from_pretrained("sgugger/rwkv-430M-pile")

inputs = tokenizer("This is an example.", return_tensors="pt").to(model.device)
# Feed everything to the model
outputs = model(inputs["input_ids"])
output_whole = outputs.last_hidden_state

outputs = model(inputs["input_ids"][:, :2])
output_one = outputs.last_hidden_state

# Using the state computed on the first inputs, we will get the same output
outputs = model(inputs["input_ids"][:, 2:], state=outputs.state)
output_two = outputs.last_hidden_state

torch.allclose(torch.cat([output_one, output_two], dim=1), output_whole, atol=1e-5)
```

Si vous souhaitez vous assurer que le modèle cesse de générer lorsque `'\n\n'` est détecté, nous recommandons d'utiliser les critères d'arrêt suivants :

```python
from transformers import StoppingCriteria

class RwkvStoppingCriteria(StoppingCriteria):
    def __init__(self, eos_sequence = [187,187], eos_token_id = 537):
        self.eos_sequence = eos_sequence
        self.eos_token_id = eos_token_id

    def __call__(self, input_ids: torch.LongTensor, scores: torch.Tensor, **kwargs) -> bool:
        last_2_ids = input_ids[:,-2:].tolist()
        return self.eos_sequence in last_2_ids

output = model.generate(inputs["input_ids"], max_new_tokens=64, stopping_criteria = [RwkvStoppingCriteria()])
```

## Notes

- Utilisez le padding à gauche pour la génération par lots. Voir [Padding side](../llm_tutorial#padding-side).

## RwkvConfig[[transformers.RwkvConfig]]

#### transformers.RwkvConfig[[transformers.RwkvConfig]]

```python
transformers.RwkvConfig(transformers_version: str | None = None, architectures: list[str] | None = None, output_hidden_states: bool | None = False, return_dict: bool | None = True, dtype: str | torch.dtype | None = None, chunk_size_feed_forward: int = 0, is_encoder_decoder: bool = False, id2label: dict[int, str] | dict[str, str] | None = None, label2id: dict[str, int] | dict[str, str] | None = None, problem_type: Literal['regression', 'single_label_classification', 'multi_label_classification'] | None = None, vocab_size: int = 50277, context_length: int = 1024, hidden_size: int = 4096, num_hidden_layers: int = 32, attention_hidden_size: int | None = None, intermediate_size: int | None = None, layer_norm_epsilon: float = 1e-05, bos_token_id: int | None = 0, eos_token_id: int | list[int] | None = 0, rescale_every: int = 6, tie_word_embeddings: bool = False, use_cache: bool = True)
```

[Source](https://github.com/huggingface/transformers/blob/main/src/transformers/models/rwkv/configuration_rwkv.py#L25)

**Paramètres :**

vocab_size (`int`, *facultatif*, valeur par défaut `50277`) : Taille du vocabulaire du modèle. Définit le nombre de jetons différents qui peuvent être représentés par `input_ids`.

context_length (`int`, *facultatif*, valeur par défaut : 1024) : La longueur de séquence maximale avec laquelle ce modèle peut être utilisé lors d'un seul passage avant (son utilisation en mode RNN permet d'utiliser n'importe quelle longueur de séquence).

hidden_size (`int`, *facultatif*, valeur par défaut `4096`) : Dimension des représentations cachées.

num_hidden_layers (`int`, *facultatif*, valeur par défaut `32`) : Nombre de couches cachées dans le décodeur Transformer.

attention_hidden_size (`int`, *facultatif*) : Dimension des états cachés de l'attention. Par défaut, elle vaut `hidden_size` si non définie.

intermediate_size (`int`, *facultatif*) : Dimension des représentations MLP.

layer_norm_epsilon (`float`, *facultatif*, valeur par défaut `1e-05`) : L'épsilon utilisé par les couches de normalisation de couche.

bos_token_id (`int`, *facultatif*, valeur par défaut `0`) : Identifiant du jeton utilisé pour le début de flux dans le vocabulaire.

eos_token_id (`Union[int, list[int]]`, *facultatif*, valeur par défaut `0`) : Identifiant de jeton utilisé pour la fin de flux dans le vocabulaire.

rescale_every (`int`, *facultatif*, valeur par défaut : 6) : Lors de l'inférence, les états cachés (ainsi que les poids des couches de sortie correspondantes) sont divisés par 2 toutes les `rescale_every` couches. Si la valeur est définie sur 0 ou un nombre négatif, aucun rééchelonnement n'est effectué.

tie_word_embeddings (`bool`, *facultatif*, valeur par défaut `False`) : Indique s'il faut lier les embeddings de poids selon la correspondance `tied_weights_keys` du modèle.

use_cache (`bool`, *facultatif*, valeur par défaut `True`) : Indique si le modèle doit retourner les dernières attentions clés/valeurs (non utilisé par tous les modèles). Pertinent uniquement si `config.is_decoder=True` ou si le modèle est un modèle génératif de type décodeur uniquement.

Ceci est la classe de configuration destinée à stocker la configuration d'un RwkvModel. Elle est utilisée pour instancier un modèle Rwkv en fonction des arguments spécifiés, en définissant l'architecture du modèle. L'instanciation d'une configuration avec les valeurs par défaut produira une configuration similaire à celle de [RWKV/rwkv-4-169m-pile](https://huggingface.co/RWKV/rwkv-4-169m-pile)

Les objets de configuration héritent de [PreTrainedConfig](/docs/transformers/main/fr/main_classes/configuration#transformers.PreTrainedConfig) et peuvent être utilisés pour contrôler les sorties du modèle. Consultez la documentation de [PreTrainedConfig](/docs/transformers/main/fr/main_classes/configuration#transformers.PreTrainedConfig) pour plus d’informations.

Exemple :

```python
>>> from transformers import RwkvConfig, RwkvModel

>>> # Initializing a Rwkv configuration
>>> configuration = RwkvConfig()

>>> # Initializing a model (with random weights) from the configuration
>>> model = RwkvModel(configuration)

>>> # Accessing the model configuration
>>> configuration = model.config
```

## RwkvModel[[transformers.RwkvModel]]

#### transformers.RwkvModel[[transformers.RwkvModel]]

```python
transformers.RwkvModel(config: RwkvConfig)
```

[Source](https://github.com/huggingface/transformers/blob/main/src/transformers/models/rwkv/modeling_rwkv.py#L487)

**Paramètres :**

config ([RwkvConfig](/docs/transformers/main/fr/model_doc/rwkv#transformers.RwkvConfig)) : Classe de configuration du modèle contenant tous les paramètres du modèle. L'initialisation à partir d'un fichier de configuration ne charge pas les poids associés au modèle, uniquement la configuration. Consultez la méthode [from_pretrained()](/docs/transformers/main/fr/main_classes/model#transformers.PreTrainedModel.from_pretrained) pour charger les poids du modèle.

Le modèle Rwkv brut, qui produit des états cachés bruts sans aucune tête spécifique au sommet.

Ce modèle hérite de [PreTrainedModel](/docs/transformers/main/fr/main_classes/model#transformers.PreTrainedModel). Consultez la documentation de la classe parente pour les méthodes génériques que la bibliothèque implémente pour tous ses modèles (tels que le téléchargement ou l'enregistrement, le redimensionnement des embeddings d'entrée, l'élagage des têtes, etc.).

Ce modèle est également une sous-classe de [torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) de PyTorch. Utilisez-le comme un module PyTorch standard et consultez la documentation de PyTorch pour tout ce qui concerne l’utilisation et le comportement généraux.

#### forward[[transformers.RwkvModel.forward]]

```python
forward(input_ids: typing.Optional[torch.LongTensor] = None, attention_mask: typing.Optional[torch.LongTensor] = None, inputs_embeds: typing.Optional[torch.Tensor] = None, state: list[torch.Tensor] | None = None, use_cache: bool | None = None, output_attentions: bool | None = None, output_hidden_states: bool | None = None, return_dict: bool | None = None, **kwargs)
```

[Source](https://github.com/huggingface/transformers/blob/main/src/transformers/models/rwkv/modeling_rwkv.py#L508)

**Paramètres :**

input_ids (`torch.LongTensor` de forme `(batch_size, input_ids_length)`) : `input_ids_length` = `sequence_length` si `past_key_values` est `None`, sinon `past_key_values.get_seq_length()` (`sequence_length` des états de clés et de valeurs passés en entrée). Indices des jetons de la séquence d'entrée dans le vocabulaire. Si `past_key_values` est utilisé, seuls les `input_ids` dont le passé n'a pas encore été calculé doivent être transmis en tant que `input_ids`. Les indices peuvent être obtenus à l'aide de [AutoTokenizer](/docs/transformers/main/fr/model_doc/auto#transformers.AutoTokenizer). Consultez [PreTrainedTokenizer.encode()](/docs/transformers/main/fr/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.encode) et [PreTrainedTokenizer.__call__()](/docs/transformers/main/fr/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.__call__) pour plus de détails. [Que sont les identifiants d'entrée ?](../glossary#input-ids)

attention_mask (`torch.LongTensor` de forme `(batch_size, sequence_length)`, *facultatif*) : Masque pour éviter d'appliquer l'attention aux indices des jetons de bourrage. Les valeurs du masque sont choisies dans `[0, 1]` : - 1 pour les jetons qui ne sont **pas masqués**, - 0 pour les jetons qui sont **masqués**. [Qu'est-ce qu'un masque d'attention ?](../glossary#attention-mask)

inputs_embeds (`torch.Tensor` de forme `(batch_size, sequence_length, hidden_size)`, *facultatif*) : Facultativement, au lieu de passer `input_ids`, vous pouvez choisir de passer directement une représentation intégrée. Cela est utile si vous souhaitez un meilleur contrôle sur la manière de convertir les indices `input_ids` en vecteurs associés, par rapport à la matrice de recherche d'intégration interne du modèle.

state (`tuple` de cinq `torch.Tensor` de forme `(batch_size, hidden_size, num_hidden_layers)`, *facultatif*) : S'il est transmis, le modèle utilise l'état précédent dans tous les blocs (ce qui donnera la sortie pour les `input_ids` fournis comme si le modèle ajoutait `state_input_ids + input_ids` comme contexte).

use_cache (`bool`, *facultatif*) : Si défini sur `True`, l'état final est renvoyé et peut être utilisé pour générer rapidement les logits suivants.

output_attentions (`bool`, *facultatif*) : Indique s'il faut ou non retourner les tenseurs d'attention de toutes les couches d'attention. Voir `attentions` sous les tenseurs retournés pour plus de détails.

output_hidden_states (`bool`, *facultatif*) : Indique s'il faut retourner les états cachés de toutes les couches. Voir `hidden_states` dans les tenseurs retournés pour plus de détails.

return_dict (`bool`, *facultatif*) : Indique s'il faut retourner un [ModelOutput](/docs/transformers/main/fr/main_classes/output#transformers.utils.ModelOutput) plutôt qu'un simple tuple.

**Retourne :** `RwkvOutput` ou `tuple(torch.Tensor)`

Un `RwkvOutput` ou un tuple de `torch.Tensor` (si `return_dict=False` est passé ou lorsque `config.return_dict=False`) comprenant divers éléments selon la configuration ([RwkvConfig](/docs/transformers/main/fr/model_doc/rwkv#transformers.RwkvConfig)) et les entrées.

La méthode forward de [RwkvModel](/docs/transformers/main/fr/model_doc/rwkv#transformers.RwkvModel) redéfinit la méthode spéciale `__call__`.

Bien que la recette de la passe avant doive être définie dans cette fonction, il faut ensuite appeler l'instance `Module` plutôt que celle-ci, car la première gère l'exécution des étapes de prétraitement et de post-traitement, tandis que la seconde les ignore silencieusement.

- **last_hidden_state** (`torch.Tensor` de forme `(batch_size, sequence_length, hidden_size)`, *facultatif*) -- Séquence d'états cachés à la sortie de la dernière couche du modèle.
- **state** (`list` de cinq `torch.Tensor` de forme `(batch_size, hidden_size, num_hidden_layers)`) -- L'état du modèle à la dernière étape temporelle. Peut être utilisé dans une méthode forward avec les `input_ids` suivants pour éviter de fournir les anciens `input_ids`.
- **hidden_states** (`tuple[torch.Tensor, ...]`, *facultatif*, renvoyé lorsque `output_hidden_states=True` est passé ou lorsque `config.output_hidden_states=True`) -- Tuple de `torch.Tensor` (un pour la sortie des embeddings, si le modèle possède une couche d'embedding, + un pour la sortie de chaque couche) de forme `(batch_size, sequence_length, hidden_size)`.

  États cachés du modèle à la sortie de chaque couche, ainsi que les sorties d'incorporation initiales facultatives.
- **attentions** (`tuple[torch.Tensor, ...]`, *facultatif*, renvoyé lorsque `output_attentions=True` est passé ou lorsque `config.output_attentions=True`) -- Tuple de `torch.Tensor` (un par couche) de forme `(batch_size, num_heads, sequence_length, sequence_length)`.

  Pondérations des attentions après le softmax d'attention, utilisées pour calculer la moyenne pondérée dans les têtes d'auto-attention.

## RwkvLMHeadModel[[transformers.RwkvForCausalLM]]

#### transformers.RwkvForCausalLM[[transformers.RwkvForCausalLM]]

```python
transformers.RwkvForCausalLM(config: RwkvConfig)
```

[Source](https://github.com/huggingface/transformers/blob/main/src/transformers/models/rwkv/modeling_rwkv.py#L667)

**Paramètres :**

config ([RwkvConfig](/docs/transformers/main/fr/model_doc/rwkv#transformers.RwkvConfig)) : Classe de configuration du modèle contenant tous les paramètres du modèle. L'initialisation à partir d'un fichier de configuration ne charge pas les poids associés au modèle, uniquement la configuration. Consultez la méthode [from_pretrained()](/docs/transformers/main/fr/main_classes/model#transformers.PreTrainedModel.from_pretrained) pour charger les poids du modèle.

Le transformateur du modèle RWKV avec une tête de modélisation de langage au sommet (couche linéaire dont les poids sont liés aux plongements d’entrée).

Ce modèle hérite de [PreTrainedModel](/docs/transformers/main/fr/main_classes/model#transformers.PreTrainedModel). Consultez la documentation de la classe parente pour les méthodes génériques que la bibliothèque implémente pour tous ses modèles (tels que le téléchargement ou l'enregistrement, le redimensionnement des embeddings d'entrée, l'élagage des têtes, etc.).

Ce modèle est également une sous-classe de [torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) de PyTorch. Utilisez-le comme un module PyTorch standard et consultez la documentation de PyTorch pour tout ce qui concerne l’utilisation et le comportement généraux.

#### forward[[transformers.RwkvForCausalLM.forward]]

```python
forward(input_ids: typing.Optional[torch.LongTensor] = None, attention_mask: typing.Optional[torch.LongTensor] = None, inputs_embeds: typing.Optional[torch.Tensor] = None, state: list[torch.Tensor] | None = None, labels: typing.Optional[torch.LongTensor] = None, use_cache: bool | None = None, output_attentions: bool | None = None, output_hidden_states: bool | None = None, return_dict: bool | None = None, logits_to_keep: typing.Union[int, torch.Tensor] = 0, **kwargs)
```

[Source](https://github.com/huggingface/transformers/blob/main/src/transformers/models/rwkv/modeling_rwkv.py#L684)

**Paramètres :**

input_ids (`torch.LongTensor` de forme `(batch_size, input_ids_length)`) : `input_ids_length` = `sequence_length` si `past_key_values` est `None`, sinon `past_key_values.get_seq_length()` (`sequence_length` des états de clés et de valeurs passés en entrée). Indices des jetons de la séquence d'entrée dans le vocabulaire. Si `past_key_values` est utilisé, seuls les `input_ids` dont le passé n'a pas encore été calculé doivent être transmis en tant que `input_ids`. Les indices peuvent être obtenus à l'aide de [AutoTokenizer](/docs/transformers/main/fr/model_doc/auto#transformers.AutoTokenizer). Consultez [PreTrainedTokenizer.encode()](/docs/transformers/main/fr/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.encode) et [PreTrainedTokenizer.__call__()](/docs/transformers/main/fr/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.__call__) pour plus de détails. [Que sont les identifiants d'entrée ?](../glossary#input-ids)

attention_mask (`torch.LongTensor` de forme `(batch_size, sequence_length)`, *facultatif*) : Masque pour éviter d'appliquer l'attention aux indices des jetons de bourrage. Les valeurs du masque sont choisies dans `[0, 1]` : - 1 pour les jetons qui ne sont **pas masqués**, - 0 pour les jetons qui sont **masqués**. [Qu'est-ce qu'un masque d'attention ?](../glossary#attention-mask)

inputs_embeds (`torch.Tensor` de forme `(batch_size, sequence_length, hidden_size)`, *facultatif*) : Facultativement, au lieu de passer `input_ids`, vous pouvez choisir de passer directement une représentation intégrée. Cela est utile si vous souhaitez un meilleur contrôle sur la manière de convertir les indices `input_ids` en vecteurs associés, par rapport à la matrice de recherche d'intégration interne du modèle.

state (`tuple` de cinq `torch.Tensor` de forme `(batch_size, hidden_size, num_hidden_layers)`, *facultatif*) : S'il est transmis, le modèle utilise l'état précédent dans tous les blocs (ce qui donnera la sortie pour les `input_ids` fournis comme si le modèle ajoutait `state_input_ids + input_ids` comme contexte).

labels (`torch.LongTensor` de forme `(batch_size, sequence_length)`, *facultatif*) : Étiquettes pour le modélisation du langage. Notez que les étiquettes **sont décalées** à l'intérieur du modèle, c'est-à-dire que vous pouvez définir `labels = input_ids` Les indices sont sélectionnés dans `[-100, 0, ..., config.vocab_size]` Toutes les étiquettes définies sur `-100` sont ignorées (masquées), la perte n'est calculée que pour les étiquettes dans `[0, ..., config.vocab_size]`

use_cache (`bool`, *facultatif*) : Si défini sur `True`, l'état final est renvoyé et peut être utilisé pour générer rapidement les logits suivants.

output_attentions (`bool`, *facultatif*) : Indique s'il faut ou non retourner les tenseurs d'attention de toutes les couches d'attention. Voir `attentions` sous les tenseurs retournés pour plus de détails.

output_hidden_states (`bool`, *facultatif*) : Indique s'il faut retourner les états cachés de toutes les couches. Voir `hidden_states` dans les tenseurs retournés pour plus de détails.

return_dict (`bool`, *facultatif*) : Indique s'il faut retourner un [ModelOutput](/docs/transformers/main/fr/main_classes/output#transformers.utils.ModelOutput) plutôt qu'un simple tuple.

logits_to_keep (`Union[int, torch.Tensor]`, *facultatif*, valeur par défaut `0`) : Si c'est un `int`, calcule les logits pour les `logits_to_keep` derniers jetons. Si c'est `0`, calcule les logits pour tous les `input_ids` (cas particulier). Seuls les logits du dernier jeton sont nécessaires pour la génération, et les calculer uniquement pour ce jeton peut faire économiser de la mémoire, ce qui devient assez significatif pour les séquences longues ou les tailles de vocabulaire importantes. Si c'est un `torch.Tensor`, il doit être 1D et correspondre aux indices à conserver dans la dimension de la longueur de la séquence. C'est utile lors de l'utilisation du format de tenseurs empilés (une seule dimension pour le lot et la longueur de la séquence).

**Retourne :** `RwkvCausalLMOutput` ou `tuple(torch.Tensor)`

Un `RwkvCausalLMOutput` ou un tuple de `torch.Tensor` (si `return_dict=False` est passé ou lorsque `config.return_dict=False`) comprenant divers éléments selon la configuration ([RwkvConfig](/docs/transformers/main/fr/model_doc/rwkv#transformers.RwkvConfig)) et les entrées.

La méthode forward de [RwkvForCausalLM](/docs/transformers/main/fr/model_doc/rwkv#transformers.RwkvForCausalLM) redéfinit la méthode spéciale `__call__`.

Bien que la recette de la passe avant doive être définie dans cette fonction, il faut ensuite appeler l'instance `Module` plutôt que celle-ci, car la première gère l'exécution des étapes de prétraitement et de post-traitement, tandis que la seconde les ignore silencieusement.

- **loss** (`torch.Tensor` de forme `(1,)`, *facultatif*, renvoyé lorsque `labels` est fourni) -- Perte de modélisation du langage (pour la prédiction du jeton suivant).
- **logits** (`torch.Tensor` de forme `(batch_size, sequence_length, config.vocab_size)`) -- Scores de prédiction de la tête de modélisation du langage (scores pour chaque jeton du vocabulaire avant SoftMax).
- **state** (`list` de cinq `torch.Tensor` de forme `(batch_size, hidden_size, num_hidden_layers)`) -- L'état du modèle à la dernière étape temporelle. Peut être utilisé dans une méthode forward avec les `input_ids` suivants pour éviter de fournir les anciens `input_ids`.
- **hidden_states** (`tuple[torch.Tensor, ...]`, *facultatif*, renvoyé lorsque `output_hidden_states=True` est passé ou lorsque `config.output_hidden_states=True`) -- Tuple de `torch.Tensor` (un pour la sortie des embeddings, si le modèle possède une couche d'embedding, + un pour la sortie de chaque couche) de forme `(batch_size, sequence_length, hidden_size)`.

  États cachés du modèle à la sortie de chaque couche, ainsi que les sorties d'incorporation initiales facultatives.
- **attentions** (`tuple[torch.Tensor, ...]`, *facultatif*, renvoyé lorsque `output_attentions=True` est passé ou lorsque `config.output_attentions=True`) -- Tuple de `torch.Tensor` (un par couche) de forme `(batch_size, num_heads, sequence_length, sequence_length)`.

  Pondérations des attentions après le softmax d'attention, utilisées pour calculer la moyenne pondérée dans les têtes d'auto-attention.

Exemple :

```python
```

## Attention Rwkv et formules récurrentes

Dans un Transformer auto-régressif traditionnel, l'attention est écrite sous la forme

$$O = \hbox{softmax}(QK^{T} / \sqrt{d}) V$$

où $Q$, $K$ et $V$ sont des matrices de forme `seq_len x hidden_size` nommées requête, clé et valeur (elles sont en réalité des matrices plus grandes avec une dimension de lot et une dimension de tête d'attention, mais nous ne nous intéressons qu'aux deux dernières, c'est-à-dire là où le produit matriciel est effectué, donc, pour la simplicité, nous ne considérons que ces deux dimensions). Le produit $QK^{T}$ a alors une forme `seq_len x seq_len` et nous pouvons effectuer le produit matriciel avec $V$ pour obtenir la sortie $O$ de la même forme que les autres.

Remplacer le softmax par sa valeur donne :

$$O_{i} = \frac{\sum_{j=1}^{i} e^{Q_{i} K_{j}^{T} / \sqrt{d}} V_{j}}{\sum_{j=1}^{i} e^{Q_{i} K_{j}^{T} / \sqrt{d}}}$$

Notez que les entrées de $QK^{T}$ correspondant à $j > i$ sont masquées (la somme s’arrête à j) car l’attention n’est pas autorisée à regarder les jetons futurs (uniquement les jetons passés).

En comparaison, l'attention RWKV est donnée par

$$O_{i} = \sigma(R_{i}) \frac{\sum_{j=1}^{i} e^{W_{i-j} + K_{j}} V_{j}}{\sum_{j=1}^{i} e^{W_{i-j} + K_{j}}}$$

où $R$ est une nouvelle matrice appelée réceptance par l'auteur, $K$ et $V$ sont toujours la clé et la valeur ($\sigma$ est ici la fonction sigmoïde). $W$ est un nouveau vecteur qui représente la position du jeton et est donné par

$$W_{0} = u \hbox{  et  } W_{k} = (k-1)w \hbox{ pour } k \geq 1$$

avec $u$ et $w$ des paramètres apprenables appelés respectivement `time_first` et `time_decay` dans le code. Le numérateur et le dénominateur peuvent tous deux être exprimés de manière récursive. En les notant $N_{i}$ et $D_{i}$, on a :

$$N_{i} = e^{u + K_{i}} V_{i} + \hat{N}_{i} \hbox{  où  } \hat{N}_{i} = e^{K_{i-1}} V_{i-1} + e^{w + K_{i-2}} V_{i-2} \cdots + e^{(i-2)w + K_{1}} V_{1}$$

ainsi `numerator_state` (appelé `numerator_state` dans le code) satisfait

$$\hat{N}_{0} = 0 \hbox{  et  } \hat{N}_{j+1} = e^{K_{j}} V_{j} + e^{w} \hat{N}_{j}$$

et

$$D_{i} = e^{u + K_{i}} + \hat{D}_{i} \hbox{  où  } \hat{D}_{i} = e^{K_{i-1}} + e^{w + K_{i-2}} \cdots + e^{(i-2)w + K_{1}}$$

ainsi `denominator_state` (appelé `denominator_state` dans le code) satisfait

$$\hat{D}_{0} = 0 \hbox{  et  } \hat{D}_{j+1} = e^{K_{j}} + e^{w} \hat{D}_{j}$$

La formule récurrente réellement utilisée est légèrement plus complexe, car, pour des raisons de stabilité numérique, nous ne souhaitons pas calculer des exponentielles de grands nombres. En général, le softmax n'est pas calculé tel quel, mais l'exponentielle du terme maximal est divisée du numérateur et du dénominateur :

$$\frac{e^{x_{i}}}{\sum_{j=1}^{n} e^{x_{j}}} = \frac{e^{x_{i} - M}}{\sum_{j=1}^{n} e^{x_{j} - M}}$$

où $M$ est le maximum de tous les $x_{j}$. Ici, en plus de sauvegarder l'état du numérateur ($\hat{N}$) et l'état du dénominateur ($\hat{D}$), nous suivons également le maximum de tous les termes rencontrés dans les exponentielles. Nous utilisons donc en réalité

$$\tilde{N}_{i} = e^{-M_{i}} \hat{N}_{i} \hbox{  et  } \tilde{D}_{i} = e^{-M_{i}} \hat{D}_{i}$$

définies par les formules récurrentes suivantes :

$$\tilde{N}_{0} = 0 \hbox{  et  } \tilde{N}_{j+1} = e^{K_{j} - q} V_{j} + e^{w + M_{j} - q} \tilde{N}_{j} \hbox{  où  } q = \max(K_{j}, w + M_{j})$$

et

$$\tilde{D}_{0} = 0 \hbox{  et  } \tilde{D}_{j+1} = e^{K_{j} - q} + e^{w + M_{j} - q} \tilde{D}_{j} \hbox{  où  } q = \max(K_{j}, w + M_{j})$$

et $M_{j+1} = q$. À partir de ceux-ci, nous pouvons ensuite calculer

$$N_{i} = e^{u + K_{i} - q} V_{i} + e^{M_{i}} \tilde{N}_{i} \hbox{  où  } q = \max(u + K_{i}, M_{i})$$

et

$$D_{i} = e^{u + K_{i} - q} + e^{M_{i}} \tilde{D}_{i} \hbox{  où  } q = \max(u + K_{i}, M_{i})$$

ce qui nous donne finalement

$$O_{i} = \sigma(R_{i}) \frac{N_{i}}{D_{i}}$$

