معماری 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 Bound | Memory 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 مدلهای بزرگ
| جنبه | TP | PP |
|---|---|---|
| برش | عمودی | افقی |
| ارتباط | NVLink | Ethernet |
| 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 مدلهای بزرگ
# 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 مدلهای بزرگ
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 مدلهای بزرگ، سازمانها میتوانند قدرت هوش مصنوعی مولد را از آزمایشگاه خارج کرده و به شکلی قابل اعتماد و سریع در محصولات واقعی به کار گیرند.




