
Deploy LLM dengan Modal: Dari pip install hingga Endpoint Produksi
Sebagian besar panduan tentang self-hosting LLM mengabaikan bagian tersulit: infrastruktur. Anda bergumul dengan driver CUDA, mengelola image Docker, mengonfigurasi autoscaling, dan entah bagaimana tetap berakhir membayar GPU yang menganggur pada pukul 3 pagi. Modal menghilangkan semua itu. Anda menulis Python, Anda deploy, Anda mendapatkan URL.
Panduan ini akan memandu Anda melalui proses men-deploy LLM open-source di Modal dengan vLLM sebagai mesin inferensinya. Pada akhirnya, Anda akan memiliki endpoint API langsung yang kompatibel dengan OpenAI yang berjalan di GPU H100 dan dapat skala ke nol (scale to zero) saat tidak ada yang menggunakannya.
Apa Itu Modal (dan Mengapa Menggunakannya untuk LLM)?
Modal adalah platform komputasi serverless yang dibangun khusus untuk beban kerja AI. Bayangkan AWS Lambda, tetapi dengan dukungan GPU, penagihan per detik, dan pengalaman pengembang yang native untuk Python. Tidak ada YAML, tidak ada Dockerfile, tidak ada Kubernetes; Anda mendefinisikan seluruh infrastruktur Anda dalam skrip Python dan men-deploy-nya dengan satu perintah.
Berikut alasan mengapa Modal menjadi pilihan utama untuk deployment LLM:
- Billing scale-to-zero, Anda tidak membayar apa pun saat endpoint Anda tidak menangani permintaan
- Harga GPU per detik, H100 sekitar $3,95/jam, A100 80GB sekitar $2,50/jam, ditagih per detik
- Cold start di bawah satu detik, container menyala dengan cepat, terutama dengan snapshot memori
- Kredit gratis $30/bulan, cukup untuk bereksperimen tanpa tagihan kartu kredit
- Tanpa DevOps, tidak ada build Docker, tidak ada Terraform, tidak ada manajemen cluster
Jika Anda telah menjalankan LLM secara lokal dan ingin memberikan mereka API yang layak tanpa mengelola server, Modal adalah jalur tercepat menuju sana.
Modal vs. RunPod vs. Lambda
| Fitur | Modal | RunPod | Lambda |
|---|---|---|---|
| Model penagihan | Per detik, scale-to-zero | Per detik, biaya minimum | Per jam, selalu aktif |
| Cold start | 2-4 detik | 6-12 detik (besar) | T/A (persisten) |
| Ketersediaan GPU | H100, A100, L40S, T4 | A100, H100, A6000 | H100, A100 |
| Infrastruktur | Python murni, tanpa file konfigurasi | Berbasis Docker, lebih banyak kontrol | Akses VM penuh |
| Tier gratis | Kredit $30/bulan | Tidak ada | Tidak ada |
| Terbaik untuk | Beban kerja bursty/pengembangan | Lalu lintas inferensi stabil | Pelatihan utilisasi tinggi |
Intinya: Modal unggul untuk beban kerja yang bersifat bursty dan pengembangan. Jika utilisasi GPU Anda secara konsisten melebihi 40%, instance khusus di RunPod atau Lambda lebih murah. Untuk hal lainnya, seperti prototyping, API intermiten, dan demo, model scale-to-zero Modal menghemat uang secara nyata.
Prasyarat
Sebelum memulai, Anda membutuhkan tiga hal:
- Python 3.10+ terinstal secara lokal
- Akun Modal, daftar gratis di modal.com
- Akun Hugging Face, untuk akses model (sebagian besar model dibatasi/gated)
Hanya itu. Tidak perlu GPU di mesin lokal Anda, tidak perlu toolkit CUDA, tidak perlu Docker.
Langkah 1: Instal Modal dan Autentikasi
Buka terminal dan instal paket Python Modal:
pip install modalKemudian jalankan perintah setup untuk menghubungkan lingkungan lokal Anda ke akun Modal:
modal setupIni akan membuka jendela browser untuk autentikasi. Setelah Anda mengonfirmasi, Modal menyimpan token secara lokal. Anda tidak perlu melakukan ini lagi.
Langkah 2: Definisikan Image Container
Container Modal didefinisikan dalam Python. Anda menentukan image dasar, menginstal dependensi, dan mengatur variabel lingkungan, semuanya sebagai kode. Buat file bernama app.py:
import modal
# Define the container image with CUDA, Python, and vLLM
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)Beberapa hal yang perlu diperhatikan. Tidak ada Dockerfile, rantai modal.Image tersebut menggantikannya sepenuhnya. Image dasar mencakup NVIDIA CUDA 12.8 dengan Ubuntu 22.04, dan kami menginstal vLLM serta klien Hugging Face Hub di atasnya.
Langkah 3: Konfigurasi Penyimpanan Model dengan Volumes
Bobot LLM berukuran besar (model 7 miliar parameter sekitar ~14 GB dalam fp16). Anda tidak ingin mengunduhnya setiap kali container dimulai. Modal Volumes memberi Anda penyimpanan persisten yang dipasang langsung ke dalam container Anda:
# Persistent volumes for caching model weights
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"Kami menggunakan Qwen3-4B-Thinking (FP8) di sini, model 4 miliar parameter yang dikuantisasi yang cepat, mumpuni, dan muat dalam satu GPU. Anda dapat menukarnya dengan model Hugging Face apa pun: Llama 3.1 8B, Mistral 7B, atau apa pun yang didukung vLLM.
Mengapa FP8? Ini mengurangi penggunaan memori hingga setengahnya dibandingkan fp16, yang berarti Anda dapat menjalankan model yang lebih besar pada GPU yang sama, atau menjalankan model yang lebih kecil pada GPU yang lebih murah. Jika Anda penasaran dengan trade-off kuantisasi, panduan kami untuk menjalankan LLM secara lokal membahas format presisi secara detail.
Langkah 4: Buat Fungsi Server vLLM
Di sinilah keajaiban Modal terjadi. Anda menghiasi fungsi Python dengan persyaratan GPU, konfigurasi scaling, dan anotasi web server. Modal menangani sisanya:
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", # Faster cold starts
]
subprocess.Popen(" ".join(cmd), shell=True)Mari kita uraikan dekorator utamanya:
gpu="H100:1", meminta satu GPU H100. Ubah menjadi"A100-80GB:1"untuk inferensi yang lebih murah, atau"H100:2"untuk model 70B+scaledown_window=15 * MINUTES, menjaga container tetap hangat selama 15 menit setelah permintaan terakhir, lalu skala ke nol@modal.concurrent(max_inputs=32), memungkinkan hingga 32 permintaan konkuren per container (vLLM menangani batching secara internal)@modal.web_server(port=8000), mengekspos server HTTP vLLM langsung sebagai endpoint web Modal--enforce-eager, melewatkan kompilasi grafik CUDA untuk cold start yang lebih cepat (trade-off: throughput puncak sedikit lebih rendah)
scaledown_window adalah tuas biaya utama Anda. Atur ke 5 menit untuk pengembangan, 15-30 menit untuk API produksi di mana Anda mengharapkan lalu lintas reguler.
Langkah 5: Deploy ke Produksi
Satu perintah. Hanya itu:
modal deploy app.pyModal membangun image container, mendorongnya ke registri mereka, dan mengembalikan URL langsung:
✓ 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.runDeploy pertama memakan waktu beberapa menit karena mengunduh bobot model ke dalam volume. Deploy berikutnya (dan cold start) jauh lebih cepat karena bobot sudah di-cache.
Untuk pengembangan, gunakan modal serve app.py sebagai gantinya, ini melakukan hot-reload saat file berubah dan memberi Anda URL sementara.
Langkah 6: Panggil Endpoint Anda (Kompatibel OpenAI)
Server vLLM yang Anda deploy mengekspos API yang kompatibel dengan OpenAI di /v1/chat/completions. Anda dapat menggunakan SDK Python OpenAI standar untuk memanggilnya, cukup arahkan base URL ke endpoint Modal Anda:
from openai import OpenAI
client = OpenAI(
api_key="not-needed", # vLLM doesn't require auth by default
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)Ini juga berfungsi dengan curl:
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
}'Alat apa pun yang mendukung API kompatibel OpenAI akan berfungsi, LangChain, LlamaIndex, aplikasi Anda sendiri. Jika Anda merutekan permintaan ke beberapa endpoint LLM, alat gateway LLM dapat membantu Anda mengelola failover dan load balancing.
Tips Optimasi Biaya
Penagihan per detik Modal sudah lebih efisien daripada penagihan per jam, tetapi Anda bisa memeras lebih banyak manfaat darinya:
1. Gunakan Kuantisasi FP8
Model FP8 menggunakan sekitar setengah VRAM dari rekan-rekan fp16 mereka. Qwen3-8B dalam FP8 muat dalam satu H100, sedangkan versi fp16 membutuhkan sebagian besar dari 80 GB GPU tersebut. Lebih sedikit VRAM berarti Anda dapat menggunakan GPU yang lebih murah (A100 40GB, L40S) untuk model yang lebih kecil.
2. Sesuaikan Jendela Scaledown
Parameter scaledown_window mengontrol berapa lama container tetap hangat setelah permintaan terakhir:
| Skenario | Jendela yang Direkomendasikan | Alasan |
|---|---|---|
| Pengembangan/testing | 5 menit | Hemat uang, cold start tidak masalah |
| API Internal (sesekali) | 10-15 menit | Seimbangkan biaya vs latensi |
| Produksi (lalu lintas reguler) | 20-30 menit | Minimalkan cold start |
| Produksi lalu lintas tinggi | Gunakan min_containers=1 | Jaga satu tetap hangat selalu |
3. Pilih GPU yang Tepat
Jangan default ke H100. Model yang lebih kecil tidak membutuhkannya:
| Ukuran Model | GPU yang Direkomendasikan | Perkiraan Biaya/jam |
|---|---|---|
| 1-4B params | L4 atau T4 | $0,59 - $0,80 |
| 7-8B params | A10 atau L40S | $1,10 - $1,95 |
| 13-14B params | A100 40GB | $2,10 |
| 30-70B params | A100 80GB atau H100 | $2,50 - $3,95 |
| 70B+ params | H100 x2 | $7,90 |
4. Aktifkan Prompt Caching
Jika beban kerja Anda melibatkan prompt sistem yang berulang atau awalan bersama, caching awalan otomatis vLLM dapat secara signifikan mengurangi latensi dan komputasi. Anda dapat mengaktifkannya dengan menambahkan --enable-prefix-caching ke perintah serve vLLM. Untuk eksplorasi lebih dalam tentang cara kerja caching di berbagai penyedia, lihat panduan caching prompt LLM kami.
5. Gunakan --enforce-eager untuk Optimasi Cold Start
Secara default, vLLM mengompilasi grafik CUDA saat startup, yang memakan waktu tambahan 1-3 menit. Flag --enforce-eager melewatkan kompilasi ini. Anda menukar ~10-15% throughput puncak untuk cold start yang jauh lebih cepat. Untuk beban kerja bursty di mana latensi lebih penting daripada throughput mentah, ini hampir selalu merupakan pilihan yang tepat.
Melangkah Lebih Jauh: Model Fine-Tuned
Setelah Anda nyaman men-deploy model dasar, langkah alami berikutnya adalah men-deploy versi fine-tuned Anda sendiri. Alur kerjanya identik, Anda hanya mengarahkan MODEL_NAME ke repo Hugging Face Anda atau volume Modal yang berisi bobot fine-tuned Anda.
Modal juga mendukung menjalankan job fine-tuning langsung di GPU mereka. Anda dapat melatih adapter LoRA di Modal, menyimpannya ke volume, dan men-deploy model yang digabungkan, semuanya tanpa meninggalkan platform. Panduan fine-tuning LLM kami membahas sisi pelatihan secara mendalam.
Lengkap app.py
Berikut adalah skrip deployment lengkap dalam satu blok siap salin-tempel:
import modal
# --- Image Definition ---
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")
)
# --- Volumes for Model Caching ---
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 Config ---
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)Deploy dengan modal deploy app.py, tukar MODEL_NAME dengan model Hugging Face apa pun, dan Anda sudah live.
Pertanyaan yang Sering Diajukan
Berapa biaya menjalankan LLM di Modal?
Tergantung pada GPU dan berapa lama endpoint Anda tetap hangat. Qwen3-4B di H100 berharga ~$3,95/jam untuk penggunaan aktif. Dengan scale-to-zero dan jendela scaledown 15 menit, endpoint yang jarang digunakan mungkin berharga $5-15/bulan. Kredit gratis bulanan sebesar $30 mencakup banyak eksperimen.
Apakah Modal skala ke nol?
Ya, itu salah satu nilai jual utamanya. Ketika tidak ada permintaan yang masuk selama durasi scaledown_window Anda, container mati dan Anda berhenti membayar. Permintaan berikutnya memicu cold start (biasanya 2-10 detik tergantung pada ukuran model dan apakah Anda menggunakan --enforce-eager).
Bisakah saya men-deploy Llama 3.1 atau Mistral di Modal?
Tentu saja. Tukar konstanta MODEL_NAME ke model apa pun yang didukung vLLM: meta-llama/Llama-3.1-8B-Instruct, mistralai/Mistral-7B-Instruct-v0.3, atau ratusan lainnya di Hugging Face. Untuk model 70B+, ubah N_GPU menjadi 2 dan gunakan gpu="H100:2".
Bagaimana perbandingan cold start dengan RunPod?
Cold start Modal biasanya 2-4 detik untuk container itu sendiri, ditambah waktu pemuatan model. Dengan bobot model di-cache di Volume dan --enforce-eager diaktifkan, totalnya sekitar 10-30 detik untuk model 7-8B. Cold start serverless RunPod berkisar dari di bawah 200ms (di-cache) hingga 6-12 detik untuk container yang lebih besar, meskipun model always-on mereka menghindari cold start sepenuhnya.
Apakah endpoint vLLM Modal benar-benar kompatibel dengan OpenAI?
Ya. vLLM mengimplementasikan endpoint /v1/chat/completions, /v1/completions, dan /v1/models yang sama dengan yang digunakan OpenAI. Anda dapat mengarahkan SDK Python openai resmi ke URL Modal Anda dan itu berfungsi langsung. Streaming, function calling, dan mode JSON semuanya berfungsi.
Apakah saya memerlukan GPU di mesin lokal saya?
Tidak. Mesin lokal Anda hanya menjalankan CLI Modal. Semua pekerjaan GPU terjadi di infrastruktur cloud Modal. Anda bahkan bisa deploy dari Chromebook jika mau.
Bagaimana cara menambahkan autentikasi ke endpoint saya?
Endpoint web Modal bersifat publik secara default. Untuk produksi, tambahkan pemeriksaan kunci API sederhana dalam kode aplikasi Anda, atau gunakan fitur autentikasi web bawaan Modal. Anda juga dapat menyiapkan lapisan proxy menggunakan gateway LLM yang menangani auth, pembatasan laju, dan perutean.
Apa perbedaan antara modal serve dan modal deploy?
modal serve membuat endpoint sementara yang melakukan hot-reload saat Anda mengedit kode Anda, sempurna untuk pengembangan. modal deploy membuat endpoint persisten yang siap produksi dengan URL stabil. Gunakan serve saat iterasi, deploy saat Anda siap meluncurkan.
Bisakah saya menggunakan SGLang alih-alih vLLM?
Ya. Dokumentasi Modal menyertakan contoh SGLang bersama dengan vLLM. SGLang cenderung memiliki overhead lebih rendah untuk beban kerja yang berat pada decoding dan model yang lebih kecil. vLLM umumnya lebih baik untuk beban kerja campuran dengan prefill yang berat. Keduanya menghasilkan endpoint yang kompatibel dengan OpenAI.
Bagaimana perbandingannya dengan deployment di Railway atau Render?
Platform seperti Railway, Render, dan Fly.io bagus untuk aplikasi web, tetapi mereka tidak menawarkan instance GPU. Modal dibangun khusus untuk beban kerja GPU dengan penagihan per detik dan autoscaling. Jika Anda perlu melayani LLM, Modal (atau RunPod) adalah alat yang tepat, platform PaaS tradisional tidak dapat melakukannya.