Small Language Models (SLM)
Tung Bui Thanh (TungDaDev)16 mins read

Thiết kế hệ thống phân tán thì cách tốt nhất không phải là ném phần cứng đắt nhất vào mọi việc, mà là cân cho khéo giữa Compute, Latency, Privacy và Cost. Gọi một model 400B+ tham số trên cloud chỉ để trích JSON hay phân loại intent là sai về kiến trúc, và sai khá nặng.
Mấy năm đầu của Generative AI, ai cũng nghĩ theo kiểu Brute-Force Scaling: model càng to càng tốt (175B, 70B, thậm chí cả nghìn tỷ tham số MoE). Nhưng tới lúc hệ thống lên Production Scale với hàng chục triệu lượt gọi mỗi ngày, CTO với Solution Architect đụng ngay bức tường thực tế (The Production Reality Wall):
- Độ trễ mạng và đuôi trễ P99 (Network & P99 Tail Latency): mỗi lần gọi API ra Cloud LLM (OpenAI, Anthropic) thường mất từ vài trăm mili giây tới vài giây tuỳ độ dài output và tải phía nhà cung cấp, đủ phá hỏng trải nghiệm của app cần tương tác realtime (Interactive UX).
- Hoá đơn cloud phình to (OpEx Bleed): tiền token tăng tuyến tính theo lưu lượng (QPS), càng đông càng tốn, gần như không có chuyện mua sỉ rẻ hơn (Economies of Scale).
- Rủi ro lộ dữ liệu và chuyện tuân thủ (Data Governance & Sovereignty): GDPR, HIPAA hay luật bảo vệ dữ liệu cá nhân trong nước đặt ra nhiều ràng buộc (hợp đồng xử lý dữ liệu, chuyển dữ liệu ra nước ngoài, lưu trữ trong nước) khi đẩy dữ liệu nhạy cảm (PII, hồ sơ bệnh án, giao dịch tài chính) sang server bên thứ ba. Không hẳn là cấm tuyệt đối, nhưng thủ tục và rủi ro đủ để nhiều nơi chọn tự chạy model.
Năm 2025 - 2026 là lúc Small Language Models (SLMs) lên ngôi: các model từ 1B tới 8B tham số như Phi-4-mini 3.8B (Microsoft), Qwen 2.5 / Qwen3 bản 0.5B - 8B (Alibaba), Llama 3.2 1B/3B (Meta), Gemma 3 (Google). Nhờ dữ liệu train sạch (Textbook-quality synthetic data) và kỹ thuật chưng cất tri thức (Knowledge Distillation), SLM bây giờ gánh tốt phần lớn việc "hẹp" của doanh nghiệp như trích xuất, phân loại, tóm tắt ngắn, với chi phí mỗi request thấp hơn nhiều lần và thời gian ra token đầu tiên chỉ vài chục mili giây khi chạy ngay tại biên (Edge / On-Premise). Bao nhiêu phần trăm việc thì tuỳ bài toán, phải tự đo trên dữ liệu của mình.
# tính vram & bộ nhớ kvCache
Muốn lên kế hoạch phần cứng (Capacity Planning) cho SLM thì không đoán mò được, phải nắm công thức GPU tiêu tốn bộ nhớ ra sao.
Tổng VRAM cần cho inference gồm:
VRAM_Total = VRAM_Weights + VRAM_KVCache + VRAM_Activation + VRAM_CUDA_Overhead# trọng số mô hình
Memory_weights = Tham_Số x (bits / 8) x 1.2 (1.2 là hệ số dự phòng overhead)- Model 7B ở chuẩn FP16 (16-bit float):
Memory ≈ 7 x 10^9 x 2 bytes ≈ 14 GB - Model 7B sau khi lượng tử hoá 4-bit (INT4):
Memory ≈ 7 x 10^9 x 0.5 bytes ≈ 3.5 GB
Hai con số trên là phần lý thuyết, chưa nhân hệ số 1.2. Thực tế file model nặng hơn một chút: Qwen2.5-7B thật ra có 7.6B tham số, và bản AWQ vẫn giữ lớp embedding, lm_head ở 16-bit, nên bản Qwen2.5-7B-Instruct-AWQ nạp lên GPU tốn cỡ 5 - 6 GB chứ không phải 3.5 GB.
# bộ nhớ đệm kvCache
Khi xử lý chuỗi dài với nhiều người dùng cùng lúc, thủ phạm gây OOM (Out-of-Memory) trên GPU thường là KV Cache, chứ không phải bản thân model weights.
KVCache_Size (Bytes) = 2 x B x L x H_kv x S x D x Precision_BytesB: Batch size (số request đang sinh token cùng lúc).L: số Transformer layers (ví dụ Qwen-2.5-7B có 28 layers).H_kv: số Key-Value heads (nhờ Grouped-Query Attention - GQA, số head này ít hơn nhiều so với số Query heads, thường chỉ 4 hoặc 8).S: Context length, số token của mỗi chuỗi (prompt + phần đã sinh).D: Head dimension, kích thước vector của mỗi head (thường là 128).Precision_Bytes: số byte cho mỗi giá trị trong cache (FP16/BF16 là 2, FP8 là 1).- Số
2ở đầu là vì phải lưu cả Key lẫn Value.
Thử tính với Qwen2.5-7B (28 layers, 4 KV heads, head dim 128, cache FP16). Mỗi token tốn 2 x 28 x 4 x 128 x 2 = 57,344 bytes, tức khoảng 56 KB:
1 request x 8,192 tokens = 57,344 x 8,192 ≈ 0.47 GB
64 request x 8,192 tokens = 57,344 x 8,192 x 64 ≈ 30 GBWeights chỉ 5 - 6 GB, nhưng 64 request cùng chạy hết context 8K thì KV Cache đã cần cỡ 30 GB, vượt một card 24 GB. Đó là lý do phải chặn --max-num-seqs và --max-model-len (xem phần cấu hình ở dưới), và là lý do GQA quan trọng: nếu model dùng đủ 28 KV heads như Multi-Head Attention cũ thì con số trên nhân thêm 7 lần.
# lượng tử hoá: awq vs gguf vs exl2
Lượng tử hoá (Quantization) là nén số thực 16-bit (FP16/BF16) xuống số nguyên 8-bit hoặc 4-bit (INT8/INT4). Có điều mỗi kỹ thuật một kiểu, không phải cái nào cũng như cái nào.
# so sánh chi tiết ba chuẩn lượng tử hoá
| Tiêu chuẩn | Target Hardware | Điểm mạnh | Điểm yếu | Hợp với |
|---|---|---|---|---|
| GGUF | CPU, Apple Silicon, Heterogeneous (CPU + GPU RAM sharing) | Chạy được trên máy không có GPU rời, nạp model rất nhanh, chỉ một file duy nhất. | Throughput thấp hơn khi phải gánh hàng trăm concurrent requests. | App desktop nội bộ, thiết bị IoT, Edge Gateways, máy dev. |
| AWQ | NVIDIA GPU (Tensor Cores: Ada Lovelace, Hopper, Ampere) | Chất lượng giảm rất ít, vLLM và TensorRT-LLM hỗ trợ sẵn, chịu concurrent rất tốt. | Cần GPU rời có CUDA, chạy thuần CPU không hiệu quả. | Cụm server On-Premise chạy production, Private Cloud vLLM cluster. |
| EXL2 | NVIDIA GPU đơn lẻ | Sinh token rất nhanh với single/low batch stream. | Kén engine, không hợp batching nhiều concurrent; ExLlamaV2 đã có bản kế nhiệm ExLlamaV3 (EXL3). | Chatbot cá nhân, xử lý tốc độ cao trên máy local. |
# phục vụ thông lượng cao: vllm & pagedAttention
Đưa SLM vào doanh nghiệp thì không thể chạy script Python transformers.generate() tuần tự được. Phải dùng inference engine chuyên dụng có PagedAttention và Continuous Batching.
# so sánh chỉ số hiệu năng
Số liệu "phí 60-80%" và "dưới 4%" ở sơ đồ trên lấy từ paper vLLM (Kwon và cộng sự, SOSP 2023).
- TTFT (Time-To-First-Token): thời gian từ lúc nhận request tới khi model nhả token đầu tiên (đo tốc độ pre-fill prompt). SLM 7B trên GPU tốt, prompt vài trăm token, tải nhẹ thì TTFT cỡ vài chục mili giây; prompt vài nghìn token hoặc hàng đợi dài thì lên hàng trăm mili giây.
- TPOT (Time-Per-Output-Token): thời gian sinh mỗi token tiếp theo ở giai đoạn decode. Với 7B 4-bit trên một GPU cỡ RTX 4090 thường rơi vào khoảng 10ms - 20ms/token (tức 50 - 100 tokens/giây cho mỗi request), batch càng lớn thì mỗi request chậm đi nhưng tổng throughput tăng.
Hai con số này phụ thuộc rất nhiều vào phần cứng, độ dài prompt và tải, nên coi là mức tham khảo rồi tự benchmark (vLLM có sẵn vllm bench serve).
# kiến trúc doanh nghiệp: compound ai system & dynamic multi-lora
Thiết kế hệ thống không bắt buộc phải chọn hoặc SLM hoặc LLM. Mình ghép cả hai trong một Compound AI System, đứng trước là một tầng định tuyến (Smart Semantic Router).
# dynamic multi-lora serving: một base model cho hàng chục nghiệp vụ
Trước đây muốn có 3 model riêng cho CSKH, sinh mã SQL và xử lý bảo hiểm thì phải chạy 3 instance riêng (tốn 3 x 16 GB = 48 GB VRAM).
Với Dynamic Multi-LoRA (vLLM hỗ trợ):
- Chỉ load đúng 1 base model vào VRAM (ví dụ Qwen 2.5 7B bản AWQ, tốn cỡ 5 - 6 GB VRAM).
- Các adapter LoRA (mỗi cái chỉ khoảng 20MB - 100MB) được khai báo lúc khởi động bằng
--lora-modules. Request gọi tên adapter nào thì vLLM nạp adapter đó vào một trong--max-lorasslot trên GPU (dư thì giữ ở RAM theo--max-cpu-loras), không phải khởi động lại model. Muốn thêm adapter mới khi server đang chạy thì bậtVLLM_ALLOW_RUNTIME_LORA_UPDATING=Truerồi gọiPOST /v1/load_lora_adapter. - Một server GPU 24GB phục vụ cùng lúc được hàng chục bộ phận nghiệp vụ trong công ty.
# blueprint triển khai production với docker & vllm
Đây là file Docker Compose kiểu production để chạy cụm serving SLM hiệu năng cao:
services:
vllm-slm-service:
image: vllm/vllm-openai:v0.6.3 # bản cũ, nên ghim theo bản mới nhất đã test
container_name: enterprise-qwen-slm
runtime: nvidia
environment:
- HUGGING_FACE_HUB_TOKEN=${HF_TOKEN}
ports:
- '8000:8000'
volumes:
- /opt/models/cache:/root/.cache/huggingface
- /opt/models/adapters:/opt/adapters
ipc: host # Bắt buộc để chia sẻ bộ nhớ chia sẻ POSIX giữa các workers
command: >
--model Qwen/Qwen2.5-7B-Instruct-AWQ
--dtype auto
--gpu-memory-utilization 0.90
--max-model-len 8192
--max-num-seqs 64
--enable-lora
--max-lora-rank 64
--lora-modules financial-adapter=/opt/adapters/financial-v1 legal-adapter=/opt/adapters/legal-v1
--port 8000
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
restart: unless-stopped
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:8000/health']
interval: 10s
timeout: 5s
retries: 3# mấy flag cần để ý
--gpu-memory-utilization 0.90: vLLM được dùng tối đa 90% VRAM (weights, activation, KV-Cache). Phần KV-Cache được cấp trước luôn từ phần còn dư, nênnvidia-smibáo gần đầy là bình thường. 10% còn lại để cho CUDA context và mấy tiến trình khác trên cùng GPU.--max-num-seqs 64: tối đa 64 request được sinh token cùng lúc trong một batch, request dư nằm trong hàng đợi (vllm:num_requests_waiting). Như phép tính ở phần KV Cache, 64 chuỗi dài 8K không thể cùng nằm trên GPU 24GB; khi cache đầy, vLLM sẽ tạm đẩy bớt request ra (preemption) và chạy lại sau, latency tăng vọt.ipc: host(trongdocker runlà--ipc=host): PyTorch và vLLM dùng shared memory để trao đổi dữ liệu giữa các tiến trình, mà/dev/shmmặc định của Docker chỉ 64MB. Không muốn dùng IPC của host thì đặtshm_sizeđủ lớn.- Không có
--quantization awq: vLLM tự đọc cấu hình lượng tử hoá trong model và chọn kernel nhanh hơn (awq_marlintrên GPU hỗ trợ). Ép--quantization awqlại thành dùng kernel AWQ cũ, chậm hơn. - Không có
--enforce-eager: cờ này tắt CUDA Graph, tiết kiệm ít VRAM nhưng decode chậm đi rõ rệt. Chỉ bật khi debug hoặc thiếu bộ nhớ thật sự. --max-lora-rank 64: mặc định chỉ nhận adapter có rank tới 16, adapter rank cao hơn sẽ báo lỗi khi nạp.- Dòng
version:đầu file đã bị Docker Compose v2 bỏ qua (và in cảnh báo), nên mình bỏ đi.
# mô hình tài chính tco & điểm hoà vốn
Muốn sếp duyệt tiền mua cụm SLM On-Premise thì phải đưa ra được bảng tính tổng chi phí sở hữu:
TCO_OnPrem = CAPEX (Phần cứng) + OPEX (Điện + Làm mát + Chỗ đặt máy chủ) + Chi phí vận hành SRE
TCO_Cloud = Số lượng requests/tháng x (Tokens / Request) x Đơn giá mỗi token# bài toán tài chính 15 triệu request mỗi tháng
| Hạng mục chi phí | Cloud LLM (GPT-4o API) | On-Prem SLM (1 server 2x RTX 4090) |
|---|---|---|
| Chi phí ban đầu (CAPEX) | $0 | ~$8,000 (Server Chassis + 2x RTX 4090 24GB + 128GB RAM) |
| Chi phí vận hành hàng tháng (OPEX) | ~60,000 / tháng _(giả định 800 input + 200 output tokens/req, giá 2.50 / $10 mỗi 1M token)_ | ~350 / tháng _(điện ~130 + khấu hao phần cứng 3 năm ~$220)_ |
| Chi phí tiền mặt năm đầu | ~$720,000 | ~$9,600 (CAPEX + 12 tháng điện, chưa tính người vận hành) |
| TTFT (thời gian ra token đầu) | Vài trăm ms tới hơn 1s (tuỳ mạng và tải bên cloud) | Vài chục ms (mạng LAN nội bộ, tải vừa phải) |
| Bảo mật | Dữ liệu đi qua cloud của bên thứ ba | Dữ liệu không rời hạ tầng nội bộ; đạt PCI-DSS / HIPAA hay không còn tuỳ quy trình, không tự có |
NOTE
Điểm hoà vốn (Break-even Point): với giả định ở bảng trên (500,000 requests/ngày), tiền API khoảng 2,000/ngày, nên tiền phần cứng 8,000 về lại chỉ sau vài ngày. Nhưng phép so này bỏ qua mấy thứ lớn hơn nhiều: lương người vận hành (dòng "Chi phí vận hành SRE" trong công thức), server dự phòng, và chuyện một model 7B không làm được mọi việc mà GPT-4o làm. Ngoài ra, giấy phép driver GeForce của NVIDIA không cho phép triển khai card dòng RTX trong datacenter, chạy production nghiêm túc thì thường phải tính giá card dòng datacenter (L4, L40S...) đắt hơn nhiều lần. Con số hoà vốn thật nằm đâu đó giữa vài ngày và vài tháng, tuỳ bạn tính đủ hay không.
Với lưu lượng 15 triệu request/tháng (trung bình khoảng 6 request/giây, giờ cao điểm có thể gấp vài lần), hai card 24GB chạy vLLM vẫn gánh được với model 7B 4-bit, nhưng nên benchmark ở tải đỉnh chứ không phải tải trung bình.
# mấy anti-pattern nên tránh khi triển khai slm
Kỳ vọng quá tay vào Zero-Shot Reasoning phức tạp:
- Sai lầm: mong một model 3B tự phân tích hợp đồng pháp lý 50 trang, hàng chục điều khoản dẫn chéo nhau, mà không có RAG hay fine-tuning.
- Cách xử lý: bài nào cần lập luận nhiều bước phức tạp thì chuyển lên Frontier LLM qua Semantic Router, hoặc chẻ nhỏ thành chuỗi atomic prompt.
Lượng tử hoá quá sâu (Q2_K hoặc 2-bit):
- Sai lầm: ép model 7B xuống 2-bit để nhét vừa thiết bị 2GB RAM.
- Hậu quả: Perplexity Degradation tăng vọt, model không sinh nổi JSON đúng cú pháp và lặp từ liên tục. Mức cân bằng hợp lý là 4-bit (AWQ hoặc Q4_K_M).
Bỏ qua System Prompt Format (Chat Template Mismatch):
- Sai lầm: dùng sai chat template (ví dụ gửi prompt kiểu Llama-3
<|start_header_id|>vào Qwen-2.5 vốn dùng<|im_start|>). - Hậu quả: model sinh rác hoặc trả chuỗi rỗng. Cứ dùng tokenizer của HuggingFace hoặc vLLM để render đúng template của từng model.
- Sai lầm: dùng sai chat template (ví dụ gửi prompt kiểu Llama-3
# checklist trước khi lên production
- 1. Sizing VRAM & KV-Cache: đã tính KV-Cache theo lúc concurrent requests cao điểm nhất chưa?
- 2. Continuous Batching Engine: đã dùng vLLM hoặc TensorRT-LLM thay vì chạy script PyTorch thuần chưa?
- 3. Fallback Circuit Breaker: đã có đường chuyển sang Cloud LLM khi cụm SLM local bị nghẽn hoặc gặp prompt vượt giới hạn token length chưa?
- 4. Quantization Verification: đã đo chất lượng giảm bao nhiêu (chạy benchmark trên tập test dữ liệu thật) sau khi lượng tử hoá INT4 chưa?
- 5. Tokenization Alignment: chat template và special tokens đã kiểm tra khớp 100% với base model chưa?
- 6. Monitoring & Alerting: đã đẩy các metric
vllm:num_requests_waiting,vllm:kv_cache_usage_perc(bản vLLM cũ tên làvllm:gpu_cache_usage_perc) lên Prometheus để cảnh báo khi queue bị dồn chưa?
# kết luận
Small Language Models không phải bản "kém" của LLM. Chúng là cách nghĩ của người làm phần mềm đã chín: tính toán vừa đủ, chuyên vào đúng việc, tiết kiệm tài nguyên và tự giữ dữ liệu của mình.
Với người thiết kế hệ thống bây giờ, kết hợp SLM ở biên với LLM trên cloud cho linh hoạt là cách hợp lý để có kiến trúc AI chạy bền, đỡ tốn tiền mà vẫn nhanh.
Chỉ là những ghi chép cá nhân với hy vọng mang lại chút giá trị. Nếu thấy hữu ích, đừng ngại chia sẻ cho bạn bè & đồng nghiệp nhé!
Happy coding 😎 👍🏻 🚀 🔥.