# Генерация текста

Генерация текста — самое популярное применение больших языковых моделей (LLM). LLM обучается генерировать следующее слово (токен) на основе начального текста (промпта) и собственных ранее сгенерированных выходов до достижения заданной длины или токена конца последовательности (`EOS`).

В Transformers API [generate()](/docs/transformers/main/ru/main_classes/text_generation#transformers.GenerationMixin.generate) отвечает за генерацию текста и доступен для всех моделей с генеративными возможностями. В этом руководстве вы познакомитесь с основами генерации текста с помощью [generate()](/docs/transformers/main/ru/main_classes/text_generation#transformers.GenerationMixin.generate) и узнаете о типичных ошибках, которых следует избегать.

> [!TIP]
> Для следующих команд убедитесь, что [`transformers serve` запущен](./serve-cli/serving).
>
> ```shell
> transformers chat Qwen/Qwen2.5-0.5B-Instruct
> ```

## Генерация по умолчанию

Прежде чем начать, рекомендуется установить [bitsandbytes](https://hf.co/docs/bitsandbytes/index) для квантования очень больших моделей с целью снижения потребления памяти.

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

Bitsandbytes поддерживает несколько бэкендов помимо CUDA-совместимых GPU. Подробнее см. в [руководстве](https://huggingface.co/docs/bitsandbytes/main/en/installation#multi-backend) по установке с несколькими бэкендами.

Загрузите LLM с помощью [from_pretrained()](/docs/transformers/main/ru/main_classes/model#transformers.PreTrainedModel.from_pretrained) и добавьте следующие два параметра для снижения требований к памяти.

- `device_map="auto"` включает функцию [Big Model Inference](./models#big-model-inference) в Accelerate, которая автоматически инициализирует каркас модели и загружает и распределяет веса модели по всем доступным устройствам, начиная с самого быстрого (GPU).
- `quantization_config` — это объект конфигурации, определяющий параметры квантования. В данном примере в качестве бэкенда квантования используется bitsandbytes (см. раздел [Quantization](./quantization/overview) для списка доступных бэкендов), а модель загружается в режиме [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)
```

Токенизируйте входные данные и установите параметр `padding_side()` в значение `"left"`, так как LLM не обучена продолжать генерацию от токенов отсечки. Токенизатор возвращает идентификаторы входных данных и маску внимания.

> [!TIP]
> Обрабатывайте несколько промптов одновременно, передавая в токенизатор список строк. Группируйте входные данные в батчи, чтобы повысить пропускную способность ценой небольшого увеличения задержки и потребления памяти.

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

Передайте входные данные в [generate()](/docs/transformers/main/ru/main_classes/text_generation#transformers.GenerationMixin.generate), чтобы сгенерировать токены, а затем используйте [batch_decode()](/docs/transformers/main/ru/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.batch_decode), чтобы преобразовать сгенерированные токены обратно в текст.

```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,"
```

## Конфигурация генерации

Все параметры генерации содержатся в [GenerationConfig](/docs/transformers/main/ru/main_classes/text_generation#transformers.GenerationConfig). В примере выше параметры генерации берутся из файла `generation_config.json` модели [mistralai/Mistral-7B-v0.1](https://huggingface.co/mistralai/Mistral-7B-v0.1). Если с моделью не сохранена конфигурация, используется стратегия декодирования по умолчанию.

Осмотрите конфигурацию через атрибут `generation_config`. Он отображает только значения, отличающиеся от конфигурации по умолчанию, в данном случае это `bos_token_id` и `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
}
```

Вы можете настроить [generate()](/docs/transformers/main/ru/main_classes/text_generation#transformers.GenerationMixin.generate), переопределив параметры и значения в [GenerationConfig](/docs/transformers/main/ru/main_classes/text_generation#transformers.GenerationConfig). См. [раздел ниже](#common-options) для часто настраиваемых параметров.

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

[generate()](/docs/transformers/main/ru/main_classes/text_generation#transformers.GenerationMixin.generate) также можно расширить с помощью внешних библиотек или собственного кода:

1. параметр `logits_processor` принимает пользовательские экземпляры [LogitsProcessor](/docs/transformers/main/ru/internal/generation_utils#transformers.LogitsProcessor) для манипуляции распределением вероятностей следующего токена;
2. Параметр `stopping_criteria` поддерживает пользовательские [StoppingCriteria](/docs/transformers/main/ru/internal/generation_utils#transformers.StoppingCriteria) для остановки генерации текста;
3. другие пользовательские методы генерации можно загрузить с помощью флага `custom_generate` ([документация](./generation_strategies#custom-generation-methods)).

См. руководство [Стратегии генерации](./generation_strategies), чтобы узнать больше о стратегиях поиска, выборки и декодирования.

### Сохранение

Создайте экземпляр [GenerationConfig](/docs/transformers/main/ru/main_classes/text_generation#transformers.GenerationConfig) и укажите нужные параметры декодирования.

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

Используйте [save_pretrained()](/docs/transformers/main/ru/main_classes/text_generation#transformers.GenerationConfig.save_pretrained), чтобы сохранить конкретную конфигурацию генерации, и установите параметр `push_to_hub` в `True`, чтобы загрузить её на Hub.

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

Оставьте параметр `config_file_name` пустым. Этот параметр следует использовать при хранении нескольких конфигураций генерации в одной директории. Он позволяет указать, какую именно конфигурацию генерации нужно загрузить. Вы можете создавать разные конфигурации для различных генеративных задач (креативная генерация текста с использованием сэмплинга, суммаризация с beam search) для использования с одной моделью.

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

## Общие параметры

[generate()](/docs/transformers/main/ru/main_classes/text_generation#transformers.GenerationMixin.generate) — это мощный инструмент, который можно глубоко настроить. Для новых пользователей это может показаться сложным. В этом разделе приведен список популярных параметров генерации, которые можно задать в большинстве инструментов текстовой генерации в Transformers: [generate()](/docs/transformers/main/ru/main_classes/text_generation#transformers.GenerationMixin.generate), [GenerationConfig](/docs/transformers/main/ru/main_classes/text_generation#transformers.GenerationConfig), `pipelines`, CLI `chat`, ...

| Название параметра | Тип | Упрощенное описание |
|---|---|---|
| `max_new_tokens` | `int` | Управляет максимальной длиной генерации. Обязательно задайте это значение, так как по умолчанию оно обычно устанавливается на небольшой размер. |
| `do_sample` | `bool` | Определяет, будет ли генерация выбирать следующий токен методом выборки (`True`) или жадным алгоритмом (`False`). В большинстве случаев этот флаг следует установить в `True`. Подробнее см. в [этом руководстве](./generation_strategies). |
| `temperature` | `float` | Насколько непредсказуемым будет следующий выбранный токен. Высокие значения (`>0.8`) подходят для творческих задач, низкие значения (например, `<0.4`) — для задач, требующих «размышлений». Требуется `do_sample=True`. |
| `num_beams` | `int` | При значении `>1` активируется алгоритм beam search. Beam search хорошо работает на задачах, привязанных к входным данным. Подробнее см. в [этом руководстве](./generation_strategies). |
| `repetition_penalty` | `float` | Установите значение `>1.0`, если модель часто повторяет себя. Большие значения означают более сильный штраф. |
| `eos_token_id` | `list[int]` | Токен(ы), которые приведут к остановке генерации. Значение по умолчанию обычно подходит, но вы можете указать другой токен. |

## Подводные камни

Раздел ниже описывает ряд типичных проблем, с которыми вы можете столкнуться при генерации текста, и способы их решения.

### Длина вывода

[generate()](/docs/transformers/main/ru/main_classes/text_generation#transformers.GenerationMixin.generate) по умолчанию возвращает не более 20 токенов, если иное не указано в [GenerationConfig](/docs/transformers/main/ru/main_classes/text_generation#transformers.GenerationConfig) модели. Настоятельно рекомендуется вручную задавать количество генерируемых токенов с помощью параметра `max_new_tokens`, чтобы контролировать длину вывода. Модели [Decoder-only](https://hf.co/learn/nlp-course/chapter1/6?fw=pt) возвращают исходный промпт вместе с сгенерированными токенами.

```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,'
```

### Стратегия декодирования

Стратегия декодирования по умолчанию в [generate()](/docs/transformers/main/ru/main_classes/text_generation#transformers.GenerationMixin.generate) — это *жадкий поиск*, который выбирает следующий наиболее вероятный токен, если в [GenerationConfig](/docs/transformers/main/ru/main_classes/text_generation#transformers.GenerationConfig) модели не указано иное. Хотя эта стратегия хорошо работает для задач, основанных на входных данных (транскрипция, перевод), она не является оптимальной для более творческих сценариев использования (написание рассказов, чат-приложения).

Например, включите стратегию [multinomial sampling](./generation_strategies#sampling), чтобы получать более разнообразные результаты. Дополнительные сведения о стратегиях декодирования см. в руководстве [Generation strategy](./generation_strategies).

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

### Сторона отступов

Если входные данные имеют разную длину, их необходимо дополнить (padding). Однако LLM не обучены продолжать генерацию от токенов padding, поэтому параметр `padding_side()` должен быть установлен в значение left. Правосторонний padding хуже для рекуррентных и гибридных моделей, поскольку их рекуррентное состояние продолжает обновляться на хвостовых токенах padding, из-за чего кэш перестаёт соответствовать концу промпта.

```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,'
```

### Формат запроса

Некоторые модели и задачи ожидают определённый формат входного промпта, и если формат неверен, модель возвращает неоптимальный результат. Подробнее о промптинге можно узнать в руководстве по [инженерии промптов](./tasks/prompting).

Например, чат-модель ожидает входные данные в формате [шаблона чата](./chat_templating). В вашем запросе должны быть указаны `role` и `content`, чтобы обозначить участников диалога. Если вы передадите запрос как одну строку, модель не всегда вернёт ожидаемый результат.

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

## Ресурсы

Ниже представлены более специализированные библиотеки для генерации текста.

- [Optimum](https://github.com/huggingface/optimum): расширение Transformers, ориентированное на оптимизацию обучения и инференса на конкретных аппаратных устройствах
- [Outlines](https://github.com/dottxt-ai/outlines): библиотека для генерации текста с ограничениями (например, генерация файлов JSON).
- [SynCode](https://github.com/uiuc-focal-lab/syncode): библиотека для генерации, управляемой контекстно-свободной грамматикой (JSON, SQL, Python).
- [Text Generation Inference](https://github.com/huggingface/text-generation-inference): готовый к работе в продакшене сервер для LLM.
- [Text generation web UI](https://github.com/oobabooga/text-generation-webui): веб-интерфейс на Gradio для генерации текста.
- [logits-processor-zoo](https://github.com/NVIDIA/logits-processor-zoo): дополнительные logits-процессоры для управления генерацией текста.

