علوم داده - Data Science

Serving مدل‌های بزرگ

مهندسی در لبه تکنولوژی

معماری Serving مدل‌های بزرگ (LLMs) برای کاربردهای بلادرنگ: مهندسی در لبه تکنولوژی

🔴 مقدمه: تغییر پارادایم از CPU به GPU-Scale در Serving مدل‌های بزرگ

استقرار مدل‌های یادگیری ماشین سنتی (مانند XGBoost یا ResNet) در مقایسه با Serving مدل‌های بزرگ (LLM) مانند Llama 3 یا Mixtral، شبیه مقایسه راندن دوچرخه با هدایت یک هواپیمای جت است. این تفاوت نه تنها در مقیاس، بلکه در ماهیت چالش‌ها نیز وجود دارد.

در کاربردهای بلادرنگ (Real-time) برای Serving مدل‌های بزرگ، ما با سه محدودیت سخت روبرو هستیم که معمولاً در تضاد با یکدیگرند:

محدودیتتوضیحچالش
⚡ تأخیر (Latency)کاربر انتظار پاسخ بلافاصله داردTime To First Token
📊 توان عملیاتی (Throughput)هزاران درخواست همزماناستفاده بهینه از GPU
💰 هزینه (Cost)GPU کمیاب و گران استبهینه‌سازی منابع

این سه عامل مثلثی را تشکیل می‌دهند که بهینه‌سازی همزمان هر سه در Serving مدل‌های بزرگ تقریباً غیرممکن است. این راهنما معماری‌هایی را بررسی می‌کند که این مثلث غیرممکن را ممکن می‌سازند.

🔑 نکته کلیدی: موفقیت در Serving مدل‌های بزرگ، هنر ایجاد تعادل هوشمندانه بین Latency، Throughput و Cost است.


🟠 فصل اول: آناتومی یک درخواست استنتاج در Serving مدل‌های بزرگ (Inference Anatomy)

برای طراحی معماری Serving مدل‌های بزرگ، ابتدا باید بفهمیم در دل یک LLM چه می‌گذرد.

⚡ ۱.۱. مرحله پیش‌پردازش (Prefill Phase) در Serving مدل‌های بزرگ

عملکرد: مدل تمام توکن‌های ورودی (Prompt) را به صورت موازی پردازش می‌کند.

ماهیت: محدود به توان محاسباتی (Compute Bound). ماتریس‌های بزرگ در هم ضرب می‌شوند.

چالش: اگر Prompt بسیار طولانی باشد (مثلاً RAG با هزاران توکن)، این مرحله گلوگاه می‌شود و TTFT را افزایش می‌دهد.

🔄 ۱.۲. مرحله تولید (Decode Phase) در Serving مدل‌های بزرگ

عملکرد: مدل توکن‌ها را یکی‌یکی و به صورت متوالی (Autoregressive) تولید می‌کند.

ماهیت: محدود به پهنای باند حافظه (Memory Bandwidth Bound). در هر گام، کل وزن‌های مدل باید از حافظه HBM به واحدهای محاسباتی GPU منتقل شوند.

چالش: این مرحله بسیار کند است و بهره‌وری GPU را به شدت پایین می‌آورد.

هدف معماری در Serving مدل‌های بزرگ: بهینه‌سازی همزمان برای Prefill (برای پاسخ سریع اولیه) و Decode (برای سرعت تایپ پاسخ).

📊 جدول مقایسه دو مرحله در Serving مدل‌های بزرگ

جنبه⚡ PREFILL🔄 DECODE
پردازشموازیمتوالی
محدودیتCompute BoundMemory Bound
بهره‌وری GPUبالاپایین
تأثیر بر TTFTمستقیمغیرمستقیم

🟡 فصل دوم: استراتژی‌های بهینه‌سازی پیشرفته در Serving مدل‌های بزرگ (The Optimization Stack)

قبل از چیدن سرورها، باید نرم‌افزار را برای Serving مدل‌های بزرگ بهینه کنیم.

💾 ۲.۱. مدیریت حافظه با PagedAttention در Serving مدل‌های بزرگ

مدل‌های سنتی حافظه KV Cache را به صورت پیوسته رزرو می‌کردند. این باعث هدررفت شدید حافظه (Fragmentation) می‌شد.

راهکار: تکنیک PagedAttention (معرفی شده توسط vLLM) از ایده «حافظه مجازی» سیستم‌عامل الهام گرفته است. حافظه KV Cache به بلوک‌های کوچک تقسیم می‌شود و به صورت ناپیوسته در حافظه GPU پخش می‌شود.

نتیجه: افزایش توان عملیاتی (Throughput) تا ۱۰ برابر در Serving مدل‌های بزرگ، زیرا می‌توان درخواست‌های (Batch Size) بیشتری را در حافظه جای داد.

📦 ۲.۲. دسته‌بندی پیوسته (Continuous Batching) در Serving مدل‌های بزرگ

در Batching سنتی، اگر یک درخواست تمام شود ولی بقیه درخواست‌های داخل دسته هنوز در حال پردازش باشند، GPU منتظر می‌ماند.

راهکار: در Continuous Batching (یا Iteration-level scheduling)، به محض اینکه پردازش یک درخواست تمام شد، سیستم بلافاصله یک درخواست جدید را جایگزین آن می‌کند. این رویکرد GPU را همیشه مشغول نگه می‌دارد.

🔢 ۲.۳. کوانتیزاسیون (Quantization) در Serving مدل‌های بزرگ

کاهش دقت وزن‌های مدل از FP16 (16 بیت) به INT8 یا INT4.

AWQ (Activation-aware Weight Quantization): روشی نوین که فقط وزن‌های کم‌اهمیت را فشرده می‌کند و وزن‌های حیاتی را با دقت بالا نگه می‌دارد.

مدلحالت عادیکوانتایز ۴ بیتی
70B۱۴۰ گیگابایت (۲×A100)۴۰ گیگابایت (۱×A100)

🎯 ۲.۴. Speculative Decoding در Serving مدل‌های بزرگ

یک مدل کوچک (Draft Model) سریعاً چند توکن حدس می‌زند و مدل اصلی (Target Model) صحت آن‌ها را به صورت موازی تایید می‌کند. اگر حدس‌ها درست باشند، ما چندین گام جلو افتاده‌ایم.


🟢 فصل سوم: الگوهای موازی‌سازی در Serving مدل‌های بزرگ (Parallelism Patterns)

وقتی مدل در یک GPU جا نمی‌شود، چگونه آن را تقسیم کنیم؟

📊 ۳.۱. موازی‌سازی تانسور (Tensor Parallelism – TP) در Serving مدل‌های بزرگ

روش: هر لایه از شبکه عصبی (مثلاً ماتریس‌های Attention) به صورت عمودی برش خورده و بین چند GPU تقسیم می‌شود.

ارتباط: نیاز به ارتباط بسیار سریع بین GPUها دارد (NVLink).

کاربرد: برای کاهش تأخیر (Latency) در یک Node واحد.

📊 ۳.۲. موازی‌سازی پایپ‌لاین (Pipeline Parallelism – PP) در Serving مدل‌های بزرگ

روش: لایه‌های مدل به صورت افقی تقسیم می‌شوند. لایه‌های ۱ تا ۱۰ در GPU-1، لایه‌های ۱۱ تا ۲۰ در GPU-2.

ارتباط: کندتر است و می‌توان از شبکه اترنت استفاده کرد.

کاربرد: وقتی مدل آنقدر بزرگ است که در یک سرور جا نمی‌شود.

📊 جدول مقایسه موازی‌سازی در Serving مدل‌های بزرگ

جنبهTPPP
برشعمودیافقی
ارتباطNVLinkEthernet
Latencyکمزیاد
مناسب براییک Nodeچند Node

🔵 فصل چهارم: معماری مرجع سیستم Serving مدل‌های بزرگ (Reference Architecture)

یک سیستم Enterprise-Grade برای Serving مدل‌های بزرگ شامل اجزای زیر است:

🚪 لایه ۱: دروازه ورودی (The Gateway) در Serving مدل‌های بزرگ

Load Balancer: باید از پروتکل‌های gRPC و SSE (Server-Sent Events) برای استریمینگ پشتیبانی کند.

Queue Management: لود بالانسر باید از «تعداد توکن‌های در حال پردازش» در هر نود آگاه باشد و درخواست‌ها را به نودی با ظرفیت آزاد بیشتر هدایت کند.

🎼 لایه ۲: ارکستراسیون (The Orchestrator) در Serving مدل‌های بزرگ

Ray Serve: استاندارد صنعتی فعلی. Ray به شما اجازه می‌دهد کلاستر پایتونی بسازید که مدیریت منابع GPU، مقیاس‌دهی (Autoscaling) و مدیریت خرابی (Fault Tolerance) را انجام می‌دهد.

Kubernetes (K8s): برای مدیریت کانتینرها، اما مدیریت مستقیم GPU در K8s پیچیده است، لذا Ray روی K8s اجرا می‌شود.

⚙️ لایه ۳: موتور استنتاج (The Inference Engine) در Serving مدل‌های بزرگ

این قلب تپنده سیستم است:

موتورمزایامعایب
🏆 vLLMبالاترین Throughput، PagedAttentionنیاز به تنظیم دقیق
🎯 NVIDIA TRT-LLMبهینه برای انویدیانیاز به کامپایل
🛡️ TGIپایدار و ایمنThroughput کمتر

🔧 لایه ۴: آداپتورها (LoRA Serving) در Serving مدل‌های بزرگ

برای سرویس‌های SaaS که صدها مدل فاین‌تیون شده برای مشتریان مختلف دارند. به جای لود کردن ۱۰۰ مدل کامل، یک مدل پایه لود می‌شود و آداپتورهای سبک LoRA به صورت پوسته روی درخواست‌ها اعمال می‌شوند (Multi-LoRA Serving).

برای مطالعه بیشتر درباره vLLM، مستندات رسمی vLLM را ببینید.

مقاله داخلی ما با عنوان «PagedAttention چیست؟» را مطالعه کنید.


🟣 فصل پنجم: راهنمای پیاده‌سازی گام‌به‌گام Serving مدل‌های بزرگ

📋 سناریو: چت‌بات سازمانی با Llama-3-70B

نیازمقدار
🎯 مدلLlama-3-70B-Instruct
⚡ TTFTزیر ۱۰۰ میلی‌ثانیه
👥 کاربران همزمان۵۰۰
💰 بودجهبهینه

🎯 گام ۱: انتخاب سخت‌افزار در Serving مدل‌های بزرگ

مدل Llama-3-70B در حالت FP16 حدود ۱۴۰ گیگابایت VRAM نیاز دارد:

گزینهسخت‌افزارمزیت
1️⃣ دقت کامل۲× A100 (80GB) + NVLinkکیفیت بالا
2️⃣ کوانتایز AWQ۱× A100 (80GB)هزینه کمتر

تصمیم: برای کیفیت بالا، گزینه ۱ را انتخاب می‌کنیم (FP16).

🎯 گام ۲: انتخاب پشته نرم‌افزاری در Serving مدل‌های بزرگ

  • Engine: vLLM (به خاطر PagedAttention)

  • Serving Framework: Ray Serve

  • API: FastAPI

🎯 گام ۳: کدنویسی انجین در Serving مدل‌های بزرگ

python
# deployment.py
import os
from vllm import AsyncLLMEngine, EngineArgs, SamplingParams
from ray import serve
from fastapi import FastAPI, Request
from fastapi.responses import StreamingResponse
import uuid

app = FastAPI()

@serve.deployment(num_gpus=2)
class VLLMDeployment:
    def __init__(self):
        args = EngineArgs(
            model="meta-llama/Meta-Llama-3-70B-Instruct",
            tensor_parallel_size=2,
            gpu_memory_utilization=0.90,
            max_num_batched_tokens=8192,
            trust_remote_code=True
        )
        self.engine = AsyncLLMEngine.from_engine_args(args)

    async def stream_results(self, results_generator):
        async for request_output in results_generator:
            text_delta = request_output.outputs[0].text
            yield f"data: {text_delta}\n\n"

    @app.post("/generate")
    async def generate(self, request: Request):
        json_body = await request.json()
        prompt = json_body.get("prompt")
        
        sampling_params = SamplingParams(
            temperature=0.7,
            max_tokens=512
        )
        
        request_id = str(uuid.uuid4())
        results_generator = self.engine.generate(
            prompt, sampling_params, request_id
        )
        
        return StreamingResponse(self.stream_results(results_generator))

deployment = VLLMDeployment.bind()

🎯 گام ۴: پیکربندی کلاستر Ray در Serving مدل‌های بزرگ

yaml
apiVersion: ray.io/v1
kind: RayService
metadata:
  name: llama-70b-service
spec:
  serveConfigV2:
    applications:
      - name: llama_app
        importPath: deployment:deployment
        runtimeEnv:
          pip: ["vllm", "ray[serve]"]
  rayClusterConfig:
    workerGroupSpecs:
      - groupName: gpu-group
        rayStartParams: {}
        replicas: 1
        minReplicas: 1
        maxReplicas: 5
        template:
          spec:
            containers:
              - name: ray-worker
                image: rayproject/ray-ml:latest-gpu
                resources:
                  limits:
                    nvidia.com/gpu: 2

🟤 فصل ششم: استراتژی‌های پیشرفته در Serving مدل‌های بزرگ (The “Secret Sauce”)

🎯 ۶.۱. کش‌گذاری پیشوندها (Prefix Caching / Radix Attention) در Serving مدل‌های بزرگ

در بسیاری از کاربردها (مثل چت‌بات با دستورالعمل‌های طولانی «System Prompt»)، بخش ابتدایی پرامپت ثابت است.

تکنیک: Radix Attention (در vLLM موجود است) درخت توکن‌ها را در KV Cache نگه می‌دارد. اگر درخواست جدیدی با همان پرامپت سیستم بیاید، نیازی به محاسبه مجدد آن بخش نیست.

تاثیر: کاهش زمان Prefill تا ۸۰٪ برای پرامپت‌های تکراری.

📊 ۶.۲. نظارت و متریک‌های حیاتی (Observability) در Serving مدل‌های بزرگ

فقط مانیتور کردن مصرف CPU/GPU کافی نیست:

متریکتوضیحاهمیت
⚡ TTFTزمان تا اولین توکن⭐ حیاتی
📊 TPOTسرعت تولید کلمات⭐ حیاتی
📥 Queue Depthدرخواست‌های منتظربالا
💾 KV Cache Usageدرصد پر بودن حافظه⭐ حیاتی

📈 ۶.۳. مقیاس‌دهی خودکار (Autoscaling) در Serving مدل‌های بزرگ

Autoscaling بر اساس CPU اشتباه است. باید بر اساس تعداد درخواست‌های در صف یا تأخیر مقیاس‌دهی کنید.

قانون: اگر avg_queue_wait_time > 200ms، یک کانتینر جدید اضافه کن.


⚫ فصل هفتم: چالش‌های امنیتی و عملیاتی در Serving مدل‌های بزرگ

🛡️ ۷.۱. حمله منع سرویس (DoS) با پرامپت‌های طولانی در Serving مدل‌های بزرگ

یک کاربر مخرب می‌تواند متنی با ۱۰۰ هزار توکن بفرستد و سرور شما را برای دقایقی قفل کند (OOM – Out of Memory).

دفاع: محدود کردن max_model_len در سطح انجین و اعتبارسنجی طول توکن‌ها در سطح API Gateway قبل از رسیدن به مدل.

🛡️ ۷.۲. مدل‌های سمی و گاردریل‌ها (Guardrails) در Serving مدل‌های بزرگ

مدل نباید پاسخ‌های مضر تولید کند.

معماری: اضافه کردن یک لایه میانی (Middleware) که خروجی مدل را قبل از ارسال به کاربر چک می‌کند (مثلاً با استفاده از Llama Guard یا ابزارهای Regex).

📊 جدول چالش‌ها و راهکارها در Serving مدل‌های بزرگ

چالشراهکار
🛡️ DoS با پرامپت طولانیمحدودیت max_model_len
🛡️ خروجی سمیGuardrails و Middleware
💾 KV Cache پرمانیتورینگ و Autoscaling
💰 هزینه GPUکوانتیزاسیون + Spot Instances

✅ نتیجه‌گیری: چک‌لیست نهایی Serving مدل‌های بزرگ

معماری Serving مدل‌های بزرگ در محیط Real-time یک چالش چندوجهی است که مرزهای مهندسی نرم‌افزار و سخت‌افزار را در می‌نوردد.

📌 سه اصل کلیدی در Serving مدل‌های بزرگ

اصلتوضیح
⚙️ انتخاب دقیق انجینvLLM یا TRT-LLM برای PagedAttention
💾 مدیریت هوشمند منابعکوانتیزاسیون + Tensor Parallelism
📈 معماری مقیاس‌پذیرRay Serve روی Kubernetes

💡 پیام نهایی: با پیاده‌سازی این الگوها در Serving مدل‌های بزرگ، سازمان‌ها می‌توانند قدرت هوش مصنوعی مولد را از آزمایشگاه خارج کرده و به شکلی قابل اعتماد و سریع در محصولات واقعی به کار گیرند.

نمایش بیشتر

هادی محمدیان

هادی محمدیان | متخصص پایگاه داده، تحلیل داده و فرآیندهای سازمانی با تجربه عملی در طراحی و بهینه‌سازی زیرساخت‌های داده. در hadimohammadian.ir مفاهیم کاربردی مدیریت پایگاه داده، تحلیل داده، SQL، Python و اصول مهندسی داده را همراه با نگاه فرآیندمحور به زبان فارسی آموزش می‌دهم. هدف من پیوند دادن دانش فنی داده با نیازهای واقعی کسب‌وکار و کمک به سازمان‌ها برای تصمیم‌گیری داده‌محور است.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا