# Génération de texte

La génération de texte est l’application la plus populaire des grands modèles de langage (LLM). Un LLM est entraîné à générer le mot suivant (jeton) à partir d’un texte initial (invite) ainsi que de ses propres sorties générées, jusqu’à une longueur prédéfinie ou lorsqu’il atteint un jeton de fin de séquence (`EOS`).

Dans Transformers, l'API [generate()](/docs/transformers/v5.23.0/fr/main_classes/text_generation#transformers.GenerationMixin.generate) gère la génération de texte et est disponible pour tous les modèles dotés de capacités génératives. Ce guide vous présente les bases de la génération de texte avec [generate()](/docs/transformers/v5.23.0/fr/main_classes/text_generation#transformers.GenerationMixin.generate) ainsi que les pièges courants à éviter.

> [!TIP]
> Pour les commandes suivantes, assurez-vous que [`transformers serve` est en cours d'exécution](./serve-cli/serving).
>
> ```shell
> transformers chat Qwen/Qwen2.5-0.5B-Instruct
> ```

## Génération par défaut

Avant de commencer, il est utile d'installer [bitsandbytes](https://hf.co/docs/bitsandbytes/index) pour quantifier les très grands modèles afin de réduire leur consommation mémoire.

```bash
!pip install -U transformers bitsandbytes
```

Bitsandbytes prend en charge plusieurs backends en plus des GPU basés sur CUDA. Consultez le [guide](https://huggingface.co/docs/bitsandbytes/main/en/installation#multi-backend) d’installation multi-backend pour en savoir plus.

Chargez un LLM avec [from_pretrained()](/docs/transformers/v5.23.0/fr/main_classes/model#transformers.PreTrainedModel.from_pretrained) et ajoutez les deux paramètres suivants pour réduire les besoins en mémoire.

- `device_map="auto"` active la fonctionnalité [Big Model Inference](./models#big-model-inference) d'Accelerate, qui initialise automatiquement le squelette du modèle et charge et répartit les poids du modèle sur tous les appareils disponibles, en commençant par l'appareil le plus rapide (GPU).
- `quantization_config` est un objet de configuration qui définit les paramètres de quantification. Cet exemple utilise bitsandbytes comme backend de quantification (voir la section [Quantization](./quantization/overview) pour d'autres backends disponibles) et charge le modèle en [4-bits](./quantization/bitsandbytes).

```py
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(load_in_4bit=True)
model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-v0.1", device_map="auto", quantization_config=quantization_config)
```

Tokenisez votre entrée et définissez le paramètre `padding_side()` sur `"left"`, car un LLM n'est pas entraîné à poursuivre la génération à partir de jetons de bourrage. Le tokeniseur renvoie les identifiants d'entrée et le masque d'attention.

> [!TIP]
> Traitez plusieurs invites à la fois en passant une liste de chaînes au tokenizer. Regroupez les entrées en lots pour améliorer le débit, au prix d'un léger surcoût en latence et en mémoire.

```py
tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-v0.1", padding_side="left")
model_inputs = tokenizer(["A list of colors: red, blue"], return_tensors="pt").to(model.device)
```

Transmettez les entrées à [generate()](/docs/transformers/v5.23.0/fr/main_classes/text_generation#transformers.GenerationMixin.generate) pour générer des jetons, puis utilisez [batch_decode()](/docs/transformers/v5.23.0/fr/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.batch_decode) pour convertir les jetons générés en texte.

```py
generated_ids = model.generate(**model_inputs)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
"A list of colors: red, blue, green, yellow, orange, purple, pink,"
```

## Configuration de génération

Tous les paramètres de génération sont contenus dans [GenerationConfig](/docs/transformers/v5.23.0/fr/main_classes/text_generation#transformers.GenerationConfig). Dans l’exemple ci-dessus, les paramètres de génération sont dérivés du fichier `generation_config.json` de [mistralai/Mistral-7B-v0.1](https://huggingface.co/mistralai/Mistral-7B-v0.1). Une stratégie de décodage par défaut est utilisée lorsqu’aucune configuration n’est enregistrée avec un modèle.

Inspectez la configuration via l'attribut `generation_config`. N'affiche que les valeurs différentes de la configuration par défaut, en l'occurrence `bos_token_id` et `eos_token_id`.

```py
from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-v0.1", device_map="auto")
model.generation_config
GenerationConfig {
  "bos_token_id": 1,
  "eos_token_id": 2
}
```

Vous pouvez personnaliser [generate()](/docs/transformers/v5.23.0/fr/main_classes/text_generation#transformers.GenerationMixin.generate) en surchargeant les paramètres et les valeurs de [GenerationConfig](/docs/transformers/v5.23.0/fr/main_classes/text_generation#transformers.GenerationConfig). Consultez [cette section ci-dessous](#common-options) pour les paramètres couramment ajustés.

```py
# enable beam search sampling strategy
model.generate(**inputs, num_beams=4, do_sample=True)
```

[generate()](/docs/transformers/v5.23.0/fr/main_classes/text_generation#transformers.GenerationMixin.generate) peut également être étendu avec des bibliothèques externes ou du code personnalisé :

1. le paramètre `logits_processor` accepte des instances personnalisées de [LogitsProcessor](/docs/transformers/v5.23.0/fr/internal/generation_utils#transformers.LogitsProcessor) pour manipuler la distribution de probabilité du jeton suivant ;
2. le paramètre `stopping_criteria` prend en charge des [StoppingCriteria](/docs/transformers/v5.23.0/fr/internal/generation_utils#transformers.StoppingCriteria) personnalisés pour arrêter la génération de texte ;
3. d'autres méthodes de génération personnalisées peuvent être chargées via le drapeau `custom_generate` ([docs](./generation_strategies#custom-generation-methods)).

Consultez le guide [Stratégies de génération](./generation_strategies) pour en savoir plus sur les stratégies de recherche, d'échantillonnage et de décodage.

### Enregistrement

Créez une instance de [GenerationConfig](/docs/transformers/v5.23.0/fr/main_classes/text_generation#transformers.GenerationConfig) et spécifiez les paramètres de décodage souhaités.

```py
from transformers import AutoModelForCausalLM, GenerationConfig

model = AutoModelForCausalLM.from_pretrained("my_account/my_model")
generation_config = GenerationConfig(
    max_new_tokens=50, do_sample=True, top_k=50, eos_token_id=model.config.eos_token_id
)
```

Utilisez [save_pretrained()](/docs/transformers/v5.23.0/fr/main_classes/text_generation#transformers.GenerationConfig.save_pretrained) pour enregistrer une configuration de génération spécifique et définissez le paramètre `push_to_hub` sur `True` pour le téléverser sur le Hub.

```py
generation_config.save_pretrained("my_account/my_model", push_to_hub=True)
```

Laissez le paramètre `config_file_name` vide. Ce paramètre doit être utilisé lors du stockage de plusieurs configurations de génération dans un même répertoire. Il vous permet de spécifier quelle configuration de génération charger. Vous pouvez créer différentes configurations pour différentes tâches génératives (génération de texte créatif avec échantillonnage, résumés avec beam search) à utiliser avec un seul modèle.

```py
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer, GenerationConfig

tokenizer = AutoTokenizer.from_pretrained("google-t5/t5-small")
model = AutoModelForSeq2SeqLM.from_pretrained("google-t5/t5-small")

translation_generation_config = GenerationConfig(
    num_beams=4,
    early_stopping=True,
    decoder_start_token_id=0,
    eos_token_id=model.config.eos_token_id,
    pad_token=model.config.pad_token_id,
)

translation_generation_config.save_pretrained("/tmp", config_file_name="translation_generation_config.json", push_to_hub=True)

generation_config = GenerationConfig.from_pretrained("/tmp", config_file_name="translation_generation_config.json")
inputs = tokenizer("translate English to French: Configuration files are easy to use!", return_tensors="pt")
outputs = model.generate(**inputs, generation_config=generation_config)
print(tokenizer.batch_decode(outputs, skip_special_tokens=True))
```

## Options courantes

[generate()](/docs/transformers/v5.23.0/fr/main_classes/text_generation#transformers.GenerationMixin.generate) est un outil puissant qui peut être fortement personnalisé. Cela peut intimider les nouveaux utilisateurs. Cette section contient une liste des options de génération populaires que vous pouvez définir dans la plupart des outils de génération de texte de Transformers : [generate()](/docs/transformers/v5.23.0/fr/main_classes/text_generation#transformers.GenerationMixin.generate), [GenerationConfig](/docs/transformers/v5.23.0/fr/main_classes/text_generation#transformers.GenerationConfig), `pipelines`, le CLI `chat`, ...

| Nom de l'option | Type | Description simplifiée |
|---|---|---|
| `max_new_tokens` | `int` | Contrôle la longueur maximale de génération. Assurez-vous de le définir, car il est généralement défini par défaut sur une valeur faible. |
| `do_sample` | `bool` | Définit si la génération échantillonne le jeton suivant (`True`) ou si elle est au contraire gloutonne (`False`). La plupart des cas d’utilisation doivent définir ce drapeau sur `True`. Consultez [ce guide](./generation_strategies) pour plus d’informations. |
| `temperature` | `float` | Le degré d’imprévisibilité du prochain jeton sélectionné. Des valeurs élevées (`>0.8`) sont adaptées aux tâches créatives, tandis que des valeurs faibles (par ex. `<0.4`) conviennent aux tâches nécessitant de la « réflexion ». Nécessite `do_sample=True`. |
| `num_beams` | `int` | Lorsqu'il est défini sur `>1`, active l'algorithme de beam search. Le beam search est efficace pour les tâches fondées sur l'entrée. Consultez [ce guide](./generation_strategies) pour plus d'informations. |
| `repetition_penalty` | `float` | Réglez-le sur `>1.0` si vous constatez que le modèle se répète souvent. Des valeurs plus élevées appliquent une pénalité plus importante. |
| `eos_token_id` | `list[int]` | Le(s) jeton(s) qui provoqueront l'arrêt de la génération. La valeur par défaut est généralement bonne, mais vous pouvez spécifier un jeton différent. |

## Pièges

La section ci-dessous aborde certains problèmes courants que vous pouvez rencontrer lors de la génération de texte et comment les résoudre.

### Longueur de la sortie

[generate()](/docs/transformers/v5.23.0/fr/main_classes/text_generation#transformers.GenerationMixin.generate) renvoie par défaut jusqu’à 20 jetons, sauf si une autre valeur est spécifiée dans la [GenerationConfig](/docs/transformers/v5.23.0/fr/main_classes/text_generation#transformers.GenerationConfig) du modèle. Il est fortement recommandé de définir manuellement le nombre de jetons générés à l’aide du paramètre `max_new_tokens` afin de contrôler la longueur de la sortie. Les modèles [Decoder-only](https://hf.co/learn/nlp-course/chapter1/6?fw=pt) renvoient le prompt initial ainsi que les jetons générés.

```py
model_inputs = tokenizer(["A sequence of numbers: 1, 2"], return_tensors="pt").to(model.device)
```

```py
generated_ids = model.generate(**model_inputs)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
'A sequence of numbers: 1, 2, 3, 4, 5'
```

```py
generated_ids = model.generate(**model_inputs, max_new_tokens=50)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
'A sequence of numbers: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,'
```

### Stratégie de décodage

La stratégie de décodage par défaut dans [generate()](/docs/transformers/v5.23.0/fr/main_classes/text_generation#transformers.GenerationMixin.generate) est la *recherche gloutonne*, qui sélectionne le jeton le plus probable, sauf si une autre stratégie est spécifiée dans la [GenerationConfig](/docs/transformers/v5.23.0/fr/main_classes/text_generation#transformers.GenerationConfig) d’un modèle. Bien que cette stratégie de décodage fonctionne bien pour les tâches ancrées dans l’entrée (transcription, traduction), elle n’est pas optimale pour les cas d’usage plus créatifs (rédaction de récits, applications de chat).

Par exemple, activez une stratégie de [multinomial sampling](./generation_strategies#sampling) pour générer des sorties plus variées. Consultez le guide [Generation strategy](./generation_strategies) pour en savoir plus sur les stratégies de décodage.

```py
model_inputs = tokenizer(["I am a cat."], return_tensors="pt").to(model.device)
```

```py
generated_ids = model.generate(**model_inputs)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
```

```py
generated_ids = model.generate(**model_inputs, do_sample=True)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
```

### Côté de bourrage

Les entrées doivent être remplies (padding) si elles n’ont pas la même longueur. Mais les LLM ne sont pas entraînés à poursuivre la génération à partir de jetons de remplissage, ce qui signifie que le paramètre `padding_side()` doit être défini à gauche de l’entrée. Le remplissage à droite est plus défavorable pour les modèles à espace d’état et hybrides, car leur état récurrent continue de se mettre à jour sur les jetons de remplissage en fin de séquence, si bien que le cache ne correspond plus à la fin du prompt.

```py
model_inputs = tokenizer(
    ["1, 2, 3", "A, B, C, D, E"], padding=True, return_tensors="pt"
).to(model.device)
generated_ids = model.generate(**model_inputs)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
'1, 2, 33333333333'
```

```py
tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-v0.1", padding_side="left")
tokenizer.pad_token = tokenizer.eos_token
model_inputs = tokenizer(
    ["1, 2, 3", "A, B, C, D, E"], padding=True, return_tensors="pt"
).to(model.device)
generated_ids = model.generate(**model_inputs)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
'1, 2, 3, 4, 5, 6,'
```

### Format du prompt

Certains modèles et tâches attendent un format de prompt d’entrée spécifique, et si le format est incorrect, le modèle renvoie une sortie sous-optimale. Vous pouvez en savoir plus sur le prompting dans le guide [prompt engineering](./tasks/prompting).

Par exemple, un modèle de chat s’attend à recevoir l’entrée au format [chat template](./chat_templating). Votre invite doit inclure un `role` et un `content` pour indiquer qui participe à la conversation. Si vous essayez de transmettre votre invite sous forme de simple chaîne de caractères, le modèle ne renvoie pas toujours la sortie attendue.

```py
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig

tokenizer = AutoTokenizer.from_pretrained("HuggingFaceH4/zephyr-7b-alpha")
model = AutoModelForCausalLM.from_pretrained(
    "HuggingFaceH4/zephyr-7b-alpha", device_map="auto", quantization_config=BitsAndBytesConfig(load_in_4bit=True)
)
```

```py
prompt = """How many cats does it take to change a light bulb? Reply as a pirate."""
model_inputs = tokenizer([prompt], return_tensors="pt").to(model.device)
input_length = model_inputs.input_ids.shape[1]
generated_ids = model.generate(**model_inputs, max_new_tokens=50)
print(tokenizer.batch_decode(generated_ids[:, input_length:], skip_special_tokens=True)[0])
"Aye, matey! 'Tis a simple task for a cat with a keen eye and nimble paws. First, the cat will climb up the ladder, carefully avoiding the rickety rungs. Then, with"
```

```py
messages = [
    {
        "role": "system",
        "content": "You are a friendly chatbot who always responds in the style of a pirate",
    },
    {"role": "user", "content": "How many cats does it take to change a light bulb?"},
]
model_inputs = tokenizer.apply_chat_template(messages, add_generation_prompt=True, return_tensors="pt").to(model.device)
input_length = model_inputs["input_ids"].shape[1]
generated_ids = model.generate(**model_inputs, do_sample=True, max_new_tokens=50)
print(tokenizer.batch_decode(generated_ids[:, input_length:], skip_special_tokens=True)[0])
"Arr, matey! According to me beliefs, 'twas always one cat to hold the ladder and another to climb up it an’ change the light bulb, but if yer looking to save some catnip, maybe yer can
```

## Ressources

Consultez ci-dessous quelques bibliothèques de génération de texte plus spécifiques et spécialisées.

- [Optimum](https://github.com/huggingface/optimum) : une extension de Transformers axée sur l’optimisation de l’entraînement et de l’inférence sur des dispositifs matériels spécifiques
- [Outlines](https://github.com/dottxt-ai/outlines) : une bibliothèque pour la génération de texte contrainte (générer des fichiers JSON, par exemple).
- [SynCode](https://github.com/uiuc-focal-lab/syncode) : une bibliothèque pour la génération guidée par grammaires sans contexte (JSON, SQL, Python).
- [Text Generation Inference](https://github.com/huggingface/text-generation-inference) : un serveur prêt pour la production destiné aux LLM.
- [Text generation web UI](https://github.com/oobabooga/text-generation-webui) : une interface web Gradio pour la génération de texte.
- [logits-processor-zoo](https://github.com/NVIDIA/logits-processor-zoo) : processeurs de logits supplémentaires pour contrôler la génération de texte.

