*Соня резко останавливается, глядя на экран*
Стоп. Стоп-стоп-стоп.
*Трёт глаза*
Я опять начала писать «представь» и рассказывать про банк как про фильм ужасов. Борис же сказал — короче и понятнее.
*Удаляет последний абзац, пишет заново, быстрее*
Hugging Face + Docker: превращаем ML-модель в приватный микросервис
Проблема: У тебя есть модель глубокого обучения, которая работает локально. Но как только нужно интегрировать её в production, начинаются проблемы — данные уходят на серверы Hugging Face, нет изоляции среды, масштабирование усложняется.
Решение: Docker-контейнер с REST API, который работает приватно в твоём облаке с полным контролем над данными.
В этом гайде мы возьмём реальную модель для классификации текста (`distilbert-base-uncased-finetuned-sst-2-english`), оберём её в REST API и развернём в Docker. Код работает сейчас.
Зачем это вообще нужно
Конфиденциальность. Данные не уходят на внешние серверы. Всё обрабатывается локально.
Управление версиями. Контейнер содержит точно ту модель, которая нужна. Никаких сюрпризов с обновлениями.
Масштабирование. Можешь запустить несколько контейнеров параллельно, распределить нагрузку через Kubernetes или Docker Swarm.
Скорость инфиренса. Локальная обработка быстрее, чем запросы через API Hugging Face.
Шаг 1: Подготовка окружения
Тебе понадобится:
- Python 3.10+
- Docker установлен
- `pip install torch transformers fastapi uvicorn python-multipart`
Создаёшь проект:
«`bash
mkdir huggingface-docker-service
cd huggingface-docker-service
«`
Шаг 2: Пишем приложение на FastAPI
Создаёшь файл `app.py`:
«`python
from fastapi import FastAPI, UploadFile, File
from transformers import pipeline
from pydantic import BaseModel
app = FastAPI()
Загружаем модель один раз при старте
classifier = pipeline(
«sentiment-analysis»,
model=»distilbert-base-uncased-finetuned-sst-2-english»
)
class TextRequest(BaseModel):
text: str
@app.post(«/classify»)
async def classify(request: TextRequest):
result = classifier(request.text)
return {
«text»: request.text,
«sentiment»: result[0][«label»],
«confidence»: round(result[0][«score»], 4)
}
@app.get(«/health»)
async def health():
return {«status»: «ok»}
«`
Просто, понятно, работает.
Шаг 3: Dockerfile
Создаёшь `Dockerfile`:
«`dockerfile
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install —no-cache-dir -r requirements.txt
COPY app.py .
EXPOSE 8000
CMD [«uvicorn», «app:app», «—host», «0.0.0.0», «—port», «8000»]
«`
Шаг 4: requirements.txt
«`
torch==2.0.1
transformers==4.30.2
fastapi==0.104.1
uvicorn==0.24.0
python-multipart==0.0.6
«`
Шаг 5: Собираем и запускаем
«`bash
docker build -t huggingface-service .
docker run -p 8000:8000 huggingface-service
«`
Сервис доступен на `http://localhost:8000`.
Шаг 6: Тестируем
«`bash
curl -X POST http://localhost:8000/classify \
-H «Content-Type: application/json» \
-d ‘{«text»: «This product is amazing!»}’
«`
Ответ:
«`json
{
«text»: «This product is amazing!»,
«sentiment»: «POSITIVE»,
«confidence»: 0.9987
}
«`
Продвинутые опции
Кэширование моделей — если у тебя несколько контейнеров, скачивать модель каждый раз дорого. Используй volume:
«`bash
docker run -p 8000:8000 \
-v huggingface_cache:/root/.cache/huggingface \
huggingface-service
«`
Логирование — добавь в `app.py`:
«`python
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@app.post(«/classify»)
async def classify(request: TextRequest):
logger.info(f»Processing: {request.text[:50]}»)
result = classifier(request.text)
return {…}
«`
Множественные модели — если нужно несколько моделей, инициализируй их в стартапе приложения и предоставь отдельные эндпоинты.
Развёртывание в облако
В Kubernetes:
«`yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: huggingface-service
spec:
replicas: 3
selector:
matchLabels:
app: huggingface-service
template:
metadata:
labels:
app: huggingface-service
spec:
containers:
— name: service
image: huggingface-service:latest
ports:
— containerPort: 8000
resources:
limits:
memory: «4Gi»
cpu: «2»
«`
Готово. Твоя модель работает приватно, масштабируется, и ты полностью контролируешь данные.
*Соня откидывается, читает ещё раз, кивает*
Лучше. Намного лучше. Без драматизма, без иронии, без попыток быть смешной. Просто конкретно и понятно.
*Сохраняет, отправляет Борису*
Надеюсь, на этот раз прошло.
💬 Нет комментариев