# Cartuchos

Cartridges é um método de aprendizado de prompt que armazena uma representação de contexto longo comprimida como um prefixo de KV-cache parametrizado. A ideia central vem do artigo [Cartridges: Lightweight and general-purpose long context representations via self-study](https://huggingface.co/papers/2506.06266).

Para uma visão geral e a motivação, consulte o post no blog [Cartridges: Storing long contexts in tiny caches with self-study](https://hazyresearch.stanford.edu/blog/2025-06-08-cartridges).

## Como os Cartridges diferem do Prefix Tuning

Tanto o Prefix Tuning quanto o Cartridges são executados por meio da injeção de `past_key_values` (um cache KV de prefixo) no modelo base.

- Prefix Tuning aprende incorporações de tokens virtuais (e, opcionalmente, uma projeção MLP) e produz um prefixo KV.
- Os cartuchos aprendem diretamente o próprio prefixo KV (os vetores de chave/valor por camada para `p` tokens virtuais) e são projetados para serem inicializados a partir de KV de pré-preenchimento real (por exemplo, os primeiros `p` tokens de um corpus/prompt de sistema).

O artigo também recomenda congelar o primeiro token como um ponto de atenção para estabilidade (`num_frozen_tokens=1` é o padrão).

## Usage (inferência)

Carregue um adaptador CARTRIDGE treinado e execute a geração:

```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))
```

Se você precisar criar e inicializar um cartucho antes do treinamento, consulte as opções de inicialização abaixo.

## Opções de inicialização

O artigo discute algumas estratégias práticas de inicialização:

- KV aleatório (padrão): crie um `CartridgeConfig` e inicie o treinamento. Isso inicializa o prefixo KV aleatoriamente.
- KV dos primeiros tokens de um prompt/corpus: use `initialize_kv_prefix_from_text(model, tokenizer, text=...)`. Isso executa um prefill em `text` e copia o cache KV resultante para os primeiros `num_virtual_tokens` no adaptador.
- KV de um cache existente: use `initialize_kv_prefix_from_past_key_values(model, past_key_values=...)` se você já tiver um objeto `past_key_values` de um prefill de um modelo base.

## Treinamento

O paper Cartridges propõe um objetivo de destilação de AUTOESTUDO (um modelo base congelado fornece os logits do professor; o adaptador CARTRIDGE é treinado para que o aluno corresponda à distribuição de próximo token do professor sobre o segmento alvo). O PEFT mantém a lógica de treinamento fora da biblioteca principal; consulte `https://github.com/huggingface/peft/tree/main/examples/cartridge_self_study` para um fluxo de trabalho de referência. Os scripts de exemplo usam o modelo base congelado como professor e o modelo adaptado como aluno, de modo que ambos compartilham o mesmo checkpoint subjacente.

## Composição

Para concatenar cartuchos treinados de forma independente em um único adaptador, use `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)
```

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

**Parâmetros:**

num_frozen_tokens (`int`, padrão 1) : Número de tokens de *prefixo* no início do cartucho que devem permanecer congelados (sem gradientes). O paper de Cartridges recomenda congelar o primeiro token como um *attention sink* para estabilidade (defina este valor como `1`), pois muitos LLMs usam tokens iniciais como *attention sinks* e alterá-los pode prejudicar o treinamento.

Configuração para CARTRIDGE, um adaptador de prefixo parametrizado por KV-cache.

Isso é semelhante ao prefix-tuning em como é servido (como `past_key_values`), mas ele armazena o cache KV diretamente como parâmetros treináveis, em vez de aprendê-lo por meio de uma projeção MLP.

Inicialização: O paper Cartridges discute várias opções de inicialização. No PEFT, a inicialização é uma etapa *separada* da construção da configuração do adaptador:

- **Inicialização aleatória de KV (opção 2 do paper)**: Crie o adaptador via `get_peft_model(...)`. Os parâmetros do codificador de prompt do CARTRIDGE são inicializados aleatoriamente pelo PyTorch.

- **KV derivado dos primeiros tokens de um prompt/corpus (opção 3 do paper)**: Execute um prefill sem gradiente no *modelo base* e copie os primeiros `num_virtual_tokens` tokens KV em cache para o adaptador. O PEFT fornece utilitários para isso (importáveis de `peft` ou de `peft.tuners.cartridge.utils`):

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

  Se você já possui um tensor de prefixo KV achatado, pode carregá-lo diretamente por meio do método `load_prompt_embeddings(...)` do codificador de prompt.

## CartridgeEncoder[[peft.CartridgeEncoder]]

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

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

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

Um cache KV de prefixo parametrizado.

Os parâmetros são armazenados no mesmo layout achatado da saída 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
executado por `_prepare_prompt_learning_config`).

Se `num_frozen_tokens > 0`, os primeiros `num_frozen_tokens` tokens virtuais são armazenados como um parâmetro não treinável, e os tokens restantes são treináveis.

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

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

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

Carregue os embeddings de prompt achatados salvos pelo PEFT (`prompt_embeddings`).

PEFT salva adaptadores de prompt-learning como um único tensor `prompt_embeddings`. Para CARTRIDGE, dividimos esse tensor em segmentos congelados e treináveis de acordo com `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)
```

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

Inicialize um adaptador de aprendizado de prompt com prefixo KV a partir de um prefixo em cache existente (`past_key_values`).

Retorna o tensor de embeddings do prompt que foi carregado no adaptador.

## 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)
```

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

Converte um cache `past_key_values` (legado) para o tensor de embeddings de prompt achatado salvo pelo PEFT.

A saída corresponde ao layout esperado por `PeftModel.get_prompt()` para aprendizado de prompt no estilo prefixo: forma `[num_virtual_tokens, num_layers * 2 * token_dim]`.

