Transformers documentation

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

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

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

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

В Transformers API generate() отвечает за генерацию текста и доступен для всех моделей с генеративными возможностями. В этом руководстве вы познакомитесь с основами генерации текста с помощью generate() и узнаете о типичных ошибках, которых следует избегать.

Для следующих команд убедитесь, что transformers serve запущен.

transformers chat Qwen/Qwen2.5-0.5B-Instruct

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

Прежде чем начать, рекомендуется установить bitsandbytes для квантования очень больших моделей с целью снижения потребления памяти.

!pip install -U transformers bitsandbytes

Bitsandbytes поддерживает несколько бэкендов помимо CUDA-совместимых GPU. Подробнее см. в руководстве по установке с несколькими бэкендами.

Загрузите LLM с помощью from_pretrained() и добавьте следующие два параметра для снижения требований к памяти.

  • device_map="auto" включает функцию Big Model Inference в Accelerate, которая автоматически инициализирует каркас модели и загружает и распределяет веса модели по всем доступным устройствам, начиная с самого быстрого (GPU).
  • quantization_config — это объект конфигурации, определяющий параметры квантования. В данном примере в качестве бэкенда квантования используется bitsandbytes (см. раздел Quantization для списка доступных бэкендов), а модель загружается в режиме 4-bits.
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 не обучена продолжать генерацию от токенов отсечки. Токенизатор возвращает идентификаторы входных данных и маску внимания.

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

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(), чтобы сгенерировать токены, а затем используйте batch_decode(), чтобы преобразовать сгенерированные токены обратно в текст.

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. В примере выше параметры генерации берутся из файла generation_config.json модели mistralai/Mistral-7B-v0.1. Если с моделью не сохранена конфигурация, используется стратегия декодирования по умолчанию.

Осмотрите конфигурацию через атрибут generation_config. Он отображает только значения, отличающиеся от конфигурации по умолчанию, в данном случае это bos_token_id и eos_token_id.

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(), переопределив параметры и значения в GenerationConfig. См. раздел ниже для часто настраиваемых параметров.

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

generate() также можно расширить с помощью внешних библиотек или собственного кода:

  1. параметр logits_processor принимает пользовательские экземпляры LogitsProcessor для манипуляции распределением вероятностей следующего токена;
  2. Параметр stopping_criteria поддерживает пользовательские StoppingCriteria для остановки генерации текста;
  3. другие пользовательские методы генерации можно загрузить с помощью флага custom_generate (документация).

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

Сохранение

Создайте экземпляр GenerationConfig и укажите нужные параметры декодирования.

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(), чтобы сохранить конкретную конфигурацию генерации, и установите параметр push_to_hub в True, чтобы загрузить её на Hub.

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

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

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() — это мощный инструмент, который можно сильно настроить. Для новых пользователей это может показаться сложным. В этом разделе приведен список популярных параметров генерации, которые можно задать в большинстве инструментов текстовой генерации в Transformers: generate(), GenerationConfig, pipelines, CLI chat, …

Название параметраТипУпрощенное описание
max_new_tokensintУправляет максимальной длиной генерации. Обязательно задайте это значение, так как по умолчанию оно обычно устанавливается на небольшой размер.
do_sampleboolОпределяет, будет ли генерация выбирать следующий токен методом выборки (True) или жадным алгоритмом (False). В большинстве случаев этот флаг следует установить в True. Подробнее см. в этом руководстве.
temperaturefloatНасколько непредсказуемым будет следующий выбранный токен. Высокие значения (>0.8) подходят для творческих задач, низкие значения (например, <0.4) — для задач, требующих «размышлений». Требуется do_sample=True.
num_beamsintПри значении >1 активируется алгоритм beam search. Beam search хорошо работает на задачах, привязанных к входным данным. Подробнее см. в этом руководстве.
repetition_penaltyfloatУстановите значение >1.0, если модель часто повторяет себя. Большие значения означают более сильный штраф.
eos_token_idlist[int]Токен(ы), которые приведут к остановке генерации. Значение по умолчанию обычно подходит, но вы можете указать другой токен.

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

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

Длина вывода

generate() по умолчанию возвращает не более 20 токенов, если иное не указано в GenerationConfig модели. Настоятельно рекомендуется вручную задавать количество генерируемых токенов с помощью параметра max_new_tokens, чтобы контролировать длину вывода. Модели Decoder-only возвращают исходный промпт вместе с сгенерированными токенами.

model_inputs = tokenizer(["A sequence of numbers: 1, 2"], return_tensors="pt").to(model.device)
длина по умолчанию
max_new_tokens
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'

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

Стратегия декодирования по умолчанию в generate() — это жадкий поиск, который выбирает следующий наиболее вероятный токен, если в GenerationConfig модели не указано иное. Хотя эта стратегия хорошо работает для задач, основанных на входных данных (транскрипция, перевод), она не является оптимальной для более творческих сценариев использования (написание рассказов, чат-приложения).

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

model_inputs = tokenizer(["I am a cat."], return_tensors="pt").to(model.device)
жадный поиск
многономиальная выборка
generated_ids = model.generate(**model_inputs)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

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

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

правая отсечка
left pad
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'

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

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

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

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)
)
no format
шаблон чата
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"

Ресурсы

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

  • Optimum: расширение Transformers, ориентированное на оптимизацию обучения и инференса на конкретных аппаратных устройствах
  • Outlines: библиотека для генерации текста с ограничениями (например, генерация файлов JSON).
  • SynCode: библиотека для генерации, управляемой контекстно-свободной грамматикой (JSON, SQL, Python).
  • Text Generation Inference: готовый к работе в продакшене сервер для LLM.
  • Text generation web UI: веб-интерфейс на Gradio для генерации текста.
  • logits-processor-zoo: дополнительные logits-процессоры для управления генерацией текста.
Update on GitHub