Делайте время поколения вашей ламы летающим с AWS Inferentia2.

Сделайте время, когда ваша лама летает, используя AWS Inferentia2.

В предыдущем посте на блоге Hugging Face мы представили AWS Inferentia2, ускоритель второго поколения AWS Inferentia, и объяснили, как можно использовать optimum-neuron для быстрой развертывания моделей Hugging Face для стандартных текстовых и видео задач на инстанциях AWS Inferencia 2.

В дальнейшем этапе интеграции с AWS Neuron SDK теперь можно использовать 🤗 optimum-neuron для развертывания моделей LLM для генерации текста на AWS Inferentia2.

И какую лучшую модель мы могли бы выбрать для этой демонстрации, чем Llama 2, одну из самых популярных моделей на Hugging Face hub.

Установка 🤗 optimum-neuron на вашем экземпляре Inferentia2

Наши рекомендации: использовать Hugging Face Neuron Deep Learning AMI (DLAMI). DLAMI поставляется с предустановленными библиотеками, включая Optimum Neuron, Neuron Drivers, Transformers, Datasets и Accelerate.

Кроме того, вы можете использовать Hugging Face Neuron SDK DLC для развертывания на Amazon SageMaker.

Примечание: следите за следующим постом, посвященным развертыванию на SageMaker.

Наконец, эти компоненты также можно установить вручную на новом экземпляре Inferentia2, следуя инструкциям по установке optimum-neuron здесь.

Экспорт модели Llama 2 в Neuron

Как объясняется в документации optimum-neuron, модели должны быть скомпилированы и экспортированы в сериализованный формат перед запуском их на устройствах Neuron.

К счастью, 🤗 optimum-neuron предлагает очень простой API для экспорта стандартных моделей 🤗 transformers в формат Neuron.

>>> from optimum.neuron import NeuronModelForCausalLM>>> compiler_args = {"num_cores": 24, "auto_cast_type": 'fp16'}>>> input_shapes = {"batch_size": 1, "sequence_length": 2048}>>> model = NeuronModelForCausalLM.from_pretrained(        "meta-llama/Llama-2-7b-hf",        export=True,        **compiler_args,        **input_shapes)

Это заслуживает небольшого объяснения:

  • используя compiler_args, мы указываем, на скольких ядрах мы хотим развернуть модель (каждое устройство neuron имеет два ядра) и с какой точностью (здесь float16),
  • используя input_shape, мы устанавливаем статические размеры ввода и вывода модели. Все компиляторы моделей требуют статических размеров, и neuron не исключение. Обратите внимание, что sequence_length ограничивает не только длину входного контекста, но и длину KV-кэша, и, следовательно, длину вывода.

В зависимости от выбора параметров и хоста inferentia, это может занять от нескольких минут до нескольких часов.

К счастью, вам придется сделать это только один раз, потому что вы можете сохранить свою модель и затем загрузить ее.

>>> model.save_pretrained("место_для_скомпилированной_модели")

Еще лучше, вы можете загрузить ее в Hugging Face hub.

>>> model.push_to_hub(        "место_для_скомпилированной_модели",        repository_id="aws-neuron/Llama-2-7b-hf-neuron-latency")

Генерация текста с помощью Llama 2 на AWS Inferentia2

После экспорта вашей модели вы можете генерировать текст с использованием библиотеки transformers, как это было описано в деталях в этом предыдущем сообщении.

>>> from optimum.neuron import NeuronModelForCausalLM>>> from transformers import AutoTokenizer>>> model = NeuronModelForCausalLM.from_pretrained('aws-neuron/Llama-2-7b-hf-neuron-latency')>>> tokenizer = AutoTokenizer.from_pretrained("aws-neuron/Llama-2-7b-hf-neuron-latency")>>> inputs = tokenizer("What is deep-learning ?", return_tensors="pt")>>> outputs = model.generate(**inputs,                             max_new_tokens=128,                             do_sample=True,                             temperature=0.9,                             top_k=50,                             top_p=0.9)>>> tokenizer.batch_decode(outputs, skip_special_tokens=True)['What is deep-learning ?\nТермин "глубокое обучение" относится к типу машинного обучения, целью которого является построение высокоуровневых абстракций данных в виде иерархии из множества слоев все более сложных узлов обработки.']

Примечание: при передаче нескольких входных промптов в модель, получившиеся последовательности токенов должны быть заполнены слева символом конца потока. Токенизаторы, сохраненные с экспортированными моделями, настроены соответствующим образом.

Поддерживаются следующие стратегии генерации:

  • жадный поиск,
  • мультиномиальная выборка с использованием top-k и top-p (с температурой).

Поддерживаются большинство предварительной обработки / фильтров логитов (например, штраф за повторение).

Все в одном с помощью конвейеров optimum-neuron

Для тех, кто предпочитает сохранять все простым, есть еще более простой способ использования модели LLM на AWS inferentia 2 с помощью конвейеров optimum-neuron.

Их использование такое же простое, как:

>>> from optimum.neuron import pipeline>>> p = pipeline('text-generation', 'aws-neuron/Llama-2-7b-hf-neuron-budget')>>> p("Мое любимое место на земле -", max_new_tokens=64, do_sample=True, top_k=50)[{'generated_text': 'Мое любимое место на земле - океан. Там я чувствую себя наиболее спокойным. Обожаю путешествовать и видеть новые места. У меня'}]

Оценки

Но насколько эффективна генерация текста на Inferentia2? Давайте разберемся!

Мы загрузили на хабе заранее скомпилированные версии моделей LLama 2 7B и 13B с разными конфигурациями:

Примечание: все модели скомпилированы с максимальной длиной последовательности 2048.

Модель llama2 7B “budget” предназначена для развертывания на экземпляре inf2.xlarge, который имеет только одно устройство с нейроном и достаточно памяти cpu для загрузки модели.

Все остальные модели скомпилированы для использования полной мощности доступных ядер на экземпляре inf2.48xlarge.

Примечание: для получения подробной информации о доступных экземплярах обратитесь к странице продукта inferentia2.

Мы создали две конфигурации с ориентацией на “задержку” для моделей llama2 7B и llama2 13B, которые могут обслуживать только один запрос одновременно, но с максимальной скоростью.

Мы также создали две конфигурации с ориентацией на “пропускную способность”, чтобы обслуживать до четырех запросов параллельно.

Для оценки моделей мы генерируем токены до общей длины последовательности 1024, начиная с 256 входных токенов (т.е. мы генерируем 256, 512 и 768 токенов).

Примечание: номера моделей “бюджета” указаны, но не включены в графики для более удобного чтения.

Время кодирования

Время кодирования – это время, необходимое для обработки входных токенов и генерации первого выходного токена. Это очень важная метрика, так как она соответствует задержке, прямо воспринимаемой пользователем при потоковой генерации токенов.

Мы тестируем время кодирования для увеличивающихся размеров контекста: 256 входных токенов соответствуют примерно типичному использованию вопрос-ответ (Q/A), тогда как 768 более типичны для использования с захватом информации Retrieval Augmented Generation (RAG).

Модель “бюджетного” уровня (Llama2 7B-B) развертывается на экземпляре inf2.xlarge, в то время как другие модели развертываются на экземпляре inf2.48xlarge.

Время кодирования выражается в секундах.

Llama2 inferentia2 encoding-time

Мы видим, что все развернутые модели обладают отличными временами отклика, даже для длинных контекстов.

Полная задержка

Полная задержка соответствует общему времени достижения длины последовательности в 1024 токена.

Она включает время кодирования и генерации.

Модель “бюджетного” уровня (Llama2 7B-B) развертывается на экземпляре inf2.xlarge, в то время как другие модели развертываются на экземпляре inf2.48xlarge.

Задержка выражается в секундах.

Llama2 inferentia2 end-to-end latency

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

Задержка модели “бюджетного” уровня значительно выше, но все равно приемлема.

Пропускная способность

Мы используем ту же конвенцию, что и другие бенчмарки, для оценки пропускной способности путем деления полной задержки на сумму входных и выходных токенов. Другими словами, мы делим полную задержку на batch_size * sequence_length, чтобы получить количество сгенерированных токенов в секунду.

Модель “бюджетного” уровня (Llama2 7B-B) развертывается на экземпляре inf2.xlarge, в то время как другие модели развертываются на экземпляре inf2.48xlarge.

Пропускная способность выражается в токенах/секунду.

Llama2 inferentia2 throughput

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

У модели “бюджетного” уровня гораздо более низкая пропускная способность, однако для потокового использования это все равно приемлемо, учитывая, что средний читатель читает около 5 слов в секунду.

Заключение

Мы показали, насколько легко развернуть модели llama2 из хаба Hugging Face на платформеAWS Inferentia2 с использованием 🤗 optimum-neuron.

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

Интересно, что задержка развернутых моделей не слишком зависит от размера пакета, что открывает путь к их развертыванию на конечные точки вывода, обслуживающие несколько запросов параллельно.

Однако здесь все еще много места для улучшений:

  • в текущей реализации единственный способ увеличить пропускную способность – увеличить размер пакета, но он в настоящее время ограничен памятью устройства. В настоящее время внедрены альтернативные варианты, такие как конвейеризация,
  • статическая длина последовательности ограничивает возможность модели кодировать длинные контексты. Было бы интересно узнать, может ли использование блоков внимания быть действительным вариантом для решения этой проблемы.