Инструменты LLM-инженера: Hugging Face, accelerate, серверы, терминал
Карта инструментов, на которых держатся практики «На вашей машине» ступеней 5–10 — библиотеки Hugging Face, запуск на нескольких GPU, серверы инференса, терминальные помощники, версии и типичные ошибки — и чек-лист, после которого всё это работает у вас.
Зачем это нужно
Заголовок раздела «Зачем это нужно»До сих пор вы писали всё сами: автоград, биграмму, внимание, GPT и KV-кэш. Со ступени 5 практики «🖥 На вашей машине»
переходят на настоящие модели и настоящие инструменты. В одном уроке встретится torchrun --nproc_per_node 4, в другом
accelerate launch, в третьем vllm serve Qwen/Qwen3-8B и запрос через curl, в четвёртом — совет держать открытым nvtop.
Каждый урок объясняет свой инструмент ровно настолько, насколько ему нужно, и общая картина легко теряется.
Этот урок — карта и техосмотр. Разберём, какой инструмент за что отвечает, когда какой выбирать и как диагностировать
типичные поломки. А в конце пройдём чек-лист: скачать маленькую модель, сгенерировать текст через transformers,
поднять её на сервере и обратиться к нему через curl. После этого практики ступеней 5–10 будут работать
у вас без сюрпризов.
Карта инструментов
Заголовок раздела «Карта инструментов»flowchart TB subgraph T["Терминал и железо"] T1["nvidia-smi, nvtop, htop"] --- T2["tmux, watch, curl"] --- T3["CUDA_VISIBLE_DEVICES"] end subgraph E["Окружение"] E1["venv / uv"] --- E2["requirements.txt, pip freeze"] end subgraph H["Экосистема Hugging Face"] H1["huggingface_hub: скачать, кэш"] --> H2["transformers + tokenizers"] H3["datasets"] --> H2 H2 --> H4["peft: LoRA"] --> H5["trl: SFT, DPO, GRPO"] H6["accelerate: устройства, несколько GPU"] --> H2 end subgraph L["Запуск обучения"] L1["python train.py"] --- L2["torchrun"] --- L3["accelerate launch"] end subgraph S["Серверы инференса"] S1["vLLM"] --- S2["SGLang"] --- S3["llama.cpp"] --- S4["Ollama"] end E --> H --> L H --> S
Пойдём по слоям снизу вверх: окружение, библиотеки, запуск на нескольких картах, серверы, терминал.
Окружение и версии
Заголовок раздела «Окружение и версии»Виртуальные окружения и requirements.txt вы освоили в уроке 0.1.2.
Для LLM-инструментов к этому добавляются три правила.
1. Отдельное окружение под каждую «тяжёлую» задачу. vLLM и SGLang при установке требуют определённую версию
PyTorch и могут молча заменить ваш torch. Поэтому держите минимум два окружения: одно для обучения
(torch, transformers, peft, trl), другое для сервера инференса.
uv venv ~/venvs/train --python 3.12 && source ~/venvs/train/bin/activateuv pip install torch transformers datasets accelerate peft trldeactivateuv venv ~/venvs/serve --python 3.12 && source ~/venvs/serve/bin/activateuv pip install vllm # vLLM сам подтянет совместимый с собой torch2. Закрепляйте версии. Запись transformers>=4.45 в requirements.txt означает «любая новее». Через полгода
выйдет мажорная версия, и чужой скрипт сломается. Пример из жизни: в transformers 4.x параметр evaluation_strategy
переименовали в eval_strategy (старое имя потом удалили), а в версии 5 Trainer(tokenizer=...) окончательно уступил место processing_class
(см. урок 4.5.4). Рабочее окружение фиксируйте точными
версиямизакрепление версий зависимостейEN dependency pinningФиксация точных версий библиотек (numpy==2.4.6, а не numpy>=2), чтобы окружение можно было воспроизвести. Снимок текущего окружения — pip freeze > requirements.lock.txt.:
pip freeze > requirements.lock.txt # снимок «что стоит сейчас», с точными версиями (==)pip install -r requirements.lock.txt # восстановить такое же окружение на другой машине3. Первым делом — версии. При любой непонятной ошибке сначала выясните, что именно у вас стоит. Сохраните скрипт
env_check.py и запускайте его, прикладывая вывод к вопросу на форуме или ИИ-ассистенту:
"""env_check.py — что стоит в окружении и видит ли PyTorch видеокарты."""import importlibimport platform
import torch
print("Python", platform.python_version(), "| torch", torch.__version__, "| CUDA в сборке torch:", torch.version.cuda)print("GPU:", torch.cuda.device_count(), [torch.cuda.get_device_name(i) for i in range(torch.cuda.device_count())])for name in ["transformers", "tokenizers", "datasets", "accelerate", "peft", "trl", "vllm", "huggingface_hub"]: try: print(f"{name:16s}", importlib.import_module(name).__version__) except ImportError: print(f"{name:16s} не установлен")На машине без видеокарты, где писался этот урок, вывод был таким (в окружении для обучения):
Python 3.11.15 | torch 2.14.1+cu130 | CUDA в сборке torch: 13.0GPU: 0 []transformers 5.18.0tokenizers 0.23.2datasets 5.0.1accelerate 1.15.0peft 0.21.2trl не установленvllm не установленhuggingface_hub 1.33.0У вас должно быть GPU: 4 ['NVIDIA GeForce RTX 4080', …]. Номер CUDA в сборке torch — версия библиотек CUDA,
с которыми собран PyTorch. Драйвер NVIDIA должен её поддерживать: максимальную версию CUDA для драйвера показывает
правый верхний угол nvidia-smi.
Экосистема Hugging Face: кто за что отвечает
Заголовок раздела «Экосистема Hugging Face: кто за что отвечает»С тремя библиотеками вы познакомились в уроке 4.5.4. Вот вся семья:
| Библиотека | За что отвечает | Где в курсе |
|---|---|---|
huggingface_hub | скачивание и загрузка моделей и датасетов, кэш, токены доступа; CLI hf | везде, где скачиваем модели |
transformers | архитектуры моделей, AutoModel..., generate, pipeline, Trainer | 4.5.4, 6.1, 6.2, 7.2 |
tokenizers | быстрые токенизаторы на Rust; работает внутри AutoTokenizer | 4.2.3 |
datasets | загрузка, map, filter, потоковое чтение огромных корпусов | 4.5.4, 5.1.2, 5.6.2, 6.x |
accelerate | раскладка по устройствам (device_map="auto"), смешанная точность, запуск на нескольких GPU | 6.1.1, 6.4.5, 7.3.1 |
peft | параметрически-эффективное дообучение: LoRA, QLoRA | 6.2 |
trl | пост-трейнинг: SFTTrainer, DPOTrainer, GRPOTrainer | 6.1–6.4 |
safetensors | формат файлов весов: быстрый и безопасный (в отличие от pickle-файлов .bin) | внутри from_pretrained |
Как они связаны: trl построен на transformers и peft, Trainer из transformers использует accelerate, а все
вместе скачивают файлы через huggingface_hub. Поэтому версии в одном окружении должны быть совместимы: обновили
transformers — проверьте, что trl и peft с ним дружат.
Скачивание и кэш. from_pretrained("Qwen/Qwen3-0.6B") скачивает файлы в кэш ~/.cache/huggingface (переменная
HF_HOME из урока 0.1.1 переносит его, например, на большой NVMe).
То же из терминала:
hf download Qwen/Qwen3-0.6B # в кэш; с --local-dir ./qwen3-0.6b — в обычную папкуhf auth login # токен доступа — для «закрытых» моделей (Llama, Gemma)hf cache ls # что лежит в кэше и сколько веситhf cache rm model/Qwen/Qwen3-0.6B # удалить модель из кэшаСтарая команда huggingface-cli в новых версиях huggingface_hub больше не работает — в старых туториалах
замените её на hf. Если Hugging Face недоступен или медленный, есть зеркало hf-mirror.com (переменная HF_ENDPOINT)
и ModelScope — подробности в уроке «Открытые веса».
Запуск на нескольких видеокартах
Заголовок раздела «Запуск на нескольких видеокартах»CUDA_VISIBLE_DEVICES: какие карты видит процесс
Заголовок раздела «CUDA_VISIBLE_DEVICES: какие карты видит процесс»Самый частый инструмент — переменная окружения CUDA_VISIBLE_DEVICESCUDA_VISIBLE_DEVICESEN CUDA_VISIBLE_DEVICESПеременная окружения, которая ограничивает, какие видеокарты видит процесс. Внутри процесса видимые карты нумеруются заново с нуля: при CUDA_VISIBLE_DEVICES=2,3 это cuda:0 и cuda:1.. Она ограничивает, какие карты видит процесс:
CUDA_VISIBLE_DEVICES=0 python train.py --lr 3e-4 & # опыт 1 на карте 0CUDA_VISIBLE_DEVICES=1 python train.py --lr 1e-3 & # опыт 2 на карте 1CUDA_VISIBLE_DEVICES=2,3 python serve.py & # сервис на картах 2 и 3waitТонкость, на которой спотыкаются все: внутри процесса карты перенумеровываются с нуля. Во втором процессе
cuda:0 — это физическая карта 1, в третьем cuda:0 и cuda:1 — физические 2 и 3. Если в коде жёстко написано
device="cuda:1", а процессу видна одна карта, вы получите ошибку «invalid device ordinal».
torchrun и accelerate launch: одна модель на нескольких картах
Заголовок раздела «torchrun и accelerate launch: одна модель на нескольких картах»Чтобы одна модель обучалась сразу на четырёх картах (DDP, FSDP — урок 5.4.3), нужны четыре процесса, которые знают друг о друге. Их запускает torchruntorchrunEN torchrunУтилита PyTorch для запуска распределённого обучения: стартует нужное число процессов и передаёт им RANK, LOCAL_RANK, WORLD_SIZE, MASTER_ADDR и MASTER_PORT через переменные окружения. Пример: torchrun --standalone --nproc_per_node=4 train.py. — утилита, которая ставится вместе с PyTorch:
torchrun --nproc_per_node=4 train_ddp.py # 4 копии скрипта, по одной на картуКаждой копии torchrun выставляет переменные окружения: WORLD_SIZE=4 (сколько всего процессов), RANK и
LOCAL_RANK от 0 до 3 (номер процессаранг процессаEN rankНомер процесса в распределённом запуске, от 0 до world_size − 1. LOCAL_RANK — номер на своей машине, по нему выбирают GPU. Ранг 0 обычно печатает логи и сохраняет чекпоинты.). Скрипт читает LOCAL_RANK, выбирает свою карту
и вызывает torch.distributed.init_process_group("nccl"). Проверочный скрипт ddp_check.py со страницы
«Ваша лаборатория» запускается именно так.
accelerateaccelerate (библиотека Hugging Face)EN Hugging Face AccelerateБиблиотека, которая раскладывает модель и вычисления по устройствам: device_map="auto", смешанная точность, запуск на нескольких GPU (accelerate launch), интеграция с DeepSpeed и FSDP. Используется внутри Trainer и TRL. делает то же самое для кода на Hugging Face. Настройки (сколько карт, bf16, DeepSpeed/FSDP)
задаются один раз диалогом accelerate config, а запуск выглядит так:
accelerate config # один раз: ответить на вопросы о машинеaccelerate launch --num_processes 4 train_grpo.py # Trainer и TRL сами поймут, что их 4accelerate env # версии и настройки — приложить к вопросу об ошибке| Ситуация | Чем запускать |
|---|---|
| Несколько независимых опытов, по одному на карту | CUDA_VISIBLE_DEVICES=i python … |
| Свой код на чистом PyTorch с DDP/FSDP (5.4.3, 5.7.4) | torchrun --nproc_per_node=4 … |
Trainer, TRL, peft (ступень 6) | accelerate launch --num_processes 4 … |
| Модель не помещается на одну карту, нужен только инференс | device_map="auto" в from_pretrained или сервер с тензорным параллелизмом |
Серверы инференса
Заголовок раздела «Серверы инференса»model.generate из transformers хорош для опытов, но медленный для сервиса: он обрабатывает запросы по очереди и тратит
память на KV-кэш с запасом. Движки инференсаинференс-движок (сервер инференса)EN inference engine / serving engineПрограмма, которая держит модель в памяти и обслуживает запросы — планирует батчи, управляет KV-кэшем, отдаёт OpenAI-совместимый API. Примеры — vLLM, SGLang, LMDeploy, llama.cpp. решают это: собирают запросы на лету
в общий батч (непрерывный батчингнепрерывный батчингEN continuous batching (iteration-level scheduling)Состав батча пересматривается после каждого шага decode — закончившиеся запросы уходят, новые встают на их место. Идея системы Orca (2022), стандарт всех современных серверов., урок 7.1.2), хранят KV-кэш страницами (PagedAttentionPagedAttention (страничный KV-кэш)EN PagedAttentionKV-кэш хранится блоками фиксированного размера (например, по 16 токенов), а таблица блоков связывает логические позиции с физическими — как страницы виртуальной памяти в ОС. Основа vLLM.)
и выставляют модель наружу как веб-сервис с OpenAI-совместимым APIOpenAI-совместимый APIEN OpenAI-compatible APIHTTP-интерфейс в формате OpenAI Chat Completions (/v1/chat/completions). Его отдают Ollama, llama-server, vLLM, SGLang, а также DeepSeek и Qwen в облаке — код клиента не меняется.. Последнее
важно: один и тот же код клиента работает с любым из них, меняется только адрес.
| Сервер | Сильная сторона | Формат весов | Адрес по умолчанию |
|---|---|---|---|
| vLLMvLLMEN vLLMОткрытый движок инференса LLM (UC Berkeley): PagedAttention, continuous batching, тензорный параллелизм, OpenAI-совместимый сервер (vllm serve, порт 8000). Стандарт для сервисов и генерации в RL. | максимальная пропускная способность на GPU, тензорный параллелизм, стандарт индустрии | веса с Hub (BF16, FP8, AWQ, GPTQ) | http://localhost:8000/v1 |
| SGLangSGLangEN SGLangДвижок инференса от LMSYS: RadixAttention (переиспользование общего префикса запросов), быстрый структурированный вывод, ранняя поддержка новых DeepSeek и Qwen; OpenAI-совместимый сервер на порту 30000. | то же плюс RadixAttention — переиспользование общего префикса запросов; быстрая поддержка новых китайских моделей | веса с Hub | http://localhost:30000/v1 |
| llama.cppllama.cppEN llama.cppДвижок инференса на C/C++ с минимумом зависимостей: работает на CPU, GPU и их смеси, использует квантованные веса в формате GGUF; сервер llama-server с OpenAI-совместимым API (порт 8080). | работает на CPU, GPU и их смеси, сильное квантование; минимум зависимостей | GGUFGGUF (формат файлов llama.cpp)EN GGUFОдин файл с весами (обычно квантованными), токенизатором, шаблоном чата и метаданными. Типы квантования — Q8_0, Q6_K, Q4_K_M и др. Используют llama.cpp, Ollama, LM Studio. | http://localhost:8080/v1 (llama-server) |
| OllamaOllamaEN OllamaПрограмма для запуска LLM одной командой (ollama run qwen3:8b): своя библиотека моделей в формате GGUF, работа на CPU и GPU, OpenAI-совместимый API на порту 11434. | установка и запуск одной командой, своя библиотека моделей | GGUF внутри | http://localhost:11434/v1 |
Правило выбора: для себя и прототипа — Ollama; модель больше видеопамяти или нужен CPU — llama.cpp; сервис для многих пользователей, RL с генерацией (GRPO), разметка корпуса — vLLM или SGLang.
Две особенности vLLM, которые удивляют новичков. Он сразу забирает около 90% памяти карты (параметр
--gpu-memory-utilization, в свежих версиях по умолчанию 0.92) под веса и KV-кэш — это не утечка. И при старте он проверяет, что в кэш помещается хотя бы
одна последовательность максимальной для модели длины: если памяти не хватает, уменьшите --max-model-len. Подробно серверы разбираются в
уроке 7.1.2, Ollama и llama.cpp — в уроке 7.2.2.
Терминальные помощники
Заголовок раздела «Терминальные помощники»| Команда | Зачем |
|---|---|
nvidia-smi | список карт, занятая память, загрузка, процессы на GPU; nvidia-smi topo -m — как карты соединены |
watch -n 1 nvidia-smi | обновлять вывод любой команды каждую секунду |
nvtop | «диспетчер задач» для видеокарт: графики загрузки и памяти по всем четырём (sudo apt install nvtop) |
htop | загрузка 96 потоков процессора и память; видно, если обучение упёрлось в подготовку данных |
| tmuxtmux (терминальный мультиплексор)EN tmux (terminal multiplexer)Программа, которая держит терминальные сессии на сервере: обучение продолжается, если закрыть окно или оборвётся SSH. tmux new -s имя, отцепиться — Ctrl+b затем d, вернуться — tmux attach -t имя. | терминал, который живёт без вас: обучение не умрёт, если закрыть окно или оборвётся SSH |
curl | отправить HTTP-запрос из терминала — проверить сервер инференса без Python |
df -h, du -sh ~/.cache/huggingface | сколько места на дисках и сколько съел кэш моделей |
Минимум tmux, который нужен каждый день:
tmux new -s train # новая сессия с именем train; внутри запускаете обучение# Ctrl+b, затем d — «отцепиться»: сессия и обучение продолжают работатьtmux ls # список сессийtmux attach -t train # вернуться к сессии (в том числе после переподключения по SSH)Типичные ошибки и что с ними делать
Заголовок раздела «Типичные ошибки и что с ними делать»| Симптом | Причина | Что делать |
|---|---|---|
torch.cuda.OutOfMemoryError: CUDA out of memory | нехватка видеопамятинехватка видеопамяти (CUDA OOM)EN CUDA out of memory (OOM)Ошибка torch.cuda.OutOfMemoryError: веса, активации, градиенты и состояния оптимизатора не помещаются в память карты. Лечат меньшим батчем с накоплением градиентов, bf16, gradient checkpointing, LoRA, квантованием. Китайский сленг — «бао сяньцунь» («взорвать видеопамять»).: веса, активации и состояния оптимизатора не помещаются | nvidia-smi — не занята ли карта другим процессом; меньше батч + накопление градиентов (урок 4.6.3), меньше длина контекста, bf16, gradient checkpointing; для инференса — квантование (7.2) |
| vLLM падает при старте с ошибкой о нехватке памяти под KV-кэш | кэш под максимальную длину контекста не помещается | --max-model-len 8192, больше --gpu-memory-utilization (например, 0.95), --tensor-parallel-size 2; если vLLM пишет, что свободной памяти меньше запрошенной доли (карту занял другой процесс), — наоборот, меньше --gpu-memory-utilization |
TypeError: … unexpected keyword argument 'evaluation_strategy' или ImportError: cannot import name … | код написан под другую версию библиотеки | env_check.py, сверить с версией из туториала, закрепить версии |
После pip install vllm сломалось обучение | vLLM поставил свою версию torch | отдельные окружения для обучения и сервера |
torch.cuda.is_available() → False | CPU-сборка PyTorch или нет драйвера | nvidia-smi; переустановить torch со страницы «Ваша лаборатория» |
| «The NVIDIA driver on your system is too old» | драйвер старее, чем CUDA в сборке torch | обновить драйвер или поставить сборку torch под более старую CUDA |
401 / 403 при скачивании модели | «закрытая» модель: нужно принять лицензию на странице модели и войти | hf auth login с токеном |
| Скачивание еле идёт или диск переполнен | медленная сеть; кэш на маленьком диске | HF_ENDPOINT или ModelScope; HF_HOME на большой диск, hf cache rm |
Address already in use при запуске сервера | порт занят другим сервером | другой --port или найти процесс: lsof -i :8000 |
| Обучение пропало после закрытия терминала | процесс был привязан к окну | запускать в tmux |
torchrun завис на первом шаге | процессы не договорились об обмене (NCCL) | проверить ddp_check.py; разбор зависаний — в уроке 5.7.4 |
Общий алгоритм: прочитать последнюю строку ошибки (там суть), затем первую строку traceback из вашего кода,
затем env_check.py. С этими тремя фактами ИИ-ассистент или форум помогут быстрее всего.
Практика
Заголовок раздела «Практика»На вашей машине: чек-лист
Заголовок раздела «На вашей машине: чек-лист»Пройдите шаги по порядку. Модель — Qwen3-0.6B: веса занимают 1–1.5 ГБ, помещаются на любую карту и даже работают на CPU.
-
Железо.
nvidia-smiпоказывает 4 карты;nvtopоткрывается (если нет —sudo apt install nvtop). Запуститеpython env_check.pyв окружении для обучения:GPU: 4. -
Скачать модель.
hf download Qwen/Qwen3-0.6B. Затемhf cache ls— модель в кэше, видно её размер. -
Сгенерировать текст через transformers. Сохраните и запустите
gen.py:"""gen.py — генерация через transformers. CUDA_VISIBLE_DEVICES=0 python gen.py"""import torchfrom transformers import AutoModelForCausalLM, AutoTokenizerMODEL = "Qwen/Qwen3-0.6B"tok = AutoTokenizer.from_pretrained(MODEL)model = AutoModelForCausalLM.from_pretrained(MODEL, dtype=torch.bfloat16, device_map="cuda:0")messages = [{"role": "user", "content": "Объясни в двух предложениях, что такое KV-кэш."}]text = tok.apply_chat_template(messages, tokenize=False, add_generation_prompt=True,enable_thinking=False) # chat-шаблон Qwen3 (урок 4.2.3) без рассужденийinputs = tok(text, return_tensors="pt").to(model.device)out = model.generate(**inputs, max_new_tokens=120, do_sample=True, temperature=0.7, top_p=0.8)print(tok.decode(out[0, inputs["input_ids"].shape[1]:], skip_special_tokens=True))Пока генерация идёт, посмотрите в
nvtop: занята одна карта, около 1–2 ГБ памяти (оценка). -
Поднять сервер в tmux. В окружении для сервера:
Окно терминала tmux new -s vllmCUDA_VISIBLE_DEVICES=0 vllm serve Qwen/Qwen3-0.6B --port 8000 --max-model-len 8192# дождитесь строки о запуске сервера на порту 8000, затем Ctrl+b, dВ
nvtopвидно, что vLLM занял около 90% памяти карты 0 — так и задумано. -
Обратиться через curl. В обычном терминале:
Окно терминала curl http://localhost:8000/v1/modelscurl http://localhost:8000/v1/chat/completions -H "Content-Type: application/json" -d '{"model": "Qwen/Qwen3-0.6B","messages": [{"role": "user", "content": "Назови три столицы Азии. /no_think"}],"max_tokens": 100, "temperature": 0.7}'Ответ — JSON, текст лежит в
choices[0].message.content./no_think— штатный переключатель Qwen3, который выключает рассуждения. -
То же через Ollama.
curl -fsSL https://ollama.com/install.sh | sh, затемollama run qwen3:0.6b— чат прямо в терминале (выход —/bye). Тот жеcurl-запрос отправьте наhttp://localhost:11434/v1/chat/completionsс"model": "qwen3:0.6b".ollama psпокажет, какие модели загружены и где — на GPU или CPU. -
Несколько карт.
torchrun --nproc_per_node=4 ddp_check.pyсо страницы «Ваша лаборатория» печатает пропускную способность all-reduce. Затемaccelerate config(одна машина, 4 GPU, bf16) иaccelerate env. -
Убрать за собой.
tmux attach -t vllm,Ctrl+C— сервер остановлен, память освобождена (проверьте вnvtop).pip freeze > requirements.lock.txtв обоих окружениях и запишите в журнал (journal/) версии и цифры из шагов 3–7.
В браузере: какой инструмент для какой задачи
Заголовок раздела «В браузере: какой инструмент для какой задачи»Проверь себя
Заголовок раздела «Проверь себя»- Экосистема Hugging Face:
huggingface_hubскачивает,transformersдаёт модели иTrainer,datasetsготовит данные,accelerateраскладывает по устройствам,peft— LoRA,trl— SFT, DPO, GRPO. Версии должны быть совместимы. - Несколько карт: независимые опыты —
CUDA_VISIBLE_DEVICES(внутри процесса нумерация с нуля), одна модель на чистом PyTorch —torchrun, код на Hugging Face —accelerate launch. - Серверы: Ollama — для себя, llama.cpp — CPU и GGUF, vLLM и SGLang — пропускная способность на GPU. У всех
OpenAI-совместимый API, проверка —
curl …/v1/models. - Терминал:
nvidia-smi/nvtop— память и загрузка,htop— процессор,tmux— долгие задачи,curl— проверка серверов. - Отдельные окружения для обучения и сервера,
pip freezeдля воспроизводимости, при любой ошибке — сначалаenv_check.pyи последняя строка traceback.
Дальше: ступень 5 — большие модели. Начнём с законов масштабирования: сколько параметров и данных нужно модели и сколько стоит её обучение — Законы масштабирования.