У вас завалялась пара Tesla V100 по $500 каждая? Или вы нашли их по цене обеда в хорошем ресторане? Поздравляю — вы владелец маленького датацентра. Проблема одна: запустить на них современную 35-миллиардную модель типа Qwen3.5-35B (MoE, кстати) в лоб не выйдет — в FP16 она сожрёт все 32 ГБ и попросит добавки. Но с AWQ 4-bit, правильными туннелями и горсткой костылей мы сделаем из них полноценного AI-репетитора, доступного через Telegram Mini App. Никаких облаков, никаких $20 в месяц подписок.
Эта статья — не пересказ документации. Это хроника того, как заставить Volta (архитектура 2017 года!) работать с моделями 2026 года. Здесь будут команды, конфиги, проклятия в адрес FlashAttention и грязные хаки с SSH. Погнали.
Дата актуальности: 1 июня 2026. Все версии софта — последние на эту дату. Если вы читаете это позже — проверьте совместимость PyTorch и CUDA.
Почему Qwen3.5-35B, а не что-то попроще?
Qwen3.5-35B — это MoE-модель с 35B параметров, из которых активно только ~8B за токен. Она отлично дерётся с конкурентами в коде, а в multi-agent сценариях обходит многие sub-100B модели. Для репетитора — самое то: объясняет, генерирует задачи, проверяет код. Но в полной точности модель весит ~70 ГБ. Даже с двух V100 мы не поместимся. Выход — AWQ.
Внимание: V100 не поддерживает FlashAttention и INT4 тензорные ядра. Это не приговор, но добавит головной боли. Я покажу, как обойти.
Схема архитектуры
| Компонент | Роль | Технология |
|---|---|---|
| Инференс-сервер | Локально на двух V100 (Ubuntu 22.04) | vLLM + AutoAWQ |
| Туннель | Reverse SSH через VPS с белым IP | autossh, systemd |
| Фронтенд | Telegram Bot + Mini App (React) | aiogram 3, nginx |
Шаг 1: Готовим окружение на сервере с V100
Установка драйверов, CUDA и PyTorch — стандарт. Но есть нюанс: не ставьте PyTorch 2.6 с дефолтной сборкой — он тянет FlashAttention для всех архитектур, что на Volta вызовет падение. Лучше собрать PyTorch из исходников с флагом USE_FLASH_ATTENTION=0, или взять прекомпилированный wheel без flash_attn.
# Ubuntu 22.04
sudo apt update && sudo apt upgrade -y
sudo apt install -y nvidia-driver-545 python3-pip git
# CUDA 12.6 (последняя, поддерживающая V100)
wget https://developer.download.nvidia.com/compute/cuda/12.6.0/local_installers/cuda_12.6.0_545.23.06_linux.run
sudo sh cuda_12.6.0_545.23.06_linux.run --silent --toolkit
# PyTorch 2.6.0 без flash-attention
pip install torch==2.6.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126
# Устанавливаем vLLM и AutoAWQ
pip install vllm==0.8.2 autoawq==0.2.8 transformers==4.48.0 accelerate==1.5.0
Ошибка новичка: установить flash-attn и потом гадать, почему модель падает с Illegal instruction. Не ставьте! vLLM сам переключится на eager-режим для Volta, если нет flash_attn.
Шаг 2: Квантуем Qwen3.5-35B в AWQ 4-bit
Берём оригинальную модель от Qwen (она в FP16 весит ~70 ГБ). Квантуем в 4-bit с группой 128 — это даст ~18 ГБ. При квантовании обязательно выключить flash_attn, иначе AutoAWQ упадёт на Volta.
# Скачиваем модель (потребуется ~70 ГБ на диске)
huggingface-cli download Qwen/Qwen3.5-35B --local-dir ./qwen35_full
# Квантуем
CUDA_VISIBLE_DEVICES=0,1 awq quantize \
--model_path ./qwen35_full \
--quant_path ./qwen35_awq_4bit \
--w_bit 4 \
--group_size 128 \
--no_flash_attn
Флаг --no_flash_attn — наше спасение. После квантования директория ./qwen35_awq_4bit весит ~18 ГБ. Она должна поместиться на двух V100, если оставить ~1 ГБ на каждую для кеша.
Шаг 3: vLLM — сервер для инференса
vLLM умеет работать с AWQ и распределять модель на несколько GPU. Но из-за Volta придётся отключить автоматический выбор attention backend. Запускаем вручную:
CUDA_VISIBLE_DEVICES=0,1 vllm serve ./qwen35_awq_4bit \
--tensor-parallel-size 2 \
--dtype auto \
--max-model-len 8192 \
--gpu-memory-utilization 0.95 \
--enable-lora False \
--disable-flash-attn
Почему tensor-parallel-size 2? На V100 NVLink часто отсутствует или работает через PCIe. tensor параллелизм на PCIe даст большой оверхед. На практике лучше device_map='sequential' через huggingface accelerate, но vLLM пока не умеет так с MoE. Если скорость не устраивает — попробуйте --pipeline-parallel-size 2 (экспериментально). У меня вышло ~12 токенов/с — терпимо для репетитора.
После запуска API будет доступен на http://localhost:8000. Проверяем:
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"qwen35_awq","messages":[{"role":"user","content":"Hello"}]}'
Шаг 4: Обратный SSH — достучаться до сервера без белого IP
Сервер с V100 стоит в гараже/датацентре за NAT. Чтобы Telegram бот мог слать запросы к vLLM, нужен VPS с публичным IP. Через reverse SSH пробрасываем порт 8000 наружу.
# На сервере с V100
# Устанавливаем autossh для автоматического переподключения
sudo apt install autossh
# Создаем SSH-ключ и копируем на VPS
ssh-keygen -t ed25519
ssh-copy-id user@vps-ip
# Пробрасываем порт: VPS:8080 -> localhost:8000
autossh -M 0 -o "ExitOnForwardFailure=yes" -o "ServerAliveInterval=30" -o "ServerAliveCountMax=3" \
-R 8080:localhost:8000 user@vps-ip -N -f
Добавьте эту же команду в systemd сервис, чтобы туннель поднимался при старте. Пример unit-файла:
[Unit]
Description=Reverse SSH tunnel to VPS
After=network.target
[Service]
ExecStart=/usr/bin/autossh -M 0 -o "ExitOnForwardFailure=yes" -o "ServerAliveInterval=30" -o "ServerAliveCountMax=3" -R 8080:localhost:8000 user@vps-ip -N -v
Restart=always
User=youruser
[Install]
WantedBy=multi-user.target
Шаг 5: Telegram Mini App для AI-репетитора
Mini App — это веб-страница, которая открывается внутри Telegram. Мы сделаем простой чат-интерфейс, который отправляет сообщения к vLLM через VPS. Бот будет на aiogram 3, вэб-часть — на React, статика раздаётся через nginx на том же VPS.
5.1 Python bot (aiogram)
from aiogram import Bot, Dispatcher, types
from aiogram.types import WebAppInfo
from aiogram.utils import executor
API_TOKEN = "YOUR_BOT_TOKEN"
WEBHOOK_URL = "https://vps-ip/webhook" # если используете webhook
bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)
@dp.message_handler(commands=['start'])
async def start(message: types.Message):
# Кнопка для открытия Mini App
markup = types.InlineKeyboardMarkup()
markup.add(types.InlineKeyboardButton(
text="Открыть репетитора",
web_app=WebAppInfo(url="https://vps-ip/miniapp")
))
await message.answer("Нажми, чтобы начать занятие:", reply_markup=markup)
if __name__ == '__main__':
executor.start_polling(dp, skip_updates=True)
5.2 Mini App frontend (React)
import React, { useState, useEffect } from 'react';
function App() {
const [messages, setMessages] = useState([]);
const [input, setInput] = useState('');
const sendMessage = async () => {
const res = await fetch('http://vps-ip:8080/v1/chat/completions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'qwen35_awq',
messages: [
{ role: 'system', content: 'Ты — AI-репетитор по математике и программированию. Отвечай на русском, используй примеры кода.' },
{ role: 'user', content: input }
]
})
});
const data = await res.json();
const reply = data.choices[0].message.content;
setMessages([...messages, { role: 'user', text: input }, { role: 'assistant', text: reply }]);
setInput('');
};
return (
{messages.map((msg, i) => (
{msg.text}
))}
setInput(e.target.value)} />
);
}
export default App;
Не забудьте добавить CSP-заголовки для безопасности. Mini App должен обслуживаться по HTTPS (используйте Let's Encrypt на VPS).
Типичные проблемы и их решения
| Проблема | Причина | Решение |
|---|---|---|
| FlashAttention error | V100 не поддерживает sm_70 в flash_attn 2.x | Запускать vLLM с --disable-flash-attn или использовать attn_implementation='eager' |
| OOM при загрузке модели | Не хватает VRAM на одной GPU, device_map='auto' пытается разместить слишком много на одной | Явно указать max_memory как в этой статье про RTX 3060 |
| Туннель падает при обрыве сети | SSH-соединение рвётся | Используйте autossh с проверкой живучести |
| Медленная генерация | Tensor parallelism на PCIe, нет FlashAttention | Попробуйте --pipeline-parallel-size 2, увеличьте batch до 4-8 |
FAQ: самые частые вопросы
Почему AWQ, а не GPTQ?
AWQ на V100 показывает на 15–20% больше токенов/с, чем GPTQ. GPTQ использует несимметричное квантование, которое на Volта медленнее. Также AWQ легче калибровать.
Можно ли запустить Qwen3.5-35B на одной V100 32GB?
Нет. Даже в AWQ 4-bit модель занимает ~18 ГБ, но для инференса нужно место на KV-кэш (ещё 2–5 ГБ) и на активации. Две V100 — минимальный порог. Для 397B нужно 128 ГБ.
Какой system prompt оптимален для репетитора?
Я использую такой: Ты — опытный репетитор по математике, физике и программированию. Объясняй просто, используй примеры. Если задача сложная — разбей на шаги. Модель отлично справляется.
А можно ли заменить Telegram на что-то другое?
Конечно. Например, интегрировать с Open WebUI. Но Telegram удобнее для мобильных занятий.
Итог: что мы получили
За $1000–1200 (две V100 b-stock + VPS за $10/мес) вы собрали систему, способную генерировать 10–15 токенов/с на модели, которая ещё год назад требовала H100. Да, это не 100 токенов/с, но для репетитора, который думает пару секунд перед ответом — отлично.
Следующие шаги: добавить RAG на учебники, зашить поддержку голосовых сообщений через Whisper, сделать A/B тестирование промптов. Но это уже совсем другая история.
Единственное, о чём жалею — что не купил V100 год назад, когда они стоили $300. Сейчас рынок наводнён, и этот гайд — ваш шанс собрать коллапс из старья и получить рабочую LLM дома. Пока облачные провайдеры не подняли цены на инференс — действуйте.