Tại sao LLM chạy mượt trên máy local nhưng lại “sập” khi lên production?
Chạy một mô hình ngôn ngữ lớn (LLM) trên máy cá nhân rất đơn giản. Tuy nhiên, rắc rối sẽ đến khi bạn đưa nó lên server cho 5-10 người dùng cùng lúc. Lúc này, hệ thống bắt đầu chậm lại thấy rõ, thậm chí treo GPU hoàn toàn. Vấn đề không nằm ở code Python của bạn. Nó nằm ở cách quản lý tài nguyên vì LLM cực kỳ ngốn VRAM và đòi hỏi tính toán song song liên tục.
Ba rào cản lớn nhất mà bạn sẽ gặp phải bao gồm:
- Nghẽn cổ chai GPU: Một request chiếm trọn tài nguyên khiến các request khác phải xếp hàng (queue) chờ đợi hàng chục giây.
- Lãng phí ngân sách: Việc duy trì 4 GPU A100 liên tục trong khi ban đêm không có người dùng sẽ khiến chi phí server tăng vọt.
- Khó khăn khi mở rộng: Việc phân phối request giữa nhiều server vật lý là bài toán đau đầu nếu bạn tự code bộ điều phối (load balancer).
Để giải quyết bài toán này, Ray Serve là lựa chọn hàng đầu của mình. Framework này biến các mô hình AI thành microservices có khả năng tự co giãn (auto-scale) linh hoạt trên môi trường Linux.
Chuẩn bị môi trường hệ thống
Bạn nên sử dụng server Ubuntu 22.04 đã cài sẵn NVIDIA Driver và CUDA Toolkit. Thay vì dùng Docker ngay từ đầu, mình sẽ hướng dẫn cài trực tiếp trên Python để bạn nắm rõ luồng vận hành của hệ thống.
# Cập nhật hệ thống và cài đặt Python
sudo apt update && sudo apt upgrade -y
sudo apt install python3-pip -y
# Cài đặt Ray Serve và vLLM
pip install "ray[serve]" vllm torch
Trong thực tế, mình luôn kết hợp Ray Serve với vLLM. Đây là bộ engine inference có tốc độ xử lý nhanh gấp 10-20 lần so với HuggingFace Transformers nhờ kỹ thuật PagedAttention.
Thiết lập Ray Cluster: Từ một máy đến quy mô lớn
Ray vận hành theo mô hình Head node và Worker node. Head node đóng vai trò “nhạc trưởng” điều phối, trong khi Worker node là nơi trực tiếp xử lý tính toán trên GPU.
Khởi tạo Head node trên server chính bằng lệnh:
ray start --head --port=6379 --dashboard-host=0.0.0.0
Sau khi chạy, terminal sẽ hiển thị một IP và token. Nếu bạn có server thứ hai, chỉ cần chạy ray start --address='IP_HEAD_NODE:6379'. Ngay lập tức, tài nguyên GPU từ máy mới sẽ được gộp chung vào cụm tính toán của bạn.
Viết mã triển khai Inference Service
Bỏ qua các bước setup boilerplate phức tạp, Ray Serve cho phép bạn định nghĩa service thông qua Class với decorator @serve.deployment. Dưới đây là đoạn code tối ưu để chạy Qwen-2.5 hoặc Llama-3.
import ray
from ray import serve
from vllm import LLM, SamplingParams
from fastapi import FastAPI
app = FastAPI()
@serve.deployment(num_replicas=1, ray_actor_options={"num_gpus": 1})
@serve.ingress(app)
class LLMDeployment:
def __init__(self, model_name: str):
# Giới hạn VRAM để tránh lỗi Out of Memory
self.llm = LLM(model=model_name, gpu_memory_utilization=0.8)
self.sampling_params = SamplingParams(temperature=0.7, max_tokens=512)
@app.post("/generate")
async def generate(self, prompt: str):
outputs = self.llm.generate([prompt], self.sampling_params)
return {"text": outputs[0].outputs[0].text}
model_path = "Qwen/Qwen2.5-7B-Instruct"
serve.run(LLMDeployment.bind(model_path))
Lưu ý tham số num_replicas. Nếu bạn sở hữu 4 GPU, hãy tăng con số này lên để phục vụ nhiều người dùng song song hơn.
Cấu hình Auto-scaling: Bí quyết tiết kiệm 60% chi phí
Trên môi trường production, lượng truy cập thường không ổn định. Mình thường sử dụng file cấu hình YAML để Ray Serve tự động quản lý việc tăng giảm số lượng bản sao (replica) dựa trên tải thực tế.
deployments:
- name: LLMDeployment
autoscaling_config:
min_replicas: 1
max_replicas: 10
target_ongoing_requests: 5
ray_actor_options:
num_gpus: 1
Cấu hình target_ongoing_requests: 5 rất quan trọng. Nếu mỗi bản sao đang xử lý quá 5 request cùng lúc, Ray sẽ tự động kích hoạt thêm GPU mới. Khi nhu cầu giảm xuống, hệ thống tự động giải phóng GPU để tiết kiệm điện và chi phí thuê server.
Giám sát và kiểm tra hiệu năng
Bạn có thể theo dõi sức khỏe hệ thống qua Dashboard của Ray tại cổng 8265. Dashboard này cung cấp thông số trực quan về lượng request trên giây (RPS) và tình trạng sử dụng VRAM của từng GPU.
Để kiểm tra nhanh từ terminal, hãy dùng lệnh curl:
curl -X POST "http://localhost:8000/generate" \
-H "Content-Type: application/json" \
-d '{"prompt": "Ray Serve là gì?"}'
Nếu phản hồi trả về dưới 1 giây và biểu đồ GPU utilization nhảy số, hệ thống của bạn đã sẵn sàng phục vụ người dùng thực tế.
Kinh nghiệm thực chiến khi vận hành
Sau nhiều dự án triển khai thực tế, mình rút ra 3 lưu ý “xương máu” để hệ thống không bị crash:
- Kiểm soát VRAM: vLLM mặc định chiếm 90% VRAM. Nếu cần chạy thêm các tác vụ khác trên cùng GPU, hãy chỉnh
gpu_memory_utilizationxuống khoảng 0.7 – 0.8. - Cài đặt Health Checks: LLM đôi khi bị treo do lỗi driver CUDA. Hãy cấu hình health check để Ray tự động khởi động lại các tiến trình bị lỗi mà không cần can thiệp thủ công.
- Băng thông mạng: Khi chạy cụm nhiều máy, hãy đảm bảo các node kết nối qua mạng nội bộ tối thiểu 10Gbps. Điều này giúp việc truyền tải trọng số mô hình hàng chục GB diễn ra nhanh chóng.
Triển khai theo cách này ban đầu có vẻ phức tạp hơn một script Python đơn giản. Tuy nhiên, đây là con đường bền vững nhất để ứng dụng AI của bạn sống sót khi lượng người dùng tăng trưởng đột biến.

