إذا كان المستخدم مطوّرًا واحدًا على حاسوب محمول، فشغّل Ollama: تثبيته يستغرق دقائق، ويُنزّل النماذج بالاسم ويحمّلها عند الطلب. أما لفريق صغير أو جهاز Mac أو خادم بلا GPU أو بطاقة رسوميات استهلاكية، فاختر llama-server من llama.cpp، فهو يخدم نماذج GGUF مع تحكم صريح في الفتحات المتوازية ومفاتيح API ومقاييس Prometheus. ولحركة الإنتاج على وحدات GPU من فئة مراكز البيانات، شغّل vLLM، إذ تحافظ آليتا continuous batching وPagedAttention فيه على إنتاجية مرتفعة مع ازدياد التزامن. وتوفر الخوادم الثلاثة واجهة API متوافقة مع OpenAI، لذا يمكنك البدء بأحدها ثم الانتقال إلى آخر بتغيير base URL واسم النموذج.
ما الذي يُحسّنه كل خادم
يُحسّن Ollama الزمن حتى أول إجابة. يعمل تطبيقًا مكتبيًا أو خدمة في الخلفية، ويُنزّل النماذج بالاسم، ويحمّل النموذج عند أول طلب ثم يُفرغه من الذاكرة بعد فترة خمول مدتها خمس دقائق افتراضيًا وفق الأسئلة الشائعة لـ Ollama. وتحل بضعة متغيرات بيئة OLLAMA_* محل الضبط الدقيق للمُجدوِل، وهذه البساطة هي جوهر الفكرة.
يُحسّن llama.cpp قابلية النقل. إنه محرك استدلال مكتوب بلغة C/C++ ومبني على مكتبة ggml، مع واجهات خلفية Metal لـ Apple Silicon وCUDA وHIP لـ AMD وVulkan وSYCL، ومسارات CPU محسّنة لـ AVX وAVX2 وAVX-512 وAMX وARM NEON. وعندما لا يتسع النموذج في VRAM، يستطيع إبقاء جزء من الطبقات على GPU والباقي في ذاكرة النظام. أما خادم HTTP الخاص به، llama-server، فليس سوى ملف تنفيذي واحد وملف GGUF ومجموعة خيارات. يعرض README المشروع الآن أمرًا موحدًا هو llama serve في قسم البدء السريع، بينما لا تزال وثائق llama-server وصور Docker توفر الملف التنفيذي llama-server المستخدم في هذا المقال.
يُحسّن vLLM الإنتاجية على المسرّعات. يذكر README الخاص به PagedAttention لإدارة ذاكرة KV المؤقتة، وcontinuous batching وchunked prefill وprefix caching، وخدمة عدة محولات LoRA، والتوازي الموتري والتوازي بالأنابيب، وقائمة طويلة من صيغ التكميم. ويدعم وحدات GPU من NVIDIA وAMD وIntel ومعالجات x86 وARM وPowerPC، مع مسرّعات أخرى عبر إضافات عتادية.
باختصار: يناسب Ollama وllama.cpp العتاد المتواضع وعددًا قليلًا من المستخدمين المتزامنين، بينما يبرر vLLM إعداده الأثقل حين تصل طلبات كثيرة في الوقت نفسه. أما الجانب العتادي من القرار، بما في ذلك مقدار الذاكرة الذي تحتاجه الأوزان وذاكرة KV المؤقتة، فيتناوله دليل العتاد لنماذج LLM المحلية.
عميل OpenAI واحد وثلاثة عناوين base URL
تنفذ الخوادم الثلاثة المسارات /v1/chat/completions و/v1/completions و/v1/embeddings و/v1/models و/v1/responses. وتوضح صفحة توافق Ollama مع OpenAI أن دعمه لـ Responses لا يحفظ الحالة. ويوفر llama-server كذلك مسار /v1/messages المتوافق مع Anthropic، ويدرج vLLM إلى جانب مسارات OpenAI كلًا من Anthropic Messages وتفريغ الصوت وواجهات pooling.
احتفظ باختيار الخادم في الإعدادات حتى لا يتغير كود العميل أبدًا:
import os
from openai import OpenAI
# Ollama: http://127.0.0.1:11434/v1
# llama-server: http://127.0.0.1:8080/v1
# vLLM: http://127.0.0.1:8000/v1
client = OpenAI(
base_url=os.environ["LLM_BASE_URL"],
api_key=os.environ.get("LLM_API_KEY", "not-used"),
)
reply = client.chat.completions.create(
model=os.environ["LLM_MODEL"],
messages=[{"role": "user", "content": "Explain HTTP 429 in two sentences."}],
temperature=0.2,
)
print(reply.choices[0].message.content)
تشترط OpenAI SDK وجود سلسلة مفتاح، لذا مرّر قيمة بديلة حين لا يملك الخادم مفتاحًا. يتجاهل Ollama المفتاح محليًا، بينما لا يتحقق llama-server وvLLM منه إلا إذا شُغّلا بمفتاح.
تختلف الخوادم في الحقل model. يتوقع Ollama وسمًا من مكتبته مثل qwen3:8b. ويتوقع vLLM اسم مستودع Hugging Face أو قيمة --served-model-name. أما llama-server الذي يخدم نموذجًا واحدًا فيقدم ما حمّله، ويحدد الخيار --alias الاسم الذي يعيده /v1/models، وفي وضع router يختار الاسمُ النموذجَ.
ينتهي التوافق عند حدود مواصفة OpenAI. يقبل vLLM معاملات إضافية مثل top_k عبر extra_body، ويطبّق افتراضيًا ملف generation_config.json الخاص بالنموذج، ما قد يغيّر قيم أخذ العينات الافتراضية ما لم تمرّر --generation-config vllm. وقد تختلف قوالب المحادثة والمُقسِّمات أيضًا بين تحويل GGUF ونقطة الحفظ الأصلية، لذا شغّل مجموعة التقييم نفسها على الخادمين قبل التبديل، كما يشرح دليل تقييم وكلاء الذكاء الاصطناعي.
صيغ النماذج ومصدر الأوزان
لا تقرأ الخوادم الثلاثة الملفات نفسها، وكثيرًا ما يحسم ذلك المسألة قبل الأداء.
يُنزّل Ollama النماذج من مكتبته بالاسم، ويشغّل مستودعات GGUF من Hugging Face بالأمر ollama run hf.co/{user}/{repo}:{quant}، ويستورد ملفات GGUF محلية أو مجلدات Safetensors عبر ملف Modelfile يشير سطر FROM فيه إلى الأوزان. ولا يُكمّم ملفات GGUF أثناء الاستيراد، لذا كمّمها أولًا بأدوات llama.cpp.
يقرأ llama.cpp صيغة GGUF. تُحوَّل نقطة حفظ Hugging Face بالسكربت convert_hf_to_gguf.py ثم تُكمَّم، أو يُنزَّل ملف GGUF جاهز عبر -hf user/repo:quant. ويذكر README تكميمًا بالأعداد الصحيحة من 1.5 بت إلى 8 بت. وتحتاج نماذج الرؤية أيضًا إلى ملف projector ينزّله -hf تلقائيًا.
يقرأ vLLM مستودعات نماذج Hugging Face ذات أوزان Safetensors، إضافة إلى نقاط حفظ مكمّمة مثل GPTQ وAWQ وFP8 وINT8 وINT4 وcompressed-tensors. وتصف وثائقه دعم GGUF بأنه تجريبي للغاية، وقد انتقل هذا الدعم إلى إضافة خارجية هي vllm-gguf-plugin.
# Ollama: a library model, or a GGUF repository on Hugging Face
ollama pull qwen3:8b
ollama run hf.co/bartowski/Llama-3.2-3B-Instruct-GGUF:Q8_0
# llama.cpp: download a GGUF and serve it
llama-server -hf ggml-org/Qwen3.5-0.8B-GGUF --port 8080
# vLLM: serve a Hugging Face repository
vllm serve Qwen/Qwen3-0.6B --host 127.0.0.1 --port 8000
التزامن والتجميع وذاكرة KV المؤقتة
للتزامن كلفة في الذاكرة. تحتفظ كل سلسلة نشطة بمفاتيح الانتباه وقيمه لكل رمز في سياقها، لذا تنمو الذاكرة بنمو عدد السلاسل المتزامنة مضروبًا في أطوالها، فوق ما تحتاجه الأوزان. وهذا تقدير مفيد لنموذج transformer قياسي:
KV bytes per token = 2 × layers × kv_heads × head_dim × bytes_per_value
Qwen3-8B, 16-bit cache: 2 × 36 × 8 × 128 × 2 = 147,456 bytes = 144 KiB
One 32,768-token sequence: 144 KiB × 32,768 = 4.5 GiB
يؤخذ عدد الطبقات وعدد رؤوس KV وبُعد الرأس من ملف config.json الخاص بالنموذج. وتحتاج أربع سلاسل كهذه إلى 18 GiB من الذاكرة المؤقتة قبل احتساب الأوزان. أما النماذج ذات طبقات الانتباه بالنافذة المنزلقة أو الهجينة فتحتاج أقل، لذا تعطي المعادلة حدًا أعلى في حالتها.
Ollama
يحدد OLLAMA_NUM_PARALLEL عدد الطلبات التي يعالجها كل نموذج محمّل في آن واحد، وتذكر الأسئلة الشائعة أن قيمته الافتراضية 1. وتساوي OLLAMA_MAX_LOADED_MODELS افتراضيًا ثلاثة أضعاف عدد وحدات GPU، أو ثلاثة عند الاستدلال على CPU. ويسمح OLLAMA_MAX_QUEUE افتراضيًا بـ 512 طلبًا في الطابور، يرد الخادم بعدها بخطأ 503. وتحذر الأسئلة الشائعة أيضًا من أن الذاكرة المطلوبة تنمو وفق OLLAMA_NUM_PARALLEL × OLLAMA_CONTEXT_LENGTH. ويختلف وصف طول السياق الافتراضي بين صفحات الوثائق ويعتمد على VRAM المتاحة، لذا اضبطه صراحة وتحقق منه في العمود CONTEXT من مخرجات ollama ps.
OLLAMA_HOST=127.0.0.1:11434 \
OLLAMA_NUM_PARALLEL=4 \
OLLAMA_CONTEXT_LENGTH=16384 \
OLLAMA_KEEP_ALIVE=30m \
ollama serve
llama-server
يقسّم llama-server العمل إلى فتحات (slots). تحمل كل فتحة محادثة واحدة، ويحدد -np عدد الفتحات، والقيمة الافتراضية -1 تعني الاختيار التلقائي. ويكون continuous batching مفعّلًا افتراضيًا، فتنضم الطلبات الجديدة إلى الدفعة الجارية بين خطوات فك الترميز. وعندما يُختار عدد الفتحات تلقائيًا، تتشارك الفتحات كلها مخزنًا موحدًا لـ KV. أما إذا حددت -np بنفسك، فيكون المخزن الموحد معطّلًا افتراضيًا ويُقسَّم -c على الفتحات: -c 32768 -np 4 يعطي كل محادثة 8192 رمزًا. تحقق من النتيجة عبر GET /slots الذي يعرض n_ctx لكل فتحة.
يُضبط التفريغ إلى GPU بالخيار -ngl الذي يقبل رقمًا أو auto (الافتراضي) أو all. وإذا لم يتسع النموذج، فإن الطبقات المتبقية على CPU تتقيد بعرض نطاق ذاكرة النظام، فيعمل النموذج المفرَّغ جزئيًا لكنه يولّد الرموز عادة بسرعة أقل.
llama-server -m /models/qwen3-8b-q4_k_m.gguf \
--host 127.0.0.1 --port 8080 \
-c 32768 -np 4 -ngl all \
--api-key-file /etc/llama/api-keys.txt \
--metrics
vLLM
تقبل آلية continuous batching في vLLM سلاسل جديدة في كل تكرار لفك الترميز ما دامت هناك كتل فارغة في ذاكرة KV المؤقتة، ويخصص PagedAttention هذه الذاكرة في كتل ثابتة الحجم مع نمو السلاسل بدلًا من حجز الطول الأقصى مسبقًا. وعند الإقلاع يحجز vLLM نسبة ذاكرة GPU التي يحددها --gpu-memory-utilization، ويحوّل ما يتبقى بعد الأوزان ومساحة عمل التنشيطات إلى كتل ذاكرة KV. وعندما تنفد الكتل تحت الحمل، يُقصي بعض الطلبات ويعيد حسابها حين تتوفر المساحة، وهو ما يظهر في المقياس vllm:num_preemptions وفي زمن الاستجابة الطرفي.
أهم أدوات الضبط هي --max-model-len لأطول سياق تقبله، و--max-num-seqs لأقصى عدد من السلاسل في التكرار الواحد، و--max-num-batched-tokens، و--gpu-memory-utilization، و--tensor-parallel-size لتوزيع نموذج واحد على عدة وحدات GPU. وخفض --max-model-len إلى ما يحتاجه التطبيق فعلًا هو عادة أرخص طريقة لاستيعاب مزيد من الطلبات المتزامنة.
export VLLM_API_KEY="$(openssl rand -hex 32)"
vllm serve Qwen/Qwen3-8B \
--host 127.0.0.1 --port 8000 \
--max-model-len 32768 \
--max-num-seqs 64 \
--gpu-memory-utilization 0.90
المخرجات المنظَّمة واستدعاء الأدوات
تستطيع الخوادم الثلاثة تقييد المخرجات بمخطط JSON عبر الحقل response_format في OpenAI، ما يجعل هذا الطلب قابلًا للنقل بينها:
schema = {
"type": "object",
"properties": {
"severity": {"type": "string", "enum": ["low", "medium", "high"]},
"summary": {"type": "string"},
},
"required": ["severity", "summary"],
"additionalProperties": False,
}
reply = client.chat.completions.create(
model=os.environ["LLM_MODEL"],
messages=[{"role": "user", "content": "Triage this log line: disk /var is 97% full"}],
response_format={
"type": "json_schema",
"json_schema": {"name": "triage", "schema": schema},
},
)
تقبل واجهة Ollama الأصلية أيضًا القيمة "json" أو مخططًا في الحقل format، وتنصح وثائقه بتكرار المخطط في الموجّه. ويحوّل llama-server مخططات JSON إلى صيغة قواعد GBNF الخاصة به، ويقبل كذلك قواعد جاهزة لأشكال مخرجات أخرى. ويدعم vLLM الحقل response_format والكائن structured_outputs داخل extra_body بالمفاتيح json وregex وchoice وgrammar وstructural_tag. وقد أُزيلت المعاملات القديمة guided_* في الإصدار v0.12.0، كما تشير صفحة structured outputs في vLLM. يضمن فك الترميز المقيَّد صحة البنية لا صحة المضمون، والرد المقطوع بسبب max_tokens يبقى JSON غير صالح، لذا تحقق من كل نتيجة مقابل المخطط في كودك.
يعمل استدعاء الأدوات في الخوادم الثلاثة، لكن بإعداد مختلف:
- يقبل Ollama الحقل
toolsفي/api/chatوفي/v1/chat/completions، بما في ذلك الاستدعاءات المتوازية، للنماذج التي تدعم قوالبها الأدوات. - يدعم llama-server أدوات بأسلوب OpenAI عبر قوالب محادثة Jinja المفعّلة افتراضيًا. وتسرد ملاحظات llama.cpp حول function calling معالجات أصلية لعدة عائلات من النماذج ومعالجًا عامًا احتياطيًا يستهلك رموزًا أكثر. وتبقى الاستدعاءات المتوازية معطلة ما لم يضبط الطلب
"parallel_tool_calls": true. - يحتاج vLLM إلى
--enable-auto-tool-choiceومحلل--tool-call-parserيناسب عائلة النموذج، مثلhermesلـ Qwen2.5 أوllama3_jsonلـ Llama 3.1 و3.2. وتوضح صفحة tool calling في vLLM أن الدوال المسماة وtool_choice="required"تعتمد على structured outputs، بينما لا يضمن الوضعautoأن تُحلَّل الوسائط بنجاح.
vllm serve Qwen/Qwen2.5-7B-Instruct \
--host 127.0.0.1 --port 8000 \
--enable-auto-tool-choice --tool-call-parser hermes
تعامل مع وسائط الأدوات على أنها مدخلات غير موثوقة. فالنموذج هو من يختارها، ويمكن لنص داخل مستند مسترجَع أن يوجّه هذا الاختيار، كما يشرح دليل حقن الموجّهات وأمان MCP.
التشغيل في Docker مع الوصول إلى GPU
على Linux مع وحدات GPU من NVIDIA، ثبّت NVIDIA Container Toolkit أولًا حتى يعمل --gpus. تتبع الأوامر أدناه الصورة والخيارات الموثقة لكل مشروع مع تغيير واحد: يُنشر كل منفذ على 127.0.0.1 فقط. وتنص وثائق Docker حول نشر المنافذ على أن المنافذ المنشورة دون عنوان مضيف تُنشر على جميع عناوين المضيف، وتضيف ملاحظات Docker حول الجدار الناري أن حركة المنافذ المنشورة تُحوَّل قبل أن تراها قواعد ufw.
# Ollama with NVIDIA GPUs
docker run -d --name ollama --gpus=all \
-v ollama:/root/.ollama \
-p 127.0.0.1:11434:11434 \
ollama/ollama
# llama-server, CUDA build
docker run -d --name llama --gpus all \
-v /srv/models:/models:ro \
-p 127.0.0.1:8080:8080 \
ghcr.io/ggml-org/llama.cpp:server-cuda \
-m /models/qwen3-8b-q4_k_m.gguf --host 0.0.0.0 --port 8080 -ngl all
# vLLM with NVIDIA GPUs
docker run -d --name vllm --runtime nvidia --gpus all --ipc=host \
-v ~/.cache/huggingface:/root/.cache/huggingface \
--env "HF_TOKEN=$HF_TOKEN" \
-p 127.0.0.1:8000:8000 \
vllm/vllm-openai:latest \
--model Qwen/Qwen3-8B
داخل الحاوية يجب أن يستمع الخادم على 0.0.0.0، وإلا فلن يصل إليه المنفذ المنشور. وما يُبقيه خاصًا هو 127.0.0.1 في جهة المضيف. ويضيف أمر vLLM الموثق الخيار --ipc=host لأن PyTorch يتبادل البيانات بين العمليات عبر الذاكرة المشتركة، لا سيما في الاستدلال بالتوازي الموتري. ولوحدات GPU من AMD استخدم ollama/ollama:rocm مع --device /dev/kfd --device /dev/dri، أو صورتي llama.cpp server-rocm وserver-vulkan، أو vllm/vllm-openai-rocm. وفي الإنتاج ثبّت وسوم الصور أو قيم digest بدلًا من latest.
الأمان: استماع محلي ومصادقة عند الوكيل
تعامل مع منفذ الاستدلال كما تتعامل مع منفذ قاعدة بيانات. فكل من يصل إليه يستطيع استهلاك وقت GPU لديك، وقراءة كل ما يعيده النموذج، وفي بعض الإعدادات استدعاء مسارات إدارية.
ابدأ بعنوان الاستماع. يستمع Ollama افتراضيًا على 127.0.0.1:11434، ويستمع llama-server على 127.0.0.1:8080. أما vLLM فمختلف: إذا لم يُحدَّد --host فإن مُشغّله يستمع على جميع الواجهات، لذا مرّر دائمًا --host 127.0.0.1 خارج الحاويات.
ثم تحقق مما يحميه مفتاح كل خادم فعلًا:
- لا تملك واجهة Ollama المحلية أي إعداد لمفتاح API. فكل من يصل إلى المنفذ يستطيع استخدامها، لذا لا تشاركها إلا عبر وكيل يُجري المصادقة.
- يتحقق llama-server من
--api-keyأو--api-key-fileعلى واجهته، بينما يبقى/healthعامًا عن قصد. ويشير README إلى أن CORS يعكس افتراضيًا أيOrigin، ويوصي بـ--cors-originsفي الشبكات المحلية. - لا يغطي
--api-keyفي vLLM سوى بضع بادئات مسارات، منها/v1. ويسرد دليل الأمان في vLLM مسارات غير محمية مثل/invocationsالذي يصل إلى دوال الاستدلال نفسها، و/pauseأو/abort_requests، ويوصي بوكيل عكسي لا يسمح إلا بقائمة محددة من نقاط النهاية.
تغطي واجهة أمامية صغيرة على Nginx الحاجتين معًا. فهي تُنهي TLS، وتتحقق من رمز bearer، ولا تمرر إلا /v1/، وتعيد 404 لكل ما عداه.
map $http_authorization $llm_client {
default "";
"Bearer REPLACE_WITH_A_LONG_RANDOM_TOKEN" "team";
}
server {
listen 443 ssl;
server_name llm.example.internal;
ssl_certificate /etc/nginx/tls/llm.crt;
ssl_certificate_key /etc/nginx/tls/llm.key;
client_max_body_size 10m;
location /v1/ {
if ($llm_client = "") { return 401; }
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_buffering off;
proxy_read_timeout 600s;
}
location / {
return 404;
}
}
يسمح proxy_buffering off بوصول الرموز المتدفقة إلى العميل فور توليدها. وإذا كان للخادم الخلفي مفتاحه الخاص، فامنحه الرمز نفسه حتى يفشل أي طلب يتجاوز الوكيل. ولـ Ollama وجّه proxy_pass إلى المنفذ 11434 وأضف proxy_set_header Host localhost:11434 كما في مثال الأسئلة الشائعة. وأضف limit_req حين يتشارك عدة مستخدمين GPU واحدة. وعلى حاسوب المطوّر، تذكّر أن OLLAMA_ORIGINS=* يسمح لأي صفحة ويب تزورها باستدعاء الخادم المحلي عبر متصفحك.
المراقبة وفحوص السلامة
ابدأ بالجاهزية. يعيد /health في llama-server الرمز 503 أثناء تحميل النموذج و200 عندما يصبح جاهزًا، ويوفر vLLM بدوره /health. استخدمهما لفحوص سلامة الحاويات ومجسّات موازن الحمل، لا دليلًا على جودة التوليد.
يعرض vLLM مقاييس Prometheus على /metrics افتراضيًا. وتسرد صفحة المقاييس في vLLM المقاييس vllm:num_requests_running وvllm:num_requests_waiting وvllm:kv_cache_usage_perc، ومدرّجات تكرارية للزمن حتى أول رمز وللتأخير بين الرموز وللتأخير الكلي للطلب، إضافة إلى عدّاد للإقصاءات. ولا يعرض llama-server المسار /metrics إلا عند تشغيله بالخيار --metrics، ومن مقاييسه llamacpp:requests_processing وllamacpp:requests_deferred وllamacpp:prompt_tokens_seconds وllamacpp:predicted_tokens_seconds، بينما يعرض GET /slots حالة كل فتحة.
scrape_configs:
- job_name: vllm
static_configs:
- targets: ["127.0.0.1:8000"]
- job_name: llama-server
static_configs:
- targets: ["127.0.0.1:8080"]
لا تتضمن واجهة Ollama الموثقة نقطة نهاية لـ Prometheus. استخدم GET /api/ps لمعرفة النماذج المحمّلة واستهلاكها من VRAM وطول سياقها وموعد إفراغها، واقرأ حقول التوقيت في كل رد. المدد بالنانوثانية، لذا تساوي سرعة التوليد eval_count / eval_duration × 10^9 رمزًا في الثانية:
curl -s http://127.0.0.1:11434/api/generate \
-d '{"model": "qwen3:8b", "prompt": "Say ready.", "stream": false}' |
jq '{tokens: .eval_count, tokens_per_second: (.eval_count / .eval_duration * 1e9)}'
اضبط التنبيهات على الإشارات التي تعني أن المستخدمين ينتظرون: طابور waiting أو deferred لا ينزل إلى الصفر، واستخدام لذاكرة KV قريب من 1، وعدّاد إقصاءات متصاعد، وزمن حتى أول رمز يرتفع عند p95. تصف مقاييس الخادم السعة، لكنها لا تخبرك أي موجّه أو استدعاء أداة أو خطوة استرجاع أبطأت الطلب، لذا اربطها بتتبع الطلبات كما يشرح دليل قابلية مراقبة وكلاء الذكاء الاصطناعي.
مقارنة جنبًا إلى جنب
| Ollama | llama.cpp llama-server |
vLLM | |
|---|---|---|---|
| مُحسَّن لـ | التثبيت السريع وإدارة النماذج | قابلية النقل على CPU وApple Silicon وGPU الاستهلاكية | الإنتاجية على GPU مراكز البيانات |
| صيغ النماذج | نماذج المكتبة، GGUF، استيراد Safetensors | GGUF | Safetensors من Hugging Face وGPTQ وAWQ وFP8 وغيرها؛ GGUF تجريبي |
| عنوان الاستماع الافتراضي | 127.0.0.1:11434 |
127.0.0.1:8080 |
جميع الواجهات، المنفذ 8000 |
| مفتاح API مدمج | لا يوجد | --api-key، --api-key-file |
--api-key أو VLLM_API_KEY، بادئات مسارات محدودة |
| التزامن | OLLAMA_NUM_PARALLEL لكل نموذج، الافتراضي 1 |
فتحات (-np) مع continuous batching |
continuous batching مع PagedAttention |
| المخرجات المنظَّمة | format، response_format |
response_format، مخطط JSON، GBNF |
response_format، structured_outputs |
| استدعاء الأدوات | tools في المسارات الأصلية ومسارات OpenAI |
قوالب Jinja، معالجات أصلية أو عامة | --enable-auto-tool-choice مع محلل |
| المقاييس | /api/ps وتوقيتات الردود |
/metrics مع --metrics، /slots |
/metrics افتراضيًا |
| الأنسب لـ | مطوّر واحد، النماذج الأولية | الفرق الصغيرة، العتاد المتواضع أو المختلط | عدد كبير من المستخدمين المتزامنين، اتفاقيات SLO للإنتاج |
مسار القرار للتطوير والفرق والإنتاج
مرّ على هذه الأسئلة بالترتيب وتوقف عند أول إجابة واضحة.
- هل يجرّب شخص واحد النماذج على حاسوب محمول أو محطة عمل؟ استخدم Ollama. وانتقل إلى غيره حين تحتاج إلى مقاييس أو مصادقة أو تحكم على مستوى الطلب.
- هل تعمل على Mac أو خادم بلا GPU أو بطاقة استهلاكية بالكاد يتسع النموذج في ذاكرة VRAM الخاصة بها أو لا يتسع إطلاقًا؟ استخدم llama-server. فتكميم GGUF والتفريغ الجزئي يتيحان له العمل حيث يعجز vLLM عن تحميل النموذج.
- هل هو فريق صغير لديه عدد قليل من المستخدمين المتزامنين على جهاز واحد؟ استخدم llama-server مع ضبط
-npعلى ذروة التزامن، ومفتاح API، و--metrics، ووكيل. ويصلح Ollama هنا أيضًا إذا كان الجميع يستخدمون نموذجًا أو نموذجين ويتولى الوكيل المصادقة. - هل تتوقع حركة متزامنة مستمرة، أو أهدافًا لزمن الاستجابة، أو عدة وحدات GPU، أو صيغ تكميم خاصة بـ GPU مثل FP8 أو AWQ؟ استخدم vLLM مربوطًا بـ localhost خلف بوابة، مع صور مثبّتة وجمع مقاييس Prometheus منذ اليوم الأول.
ينتهي الأمر بكثير من الفرق إلى استخدام اثنين منها: Ollama أو llama-server على أجهزة المطورين، وvLLM في staging والإنتاج، وكود عميل OpenAI نفسه في كل مكان. ولا ينجح ذلك إلا إذا شُغّلت مجموعة التقييم على نسخة الإنتاج نفسها، لأن تكميم GGUF ونقطة حفظ FP8 للنموذج ذاته يتصرفان عمليًا كنموذجين مختلفين. ويغطي دليل بنية وكيل الذكاء الاصطناعي في الإنتاج البوابة ومهل الانتظار وإعادة المحاولة والبدائل الاحتياطية التي ينبغي أن تقف أمام أي من هذه الخوادم.
قائمة تحقق للنشر
- اختر الخادم وفق مسار القرار، وسجّل بدقة ملف النموذج والتكميم وقالب المحادثة التي ستخدمها.
- احسب ذاكرة KV المؤقتة لذروة التزامن وأقصى سياق، ثم اضبط
OLLAMA_CONTEXT_LENGTH، أو-cو-np، أو--max-model-lenو--max-num-seqsوفقًا لذلك. - اربط الخوادم بالعنوان
127.0.0.1، ومرّر--host 127.0.0.1إلى vLLM صراحة، وانشر منافذ Docker بالصيغة127.0.0.1:port:port. - ضع TLS والمصادقة وقائمة نقاط النهاية المسموح بها وتحديد معدل الطلبات في وكيل عكسي. ولا تكشف أبدًا منفذ استدلال بلا مصادقة.
- اضبط مفتاحًا على llama-server أو vLLM طبقةً ثانية للحماية، وأبقه خارج سجل الصدفة وطبقات الصورة.
- اجمع
/metricsمن llama-server وvLLM، واستعلم عن/api/psفي Ollama، عبر شبكة خاصة. - أجرِ اختبار حمل بموجّهاتك الخاصة عند التزامن المتوقع، وسجّل الزمن حتى أول رمز والرموز في الثانية وطول الطابور والذاكرة.
- تحقق من المخرجات المنظَّمة مقابل مخططها في الكود، وتعامل مع وسائط الأدوات على أنها مدخلات غير موثوقة.
- ثبّت الإصدارات وقيم digest للصور، وأعد تشغيل مجموعة التقييم كلما تغير الخادم أو ملف النموذج أو التكميم أو الصورة.