vLLM ومحركات الاستدلال مفتوحة المصدر

نشر vLLM في الإنتاج

4 دقيقة للقراءة

الانتقال من التطوير إلى الإنتاج يتطلب تكويناً دقيقاً للموثوقية والأداء وقابلية التوسع.

نشر Docker

إعداد Docker الأساسي

# Dockerfile لإنتاج vLLM
FROM vllm/vllm-openai:latest

# تعيين متغيرات البيئة
ENV VLLM_WORKER_MULTIPROC_METHOD=spawn
ENV CUDA_VISIBLE_DEVICES=0,1,2,3

# فحص الصحة
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s \
    CMD curl -f http://localhost:8000/health || exit 1

# الأمر الافتراضي
CMD ["--model", "meta-llama/Llama-3.3-70B-Instruct", \
     "--tensor-parallel-size", "4", \
     "--port", "8000"]

Docker Compose لـ Multi-GPU

# docker-compose.yml
version: '3.8'

services:
  vllm:
    image: vllm/vllm-openai:latest
    container_name: vllm-server
    ports:
      - "8000:8000"
    volumes:
      - ~/.cache/huggingface:/root/.cache/huggingface
    environment:
      - HUGGING_FACE_HUB_TOKEN=${HF_TOKEN}
      - CUDA_VISIBLE_DEVICES=0,1,2,3
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 4
              capabilities: [gpu]
    command: >
      --model meta-llama/Llama-3.3-70B-Instruct
      --tensor-parallel-size 4
      --gpu-memory-utilization 0.9
      --max-model-len 32768
      --enable-prefix-caching
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 120s
    restart: unless-stopped

نشر Kubernetes

النشر الأساسي

# vllm-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: vllm-server
  labels:
    app: vllm
spec:
  replicas: 1  # التوسع مع HPA
  selector:
    matchLabels:
      app: vllm
  template:
    metadata:
      labels:
        app: vllm
    spec:
      containers:
      - name: vllm
        image: vllm/vllm-openai:latest
        ports:
        - containerPort: 8000
        args:
        - "--model"
        - "meta-llama/Llama-3.3-70B-Instruct"
        - "--tensor-parallel-size"
        - "4"
        - "--gpu-memory-utilization"
        - "0.9"
        - "--port"
        - "8000"
        resources:
          limits:
            nvidia.com/gpu: 4
            memory: "128Gi"
          requests:
            nvidia.com/gpu: 4
            memory: "64Gi"
        env:
        - name: HUGGING_FACE_HUB_TOKEN
          valueFrom:
            secretKeyRef:
              name: hf-token
              key: token
        volumeMounts:
        - name: model-cache
          mountPath: /root/.cache/huggingface
        livenessProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 120
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 60
          periodSeconds: 10
      volumes:
      - name: model-cache
        persistentVolumeClaim:
          claimName: model-cache-pvc
      nodeSelector:
        nvidia.com/gpu.product: "NVIDIA-A100-SXM4-80GB"
      tolerations:
      - key: "nvidia.com/gpu"
        operator: "Exists"
        effect: "NoSchedule"
---
apiVersion: v1
kind: Service
metadata:
  name: vllm-service
spec:
  selector:
    app: vllm
  ports:
  - port: 8000
    targetPort: 8000
  type: ClusterIP

مقياس الحاوية الأفقي التلقائي

# vllm-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: vllm-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: vllm-server
  minReplicas: 1
  maxReplicas: 4
  metrics:
  - type: Pods
    pods:
      metric:
        name: vllm_num_requests_waiting
      target:
        type: AverageValue
        averageValue: "10"  # التوسع عند الطابور > 10
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 80
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
      - type: Pods
        value: 1
        periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Pods
        value: 1
        periodSeconds: 120

تكوين الإنتاج

إعدادات الخادم المحسنة

# سكريبت تشغيل الإنتاج
#!/bin/bash

export CUDA_VISIBLE_DEVICES=0,1,2,3
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export VLLM_LOGGING_LEVEL=INFO

vllm serve meta-llama/Llama-3.3-70B-Instruct \
    # التوازي
    --tensor-parallel-size 4 \

    # تحسين الذاكرة
    --gpu-memory-utilization 0.92 \
    --max-model-len 32768 \
    --enable-prefix-caching \

    # الجدولة
    --enable-chunked-prefill \
    --max-num-seqs 256 \
    --max-num-batched-tokens 8192 \

    # التكميم (اختياري)
    --quantization fp8 \

    # إعدادات الخادم
    --port 8000 \
    --host 0.0.0.0 \
    --api-key "${VLLM_API_KEY}" \

    # التسجيل
    --disable-log-requests \  # تقليل I/O
    --disable-log-stats       # أو تمكين للمراقبة

موازنة الحمل

# nginx.conf لموازنة حمل vLLM
upstream vllm_cluster {
    least_conn;  # التوجيه إلى الخادم الأقل انشغالاً

    server vllm-1:8000 weight=1;
    server vllm-2:8000 weight=1;
    server vllm-3:8000 weight=1;

    keepalive 32;
}

server {
    listen 80;

    location /v1 {
        proxy_pass http://vllm_cluster;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;

        # دعم البث
        proxy_buffering off;
        proxy_cache off;

        # المهلات للتوليد الطويل
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }

    location /health {
        proxy_pass http://vllm_cluster/health;
    }
}

النشر متعدد العقد

للنماذج الأكبر من سعة العقدة الواحدة:

# العقدة 0 (رأس Ray)
ray start --head --port=6379

# العقدة 1-N (عمال Ray)
ray start --address='head-node-ip:6379'

# تشغيل vLLM عبر المجموعة
vllm serve meta-llama/Llama-3.1-405B-Instruct \
    --tensor-parallel-size 8 \
    --pipeline-parallel-size 2 \
    --distributed-executor-backend ray
# Kubernetes متعدد العقد مع Ray
apiVersion: ray.io/v1
kind: RayCluster
metadata:
  name: vllm-cluster
spec:
  rayVersion: '2.9.0'
  headGroupSpec:
    rayStartParams:
      dashboard-host: '0.0.0.0'
    template:
      spec:
        containers:
        - name: ray-head
          image: vllm/vllm-openai:latest
          resources:
            limits:
              nvidia.com/gpu: 8
  workerGroupSpecs:
  - replicas: 1
    rayStartParams: {}
    template:
      spec:
        containers:
        - name: ray-worker
          image: vllm/vllm-openai:latest
          resources:
            limits:
              nvidia.com/gpu: 8

المراقبة وفحوصات الصحة

# نقطة نهاية فحص صحة مخصصة
import httpx
import asyncio

async def check_vllm_health(base_url: str) -> dict:
    async with httpx.AsyncClient() as client:
        # الصحة الأساسية
        health = await client.get(f"{base_url}/health")

        # المقاييس التفصيلية
        metrics = await client.get(f"{base_url}/metrics")

        # تحليل المقاييس الرئيسية
        return {
            "healthy": health.status_code == 200,
            "num_requests_running": parse_metric(metrics, "vllm_num_requests_running"),
            "num_requests_waiting": parse_metric(metrics, "vllm_num_requests_waiting"),
            "gpu_cache_usage": parse_metric(metrics, "vllm_gpu_cache_usage_perc"),
        }

نشر الإنتاج يتطلب موازنة الأداء والتكلفة والموثوقية. ابدأ بشكل محافظ واضبط بناءً على أنماط الحمل الفعلية.

التالي، سنستكشف محركات الاستدلال البديلة ومتى نختارها. :::

اختبار

الوحدة 2: vLLM ومحركات الاستدلال مفتوحة المصدر

خذ الاختبار