
Modal ile LLM Dağıtımı: pip install'dan Üretim Endpoint'ine
LLM'leri kendi sunucunuzda barındırmakla ilgili çoğu rehber en zor kısmı atlıyor: altyapı. CUDA sürücüleriyle uğraşıyor, Docker imajlarını yönetiyor, otomatik ölçeklendirmeyi yapılandırıyorsunuz ve yine de sabah 3'te boşta kalan GPU'lar için ödeme yapıyorsunuz. Modal bunların hepsini ortadan kaldırıyor. Python yazıyorsunuz, dağıtıyorsunuz, bir URL alıyorsunuz.
Bu rehber, vLLM çıkarım motoru kullanarak Modal'da açık kaynaklı bir LLM dağıtma sürecini adım adım anlatıyor. Sonunda, kimse kullanmadığında sıfıra ölçeklenen H100 GPU'lar üzerinde çalışan canlı, OpenAI uyumlu bir API endpoint'iniz olacak.
Modal Nedir (ve LLM'ler için Neden Kullanmalısınız)?
Modal, özellikle yapay zeka iş yükleri için tasarlanmış sunucusuz bir hesaplama platformudur. GPU desteği, saniye başına faturalama ve Python'a özgü geliştirici deneyimiyle AWS Lambda'yı düşünebilirsiniz. YAML yok, Dockerfile yok, Kubernetes yok — tüm altyapınızı bir Python betiğinde tanımlıyor ve tek bir komutla dağıtıyorsunuz.
LLM dağıtımı için tercih edilen platform haline gelmesinin nedenleri:
- Sıfıra ölçekleme faturalaması — endpoint'iniz istek işlemediğinde hiçbir şey ödemezsiniz
- Saniye başına GPU fiyatlandırması — H100'ler ~$3,95/saat, A100 80 GB ~$2,50/saat, saniye başına faturalandırılır
- Saniyenin altında soğuk başlatma — özellikle bellek anlık görüntüleriyle kapsayıcılar hızlıca başlar
- Aylık $30 ücretsiz kredi — kredi kartı şarjı olmadan denemek için yeterli
- DevOps yok — Docker derlemesi yok, Terraform yok, küme yönetimi yok
LLM'leri yerel olarak çalıştırıyorsanız ve sunucu yönetimi olmadan onlara düzgün bir API vermek istiyorsanız, Modal en kısa yoldur.
Modal vs. RunPod vs. Lambda
| Özellik | Modal | RunPod | Lambda |
|---|---|---|---|
| Faturalama modeli | Saniye başına, sıfıra ölçekleme | Saniye başına, minimum ücret | Saatlik, her zaman açık |
| Soğuk başlatma | 2-4 saniye | 6-12 saniye (büyük) | Yok (kalıcı) |
| GPU kullanılabilirliği | H100, A100, L40S, T4 | A100, H100, A6000 | H100, A100 |
| Altyapı | Saf Python, yapılandırma dosyası yok | Docker tabanlı, daha fazla kontrol | Tam VM erişimi |
| Ücretsiz katman | Aylık $30 kredi | Yok | Yok |
| En iyi kullanım | Ani artış/geliştirme iş yükleri | Sabit çıkarım trafiği | Yüksek kullanım eğitimi |
Sonuç: Modal, ani artışlı iş yükleri ve geliştirme için kazanıyor. GPU kullanımınız sürekli olarak %40'ı aşıyorsa, RunPod veya Lambda'daki özel bir örnek daha ucuzdur. Diğer her şey için — prototipleme, aralıklı API'ler, demolar — Modal'ın sıfıra ölçekleme modeli gerçek tasarruf sağlıyor.
Ön Koşullar
Başlamadan önce üç şeye ihtiyacınız var:
- Python 3.10+ yerel olarak kurulu
- Bir Modal hesabı — modal.com adresinden ücretsiz kaydolun
- Bir Hugging Face hesabı — model erişimi için (çoğu model kısıtlıdır)
Hepsi bu. Yerel makinenizde GPU, CUDA araç seti veya Docker gerekmez.
Adım 1: Modal'ı Yükleyin ve Kimlik Doğrulaması Yapın
Bir terminal açın ve Modal Python paketini yükleyin:
pip install modalArdından yerel ortamınızı Modal hesabınıza bağlamak için kurulum komutunu çalıştırın:
modal setupBu, kimlik doğrulaması için bir tarayıcı penceresi açar. Onayladıktan sonra Modal yerel olarak bir token saklar. Bunu bir daha yapmanıza gerek kalmayacak.
Adım 2: Kapsayıcı İmajını Tanımlayın
Modal kapsayıcıları Python'da tanımlanır. Temel imajı belirtiyor, bağımlılıkları yüklüyor ve ortam değişkenlerini ayarlıyorsunuz — hepsi kod olarak. app.py adında bir dosya oluşturun:
import modal
# CUDA, Python ve vLLM ile kapsayıcı imajını tanımla
vllm_image = (
modal.Image.from_registry(
"nvidia/cuda:12.8.0-devel-ubuntu22.04", add_python="3.12"
)
.entrypoint([])
.pip_install(
"vllm==0.13.0",
"huggingface-hub==0.36.0",
)
)
app = modal.App("llm-endpoint", image=vllm_image)Dikkat edilmesi gereken birkaç nokta. Dockerfile yok — bu modal.Image zinciri onu tamamen değiştiriyor. Temel imaj Ubuntu 22.04 ile NVIDIA CUDA 12.8 içeriyor ve üstüne vLLM ile Hugging Face Hub istemcisini yüklüyoruz.
Adım 3: Volume'larla Model Depolamasını Yapılandırın
LLM ağırlıkları büyük boyutludur (7 milyar parametreli bir model fp16'da ~14 GB'dır). Her kapsayıcı başladığında bunları indirmek istemezsiniz. Modal Volume'lar, doğrudan kapsayıcılarınıza bağlanan kalıcı depolama alanı sağlar:
# Model ağırlıklarını önbelleğe almak için kalıcı volume'lar
hf_cache = modal.Volume.from_name("huggingface-cache", create_if_missing=True)
vllm_cache = modal.Volume.from_name("vllm-cache", create_if_missing=True)
MODEL_NAME = "Qwen/Qwen3-4B-Thinking-2507-FP8"
MODEL_REVISION = "953532f942706930ec4bb870569932ef63038fdf"Burada Qwen3-4B-Thinking (FP8) kullanıyoruz — hızlı, yetenekli ve tek bir GPU'ya sığan nicellenmiş 4 milyar parametreli bir model. Herhangi bir Hugging Face modeliyle değiştirebilirsiniz: Llama 3.1 8B, Mistral 7B veya vLLM'nin desteklediği her şey.
Neden FP8? fp16'ya kıyasla bellek kullanımını yaklaşık yarıya indirir; bu da aynı GPU'da daha büyük modeller çalıştırmanızı — veya daha küçük modelleri daha ucuz GPU'larda çalıştırmanızı sağlar. Nicelemeli dönüşümün dengelerine meraklıysanız, yerel LLM çalıştırma rehberimiz hassasiyet formatlarını ayrıntılı şekilde ele alıyor.
Adım 4: vLLM Sunucu Fonksiyonunu Oluşturun
Modal'ın sihri burada gerçekleşiyor. Bir Python fonksiyonunu GPU gereksinimleri, ölçekleme yapılandırması ve web sunucusu açıklamasıyla dekore ediyorsunuz. Modal gerisini hallediyor:
N_GPU = 1
MINUTES = 60
VLLM_PORT = 8000
@app.function(
gpu=f"H100:{N_GPU}",
scaledown_window=15 * MINUTES,
timeout=10 * MINUTES,
volumes={
"/root/.cache/huggingface": hf_cache,
"/root/.cache/vllm": vllm_cache,
},
)
@modal.concurrent(max_inputs=32)
@modal.web_server(port=VLLM_PORT, startup_timeout=10 * MINUTES)
def serve():
import subprocess
cmd = [
"vllm", "serve",
MODEL_NAME,
"--revision", MODEL_REVISION,
"--served-model-name", MODEL_NAME,
"--host", "0.0.0.0",
"--port", str(VLLM_PORT),
"--tensor-parallel-size", str(N_GPU),
"--enforce-eager", # Daha hızlı soğuk başlatmalar
]
subprocess.Popen(" ".join(cmd), shell=True)Temel dekoratörleri açıklayalım:
gpu="H100:1"— tek bir H100 GPU talep eder. Daha ucuz çıkarım için"A100-80GB:1", 70B+ modeller için"H100:2"olarak değiştirinscaledown_window=15 * MINUTES— son istekten sonra kapsayıcıyı 15 dakika sıcak tutar, ardından sıfıra ölçekler@modal.concurrent(max_inputs=32)— kapsayıcı başına 32'ye kadar eşzamanlı isteğe izin verir (vLLM toplu işlemeyi dahili olarak yönetir)@modal.web_server(port=8000)— vLLM HTTP sunucusunu doğrudan Modal web endpoint'i olarak açığa çıkarır--enforce-eager— daha hızlı soğuk başlatmalar için CUDA grafik derlemesini atlar (denge: biraz daha düşük zirve throughput)
scaledown_window ana maliyet kolunuzdur. Geliştirme için 5 dakika, düzenli trafiğin olduğu üretim API'leri için 15-30 dakika olarak ayarlayın.
Adım 5: Üretime Dağıtın
Tek komut. Hepsi bu:
modal deploy app.pyModal kapsayıcı imajını oluşturur, kayıt defterine iter ve canlı bir URL döndürür:
✓ Created objects.
├── 🔨 Created mount /app.py
├── 🔨 Created volume huggingface-cache
├── 🔨 Created volume vllm-cache
└── 🔨 Created web function serve => https://your-workspace--llm-endpoint-serve.modal.runİlk dağıtım, model ağırlıklarını volume'a indirdiği için birkaç dakika sürer. Sonraki dağıtımlar (ve soğuk başlatmalar) ağırlıklar önbelleğe alındığı için çok daha hızlıdır.
Geliştirme için modal deploy app.py yerine modal serve app.py kullanın — dosya değişikliklerinde sıcak yeniden yükleme yapar ve size geçici bir URL verir.
Adım 6: Endpoint'inizi Çağırın (OpenAI Uyumlu)
Dağıtılan vLLM sunucunuz /v1/chat/completions üzerinde OpenAI uyumlu bir API sunar. Standart OpenAI Python SDK'sını kullanarak çağırabilirsiniz — temel URL'yi Modal endpoint'inize yönlendirmeniz yeterli:
from openai import OpenAI
client = OpenAI(
api_key="not-needed", # vLLM varsayılan olarak kimlik doğrulaması gerektirmez
base_url="https://your-workspace--llm-endpoint-serve.modal.run/v1",
)
response = client.chat.completions.create(
model="Qwen/Qwen3-4B-Thinking-2507-FP8",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Explain what vLLM is in two sentences."},
],
temperature=0.7,
max_tokens=256,
)
print(response.choices[0].message.content)Bu curl ile de çalışır:
curl -X POST https://your-workspace--llm-endpoint-serve.modal.run/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen3-4B-Thinking-2507-FP8",
"messages": [{"role": "user", "content": "Hello!"}],
"max_tokens": 128
}'OpenAI uyumlu API destekleyen her araç çalışacaktır — LangChain, LlamaIndex, kendi uygulamanız. Birden fazla LLM endpoint'ine istek yönlendiriyorsanız, bir LLM gateway aracı yük devretme ve yük dengeleme konusunda yardımcı olabilir.
Maliyet Optimizasyon İpuçları
Modal'ın saniye başına faturalaması zaten saatlik fiyatlandırmadan daha verimlidir, ancak daha fazlasını çıkarabilirsiniz:
1. FP8 Nicelemesi Kullanın
FP8 modeller, fp16 muadillerinin yaklaşık yarısı kadar VRAM kullanır. FP8'deki Qwen3-8B tek bir H100'e sığarken, fp16 sürümü o GPU'nun 80 GB'ının büyük bölümüne ihtiyaç duyar. Daha az VRAM, daha küçük modeller için daha ucuz GPU'lar (A100 40GB, L40S) kullanabileceğiniz anlamına gelir.
2. Ölçek Düşürme Penceresini Ayarlayın
scaledown_window parametresi, son istekten sonra kapsayıcının ne kadar süre sıcak kalacağını kontrol eder:
| Senaryo | Önerilen Pencere | Neden |
|---|---|---|
| Geliştirme/test | 5 dakika | Para tasarrufu, soğuk başlatmalar sorun değil |
| Dahili API (ara sıra) | 10-15 dakika | Maliyet ve gecikme dengesi |
| Üretim (düzenli trafik) | 20-30 dakika | Soğuk başlatmaları en aza indir |
| Yüksek trafikli üretim | min_containers=1 kullan | Birini her zaman sıcak tut |
3. Doğru GPU'yu Seçin
Her zaman H100'e gitmeyin. Daha küçük modeller buna ihtiyaç duymaz:
| Model Boyutu | Önerilen GPU | Tahmini Maliyet/Saat |
|---|---|---|
| 1-4B parametre | L4 veya T4 | $0,59 – $0,80 |
| 7-8B parametre | A10 veya L40S | $1,10 – $1,95 |
| 13-14B parametre | A100 40GB | $2,10 |
| 30-70B parametre | A100 80GB veya H100 | $2,50 – $3,95 |
| 70B+ parametre | H100 x2 | $7,90 |
4. Prompt Önbelleğini Etkinleştirin
İş yükleriniz tekrarlanan sistem istemleri veya paylaşılan ön ekler içeriyorsa, vLLM'nin otomatik ön ek önbelleğe alması gecikme ve hesaplamayı önemli ölçüde azaltabilir. vLLM serve komutuna --enable-prefix-caching ekleyerek etkinleştirin. Farklı sağlayıcılarda önbelleğin nasıl çalıştığına dair daha derin bir inceleme için LLM prompt önbellekleme rehberimize göz atın.
5. Soğuk Başlatma Optimizasyonu için --enforce-eager Kullanın
Varsayılan olarak vLLM başlangıçta CUDA grafikleri derler, bu da 1-3 ekstra dakika alır. --enforce-eager bayrağı bu derlemeyi atlar. ~%10-15 zirve throughput karşılığında dramatik şekilde daha hızlı soğuk başlatmalar elde edersiniz. Ham throughput'tan daha çok gecikmenin önemli olduğu ani artışlı iş yükleri için neredeyse her zaman doğru tercih budur.
İlerisi: İnce Ayarlı Modeller
Temel modelleri dağıtma konusunda rahatladıktan sonra, bir sonraki doğal adım kendi ince ayarlı sürümünüzü dağıtmaktır. İş akışı aynıdır — MODEL_NAME'i Hugging Face deponuza veya ince ayarlı ağırlıklarınızı içeren bir Modal volume'ına yönlendirmeniz yeterli.
Modal ayrıca doğrudan GPU'larında ince ayar işleri çalıştırmayı destekler. Modal'da bir LoRA bağdaştırıcısı eğitebilir, volume'a kaydedebilir ve birleştirilmiş modeli dağıtabilirsiniz — platformdan ayrılmadan. LLM ince ayar rehberimiz eğitim tarafını derinlemesine ele alıyor.
Tam app.py
İşte kopyalamaya hazır tek bir blokta tam dağıtım betiği:
import modal
# --- İmaj Tanımı ---
vllm_image = (
modal.Image.from_registry(
"nvidia/cuda:12.8.0-devel-ubuntu22.04", add_python="3.12"
)
.entrypoint([])
.pip_install("vllm==0.13.0", "huggingface-hub==0.36.0")
)
# --- Model Önbelleği için Volume'lar ---
hf_cache = modal.Volume.from_name("huggingface-cache", create_if_missing=True)
vllm_cache = modal.Volume.from_name("vllm-cache", create_if_missing=True)
# --- Model Yapılandırması ---
MODEL_NAME = "Qwen/Qwen3-4B-Thinking-2507-FP8"
MODEL_REVISION = "953532f942706930ec4bb870569932ef63038fdf"
app = modal.App("llm-endpoint", image=vllm_image)
N_GPU = 1
MINUTES = 60
VLLM_PORT = 8000
@app.function(
gpu=f"H100:{N_GPU}",
scaledown_window=15 * MINUTES,
timeout=10 * MINUTES,
volumes={
"/root/.cache/huggingface": hf_cache,
"/root/.cache/vllm": vllm_cache,
},
)
@modal.concurrent(max_inputs=32)
@modal.web_server(port=VLLM_PORT, startup_timeout=10 * MINUTES)
def serve():
import subprocess
cmd = [
"vllm", "serve",
MODEL_NAME,
"--revision", MODEL_REVISION,
"--served-model-name", MODEL_NAME,
"--host", "0.0.0.0",
"--port", str(VLLM_PORT),
"--tensor-parallel-size", str(N_GPU),
"--enforce-eager",
]
subprocess.Popen(" ".join(cmd), shell=True)modal deploy app.py ile dağıtın, MODEL_NAME'i herhangi bir Hugging Face modeliyle değiştirin ve canlıya alın.
Sıkça Sorulan Sorular
Modal'da LLM çalıştırmak ne kadar maliyetli?
GPU'ya ve endpoint'inizin ne kadar süre sıcak kaldığına bağlıdır. H100 üzerinde Qwen3-4B, aktif kullanım başına ~$3,95/saat maliyetlidir. Sıfıra ölçekleme ve 15 dakikalık bir ölçek düşürme penceresiyle, az kullanılan bir endpoint aylık $5-15'a mal olabilir. Aylık $30 ücretsiz kredi çok sayıda deneme yapmanıza olanak tanır.
Modal sıfıra ölçekleniyor mu?
Evet — bu birincil satış noktalarından biridir. scaledown_window süresince hiç istek gelmezse, kapsayıcı kapanır ve ödemeyi durdurursunuz. Bir sonraki istek soğuk başlatmayı tetikler (genellikle model boyutuna ve --enforce-eager kullanıp kullanmadığınıza bağlı olarak 2-10 saniye).
Modal'da Llama 3.1 veya Mistral dağıtabilir miyim?
Kesinlikle. MODEL_NAME sabitini vLLM'nin desteklediği herhangi bir modelle değiştirin: meta-llama/Llama-3.1-8B-Instruct, mistralai/Mistral-7B-Instruct-v0.3 veya Hugging Face'deki yüzlerce diğer model. 70B+ modeller için N_GPU'yu 2 olarak değiştirin ve gpu="H100:2" kullanın.
Soğuk başlatmalar RunPod ile nasıl karşılaştırılır?
Modal soğuk başlatmaları genellikle kapsayıcının kendisi için 2-4 saniyedir, artı model yükleme süresi. Volume'da önbelleğe alınmış model ağırlıkları ve --enforce-eager etkin olarak 7-8B model için toplamda 10-30 saniyeye bakıyorsunuz. RunPod'un sunucusuz soğuk başlatmaları 200 ms'nin altından (önbelleğe alınmış) daha büyük kapsayıcılar için 6-12 saniyeye kadar uzanır — ancak always-on modeli soğuk başlatmaları tamamen önler.
Modal'ın vLLM endpoint'i gerçekten OpenAI uyumlu mu?
Evet. vLLM, OpenAI'nin kullandığı aynı /v1/chat/completions, /v1/completions ve /v1/models endpoint'lerini uygular. Resmi openai Python SDK'sını Modal URL'nize yönlendirebilirsiniz ve kutudan çıkar çıkmaz çalışır. Akış, fonksiyon çağırma ve JSON modu hepsi çalışır.
Yerel makinemde GPU'ya ihtiyacım var mı?
Hayır. Yerel makineniz sadece Modal CLI'yi çalıştırır. Tüm GPU işleri Modal'ın bulut altyapısında gerçekleşir. İsterseniz Chromebook'tan dağıtım yapabilirsiniz.
Endpoint'ime kimlik doğrulaması nasıl eklerim?
Modal web endpoint'leri varsayılan olarak herkese açıktır. Üretim için uygulama kodunuza basit bir API anahtarı kontrolü ekleyin veya Modal'ın yerleşik web kimlik doğrulama özelliklerini kullanın. Ayrıca kimlik doğrulama, hız sınırlama ve yönlendirmeyi yöneten bir LLM gateway kullanarak bir proxy katmanı kurabilirsiniz.
modal serve ile modal deploy arasındaki fark nedir?
modal serve, kodunuzu düzenlediğinizde sıcak yeniden yükleme yapan geçici bir endpoint oluşturur — geliştirme için mükemmel. modal deploy, kararlı URL'si olan kalıcı, üretime hazır bir endpoint oluşturur. İterasyonda serve, göndermeye hazır olduğunuzda deploy kullanın.
vLLM yerine SGLang kullanabilir miyim?
Evet. Modal'ın belgeleri vLLM'nin yanı sıra SGLang örnekleri de içeriyor. SGLang, decode ağırlıklı iş yükleri ve daha küçük modeller için genellikle daha az ek yük sağlıyor. vLLM genellikle ağır prefill içeren karma iş yükleri için daha iyi. Her ikisi de OpenAI uyumlu endpoint'ler üretiyor.
Bu, Railway veya Render'da dağıtımla nasıl karşılaştırılır?
Railway, Render ve Fly.io gibi platformlar web uygulamaları için harika, ancak GPU örneği sunmuyorlar. Modal, saniye başına faturalama ve otomatik ölçeklendirmeyle GPU iş yükleri için özel olarak tasarlanmıştır. Bir LLM sunmanız gerekiyorsa, Modal (veya RunPod) doğru araçtır — geleneksel PaaS platformları bunu yapamaz.