# Cartouches

Les cartouches sont une méthode d'apprentissage par prompt qui stocke une représentation de contexte long compressée sous forme de préfixe de cache KV paramétré. L'idée centrale provient de l'article [Cartridges: Lightweight and general-purpose long context representations via self-study](https://huggingface.co/papers/2506.06266).

Pour un aperçu général et la motivation, consultez le billet de blog [Cartridges: Storing long contexts in tiny caches with self-study](https://hazyresearch.stanford.edu/blog/2025-06-08-cartridges).

## En quoi les Cartridges diffèrent du Prefix Tuning

Prefix Tuning et Cartridges sont tous deux servis en injectant `past_key_values` (un cache KV préfixe) dans le modèle de base.

- Prefix Tuning apprend des embeddings de jetons virtuels (et éventuellement une projection MLP) et génère un préfixe KV.
- Les cartouches apprennent directement le préfixe KV lui-même (les vecteurs clé/valeur par couche pour `p` jetons virtuels) et sont conçus pour être initialisés à partir de KV de préremplissage réels (par exemple, les `p` premiers jetons d’un corpus/invite système).

L’article recommande également de geler le premier jeton comme puits d’attention pour la stabilité (`num_frozen_tokens=1` est la valeur par défaut).

## Usage (Inférence)

Charger un adaptateur CARTRIDGE entraîné et exécuter la génération :

```py
from transformers import AutoModelForCausalLM, AutoTokenizer

from peft import PeftModel

model_id = "Qwen/Qwen2.5-0.5B-Instruct"
adapter_path = "path/to/cartridge_adapter"

base = AutoModelForCausalLM.from_pretrained(model_id)
model = PeftModel.from_pretrained(base, adapter_path)

tok = AutoTokenizer.from_pretrained(model_id)
if tok.pad_token is None:
    tok.pad_token = tok.eos_token

out = model.generate(**tok("Question about the corpus:", return_tensors="pt"), max_new_tokens=64)
print(tok.decode(out[0], skip_special_tokens=True))
```

Si vous devez créer et initialiser une cartouche avant l’entraînement, consultez les options d’initialisation ci-dessous.

## Options d'initialisation

L'article aborde quelques stratégies d'initialisation pratiques :

- KV aléatoire (par défaut) : créez un `CartridgeConfig` et lancez l’entraînement. Cela initialise le préfixe KV de manière aléatoire.
- KV des premiers jetons d’un prompt/corpus : utilisez `initialize_kv_prefix_from_text(model, tokenizer, text=...)`. Cette fonction exécute un prefill sur `text` et copie le cache KV résultant pour les `num_virtual_tokens` premiers jetons dans l’adaptateur.
- KV à partir d’un cache existant : utilisez `initialize_kv_prefix_from_past_key_values(model, past_key_values=...)` si vous disposez déjà d’un objet `past_key_values` issu du préremplissage d’un modèle de base.

## Entraînement

L’article Cartridges propose un objectif de distillation par AUTO-APPRENTISSAGE (un modèle de base figé fournit les logits de l’enseignant ; l’adaptateur CARTRIDGE est entraîné afin que l’élève corresponde à la distribution du jeton suivant de l’enseignant sur le segment cible). PEFT maintient la logique d’entraînement en dehors de la bibliothèque principale ; voir `https://github.com/huggingface/peft/tree/main/examples/cartridge_self_study` pour un flux de travail de référence. Les scripts d’exemple utilisent le modèle de base figé comme enseignant et le modèle adapté comme élève, de sorte que les deux partagent le même point de contrôle sous-jacent.

## Composition

Pour concaténer des cartouches entraînées indépendamment en un seul adaptateur, utilisez `compose_cartridge_adapters(...)`.

# API

## CartridgeConfig[[peft.CartridgeConfig]]

#### peft.CartridgeConfig[[peft.CartridgeConfig]]

```python
peft.CartridgeConfig(task_type: Optional[Union[str, TaskType]] = None, peft_type: Optional[Union[str, PeftType]] = None, auto_mapping: Optional[dict] = None, peft_version: Optional[str] = None, base_model_name_or_path: Optional[str] = None, revision: Optional[str] = None, inference_mode: bool = False, num_virtual_tokens: int = None, token_dim: int = None, num_transformer_submodules: Optional[int] = None, num_attention_heads: Optional[int] = None, num_layers: Optional[int] = None, modules_to_save: Optional[list[str]] = None, num_frozen_tokens: int = 1)
```

[Source](https://github.com/huggingface/peft/blob/main/src/peft/tuners/cartridge/config.py#L22)

**Paramètres :**

num_frozen_tokens (`int`, par défaut 1) : Nombre de jetons de *préfixe* au début de la cartouche à conserver figés (sans gradients). L’article Cartridges recommande de figer le premier jeton comme puits d’attention pour la stabilité (fixez cette valeur à `1`), car de nombreux LLM utilisent les jetons initiaux comme puits d’attention et les modifier peut nuire à l’entraînement.

Configuration pour CARTRIDGE, un adaptateur de préfixe paramétré par cache KV.

Cela ressemble au prefix-tuning en ce qui concerne la manière dont il est servi (sous forme de `past_key_values`), mais il stocke le cache KV directement en tant que paramètres entraînables, au lieu de l’apprendre via une projection MLP.

Initialisation : l’article Cartridges aborde plusieurs options d’initialisation. Dans PEFT, l’initialisation est une étape *séparée* de la construction de la configuration de l’adaptateur :

- **Initialisation aléatoire des KV (option 2 du papier)** : créez l'adaptateur via `get_peft_model(...)`. Les paramètres de l'encodeur de prompt CARTRIDGE sont initialisés aléatoirement par PyTorch.

- **KV dérivé des premiers jetons d’un prompt/corpus (option 3 du papier)** : exécutez un préremplissage sans gradient sur le *modèle de base* et copiez les premiers jetons KV mis en cache, au nombre de `num_virtual_tokens`, dans l’adaptateur. PEFT fournit des utilitaires à cet effet (importables depuis `peft` ou depuis `peft.tuners.cartridge.utils`) :

  - `initialize_kv_prefix_from_text(model, tokenizer, text=...)`
  - `initialize_kv_prefix_from_past_key_values(model, past_key_values=...)`

  Si vous disposez déjà d'un tenseur de préfixe KV aplati, vous pouvez le charger directement via la méthode `load_prompt_embeddings(...)` de l'encodeur de prompt.

## CartridgeEncoder[[peft.CartridgeEncoder]]

#### peft.CartridgeEncoder[[peft.CartridgeEncoder]]

```python
peft.CartridgeEncoder(config)
```

[Source](https://github.com/huggingface/peft/blob/main/src/peft/tuners/cartridge/model.py#L22)

Un cache KV préfixe paramétré.

Les paramètres sont stockés dans la même disposition aplatie que la sortie de `PrefixEncoder` : `[num_virtual_tokens, num_layers
* 2 * token_dim]`, where `token_dim` is per-head hidden size times number of heads (after any GQA adjustment
réalisée par `_prepare_prompt_learning_config`).

Si `num_frozen_tokens > 0`, les `num_frozen_tokens` premiers jetons virtuels sont stockés en tant que paramètre non entraînable, et les jetons restants sont entraînables.

#### load_prompt_embeddings[[peft.CartridgeEncoder.load_prompt_embeddings]]

```python
load_prompt_embeddings(prompt_embeddings: torch.Tensor)
```

[Source](https://github.com/huggingface/peft/blob/main/src/peft/tuners/cartridge/model.py#L91)

Chargez les embeddings de prompt aplatis enregistrés par PEFT (`prompt_embeddings`).

PEFT enregistre les adaptateurs d'apprentissage de prompts sous forme d'un unique tenseur `prompt_embeddings`. Pour CARTRIDGE, nous divisons ce tenseur en segments gelés et entraînables en fonction de `self.num_frozen_tokens`.

## initialize_kv_prefix_from_past_key_values[[peft.initialize_kv_prefix_from_past_key_values]]

#### peft.initialize_kv_prefix_from_past_key_values[[peft.initialize_kv_prefix_from_past_key_values]]

```python
peft.initialize_kv_prefix_from_past_key_values(model, adapter_name: Optional[str] = None, past_key_values: Any, num_virtual_tokens: Optional[int] = None)
```

[Source](https://github.com/huggingface/peft/blob/main/src/peft/tuners/cartridge/utils.py#L100)

Initialiser un adaptateur d’apprentissage de préfixe KV à partir d’un préfixe mis en cache existant (`past_key_values`).

Retourne le tenseur d'embeddings du prompt qui a été chargé dans l'adaptateur.

## prompt_embeddings_from_past_key_values[[peft.prompt_embeddings_from_past_key_values]]

#### peft.prompt_embeddings_from_past_key_values[[peft.prompt_embeddings_from_past_key_values]]

```python
peft.prompt_embeddings_from_past_key_values(past_key_values: Any, num_virtual_tokens: int)
```

[Source](https://github.com/huggingface/peft/blob/main/src/peft/tuners/cartridge/utils.py#L48)

Convertir un cache `past_key_values` (légacy) en tenseur d'embeddings de prompt aplati enregistré par PEFT.

La sortie correspond à la disposition attendue par `PeftModel.get_prompt()` pour l'apprentissage de prompts de type préfixe : forme `[num_virtual_tokens, num_layers * 2 * token_dim]`.

