
Αναπτύξτε ένα LLM με το Modal: Από το pip install έως το Production Endpoint
Οι περισσότεροι οδηγοί για το self-hosting LLMs παραβλέπουν το πιο δύσκολο κομμάτι: τις υποδομές. Παλεύετε με drivers CUDA, διαχειρίζεστε εικόνες Docker, ρυθμίζετε το autoscaling και καταλήγετε somehow να πληρώνετε για αδρανείς GPUs στις 3 π.μ. Το Modal εξαλείφει όλα αυτά. Γράφετε Python, κάνετε deploy και παίρνετε ένα URL.
Αυτός ο οδηγός σας καθοδηγεί στη διαδικασία ανάπτυξης ενός open-source LLM στο Modal χρησιμοποιώντας το vLLM ως μηχανισμό inference. Στο τέλος, θα έχετε ένα ζωντανό API endpoint συμβατό με το OpenAI που τρέχει σε GPUs H100 και κάνει scale to zero όταν κανείς δεν το χρησιμοποιεί.
Τι είναι το Modal (και γιατί να το χρησιμοποιήσετε για LLMs);
Το Modal είναι μια serverless πλατφόρμα υπολογιστικής ισχύος χτισμένη ειδικά για φορτία εργασίας AI. Σκεφτείτε το AWS Lambda, αλλά με υποστήριξη GPU, χρέωση ανά δευτερόλεπτο και εμπειρία προγραμματιστή native για Python. Δεν υπάρχουν YAML, ούτε Dockerfiles, ούτε Kubernetes· ορίζετε ολόκληρη την υποδομή σας σε ένα script Python και κάνετε deploy με μία μόνο εντολή.
Γιατί έχει γίνει η首选 επιλογή για την ανάπτυξη LLM:
- Χρέωση scale-to-zero, δεν πληρώνετε τίποτα όταν το endpoint σας δεν διαχειρίζεται αιτήματα
- Τιμολόγηση GPU ανά δευτερόλεπτο, H100s στα ~$3.95/ώρα, A100 80GB στα ~$2.50/ώρα, με χρέωση ανά δευτερόλεπτο
- Cold starts υπο-δευτερολέπτου, τα containers ξεκινούν γρήγορα, ειδικά με memory snapshots
- $30/μήνα δωρεάν πιστώσεις, αρκετά για πειραματισμούς χωρίς χρέωση στην κάρτα
- Χωρίς DevOps, χωρίς builds Docker, χωρίς Terraform, χωρίς διαχείριση cluster
Αν τρέχατε LLMs τοπικά και θέλετε να τους δώσετε ένα σωστό API χωρίς να διαχειρίζεστε servers, το Modal είναι ο συντομότερος δρόμος.
Modal vs. RunPod vs. Lambda
| Χαρακτηριστικό | Modal | RunPod | Lambda |
|---|---|---|---|
| Μοντέλο χρέωσης | Ανά δευτερόλεπτο, scale-to-zero | Ανά δευτερόλεπτο, ελάχιστη χρέωση | Ανά ώρα, πάντα ενεργό |
| Cold start | 2-4 δευτερόλεπτα | 6-12 δευτερόλεπτα (μεγάλα) | N/A (persistent) |
| Διαθεσιμότητα GPU | H100, A100, L40S, T4 | A100, H100, A6000 | H100, A100 |
| Υποδομή | Pure Python, χωρίς αρχεία config | Βασισμένο σε Docker, περισσότερος έλεγχος | Πλήρης πρόσβαση VM |
| Δωρεάν επίπεδο | $30/μήνα πιστώσεις | Καμία | Καμία |
| Καλύτερο για | Bursty/dev φορτία εργασίας | Σταθερή κίνηση inference | Εκπαίδευση υψηλής χρησιμοποίησης |
Συμπέρασμα: Το Modal κερδίζει σε bursty φορτία εργασίας και ανάπτυξη. Εάν η χρησιμοποίηση της GPU σας ξεπερνά consistently το 40%, ένα dedicated instance στο RunPod ή Lambda είναι φθηνότερο. Για όλα τα άλλα, πρωτοτυπίες, intermittent APIs, demos, το μοντέλο scale-to-zero του Modal εξοικονομεί πραγματικά χρήματα.
Προαπαιτούμενα
Πριν ξεκινήσετε, χρειάζεστε τρία πράγματα:
- Python 3.10+ εγκατεστημένο τοπικά
- Λογαριασμό Modal, εγγραφείτε δωρεάν στο modal.com
- Λογαριασμό Hugging Face, για πρόσβαση στα μοντέλα (τα περισσότερα μοντέλα είναι gated)
Αυτό είναι όλο. Χωρίς GPU στον τοπικό σας υπολογιστή, χωρίς toolkit CUDA, χωρίς Docker.
Βήμα 1: Εγκατάσταση Modal και Αυθεντικοποίηση
Ανοίξτε ένα terminal και εγκαταστήστε το πακέτο Python του Modal:
pip install modalΣτη συνέχεια, εκτελέστε την εντολή setup για να συνδέσετε το τοπικό σας περιβάλλον με τον λογαριασμό Modal:
modal setupΑυτό ανοίγει ένα παράθυρο browser για αυθεντικοποίηση. Μόλις επιβεβαιώσετε, το Modal αποθηκεύει ένα token τοπικά. Δεν θα χρειαστεί να το κάνετε ξανά.
Βήμα 2: Ορισμός της Εικόνας Container
Τα containers του Modal ορίζονται σε Python. Καθορίζετε την base image, εγκαθιστάτε εξαρτήσεις και ορίζετε environment variables, όλα ως κώδικας. Δημιουργήστε ένα αρχείο με όνομα 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)Μερικά πράγματα που αξίζει να προσέξετε. Δεν υπάρχει Dockerfile, η αλυσίδα modal.Image την αντικαθιστά πλήρως. Η base image περιλαμβάνει NVIDIA CUDA 12.8 με Ubuntu 22.04 και εγκαθιστούμε πάνω σε αυτή το vLLM και τον client του Hugging Face Hub.
Βήμα 3: Ρύθμιση Αποθήκευσης Μοντέλου με Volumes
Τα weights των LLM είναι μεγάλα (ένα μοντέλο 7B παραμέτρων είναι ~14 GB σε fp16). Δεν θέλετε να τα κατεβάζετε κάθε φορά που ξεκινά ένα container. Τα Modal Volumes σας παρέχουν persistent storage που mount-άρεται απευθείας στα containers σας:
# 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"Εδώ χρησιμοποιούμε το Qwen3-4B-Thinking (FP8), ένα quantized μοντέλο 4 δισεκατομμυρίων παραμέτρων που είναι γρήγορο, ικανό και χωράει σε μία μόνο GPU. Μπορείτε να το αντικαταστήσετε με οποιοδήποτε μοντέλο του Hugging Face: Llama 3.1 8B, Mistral 7B ή οτιδήποτε υποστηρίζει το vLLM.
Γιατί FP8; Μειώνει τη χρήση μνήμης περίπου στο μισό σε σύγκριση με το fp16, что σημαίνει ότι μπορείτε να τρέξετε μεγαλύτερα μοντέλα στην ίδια GPU ή μικρότερα μοντέλα σε φθηνότερες GPUs. Αν σας ενδιαφέρουν οι trade-offs της quantization, ο οδηγός μας για την εκτέλεση LLMs τοπικά καλύπτει αναλυτικά τις μορφές precision.
Βήμα 4: Δημιουργία της Συνάρτησης Server vLLM
Εδώ συμβαίνει η μαγεία του Modal. Διακοσμείτε μια συνάρτηση Python με απαιτήσεις GPU, ρυθμίσεις scaling και ένα annotation web server. Το Modal διαχειρίζεται τα υπόλοιπα:
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)Ας αναλύσουμε τους βασικούς decorators:
gpu="H100:1", ζητά μία μόνο GPU H100. Αλλάξτε σε"A100-80GB:1"για φθηνότερο inference ή"H100:2"για μοντέλα 70B+scaledown_window=15 * MINUTES, κρατά το container warm για 15 λεπτά μετά το τελευταίο αίτημα και στη συνέχεια κάνει scale to zero@modal.concurrent(max_inputs=32), επιτρέπει έως 32 concurrent requests ανά container (το vLLM διαχειρίζεται το batching εσωτερικά)@modal.web_server(port=8000), εκθέτει τον HTTP server του vLLM απευθείας ως web endpoint του Modal--enforce-eager, παρακάμπτει τη compilation των CUDA graphs για γρηγορότερα cold starts (trade-off: ελαφρώς χαμηλότερο peak throughput)
Το scaledown_window είναι ο κύριος μοχλός κόστους σας. Ορίστε το στα 5 λεπτά για dev, 15-30 λεπτά για production APIs όπου αναμένετε regular traffic.
Βήμα 5: Deployment σε Production
Μία εντολή. Αυτό είναι όλο:
modal deploy app.pyΤο Modal χτίζει την εικόνα container, την push-άρει στο registry του και επιστρέφει ένα live URL:
✓ 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Το πρώτο deploy takes a few minutes επειδή κατεβάζει τα weights του μοντέλου στο volume. Τα επόμενα deploys (και τα cold starts) είναι πολύ πιο γρήγορα καθώς τα weights είναι cached.
Για ανάπτυξη, χρησιμοποιήστε modal serve app.py αντί αυτού, κάνει hot-reload στις αλλαγές αρχείων και σας δίνει ένα προσωρινό URL.
Βήμα 6: Κλήση του Endpoint σας (Συμβατό με OpenAI)
Ο deployed server vLLM εκθέτει ένα API συμβατό με OpenAI στο /v1/chat/completions. Μπορείτε να χρησιμοποιήσετε το standard OpenAI Python SDK για να το καλέσετε, απλά pointing το base URL στο Modal endpoint σας:
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)Αυτό λειτουργεί επίσης με 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
}'Οποιοδήποτε εργαλείο που υποστηρίζει API συμβατό με OpenAI θα λειτουργήσει, LangChain, LlamaIndex, η δική σας εφαρμογή. Αν δρομολογείτε requests across multiple LLM endpoints, ένα εργαλείο LLM gateway μπορεί να σας βοηθήσει να διαχειριστείτε το failover και το load balancing.
Συμβουλές Βελτιστοποίησης Κόστους
Η χρέωση ανά δευτερόλεπτο του Modal είναι ήδη πιο αποδοτική από την ωριαία τιμολόγηση, αλλά μπορείτε να.extract more από αυτό:
1. Χρησιμοποιήστε Quantization FP8
Τα μοντέλα FP8 χρησιμοποιούν περίπου τη μισή VRAM σε σχέση με τις fp16 εκδόσεις τους. Ένα Qwen3-8B σε FP8 χωράει σε μία μόνο H100, ενώ η έκδοση fp16 χρειάζεται το μεγαλύτερο μέρος των 80 GB αυτής της GPU. Λιγότερη VRAM σημαίνει ότι μπορείτε να χρησιμοποιήσετε φθηνότερες GPUs (A100 40GB, L40S) για μικρότερα μοντέλα.
2. Ρυθμίστε το Scaledown Window
Η παράμετρος scaledown_window ελέγχει πόσο χρόνο παραμένει warm ένα container μετά το τελευταίο αίτημα:
| Σενάριο | Προτεινόμενο Παράθυρο | Γιατί |
|---|---|---|
| Development/testing | 5 λεπτά | Εξοικονόμηση χρημάτων, τα cold starts είναι αποδεκτά |
| Internal API (occasional) | 10-15 λεπτά | Ισορροπία κόστους vs latency |
| Production (regular traffic) | 20-30 λεπτά | Ελαχιστοποίηση cold starts |
| High-traffic production | Χρησιμοποιήστε min_containers=1 | Διατηρήστε ένα πάντα warm |
3. Επιλέξτε τη Σωστή GPU
Μην επιλέγετε default την H100. Τα μικρότερα μοντέλα δεν την χρειάζονται:
| Μέγεθος Μοντέλου | Προτεινόμενη GPU | Περίπου Κόστος/ώρα |
|---|---|---|
| 1-4B params | L4 ή T4 | $0.59 - $0.80 |
| 7-8B params | A10 ή L40S | $1.10 - $1.95 |
| 13-14B params | A100 40GB | $2.10 |
| 30-70B params | A100 80GB ή H100 | $2.50 - $3.95 |
| 70B+ params | H100 x2 | $7.90 |
4. Ενεργοποιήστε Prompt Caching
Αν τα φορτία εργασίας σας περιλαμβάνουν επαναλαμβανόμενα system prompts ή shared prefixes, το automatic prefix caching του vLLM μπορεί να μειώσει σημαντικά το latency και τον υπολογισμό. Μπορείτε να το ενεργοποιήσετε προσθέτοντας --enable-prefix-caching στην εντολή serve του vLLM. Για βαθύτερη ανάλυση του πώς λειτουργεί το caching across different providers, δείτε τον οδηγό μας για LLM prompt caching.
5. Χρησιμοποιήστε --enforce-eager για Βελτιστοποίηση Cold Start
By default, το vLLM κάνει compile τα CUDA graphs κατά την εκκίνηση, κάτι που takes 1-3 extra minutes. Η flag --enforce-eager παρακάμπτει αυτή τη compilation. Ανταλλάσσετε ~10-15% peak throughput για δραματικά γρηγορότερα cold starts. Για bursty φορτία εργασίας όπου το latency έχει μεγαλύτερη σημασία από το raw throughput, είναι σχεδόν πάντα η σωστή επιλογή.
Πέρα από τα Βασικά: Fine-Tuned Μοντέλα
Μόλις νιώσετε άνετα με την ανάπτυξη base models, το φυσικό επόμενο βήμα είναι η ανάπτυξη της δικής σας fine-tuned έκδοσης. Η ροή εργασίας είναι identical, απλά point-άρετε το MODEL_NAME στο repo του Hugging Face ή σε ένα Modal volume που περιέχει τα fine-tuned weights σας.
Το Modal υποστηρίζει επίσης την εκτέλεση jobs fine-tuning απευθείας στις GPUs του. Μπορείτε να train-άρετε έναν LoRA adapter στο Modal, να τον αποθηκεύσετε σε ένα volume και να κάνετε deploy το merged model, όλα χωρίς να φύγετε από την πλατφόρμα. Ο οδηγός μας για fine-tuning LLM καλύπτει αναλυτικά την πλευρά της εκπαίδευσης.
Το Πλήρες app.py
Εδώ είναι το full deployment script σε ένα block ready για copy-paste:
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 με modal deploy app.py, αντικαταστήστε το MODEL_NAME με οποιοδήποτε μοντέλο του Hugging Face και είστε live.
Συχνές Ερωτήσεις
Πόσο κοστίζει η εκτέλεση ενός LLM στο Modal;
Εξαρτάται από την GPU και πόσο χρόνο παραμένει warm το endpoint σας. Ένα Qwen3-4B σε H100 κοστίζει ~$3.95/ώρα active use. Με scale-to-zero και παράθυρο scaledown 15 λεπτών, ένα lightly-used endpoint μπορεί να κοστίζει $5-15/μήνα. Οι $30 δωρεάν μηνιαίες πιστώσεις καλύπτουν πολλούς πειραματισμούς.
Το Modal κάνει scale to zero;
Ναι, αυτό είναι ένα από τα κύρια selling points του. Όταν δεν φτάνουν requests για τη διάρκεια του scaledown_window, το container shuts down και σταματάτε να πληρώνετε. Το επόμενο αίτημα trigger-άρει ένα cold start (typically 2-10 δευτερόλεπτα ανάλογα με το μέγεθος του μοντέλου και αν χρησιμοποιείτε --enforce-eager).
Μπορώ να κάνω deploy Llama 3.1 ή Mistral στο Modal;
Απολύτως. Αντικαταστήστε τη σταθερά MODEL_NAME με οποιοδήποτε μοντέλο υποστηρίζει το vLLM: meta-llama/Llama-3.1-8B-Instruct, mistralai/Mistral-7B-Instruct-v0.3 ή εκατοντάδες άλλα στο Hugging Face. Για μοντέλα 70B+, αλλάξτε το N_GPU σε 2 και χρησιμοποιήστε gpu="H100:2".
Πώς συγκρίνονται τα cold starts με το RunPod;
Τα cold starts του Modal are typically 2-4 δευτερόλεπτα για το ίδιο το container, plus ο χρόνος φόρτωσης του μοντέλου. Με τα weights του μοντέλου cached σε ένα Volume και ενεργοποιημένο το --enforce-eager, μιλάμε για 10-30 δευτερόλεπτα συνολικά για ένα μοντέλο 7-8B. Τα serverless cold starts του RunPod κυμαίνονται από κάτω από 200ms (cached) έως 6-12 δευτερόλεπτα για larger containers, αν και το always-on model τους avoids entirely τα cold starts.
Είναι το vLLM endpoint του Modal truly OpenAI-compatible;
Ναι. Το vLLM implement-άρει τα ίδια endpoints /v1/chat/completions, /v1/completions και /v1/models που χρησιμοποιεί το OpenAI. Μπορείτε να point-άρετε το official openai Python SDK στο Modal URL σας και λειτουργεί out of the box. Το Streaming, function calling και JSON mode λειτουργούν όλα.
Χρειάζομαι GPU στον τοπικό μου υπολογιστή;
Όχι. Ο τοπικός σας υπολογιστής απλά τρέχει το Modal CLI. Όλη η εργασία GPU γίνεται στην cloud infrastructure του Modal. Θα μπορούσατε να κάνετε deploy από ένα Chromebook αν θέλατε.
Πώς προσθέτω authentication στο endpoint μου;
Τα web endpoints του Modal είναι public by default. Για production, προσθέστε έναν απλό έλεγχο API key στον κώδικα της εφαρμογής σας ή χρησιμοποιήστε τις built-in δυνατότητες web authentication του Modal. Μπορείτε επίσης να set up ένα proxy layer χρησιμοποιώντας ένα LLM gateway που διαχειρίζεται auth, rate limiting και routing.
Ποια είναι η διαφορά μεταξύ modal serve και modal deploy;
Το modal serve δημιουργεί ένα temporary endpoint που κάνει hot-reload όταν edit-άρετε τον κώδικά σας, ιδανικό για development. Το modal deploy δημιουργεί ένα persistent, production-ready endpoint με stable URL. Χρησιμοποιήστε το serve ενώ iter-άρετε, το deploy όταν είστε ready να ship-άρετε.
Μπορώ να χρησιμοποιήσω SGLang αντί για vLLM;
Ναι. Η τεκμηρίωση του Modal includes SGLang examples alongside το vLLM. Το SGLang tends to have lower overhead για decode-heavy φορτία εργασίας και smaller models. Το vLLM είναι generally better για mixed workloads με heavy prefill. Και τα δύο παράγουν endpoints συμβατά με OpenAI.
Πώς συγκρίνεται αυτό με την ανάπτυξη σε Railway ή Render;
Πλατφόρμες όπως τα Railway, Render και Fly.io είναι great για web apps, αλλά δεν offer GPU instances. Το Modal είναι purpose-built για GPU workloads με χρέωση ανά δευτερόλεπτο και autoscaling. Αν χρειάζεται να serve-άρετε ένα LLM, το Modal (ή το RunPod) είναι το σωστό εργαλείο, οι traditional PaaS πλατφόρμες δεν μπορούν να το κάνουν.