الدرس 19 من 22

الأداء والتحسين

vLLM للإنتاج

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

عندما تحتاج أقصى إنتاجية ومستخدمين متزامنين، vLLM هو خادم الاستدلال المُعد للإنتاج. تعلم متى تنتقل من Ollama.

Ollama مقابل vLLM

┌─────────────────────────────────────────────────────────────────┐
│                   مقارنة Ollama و vLLM                          │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  الجانب           │ Ollama         │ vLLM                       │
│  ──────────────────│────────────────│─────────────────────────  │
│  الإعداد          │ أمر واحد       │ يتطلب تكوين               │
│  الإنتاجية        │ جيدة           │ ممتازة (2-4x أعلى)        │
│  المستخدمين       │ محدود          │ مُصمم للتوسع              │
│  الدفعات          │ أساسي          │ دفعات مستمرة              │
│  كفاءة الذاكرة    │ جيدة           │ PagedAttention (أفضل)     │
│  دعم النماذج      │ GGUF فقط       │ تنسيقات متعددة            │
│  الأفضل لـ        │ التطوير        │ خوادم الإنتاج             │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

متى تفكر في vLLM

ابقَ مع Ollama إذا:

  • مستخدم واحد أو فريق صغير
  • تطوير واختبار
  • البساطة أولوية
  • بيئة محدودة الذاكرة

انتقل لـ vLLM إذا:

  • مستخدمين متزامنين (>5-10)
  • متطلبات إنتاجية عالية
  • نشر إنتاجي
  • تحتاج أقصى توكنات/ثانية

تثبيت vLLM

# ثبّت vLLM (يتطلب NVIDIA GPU مع CUDA)
pip install vllm

# أو بإصدار CUDA محدد
pip install vllm --extra-index-url https://download.pytorch.org/whl/cu121

تشغيل خادم vLLM

# ابدأ vLLM بنموذج من HuggingFace
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3.2-3B-Instruct \
    --port 8000

# مع الضغط (AWQ)
python -m vllm.entrypoints.openai.api_server \
    --model TheBloke/Llama-2-7B-AWQ \
    --quantization awq \
    --port 8000

# مع حد ذاكرة GPU
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3.2-3B-Instruct \
    --gpu-memory-utilization 0.9 \
    --port 8000

خيارات تكوين vLLM

# vllm_config.py
from vllm import LLM, SamplingParams

# هيئ محرك vLLM
llm = LLM(
    model="meta-llama/Llama-3.2-3B-Instruct",
    tensor_parallel_size=1,      # GPUs للاستخدام
    gpu_memory_utilization=0.9,  # % من ذاكرة GPU
    max_model_len=4096,          # أقصى طول سياق
    dtype="auto",                # الدقة (auto, float16, bfloat16)
)

# كوّن العينات
sampling_params = SamplingParams(
    temperature=0.7,
    top_p=0.9,
    max_tokens=256,
)

# ولّد
outputs = llm.generate(["ما هو تعلم الآلة؟"], sampling_params)
print(outputs[0].outputs[0].text)

API متوافق مع OpenAI

vLLM يوفر نقطة نهاية متوافقة مع OpenAI.

from openai import OpenAI

# أشر لخادم vLLM
client = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="not-needed"  # vLLM لا يتطلب مفتاح API افتراضياً
)

# استخدم تماماً مثل OpenAI
response = client.chat.completions.create(
    model="meta-llama/Llama-3.2-3B-Instruct",
    messages=[
        {"role": "user", "content": "اشرح الحوسبة الكمية"}
    ],
    temperature=0.7,
    max_tokens=256
)

print(response.choices[0].message.content)

قياس vLLM مقابل Ollama

import time
import requests
import concurrent.futures

def benchmark_endpoint(url: str, payload: dict, num_requests: int = 50):
    """قيّم نقطة نهاية استدلال بطلبات متزامنة."""

    def make_request():
        start = time.time()
        response = requests.post(url, json=payload)
        return time.time() - start, response.status_code

    start_total = time.time()

    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        results = list(executor.map(lambda _: make_request(), range(num_requests)))

    total_time = time.time() - start_total
    latencies = [r[0] for r in results]
    success_count = sum(1 for r in results if r[1] == 200)

    return {
        "total_time": total_time,
        "requests_per_second": num_requests / total_time,
        "avg_latency": sum(latencies) / len(latencies),
        "success_rate": success_count / num_requests
    }

# قيّم Ollama
ollama_result = benchmark_endpoint(
    "http://localhost:11434/api/generate",
    {"model": "llama3.2", "prompt": "مرحباً", "stream": False}
)

# قيّم vLLM
vllm_result = benchmark_endpoint(
    "http://localhost:8000/v1/completions",
    {"model": "meta-llama/Llama-3.2-3B-Instruct", "prompt": "مرحباً", "max_tokens": 50}
)

print(f"Ollama: {ollama_result['requests_per_second']:.1f} طلب/ثانية")
print(f"vLLM: {vllm_result['requests_per_second']:.1f} طلب/ثانية")

ميزة PagedAttention

ابتكار vLLM الرئيسي هو PagedAttention لإدارة ذاكرة فعالة.

┌─────────────────────────────────────────────────────────────────┐
│                   إدارة ذاكرة PagedAttention                    │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  تقليدي (Ollama):                                               │
│  ┌────────────────────────────────────────┐                    │
│  │ طلب 1: [██████████░░░░░░░░░░] 50%     │ مخصص مسبقاً        │
│  │ طلب 2: [████████████░░░░░░░░] 60%     │ مساحة مهدرة        │
│  └────────────────────────────────────────┘                    │
│                                                                 │
│  PagedAttention (vLLM):                                         │
│  ┌────────────────────────────────────────┐                    │
│  │ [R1][R2][R1][R2][R1][R2]...           │ صفحات ديناميكية    │
│  │ الذاكرة مشتركة بكفاءة                  │ ~2-4x مستخدمين أكثر │
│  └────────────────────────────────────────┘                    │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

نشر Docker مع vLLM

# docker-compose.yml
version: '3.8'

services:
  vllm:
    image: vllm/vllm-openai:latest
    ports:
      - "8000:8000"
    volumes:
      - ~/.cache/huggingface:/root/.cache/huggingface
    environment:
      - HUGGING_FACE_HUB_TOKEN=${HF_TOKEN}
    command: >
      --model meta-llama/Llama-3.2-3B-Instruct
      --gpu-memory-utilization 0.9
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
# ابدأ vLLM مع Docker
docker compose up -d

# تحقق من السجلات
docker compose logs -f vllm

بنية هجينة

استخدم كلاً من Ollama و vLLM لاحتياجات مختلفة.

import os

class HybridInference:
    """وجّه الطلبات بين Ollama (تطوير) و vLLM (إنتاج)."""

    def __init__(self):
        self.env = os.getenv("ENVIRONMENT", "development")
        self.ollama_url = "http://localhost:11434"
        self.vllm_url = "http://localhost:8000"

    def generate(self, prompt: str, **kwargs):
        if self.env == "production":
            return self._vllm_generate(prompt, **kwargs)
        return self._ollama_generate(prompt, **kwargs)

    def _ollama_generate(self, prompt: str, **kwargs):
        import ollama
        response = ollama.generate(model="llama3.2", prompt=prompt, **kwargs)
        return response["response"]

    def _vllm_generate(self, prompt: str, **kwargs):
        from openai import OpenAI
        client = OpenAI(base_url=f"{self.vllm_url}/v1", api_key="none")
        response = client.completions.create(
            model="meta-llama/Llama-3.2-3B-Instruct",
            prompt=prompt,
            max_tokens=kwargs.get("num_predict", 256)
        )
        return response.choices[0].text

# الاستخدام
inference = HybridInference()
result = inference.generate("اشرح المحولات في تعلم الآلة")

مصفوفة القرار

المتطلب Ollama vLLM
إعداد سريع الأفضل أكثر تعقيداً
التطوير الأفضل مبالغ فيه
API إنتاجي ممكن الأفضل
تزامن عالي محدود الأفضل
كفاءة الذاكرة جيدة الأفضل
استدلال CPU مدعوم GPU فقط

vLLM يفتح أداء بمستوى الإنتاج. في الوحدة التالية، سننشر نماذج اللغة المحلية مع Docker واستراتيجيات التوسع. :::

اختبار

الوحدة 5: الأداء والتحسين

خذ الاختبار