{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "uVjSCjmCwxwl", "tags": [] }, "source": [ "# Введение в анализ данных" ] }, { "cell_type": "markdown", "metadata": { "id": "LT325GAf74_q" }, "source": [ "В предыдущем ноутбуке на примере двух задач мы познакомились с новым типом нейронных сетей, а именно с RNN. Чуть ранее на занятии мы узнали, что современные LLM построены на основе архитектуры Transformer. В этом ноутбуке мы обзорно познакомимся с популярной библиотекой для работы с актуальными LLM и решим всю ту же задачу анализа тональности текста, но уже с помощью самых последних языковых моделей." ] }, { "cell_type": "markdown", "metadata": { "id": "TvAf0wI0refj" }, "source": [ "## 1. Введение в `transformers`\n", "\n", "Что такое `transformers`? Это открытая библиотека от Hugging Face, которая предоставляет единый API для загрузки, обучения и использования различных моделей. Hugging Face через свои open-source библиотеки и платформу Hugging Face Hub предоставляет доступ к:\n", "\n", "* Моделям. Как к коду их реализации, так и к предобученным весам, включая последние открытые LLM: Llama3, DeepSeek, Gemma3 и др.\n", "\n", "* Пайплайнам (готовым решениям) для стандартных NLP-задач.\n", "\n", "* Датасетам, метриками, инструментам для быстрого файнтюнинга через доп. библиотеки `datasets`, `accelerate`, `peft` и тд.\n", "\n", "\n", "Этот ноутбук содержит базовые примеры. Более подробно с библиотекой вы сможете познакомиться на курсах DS-потока.\n", "\n", "Что мы сделаем на семинаре:\n", "* Посмотрим на токенизацию и чат-шаблоны (chat-template):\n", " * Как текст превращается в токены для современных моделей.\n", " * Схемы форматирования промптов для инструктивных моделей.\n", "\n", "* Научимся генерировать текст с помощью маленьких языковых моделей:\n", " * Потестируем генерацию на open-source вариантах небольших современных LLM.\n", "\n", "* Увидим, как небольшие модели (2-7B параметров) справляются с реальной задачей.\n", " * Классифицируем отзывы IMDB с первой части семинара.\n", "\n", "\n", "\n", "\n", "Дополнительные материалы:\n", "* [Документация `transformers`](https://huggingface.co/docs/transformers/index)\n", "* [Обзорный курс от Hugging Face](https://huggingface.co/course/)\n", "* [Примеры на Github](https://github.com/huggingface/transformers/tree/main/examples/pytorch)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "IP6CvB7NOBsv" }, "outputs": [], "source": [ "# установка нужных библиотек\n", "# !pip install datasets\n", "# !pip install vllm" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "td_TVZxD67IO", "outputId": "f32d4668-f28b-48bf-c012-fbb2155d8f5c" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4.50.0\n", "2.6.0+cu124\n" ] } ], "source": [ "import torch\n", "import transformers\n", "\n", "from datasets import Dataset, load_dataset\n", "from enum import Enum\n", "\n", "\n", "from transformers import AutoModelForCausalLM, AutoTokenizer, AutoProcessor\n", "\n", "from pprint import pprint\n", "from pydantic import BaseModel\n", "\n", "print(transformers.__version__)\n", "print(torch.__version__)" ] }, { "cell_type": "markdown", "metadata": { "id": "Xr730s-_8jVp" }, "source": [ "Посмотрим на какую-нибудь популярную модель на [Hugging Face Hub](https://huggingface.co/models). Пользователи могут загружать свои модели для общего дсотупа.\n", "\n", "\n", "Для работы необходимо инициализировать два объекта:\n", "\n", "* Токенизатор. Он привязан к модели, токенизирует текст, преобразуя его в список токенов из словаря. Токенизатор используется для подготовки входных данных в нужный для модели формат.\n", "* Модель — обычный PyTorch-модуль (torch.nn.Module) с предобученными весами. Библиотека дает возможность подключить нужный класс для задачи: классификация, генерация и т. д." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 510, "referenced_widgets": [ "0384373898204a7d83d2441b24a6d79e", "7a9d3a802db94041b84073d604b67c37", "8589894c4cf149559827e87a0aeed648", "9258300e1c884c2997478bc76493b4a4", "a144c87b7b414efcb8e83f58136c820c", "21d16d23636f477cbc6cdbf3585dd48b", "02c9d093a3674cab86faeeb5c3bedb76", "e916a8b8e3264ca8b1e5cc18bb8009d6", "56434f6d1c9c4dc4a62a24dbe9b03b9a", "ac8c1a3180304657b1af726d283430c5", "4b30be74620945ed9d924d93a4bacd73", "bcd9554dd76344ac8c693b4ae40854fc", "ff1aeb8ecc034bd19dffd962ef38b4a0", "81129642f1644f679fd45fdc7dc0c3b3", "0a449f16ecac470d8dd04cca1dd99f37", "7640bce810c847e6a2a9b9585d1bb672", "7081c53be64f44a5a104b4efdcfae7c4", "6ef50a4ae5384468b51c3aa97e899f1b", "2e8d7d3cb05f4429affcbff63f07f1b2", "5c91150090aa465fa9421bba89e8d51b", "4f2ba7a06f844278911796d1f96588fe", "6aac93d153cd484aa860c3b56312c7b0", "db362c10f0a842c4955abe8b07ca580a", "ac03a17f77c848ce81c9a475fe0e8bff", "7467994a21f141c692f19c399943b348", "134ba66ef97643f39287b86c0e38279f", "eef40093e54947c39a855500055464eb", "3d6378afd99a44eeb110f5344ab3eff7", "07aa6bc56838418297c6ab80103de4ad", "68513d37bbe740fabfca93419c56ed9b", "aec6343d6ca043e888c4dba6ec900a64", "b0680754408b44108ed004fdd1eaf5b2", "47b6808d9b634d65bf3cc0719d186b2f", "380d936333c64f64a87298b5b94832ec", "04a85a86b4eb45ddadb271ae42a86f12", "1328463d9f3a457cac132ee25ffe02dd", "a897f4119c3e47ffaedaab74bf35641d", "40975a52eb2c40039f4c5b6673019b09", "3d9c7e49ee0d484696e182c1f67b5a14", "e5d5fb20873343f79d314d9219fce09c", "9868af2392b64d7ba44288877440bbaa", "e4d3180296d948c48f5b9578c31d3f98", "dbbbb329a6004d2d8985d95e49034324", "504b88724afd46c79932178f261cdd8f", "d9ba7f37afc0446fbd0ced16c8d43988", "d1ede4b523ec4c3a9983c332010c91a1", "d1e688382fb34e528d1e729635663344", "6be684c6225a411aa3580dc5c248fbe3", "d246517f1bf64bc6a88a16a4b551d2a2", "bd3cc88fc6e64b8ca2a7591feb1209b0", "70a9ad3419e549718017a47eb05b8e64", "ac9539f362854760a13161ce76d94a2f", "7f0e671a0b2f46d39b2f8402228bd69b", "3de33ac5f5444dd5809685c61f4b0b77", "1fed88cf1a104bb3b1c8c34caf2cfa62", "22cf3895d5be48749be846856a29b72d", "5ecd3a857bd442c7b06f00be462a64e6", "9fb8b7afcc5d4de9b8e94b4576f2f2f0", "73eda7d731b248b4a9a131618b98d988", "22bfa44c531e45648afb21d947ce1d0d", "0aaca5ec0d354ffe87692326cec05209", "8ec9ba1eb6d2474894f89884b2bf93a1", "0416065ae2484d6ba058209b2fa9f76b", "5056b6f305e1484f98fa60fb88c9c4fc", "f452c887829440e88475e1481a5f898d", "360dc97a38a345c4a0ffcbbeb36a178c", "0647302653c54453be481bd73633e229", "d4d84e1c5c8a4bcc807f1ba41264fe75", "c65e55e7e0894c6d9f65227c69cdee0e", "e53bc9eb0f724347868da18ce0b3ff91", "ac4c07e0bc7147589e6a05cc400a57be", "97b0a11a3f6f4b54a11b732cc1c2e879", "9659488e7f56410490f077ca39d7a18f", "82ac6a571ae0482eb40c677b89fe0056", "3331a5f94f3b44c5a38887f4ff697485", "de3ac1c121e54372b04565baf5cee31b", "905bf884497c4b51899e9c7ed0ca1fed", "2c7d5a3ad1fa404bbc27bc2896cf9b99", "c41d6a6f8d724c5b97a5a6e067d2fff8", "f521527c36774cbea0714208c6f7ba09", "e764386c10dc43d6b4f9e1d06d339f47", "cc66659bf0624358946e0d94405365c3", "ff0cb9548eca49139e1651aa23fbff64", "5c93b181d5fa488aabbbb826df785722", "467413508e174507a422a47b4f52eb27", "5f8edf4a22df48e2b9c22d447c3b5935", "330835f405cd4193ad009bb1f7150403", "970c080b3272482381495550be38f1b7", "8000bc2f6278450db77ef40efdf6e4fb", "5046d8c4380d464594c884fd815f7cb9", "64be980db36d4b9faa59ffaabb94964c", "40046e492823424886d7e31f9c99148c", "5fae9b1c1c564996b077240773c47849", "a80381f6d4b74f018acdcd36c381f079", "dfcf926d9bd046909e218f53ce44b607", "030bc18ad0c8468e99566fb0a469d390", "be07791da9a0461cac5da20008896b03", "d0f3f9bd942c4a31ad95b9fa3afbc084", "fd46cd38728d4605b938fd55ff78b232", "98c6d577088f4d1cae72dfa6e12798cc", "7ce7b88ba65e4c2291d0e6d0fa58731c", "d053ac2a728c475eaa1c235364f7cde8", "cb8a24d3074c458a8f7e08c05b890866", "a05443da74654a7e9d86e7a88a86de5c", "756ba4d812e7417b8b44163996d1bcb1", "8ec27e9dd9b54aac85f9d89b9336f333", "00ef47ae9a3941ffaf5623e0b40d7291", "cb708dcb9d3541d9b45ef81aa4708bc4", "1c33d15fab0d4f4595ba5caa51d5dd25", "266cc81db5be4dd1bcfaeb4cfb6c3256", "ceabb23182154bc0954556752926d3c8", "169f58607a37478f8602116887ca43d9", "c5a7152a1f04499e9f5ee3e6c08ef0be", "ed2efa8c62df441db449dbc5a6b7756d", "acd3eb6f2455480ea88b362e3987e32e", "0db881f94fc84b7fabd60b003f1944f5", "cefceb5c7c9c4ff9aa4a418aeb22d7e8", "44ccaaade05c4a7097b921d0f49b5802", "0be195d9a20b4cc9abe8802c1f7a099d", "e1d2939d7015404f8cc4748a5228e111", "05a75f75451a49e88d0ae001c4cbe7a1" ] }, "id": "4iEAJRcN7EX_", "outputId": "94020b25-c8fc-48e8-9481-2ee489e8774a" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.11/dist-packages/huggingface_hub/utils/_auth.py:94: UserWarning: \n", "The secret `HF_TOKEN` does not exist in your Colab secrets.\n", "To authenticate with the Hugging Face Hub, create a token in your settings tab (https://huggingface.co/settings/tokens), set it as secret in your Google Colab and restart your session.\n", "You will be able to reuse this secret in all of your notebooks.\n", "Please note that authentication is recommended but still optional to access public models or datasets.\n", " warnings.warn(\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "0384373898204a7d83d2441b24a6d79e", "version_major": 2, "version_minor": 0 }, "text/plain": [ "config.json: 0%| | 0.00/683 [00:00\n" ] } ], "source": [ "generated_ids = model.generate(\n", " **tokenized_inputs.to(model.device),\n", " max_new_tokens=num_tokens_to_generate, # Максимальная длина текста\n", " do_sample=True, # Будем использовать сэмплирование\n", " temperature=1.05, # Увеличим температуру, сделаем ответы разнообразнее\n", " pad_token_id=tokenizer.eos_token_id, # Чтобы избежать предупреждений\n", ")\n", "\n", "generated_text = tokenizer.decode(generated_ids[0], skip_special_tokens=False)\n", "print(f\"Сгенерированный текст:\\n\\n{generated_text}\")" ] }, { "cell_type": "markdown", "metadata": { "id": "ZOmT2-7akrj9" }, "source": [ "Современные языковые модели (LLM) давно превратились в мощных диалоговых ассистентов. Такой формат взаимодействия оказался очень успешен, ведь чат-формат соответствует естественному человеческому общению, он интуитивно понятен пользователю и предоставляет собой единый интерфейс для решения разнородных задач.\n", "\n", "Однако исходная базовая модель обучается предсказывать только следующий токен и без явных указаний может легко запутаться, т.к. возникает ряд проблем:\n", "\n", "* Границы реплик (Где вопрос пользователя? Где ответ ассистента?)\n", "* Что в контекста важно? Как учесть временную динамику диалога?\n", "\n", "После базового предобучения на большом корпусе текстов обычно следует процесс инструктивного обучения на парах (запрос пользователя, ответ модели). При этом обычно модель обучают строго на определенном чат-шаблоне (chat-template), который спроектирован так, чтобы стрктурировать историю диалога в нужном формате, добавить важную информацию в контекст, указать начало и конец реплик пользователя / модели.\n", "\n", "Пример такого шаблона:\n", "\n", "\n", "```\n", "<|system|> Ты ИИ-ассистент. Текущая дата: 29-03-2025. <|end_of_message|>\n", "<|user|> Где расположен МФТИ? <|end_of_message|>\n", "<|assistant|> Московский Физтех находится в г. Долгопрудный... <|end_of_message|>\n", "<|user|> А сколько лет этому университету? <|end_of_message|>\n", "<|assistant|> # Модель должна продолжить текст здесь и закончить <|end_of_message|> токеном\n", "```" ] }, { "cell_type": "markdown", "metadata": { "id": "OkKuP-mQn1La" }, "source": [ "Посмотрим на `Instruct`-версию предыдущей модели." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 369, "referenced_widgets": [ "b25bf24d6921434583d7177a7513c352", "7c434e1c016c44a9b697e95e5368c9c6", "e8049a3fdfa14fcba53665eddfe354e9", "cd51a22addc4465bba92cfe93aad91d6", "4d3461827d2b4ceb9fda94f31022b87a", "8dbfca0a0768440f900e3b9ef86f3540", "96d672dc22f84c80bff10a43c950fa43", "8be525e1d52147ba940714f8e85001bc", "483a102294324601a9e6fb8b21f95f9a", "4bd50b6dec4d49e6965e3e93509d08ad", "2b0ce14e2f7d41009323ad6a1d39ce67", "a614b4c11f73439186f28337572524bb", "d6cfbaa267c14966aafb5227f32a5b82", "cec08bb4d32b47a5b200b46b49cfb19d", "05efc76cf89d4688a0a51d6f14906198", "c9c3a299abce444d95e19f6622a86f4b", "a15d486ce220440ca65acb5a569c74e3", "f1b91e82be7e479798c9f8d0b5ae6fb8", "e7024ad398f74d438faa53ed02e31772", "2b9634ee1b324583a4b23197f72444a6", "c1ac46e24c0949d39a0bb1370ad63f25", "41237b905d824467b7a80662a525de48", "8b8734d8073441c3925ccff775f09069", "610e064193ed4a22825a3343a1420014", "562c464b3b544c6c98f07946682fed45", "59600bab0b9a42768b1bbedff66cddc0", "d56184e0e00a44b2ab9e8303a05f3179", "0bc8667ba89b4e63b2d935e5f3718b3d", "3501c0c243d84b0f8ebe5cbadea9da23", "6af55c90db29416bb8e36513b3c8f970", "ba66a1a0bb26411784138f7540666c63", "8f354c8d2cf3421e83e63416ca327f6f", "c672086783274b2fbb9d7e911b3f93c4", "911affcd0f0d4a8f897784f4a26e42ac", "78531d7c471c441cbe2e2b3bcbf39b9b", "02d9145be13140b082fd1bd2bf21a737", "8cd51f14de3f4bd386c0c94250e181a1", "83abded575c544919bab57694db5688a", "bf32e12c27244698b511bba78739f960", "e90f57188f96483c9ba50a4a94f2291c", "8daced3bb6974e9e8bb20e72be7e2fc8", "5e730d6ee6ad450ca4e40514172ba8a0", "66a9b3905d9542f8afec3c84265ac89d", "54e1bd308c14428f9e08cc30ea9798c0", "04c0b66e5a024e7296bcc21c9a6bedc8", "8b37463730a2446b972c2df6a9fd198f", "49548833b325497dab9364487fc9669d", "9d6c88ba346b4d62803a665ad3a8265e", "452fb03aa543479ab37c84983813a6a6", "29d0b3abc17f4a19925e6c0c0d6c7f59", "dadada232d5e4f0c8c01ce1a84991b7f", "56821d29a01c45179a464a10b335d7d9", "0668033fe8ba42aaa679dbd63795d878", "b122d72d857a4fe4801a2317b7f48e5c", "ffc68d4984e9445e987e5f3b4fcf105b", "0b00e5ea74ae4a7dad6f0218a0d8cf07", "49a440dd1b39450b875a1518775d420c", "0c51bc5617334cf88f8776be90c199e7", "637076dc86a34703b01fc229c4bc0c46", "8797e4dc877c411cb704988c13a39239", "9886f1cce532429e9b7853aa470a790b", "53affb49338b4d03a895f908aebb5151", "8232f93195cb44f28a1a449b35f04b8d", "e644052f7a884ee0bb8ced4900d58351", "a823ff662e8b4692bd393242905b9dda", "17c0828612c341ce9d5afd0e76586ad9", "834bad3e092d44cf8fff34d7204826f2", "a256bdd10a0943b4957afa99050d2060", "fc2909a62be44e418b1b025f7efa943a", "75df787237524d769a4d1e36ec5bdce1", "d8377e470f66430891dad99b9acc0285", "ce98a4f1068c449c880cc254d4cb8123", "2129f2ee5b7f4dacbeb5d57382fb795f", "795097fc7a1b46379488b165c0a12e2d", "f61ac4d20b5341f0afff8332514dd58a", "cd7e34163b414abda91f25bda4477cc1", "04ab2577624c449eb9a55497c6731ce8", "b3e0230c5782449ea9c67fbcaaf3415f", "a569885c62f0447aa7231b4bb9a88f63", "9ff972bff91c4b0fbfd45564016beaa2", "7a16948da0c44a8cbd9d038b8fa2f443", "23fbeb80a914484c91a0a5e2640a690b", "d03ebf91bbbf4506955e8e9373368996", "8ee249c85b854896b7858e3b4f248a14", "52dbe1e0a60a4d4da29d3d8286b8d2a7", "26a36481b15c4ae7bc4cf5c055410420", "0a69145dce4b459b90618c5d110423f3", "993528194432470888c62985e14cd6ea", "032cc388c154448eb40b7124b1e9b4bd", "a766d48abd8a415a8122576c93b43f1c", "62de842965e446458ef4d7066c19e042", "cbcb32857133494e8b8fab1c6a1407ca", "2635b3c81bbe4b4ab9334506ee3b2e36", "ae00c1a6d613463d8718299302b50d59", "1f4e857b564545098e1567305189c85c", "c94f4c6da1174de6a015b64f332fc287", "4110d2e603b540d5b7d8b860eed9d067", "1fb945959ebe4f07a0f4d3f2ca2dc8c3", "5373cf11240043b2a5023d4499f09051", "dd03ef8453264d43bf26feba2f9dac84", "5fe79e517540474eacadf71cbbfcd174", "8f744859dde341dd8eadfd0fb9faf66c", "f439ffe1239d481fbac4bf446d32db5d", "03144300226e4ce1bf03dc6e18a0dbed", "a27742181ef84ff691795cac69ba4033", "4e018eef1b904d88a371303a87b8337c", "a85636eef84d489eb85932b952718a3a", "8d09b2da2a2642d4815af04c537331c6", "a91e651a38a94fc7b661c11c59f2d19c", "4a12b0194fd543f5a58a97f069f440d1", "d755e24c07624524b040b0bd5e02a3e0", "0a13b3706efa45ee8cbd4cde10a5e67a", "b3bce32bd68043ffb5bd4f4728c6b438", "f4d1bc63e96a4ba79ccf508e3d6250f6", "2f1c299d4fcd4f88a9fa989e72863357", "d88a6c989aff41ca8f11ada021ff3a9e", "2e5b643e0b6544fd8dc510e40c879fe2", "39e382f66f8f4d6c8cb9e1f70caa0df1", "5f155a59847646c7a050fdab88e8863b", "dbd45f03c85c459dbf5b90c83857e6c5", "3b9ca6499f6c4164b6f10435f233280f" ] }, "id": "9qXDZl2mWYRZ", "outputId": "8a290b74-46ec-48e6-afb5-fb1b9a292b7e" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "b25bf24d6921434583d7177a7513c352", "version_major": 2, "version_minor": 0 }, "text/plain": [ "config.json: 0%| | 0.00/661 [00:00system\\\\n\\' }}\\n {%- if messages[0][\\'role\\'] == \\'system\\' %}\\n {{- messages[0][\\'content\\'] }}\\n {%- else %}\\n {{- \\'You are Qwen, created by Alibaba Cloud. You are a helpful assistant.\\' }}\\n {%- endif %}\\n {{- \"\\\\n\\\\n# Tools\\\\n\\\\nYou may call one or more functions to assist with the user query.\\\\n\\\\nYou are provided with function signatures within XML tags:\\\\n\" }}\\n {%- for tool in tools %}\\n {{- \"\\\\n\" }}\\n {{- tool | tojson }}\\n {%- endfor %}\\n {{- \"\\\\n\\\\n\\\\nFor each function call, return a json object with function name and arguments within XML tags:\\\\n\\\\n{\\\\\"name\\\\\": , \\\\\"arguments\\\\\": }\\\\n<|im_end|>\\\\n\" }}\\n{%- else %}\\n {%- if messages[0][\\'role\\'] == \\'system\\' %}\\n {{- \\'<|im_start|>system\\\\n\\' + messages[0][\\'content\\'] + \\'<|im_end|>\\\\n\\' }}\\n {%- else %}\\n {{- \\'<|im_start|>system\\\\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>\\\\n\\' }}\\n {%- endif %}\\n{%- endif %}\\n{%- for message in messages %}\\n {%- if (message.role == \"user\") or (message.role == \"system\" and not loop.first) or (message.role == \"assistant\" and not message.tool_calls) %}\\n {{- \\'<|im_start|>\\' + message.role + \\'\\\\n\\' + message.content + \\'<|im_end|>\\' + \\'\\\\n\\' }}\\n {%- elif message.role == \"assistant\" %}\\n {{- \\'<|im_start|>\\' + message.role }}\\n {%- if message.content %}\\n {{- \\'\\\\n\\' + message.content }}\\n {%- endif %}\\n {%- for tool_call in message.tool_calls %}\\n {%- if tool_call.function is defined %}\\n {%- set tool_call = tool_call.function %}\\n {%- endif %}\\n {{- \\'\\\\n\\\\n{\"name\": \"\\' }}\\n {{- tool_call.name }}\\n {{- \\'\", \"arguments\": \\' }}\\n {{- tool_call.arguments | tojson }}\\n {{- \\'}\\\\n\\' }}\\n {%- endfor %}\\n {{- \\'<|im_end|>\\\\n\\' }}\\n {%- elif message.role == \"tool\" %}\\n {%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != \"tool\") %}\\n {{- \\'<|im_start|>user\\' }}\\n {%- endif %}\\n {{- \\'\\\\n\\\\n\\' }}\\n {{- message.content }}\\n {{- \\'\\\\n\\' }}\\n {%- if loop.last or (messages[loop.index0 + 1].role != \"tool\") %}\\n {{- \\'<|im_end|>\\\\n\\' }}\\n {%- endif %}\\n {%- endif %}\\n{%- endfor %}\\n{%- if add_generation_prompt %}\\n {{- \\'<|im_start|>assistant\\\\n\\' }}\\n{%- endif %}\\n'" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tokenizer.chat_template" ] }, { "cell_type": "markdown", "metadata": { "id": "v66VA_fdoCQV" }, "source": [ "Применим чат-шаблон и посмотрим на результат." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 52 }, "id": "D-DwvGkZYPkY", "outputId": "9296b5c9-7699-4436-ee05-d3f0fcb0b629" }, "outputs": [ { "data": { "application/vnd.google.colaboratory.intrinsic+json": { "type": "string" }, "text/plain": [ "'<|im_start|>system\\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>\\n<|im_start|>user\\nЧто такое relu в глубоком обучении?<|im_end|>\\n<|im_start|>assistant\\n'" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "text = tokenizer.apply_chat_template(\n", " messages,\n", " tokenize=False, # не будем токенизировать, а только форматируем\n", " add_generation_prompt=True, # затравка для генерации\n", ")\n", "text" ] }, { "cell_type": "markdown", "metadata": { "id": "9GvIc9bsB943" }, "source": [ "Можно заметить, что `<|im_start|>` начинает реплику с указанием роли, а `<|im_end|>` служит токеном конца реплики, отделяя текущее сообщение от следующих. В данном случае мы выставили аргумент `add_generation_prompt`, добавляющий стартовый тег ответа модели (`assistant`). Модель, продолжая текст, сгенерирует тем самым ответ ассистента." ] }, { "cell_type": "markdown", "metadata": { "id": "iqxpuTYHqhl5" }, "source": [ "Токенизируем обработанную строку." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "UhBX4FJwYVpy", "outputId": "39e14833-6188-4df6-a619-8226f261aa7f" }, "outputs": [ { "data": { "text/plain": [ "{'input_ids': tensor([[151644, 8948, 198, 2610, 525, 1207, 16948, 11, 3465,\n", " 553, 54364, 14817, 13, 1446, 525, 264, 10950, 17847,\n", " 13, 151645, 198, 151644, 872, 198, 72819, 24634, 134322,\n", " 92874, 5805, 132853, 63469, 14746, 12228, 143180, 83098, 30,\n", " 151645, 198, 151644, 77091, 198]], device='cuda:0'), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]], device='cuda:0')}" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model_inputs = tokenizer(text, return_tensors=\"pt\").to(model.device)\n", "model_inputs" ] }, { "cell_type": "markdown", "metadata": { "id": "g1-NuurfqnDj" }, "source": [ "Сгенерируем продолжение." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "58dLRg29Yiy1" }, "outputs": [], "source": [ "generated_ids = model.generate(**model_inputs, do_sample=True, max_new_tokens=1024)" ] }, { "cell_type": "markdown", "metadata": { "id": "FoEpkCfYAYmf" }, "source": [ "Обратите внимание, `generated_ids` содержит как входные токены, так и сгенерированные." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "F0EwKkAmYymr", "outputId": "5237a6d0-f315-442e-8006-880d2d8c1d47" }, "outputs": [ { "data": { "text/plain": [ "tensor([[151644, 8948, 198, 2610, 525, 1207, 16948, 11, 3465,\n", " 553, 54364, 14817, 13, 1446, 525, 264, 10950, 17847,\n", " 13, 151645, 198, 151644, 872, 198, 72819, 24634, 134322,\n", " 92874, 5805, 132853, 63469, 14746, 12228, 143180, 83098, 30,\n", " 151645, 198, 151644, 77091, 198, 79652, 320, 4415, 1870,\n", " 28263, 7954, 8, 1959, 67879, 136109, 23064, 135041, 133051,\n", " 43686, 54713, 12141, 130304, 53586, 5805, 44816, 7599, 24634,\n", " 6020, 43686, 6709, 21032, 129568, 43686, 137528, 129250, 7587,\n", " 130599, 63833, 126202, 6709, 21032, 129568, 43686, 137528, 21032,\n", " 13, 134948, 126068, 42965, 137677, 130193, 1032, 23236, 1447,\n", " 16, 13, 34348, 2247, 46705, 43758, 142567, 4235, 510,\n", " 256, 1032, 23236, 141107, 133104, 25460, 18943, 21032, 76395,\n", " 54713, 11916, 11, 130407, 133026, 26909, 137514, 7587, 5805,\n", " 73615, 72285, 91357, 70021, 61391, 11, 46253, 98745, 142189,\n", " 54908, 33513, 11, 7587, 220, 15, 11, 46253, 98745,\n", " 20264, 30103, 10373, 59890, 33513, 382, 17, 13, 66791,\n", " 31230, 3780, 30343, 510, 256, 17767, 282, 2075, 8,\n", " 284, 1124, 2810, 7, 15, 11, 856, 8, 1124,\n", " 692, 18, 13, 134004, 16104, 85530, 1478, 510, 256,\n", " 481, 79484, 24276, 13039, 1478, 20811, 135958, 3038, 61391,\n", " 25, 37660, 50645, 43767, 143180, 17175, 7587, 56825, 2247,\n", " 51574, 26619, 624, 256, 481, 44358, 51329, 132775, 63262,\n", " 60290, 1792, 60279, 130297, 4793, 46705, 18492, 5409, 126964,\n", " 16339, 330, 88454, 125153, 22496, 4235, 1, 320, 15649,\n", " 10976, 20169, 701, 131222, 36305, 132853, 63469, 14746, 66645,\n", " 34775, 60290, 10474, 624, 256, 481, 27499, 22621, 138121,\n", " 99047, 67642, 52276, 11, 47389, 66988, 13932, 135334, 17787,\n", " 143180, 17175, 382, 19, 13, 34789, 13103, 24276, 7972,\n", " 16748, 510, 256, 481, 143685, 12281, 28156, 43055, 4793,\n", " 17998, 330, 8959, 37622, 4552, 1792, 50636, 87512, 1,\n", " 320, 89, 23342, 92495, 1648, 87512, 11, 128548, 130356,\n", " 130414, 220, 15, 11, 129348, 18658, 54423, 137673, 8215,\n", " 56825, 4552, 6949, 42193, 66645, 137232, 126202, 143181, 624,\n", " 256, 481, 34789, 8178, 14497, 2184, 14005, 6020, 124448,\n", " 24725, 125879, 1802, 18673, 4552, 25, 126231, 91778, 131705,\n", " 38800, 140974, 18492, 88663, 16748, 11, 46253, 65359, 132399,\n", " 1478, 140662, 20264, 30103, 10373, 59890, 125439, 11, 24725,\n", " 125879, 1802, 18673, 66988, 61631, 128632, 143936, 11, 47389,\n", " 66988, 12281, 26991, 88238, 7665, 330, 124818, 14949, 22787,\n", " 3780, 1, 131480, 6715, 382, 20, 13, 42796, 32693,\n", " 32195, 26619, 510, 256, 1032, 23236, 135927, 143248, 51670,\n", " 20396, 52528, 7599, 127682, 124237, 141204, 126242, 47162, 38888,\n", " 45077, 10813, 7336, 130534, 2247, 12, 133486, 1802, 5805,\n", " 44816, 7599, 24634, 6020, 43686, 6709, 21032, 129568, 43686,\n", " 137528, 129250, 7587, 128488, 43116, 9923, 68675, 70729, 10474,\n", " 5409, 142746, 63833, 49707, 54713, 12141, 130304, 53586, 382,\n", " 21, 13, 79698, 46705, 61676, 510, 256, 22933, 128714,\n", " 131662, 129612, 70139, 43000, 10474, 131704, 139193, 20562, 131939,\n", " 53586, 1032, 23236, 11, 132842, 51670, 1967, 28100, 1032,\n", " 23236, 11, 6991, 16340, 1032, 23236, 7587, 17258, 52,\n", " 11, 128548, 126091, 129371, 139437, 23064, 127782, 24276, 7972,\n", " 89777, 140982, 28018, 38800, 1032, 23236, 382, 79652, 139427,\n", " 137255, 38888, 131964, 11916, 137908, 14062, 1802, 132348, 13039,\n", " 14949, 19849, 141132, 7587, 143181, 6709, 21032, 129568, 43686,\n", " 137528, 21032, 138425, 131189, 132717, 67642, 7587, 129020, 13039,\n", " 1504, 13, 151645]], device='cuda:0')" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "generated_ids" ] }, { "cell_type": "markdown", "metadata": { "id": "00mEGZ_gAjwU" }, "source": [ "Оставим только сгенерированные токены." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Rr3HnNtyZDxq" }, "outputs": [], "source": [ "generated_ids = [\n", " output_ids[len(input_ids) :]\n", " for input_ids, output_ids in zip(model_inputs[\"input_ids\"], generated_ids)\n", "]" ] }, { "cell_type": "markdown", "metadata": { "id": "9LpxyxbUrd3e" }, "source": [ "Посмотрим на ответ модели." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 140 }, "id": "BV8vXUxmYtZx", "outputId": "001f8602-787f-49f8-e132-44b1a8f92d0f" }, "outputs": [ { "data": { "application/vnd.google.colaboratory.intrinsic+json": { "type": "string" }, "text/plain": [ "'ReLU (Rectified Linear Unit) — это одна из самых популярных функций активации в сверточных нейронных сетях и других типах нейронных сетей. Вот основные характеристики ReLU:\\n\\n1. Основная идея:\\n ReLU представляет собой линейную функцию, которая принимает вход и возвращает его без изменений, если он положительный, и 0, если он отрицательный.\\n\\n2. Формула:\\n \\\\( f(x) = \\\\max(0, x) \\\\)\\n\\n3. Преимущества:\\n - Простота вычислений: быстрое обучение и предсказание.\\n - Меньшая вероятность столкновения с проблемой \"размытия\" (vanishing gradient), особенно при глубоких слоях.\\n - Снижение размерности данных, что может ускорить обучение.\\n\\n4. Недостатки:\\n - Может пропускать \"забытые значения\" (zombie activations): значения, которые всегда будут 0, могут нести информацию о предыдущих этапах обучения.\\n - Нетограниченно градиенты: во время обратного распространения ошибки, если значение выхода становится отрицательным, градиент может быть очень большим, что может привести к \"перекосу\" весов.\\n\\n5. Использование:\\n ReLU обычно используется как альтернатива сигмоидной или тангенс-функции в сверточных нейронных сетях и их комбинациях с другими типами функций активации.\\n\\n6. Обновления:\\n В более современных моделях часто используются вариации ReLU, такие как Leaky ReLU, Parametric ReLU и ELU, которые решают некоторые из недостатков оригинального ReLU.\\n\\nReLU стало стандартной частью многих библиотек для создания и обучения нейронных сетей благодаря своей эффективности и простоте.'" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# batch_decode для декодирования батча, в данном случае батч размера 1\n", "response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]\n", "response" ] }, { "cell_type": "markdown", "metadata": { "id": "q2fAgU-Ern5T" }, "source": [ "Попробуем применить небольшую инструктивную LM для решения задачи с первой части семинара. Классифицируем отзывы c IMDB.\n", "\n", "Загрузим данные." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "94TNWlPdcHD5", "outputId": "4bf73d8d-40c6-497d-c9ac-873a0b47f8ba" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.11/dist-packages/huggingface_hub/utils/_auth.py:94: UserWarning: \n", "The secret `HF_TOKEN` does not exist in your Colab secrets.\n", "To authenticate with the Hugging Face Hub, create a token in your settings tab (https://huggingface.co/settings/tokens), set it as secret in your Google Colab and restart your session.\n", "You will be able to reuse this secret in all of your notebooks.\n", "Please note that authentication is recommended but still optional to access public models or datasets.\n", " warnings.warn(\n" ] }, { "data": { "text/plain": [ "DatasetDict({\n", " train: Dataset({\n", " features: ['review', 'sentiment'],\n", " num_rows: 40000\n", " })\n", " test: Dataset({\n", " features: ['review', 'sentiment'],\n", " num_rows: 10000\n", " })\n", "})" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data = load_dataset(\"scikit-learn/imdb\", split=\"train\").train_test_split(test_size=0.2, seed=42)\n", "data" ] }, { "cell_type": "markdown", "metadata": { "id": "SUIQ1HYWHsOX" }, "source": [ "Возьмем случайный сэмпл и посмотрим на него." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "84w_fS0Xb-Z2", "outputId": "91955586-49a4-47ff-9895-06c523857f03" }, "outputs": [ { "data": { "text/plain": [ "{'review': 'and it doesn\\'t help rohmer\\'s case that a few years later Syberberg came along and made a staggeringly great piece of work on the same subject (with a little help from Wagner).

maybe this movie didn\\'t look so paltry when it came out, without the syberberg film to compare it to, which was probably shot on an even smaller sound stage with fewer resources. I actually can\\'t recall at the moment whether there are horses in the syberberg film. all I know is, the German version is pure magic, while this one looks like some college production documented on film for archival purposes.

the music... la musique... isn\\'t even credited here on IMDb... but someone based it on \\'airs from the 12th-14th centuries\" or something... well it isn\\'t a great help to the film. it comes off as inauthentic and cheesy, comme le frommage mon cher!!!

rohmer is one of those french auteurs who likes his leading men generally quite unattractive, too, and that doesn\\'t help matters. syberberg\\'s Parsifal was adorable, and can be seen on German television today selling some kind of special bicycle he invented. .. .

I shudder to think what watching the syberberg on video is like. I remember that the last time I saw the film in a theater, the print was so bad that the experience was a whopping 5 hour travesty. But even then it would have to surpass what this version has to offer, I\\'m afraid.

points for earnestness, for chutzpah, but... this film simply needed beau-coup more bucks. it doesn\\'t look like a medieval manuscript it looks CHEAPO! BON MARCHE!! oh and yeah, it just ends very arbitrarily with Parsifal going to church and this cheesy passion play being interjected... blah!',\n", " 'sentiment': 'negative'}" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "random_sample = data[\"train\"][1137]\n", "random_sample" ] }, { "cell_type": "markdown", "metadata": { "id": "L8-GaPmGwxwy" }, "source": [ "❓ **Вопрос** ❓\n", "\n", "\n", "> При использовании LLM из-за стохастичности процедуры генерации мы можем получать разные результаты для одного и того же входа. Давайте подумаем, насколько это допустимо в контексте нашей задачи классификации, и для каких задач это имеет смысл?\n", "\n", "\n", "
\n", " Кликни для показа ответа \n", " > Использовать различные процедуры сэмплирования при решении задачи классификации кажется не самым разумным подходом. Это приведет к нестабильным результатам. В продакшн-системах и для получения предсказуемых результатов обычно использую жадное декодирование, что позволяет получать детерминированные предсказания. Для этого в методе `.generate` можно указать `do_sample=False`.\n", " Получать разнообразные ответы может быть разумно например в развлекательных чат-ботах.\n", "

\n" ] }, { "cell_type": "markdown", "metadata": { "id": "bCAsEDJJsMHF" }, "source": [ "Сформируем запрос на классификацию в виде инструкции." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "JPDIS2_PsQ7n" }, "outputs": [], "source": [ "messages = [{\"role\": \"user\", \"content\": f\"Classify this sentiment: {random_sample['review']}\"}]" ] }, { "cell_type": "markdown", "metadata": { "id": "21Uxv7LWscSJ" }, "source": [ "Токенизируем лист сообщений и подготовим `Pytorch`-тензоры." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "xeOomSpacPjl", "outputId": "c8e185fc-b8ab-4bb3-86e8-1a427159fcd8" }, "outputs": [ { "data": { "text/plain": [ "{'input_ids': tensor([[151644, 8948, 198, 2610, 525, 1207, 16948, 11, 3465,\n", " 553, 54364, 14817, 13, 1446, 525, 264, 10950, 17847,\n", " 13, 151645, 198, 151644, 872, 198, 1957, 1437, 419,\n", " 25975, 25, 323, 432, 3171, 944, 1492, 926, 71,\n", " 1174, 594, 1142, 429, 264, 2421, 1635, 2937, 5718,\n", " 652, 7725, 3697, 3156, 323, 1865, 264, 39156, 11307,\n", " 2244, 6573, 315, 975, 389, 279, 1852, 3832, 320,\n", " 4197, 264, 2632, 1492, 504, 51375, 568, 27, 1323,\n", " 23976, 1323, 6206, 36760, 419, 5700, 3207, 944, 1401,\n", " 773, 10854, 1539, 979, 432, 3697, 700, 11, 2041,\n", " 279, 6568, 652, 7725, 4531, 311, 9429, 432, 311,\n", " 11, 892, 572, 4658, 6552, 389, 458, 1496, 9155,\n", " 5112, 6430, 448, 16745, 4963, 13, 358, 3520, 646,\n", " 944, 19091, 518, 279, 4445, 3425, 1052, 525, 26830,\n", " 304, 279, 6568, 652, 7725, 4531, 13, 678, 358,\n", " 1414, 374, 11, 279, 5938, 2319, 374, 10526, 10963,\n", " 11, 1393, 419, 825, 5868, 1075, 1045, 7770, 5670,\n", " 26372, 389, 4531, 369, 93947, 9895, 15757, 1323, 23976,\n", " 1323, 6206, 1782, 4627, 1112, 1187, 88569, 1112, 4436,\n", " 944, 1496, 40757, 1588, 389, 86401, 1112, 714, 4325,\n", " 3118, 432, 389, 364, 4720, 504, 279, 220, 16,\n", " 17, 339, 12, 16, 19, 339, 23631, 1, 476,\n", " 2494, 1112, 1632, 432, 4436, 944, 264, 2244, 1492,\n", " 311, 279, 4531, 13, 432, 4041, 1007, 438, 304,\n", " 3242, 4256, 323, 86747, 11, 21572, 512, 504, 52310,\n", " 1615, 22216, 12069, 27, 1323, 23976, 1323, 6206, 299,\n", " 71, 1174, 374, 825, 315, 1846, 41193, 88037, 1723,\n", " 879, 13151, 806, 6388, 2953, 8789, 5008, 650, 266,\n", " 69078, 11, 2238, 11, 323, 429, 3171, 944, 1492,\n", " 12850, 13, 6568, 652, 7725, 594, 52711, 333, 278,\n", " 572, 40608, 11, 323, 646, 387, 3884, 389, 5938,\n", " 12425, 3351, 11236, 1045, 3093, 315, 3281, 34986, 566,\n", " 35492, 13, 5241, 659, 27, 1323, 23976, 1323, 6206,\n", " 40, 557, 56129, 311, 1744, 1128, 10099, 279, 6568,\n", " 652, 7725, 389, 2766, 374, 1075, 13, 358, 6099,\n", " 429, 279, 1537, 882, 358, 5485, 279, 4531, 304,\n", " 264, 26705, 11, 279, 1173, 572, 773, 3873, 429,\n", " 279, 3139, 572, 264, 62869, 220, 20, 6460, 10137,\n", " 40239, 13, 1988, 1496, 1221, 432, 1035, 614, 311,\n", " 52020, 1128, 419, 2319, 702, 311, 3010, 11, 358,\n", " 2776, 16575, 15757, 1323, 23976, 1323, 6206, 7706, 369,\n", " 54249, 2090, 11, 369, 521, 32997, 79, 1466, 11,\n", " 714, 1112, 419, 4531, 4936, 4362, 70906, 1786, 13346,\n", " 803, 47334, 13, 432, 3171, 944, 1401, 1075, 264,\n", " 41008, 46813, 432, 5868, 49521, 84240, 0, 425, 711,\n", " 37499, 43793, 2928, 14019, 323, 21639, 11, 432, 1101,\n", " 10335, 1602, 85657, 448, 52711, 333, 278, 2087, 311,\n", " 8817, 323, 419, 86747, 11677, 1486, 1660, 946, 28303,\n", " 1112, 52561, 0, 151645, 198, 151644, 77091, 198]],\n", " device='cuda:0'), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", " 1, 1, 1, 1, 1, 1, 1, 1]], device='cuda:0')}" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def tokenize_and_apply_chat_template(messages, tokenizer):\n", " \"\"\"Токенизация списка сообщений messages и применение чат-шаблона\"\"\"\n", " return tokenizer.apply_chat_template(\n", " messages,\n", " tokenize=True,\n", " add_generation_prompt=True,\n", " return_tensors=\"pt\",\n", " return_dict=True,\n", " )\n", "\n", "\n", "tokenized_messages = tokenize_and_apply_chat_template(messages, tokenizer).to(model.device)\n", "\n", "tokenized_messages" ] }, { "cell_type": "markdown", "metadata": { "id": "bJPwvwbqsjpl" }, "source": [ "Сгенерируем ответ от модели." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "eJ0TlXWxcKk2" }, "outputs": [], "source": [ "generated_ids = model.generate(\n", " **tokenized_messages,\n", " do_sample=False, # жадная генерация для детерменированности\n", " max_new_tokens=128 # макс. кол-во новых сгенерированных токенов\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 104 }, "id": "JibUJN6cb-XA", "outputId": "c893f30b-f75e-4d11-b2e1-880fde2b1bf3" }, "outputs": [ { "data": { "application/vnd.google.colaboratory.intrinsic+json": { "type": "string" }, "text/plain": [ "'The sentiment expressed in this text is predominantly negative towards Rohmer\\'s film. The reviewer criticizes several aspects of the movie:\\n\\n1. **Comparison to Syberberg\\'s Work**: The reviewer suggests that Rohmer\\'s film looks dated and inferior when compared to Syberberg\\'s \"staggeringly great\" work, implying that Rohmer\\'s film lacks the quality and depth.\\n\\n2. **Production Quality**: The reviewer describes the film as looking \"paltry,\" \"like some college production,\" and \"CHEAPO! BON MARCHE!!\" indicating poor production values.\\n\\n3. **Music**: The music is criticized as inauthentic and'" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "input_ids_len = len(tokenized_messages[\"input_ids\"][0])\n", "tokenizer.decode(generated_ids[0][input_ids_len:])" ] }, { "cell_type": "markdown", "metadata": { "id": "GeMZA8M2tlNi" }, "source": [ "Исходя из генерации видно, что отзыв положительный, но как получить более понятный результат? Модель вроде бы выдала ответ, но возникает необходимость в его дополнительной обработке." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 35 }, "id": "itM-nlc4tw-c", "outputId": "564eb90e-c302-41ba-f783-05300e9d3c51" }, "outputs": [ { "data": { "application/vnd.google.colaboratory.intrinsic+json": { "type": "string" }, "text/plain": [ "'Negative<|im_end|>'" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "messages = [\n", " {\n", " \"role\": \"user\",\n", " # Добавим пояснение, что ожидаем positive / negative ответ\n", " \"content\": f\"Classify this sentiment: {random_sample['review']}. Return 'positive' or 'negative':\",\n", " }\n", "]\n", "\n", "# Уже знакомый код\n", "tokenized_messages = tokenize_and_apply_chat_template(messages, tokenizer).to(model.device)\n", "generated_ids = model.generate(**tokenized_messages, do_sample=False, max_new_tokens=128)\n", "\n", "input_ids_len = len(tokenized_messages[\"input_ids\"][0])\n", "tokenizer.decode(generated_ids[0][input_ids_len:])" ] }, { "cell_type": "markdown", "metadata": { "id": "EbZfOMbUuhj4" }, "source": [ "Результат получился более предсказуемый и понятный." ] }, { "cell_type": "markdown", "metadata": { "id": "X8PWbmGXeRcG" }, "source": [ "## 2. Введение в [`vLLM`](https://github.com/vllm-project/vllm)\n", "Но что делать, если мы хотим например встроить языковую модель в существующие сервисы нашего проекта или компании? Библиотека `transformers` пригодна для обучения модели или инференса для прототипирования. Однако для промышленного использования она применяется редко. В рамках семинара мы очень коротко познакомимся с библиотекой `vLLM`. `vLLM` — простой в использовании фреймворк для ускоренного инференса и развертывания LLM. Библиотека содержит в себе достаточно большое количество технических особенностей и оптимизаций: Continuous Batching, PagedAttention, оптимизированные CUDA-ядра для ряда архитектур, Speculative Decoding, Structered Output и многое-многое другое. С частью из этого вы сможете познакомиться на DS-потоке!\n", "\n", "Стоит отметить, что помимо `vLLM` есть и другие фреймворки: `llama.cpp`, `TGI`, `sglang`, `exllamav2`, `Infinity Embeddings`, `CTranslate2`." ] }, { "cell_type": "markdown", "metadata": { "id": "z2E1T-iE295W" }, "source": [ "Загрузим модель.\n", "\n", "*В случае использования Colab вы можете столкнуться с OOM, если попытаетесь продолжить исполнение ячеек с vLLM после загрузки HF-модели. Для простоты вам рекомендуется перезапустить среду.*" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 434, "referenced_widgets": [ "9485630b64654d839834c8cdfeddd26b", "8a97c786806543eabb8a604ddbc4dfa4", "8968b72a71b4414d99afde4627a18fc4", "d18797ac96674d399824790777768612", "aa4c5ef7474e40f99b2dfd5526f9ebde", "992e622f8aa6464a85a40ce4e91500b7", "7ffde9bdd7e94d28b0e9cb1a98284f8d", "bb2f735430b647b7a72daad8e3c7813d", "1698755e020042428515bc7a4636d374", "43b3071e669c49d28b2792ea37dcdf0f", "7eae2d857ee34fcd9de0008a93ddd2d6" ] }, "id": "k58K8kYreb9a", "outputId": "23f3b5c5-0f16-47b1-c7e4-46eacbed9a4b" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "INFO 03-28 17:34:25 [__init__.py:239] Automatically detected platform cuda.\n", "WARNING 03-28 17:34:26 [config.py:2614] Casting torch.bfloat16 to torch.float16.\n", "INFO 03-28 17:34:41 [config.py:585] This model supports multiple tasks: {'score', 'embed', 'classify', 'generate', 'reward'}. Defaulting to 'generate'.\n", "WARNING 03-28 17:34:41 [arg_utils.py:1854] Compute Capability < 8.0 is not supported by the V1 Engine. Falling back to V0. \n", "INFO 03-28 17:34:41 [llm_engine.py:241] Initializing a V0 LLM engine (v0.8.2) with config: model='Qwen/Qwen2.5-3B-Instruct', speculative_config=None, tokenizer='Qwen/Qwen2.5-3B-Instruct', skip_tokenizer_init=False, tokenizer_mode=auto, revision=None, override_neuron_config=None, tokenizer_revision=None, trust_remote_code=False, dtype=torch.float16, max_seq_len=32768, download_dir=None, load_format=LoadFormat.AUTO, tensor_parallel_size=1, pipeline_parallel_size=1, disable_custom_all_reduce=False, quantization=None, enforce_eager=False, kv_cache_dtype=auto, device_config=cuda, decoding_config=DecodingConfig(guided_decoding_backend='xgrammar', reasoning_backend=None), observability_config=ObservabilityConfig(show_hidden_metrics=False, otlp_traces_endpoint=None, collect_model_forward_time=False, collect_model_execute_time=False), seed=None, served_model_name=Qwen/Qwen2.5-3B-Instruct, num_scheduler_steps=1, multi_step_stream_outputs=True, enable_prefix_caching=None, chunked_prefill_enabled=False, use_async_output_proc=True, disable_mm_preprocessor_cache=False, mm_processor_kwargs=None, pooler_config=None, compilation_config={\"splitting_ops\":[],\"compile_sizes\":[],\"cudagraph_capture_sizes\":[256,248,240,232,224,216,208,200,192,184,176,168,160,152,144,136,128,120,112,104,96,88,80,72,64,56,48,40,32,24,16,8,4,2,1],\"max_capture_size\":256}, use_cached_outputs=False, \n", "INFO 03-28 17:34:43 [cuda.py:239] Cannot use FlashAttention-2 backend for Volta and Turing GPUs.\n", "INFO 03-28 17:34:43 [cuda.py:288] Using XFormers backend.\n", "INFO 03-28 17:34:44 [parallel_state.py:954] rank 0 in world size 1 is assigned as DP rank 0, PP rank 0, TP rank 0\n", "INFO 03-28 17:34:44 [model_runner.py:1110] Starting to load model Qwen/Qwen2.5-3B-Instruct...\n", "INFO 03-28 17:34:44 [weight_utils.py:265] Using model weights format ['*.safetensors']\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "9485630b64654d839834c8cdfeddd26b", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Loading safetensors checkpoint shards: 0% Completed | 0/2 [00:00