Triển khai và Tối ưu hóa LLM Quy mô lớn trên Hạ tầng Linux với vLLM và Ollama
Trong kỷ nguyên chuyển đổi số mạnh mẽ, việc sở hữu các mô hình ngôn ngữ lớn (LLM) như Llama 3, Mistral hay Gemma ngay trên hạ tầng nội bộ (on-premise) hoặc máy chủ cá nhân đã trở thành một xu hướng tất yếu cho các tổ chức coi trọng bảo mật dữ liệu và tính chủ động. Tuy nhiên, việc chạy các mô hình này không đơn giản chỉ là tải về file trọng số; nó đòi hỏi sự hiểu biết sâu sắc về quản lý bộ nhớ GPU, định dạng mô hình, và cách thức tối ưu hóa thông lượng (throughput). Bài viết này sẽ đi sâu vào phân tích và hướng dẫn cách sử dụng hai công cụ hàng đầu hiện nay: vLLM dành cho môi trường server chuyên nghiệp cần hiệu năng cao, và Ollama cho môi trường phát triển nhanh gọn, sau đó so sánh cách chúng xử lý các kỹ thuật tiên tiến như Continuous Batch và KV Cache.
Tổng quan về kiến trúc và lựa chọn công cụ
Khi nói đến việc chạy LLM trên Linux, chúng ta thường đối mặt với bài toán cân bằng giữa hiệu năng và sự tiện lợi. vLLM không chỉ là một thư viện inference mà là một hệ thống phục vụ (serving engine) được thiết kế riêng cho các mô hình Transformer. Điểm khác biệt lớn nhất của vLLM so với các framework truyền thống như HuggingFace Transformers nằm ở cách nó quản lý bộ nhớ. vLLM sử dụng kỹ thuật gọi là PagedAttention, cho phép chia sẻ bộ nhớ bộ đệm (KV cache) giữa các yêu cầu (request) khác nhau, giảm thiểu việc phân mảnh bộ nhớ GPU (VRAM). Điều này giúp vLLM đạt được thông lượng cao hơn gấp nhiều lần trong các kịch bản có nhiều người dùng truy cập cùng lúc.
Ngược lại, Ollama được thiết kế với triết lý "đơn giản hóa mọi thứ". Nó đóng gói quá trình build, tối ưu (thường sử dụng GGUF) và chạy mô hình thành một lệnh duy nhất trên dòng lệnh. Ollama cực kỳ hữu ích cho các lập trình viên muốn tích hợp AI vào ứng dụng mà không cần lo lắng về việc cấu hình server, cài đặt môi trường CUDA phức tạp hay quản lý các thư viện Python. Nó tự động xử lý việc tải mô hình từ registry, chuyển đổi định dạng, và cung cấp một API tương thích với OpenAI để bạn có thể dễ dàng gọi API từ code.
Cài đặt và Chuẩn bị Môi trường Linux cho vLLM
Để bắt đầu với vLLM, bạn cần một môi trường Linux (thường là Ubuntu 20.04 hoặc 22.04) được trang bị card đồ họa NVIDIA với driver CUDA mới nhất. Việc cài đặt vLLM tốt nhất nên thực hiện thông qua conda để tránh xung đột phiên bản giữa các thư viện Python và CUDA. Trước hết, hãy tạo một môi trường ảo mới để cách ly các dependency. Bạn sẽ cần cài đặt Python 3.10 hoặc 3.11 vì vLLM hiện đang hỗ trợ tốt nhất các phiên bản này.
Đầu tiên, hãy tạo environment và kích hoạt nó bằng các lệnh conda dưới đây. Lưu ý rằng bạn cần đã cài đặt Anaconda hoặc Minicona trước đó.
conda create -n vllm-env python=3.10 -y
conda activate vllm-env
Sau khi môi trường đã sẵn sàng, bước tiếp theo là cài đặt vLLM. Đối với các card GPU NVIDIA phổ biến như RTX 4090 hoặc A100, bạn có thể cài đặt phiên bản stable thông qua pip. Tuy nhiên, nếu bạn muốn sử dụng các tính năng mới nhất hoặc tối ưu hóa cho kiến trúc GPU cụ thể, bạn nên cân nhắc cài đặt từ nguồn code hoặc sử dụng phiên bản với các cờ tối ưu hóa đặc biệt.
pip install vllm
Khi lệnh cài đặt hoàn tất, hệ thống sẽ tự động kéo về các thư viện phụ thuộc như torch, numpy và các gói xử lý GPU. Để kiểm tra xem vLLM đã nhận diện được card GPU của bạn chưa, bạn có thể chạy một lệnh kiểm tra nhanh. Nếu không có lỗi nào liên quan đến CUDA hoặc Triton, bạn đã sẵn sàng để khởi tạo server.
Triển khai Server vLLM với Model Llama-3-8B-Instruct
Giả sử bạn muốn triển khai một phiên bản Llama 3-8B-Instruct cho nhóm phát triển của mình. VLM cho phép bạn chạy mô hình này ở độ chính xác đầy đủ (FP16) hoặc đã được lượng tử hóa (quantized) để tiết kiệm VRAM. Trong ví dụ này, chúng ta sẽ sử dụng model gốc từ HuggingFace để đạt chất lượng cao nhất, đồng thời kích hoạt chế độ continuous batching để xử lý đồng thời nhiều request.
Lệnh khởi tạo server của vLLM rất trực quan. Bạn cần chỉ định tên mô hình, thiết lập số lượng GPU sử dụng (max_num_gpu), giới hạn độ dài tối đa của prompt và response, và cổng kết nối. Một thông số quan trọng cần chú ý là --dtype. Nếu card của bạn có VRAM lớn (trên 24GB), hãy dùng float16. Nếu chỉ có 16GB, bạn nên cân nhắc dùng bfloat16 hoặc chuyển sang model quantized như AWQ hoặc GPTQ sau này.
vllm serve meta-llama/Meta-Llama-3-8B-Instruct --max-num-seqs 16 --max-model-len 8192 --tensor-parallel-size 1 --port 8000
Cú pháp trên sẽ khởi động một server HTTP tại cổng 8000. Tham số --max-num-seqs 16 cho phép server xử lý tối đa 16 yêu cầu đồng thời, tận dụng tối đa khả năng liên tục batching của vLLM. Tham số --max-model-len 8192 đặt giới hạn context window, giúp kiểm soát việc tiêu thụ bộ nhớ VRAM. Khi server chạy, bạn sẽ thấy các log hiển thị thông tin về việc tải model, phân bổ bộ nhớ KV cache, và trạng thái của GPU.
Để kiểm tra xem server có hoạt động tốt không, bạn có thể gửi một request mẫu thông qua lệnh curl từ một terminal khác hoặc từ client của bạn. Request này sẽ tương thích với định dạng OpenAI API, giúp việc tích hợp vào các ứng dụng hiện có trở nên dễ dàng hơn bao giờ hết.
curl http://localhost:8000/v1/completions -H "Content-Type: application/json" -d '{ "model": "meta-llama/Meta-Llama-3-8B-Instruct", "prompt": "Giải thích ngắn gọn về vLLM", "max_tokens": 100, "temperature": 0.7 }'
Phản hồi từ server sẽ bao gồm nội dung do AI sinh ra dưới dạng JSON. Bạn có thể thấy rằng vLLM trả về kết quả khá nhanh chóng ngay cả khi có nhiều request đang chờ. Điểm mạnh của vLLM còn thể hiện rõ khi bạn tăng tải lên gấp đôi, khi đó hệ thống sẽ tự động chia nhỏ các request để xử lý song song mà không làm giảm tốc độ sinh token đáng kể.
Cài đặt và Sử dụng Ollama để Deploy Nhanh
Sang phần phân tích về Ollama, chúng ta thấy một cách tiếp cận hoàn toàn khác. Ollama không yêu cầu bạn cài đặt Python, conda hay quản lý môi trường phức tạp. Nó cung cấp một binary file đơn giản chạy trực tiếp trên Linux. Điều này khiến nó trở thành lựa chọn hàng đầu cho các dự án Proof-of-Concept (PoC), môi trường phát triển (Dev), hoặc các máy khách nhẹ không có nhiều tài nguyên GPU chuyên dụng.
Để cài đặt Ollama trên Linux, bạn chỉ cần tải binary về hoặc sử dụng lệnh curl được cung cấp chính thức từ trang chủ của họ. Lệnh này sẽ tự động thêm Ollama vào PATH và thiết lập dịch vụ systemd để nó tự động chạy khi khởi động máy.
curl -fsSL https://ollama.com/install.sh | sh
Sau khi cài đặt xong, bạn có thể kiểm tra phiên bản và trạng thái bằng lệnh ollama --version. Điểm thú vị nhất của Ollama là khả năng tải và chạy mô hình chỉ với một lệnh duy nhất. Các mô hình trên Ollama thường được chuyển đổi sẵn sang định dạng GGUF (thường dùng GGUF từ llama.cpp), cho phép chạy trên cả CPU và GPU với hiệu năng tối ưu cho các máy cấu hình thấp. Định dạng này sử dụng kỹ thuật lượng tử hóa (quantization) để giảm kích thước file và yêu cầu VRAM mà vẫn giữ được chất lượng ngôn ngữ chấp nhận được.
So sánh Hiệu năng và Chiến lược Lượng tử hóa
Khi so sánh vLLM và Ollama, sự khác biệt cốt lõi nằm ở chiến lược lượng tử hóa và mục tiêu sử dụng. vLLM thường hoạt động tốt nhất với các mô hình ở độ chính xác cao (FP16/BF16) hoặc các định dạng lượng tử hóa tối ưu cho inference server như AWQ, GPTQ. Nó được thiết kế để tối đa hóa thông lượng trên các cụm GPU (cluster) với nhiều card đồ họa, sử dụng kỹ thuật Tensor Parallelism để chia nhỏ mô hình across nhiều GPU.
Ollama, mặt khác, tập trung vào việc chạy mượt mà trên một máy tính đơn lẻ, thường là laptop hoặc máy trạm đơn GPU. Nó sử dụng định dạng GGUF với các mức lượng tử hóa khác nhau như Q4_K_M (4-bit), Q5_K_M (5-bit), hay Q8_0 (8-bit). Mức lượng tử hóa càng thấp thì file càng nhỏ và càng ít tốn VRAM, nhưng chất lượng suy luận có thể giảm nhẹ. Tuy nhiên, đối với các mô hình hiện đại như Llama 3, ngay cả ở mức Q4_K_M, chất lượng vẫn rất ấn tượng cho các tác vụ chat thông thường.
Để minh họa sự khác biệt, hãy xem xét việc chạy cùng một mô hình Llama 3-8B trên cả hai nền tảng. Với vLLM, bạn cần tải file model gốc (khoảng 16GB+), yêu cầu ít nhất 16GB VRAM nếu chạy ở FP16. Tốc độ sinh token có thể đạt 100+ token/giây trên RTX 4090. Trong khi đó, với Ollama, bạn chỉ cần tải file GGUF Q4_K_M (khoảng 4-5GB), có thể chạy trên cả máy chỉ có 8GB VRAM hoặc thậm chí là CPU (dù chậm hơn). Tốc độ trên GPU cũng rất cao nhưng có thể thấp hơn vLLM một chút do overhead của llama.cpp.
Tuy nhiên, vLLM có lợi thế tuyệt đối khi bạn cần chạy nhiều model cùng lúc (Multi-tenant serving) hoặc cần context window cực lớn (32k, 128k) mà vẫn duy trì hiệu năng. Ollama gặp khó khăn hơn trong việc quản lý bộ nhớ khi xử lý quá nhiều request song song cùng lúc, mặc dù nó vẫn hỗ trợ một số mức độ đa nhiệm nhất định thông qua queue mechanism.
Hướng dẫn Tích hợp API từ Ứng dụng Python
Dù bạn chọn vLLM hay Ollama, cả hai đều cung cấp API tương thích với chuẩn OpenAI. Điều này có nghĩa là bạn có thể sử dụng cùng một đoạn code Python để gọi đến cả hai server mà không cần thay đổi logic nghiệp vụ. Bạn chỉ cần thay đổi URL endpoint và API Key (nếu có, vLLM thường không cần key mặc định, Ollama cũng vậy trong nội bộ).
Dưới đây là một đoạn code Python mẫu sử dụng thư viện openai để giao tiếp với cả hai hệ thống. Đầu tiên, hãy cài đặt thư viện openai bằng lệnh pip install openai. Sau đó, bạn có thể viết code như sau để gọi LLM thông qua vLLM đang chạy ở địa chỉ localhost:8000.
import openai
client = openai.OpenAI(
base_url="http://localhost:8000/v1",
api_key="not-needed"
)
response = client.chat.completions.create(
model="meta-llama/Meta-Llama-3-8B-Instruct",
messages=[
{"role": "system", "content": "Bạn là một trợ lý Sysadmin thân thiện."},
{"role": "user", "content": "Hãy hướng dẫn tôi cách xem log của systemd trên Linux."}
],
temperature=0.7,
max_tokens=200
)
print(response.choices[0].message.content)
Đối với Ollama, code sẽ giống hệt như trên, chỉ khác ở địa chỉ base_url và tên model. Ollama thường chạy tại cổng 11434 và yêu cầu tên model theo định dạng của nó (ví dụ: llama3 thay vì meta-llama/Meta-Llama-3-8B-Instruct). Bạn có thể chạy lệnh ollama list để xem danh sách model đã cài đặt.
client = openai.OpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama"
)
response = client.chat.completions.create(
model="llama3",
messages=[
{"role": "user", "content": "Hãy hướng dẫn tôi cách xem log của systemd trên Linux."}
],
temperature=0.7
)
print(response.choices[0].message.content)
Khả năng tương thích API cao này giúp các nhà phát triển dễ dàng chuyển đổi giữa các công cụ inference mà không cần refactor lại toàn bộ ứng dụng. Trong môi trường sản xuất, bạn có thể dùng vLLM cho backend chính, và dùng Ollama cho các môi trường test hoặc sandbox của developer.
Quản lý Bộ nhớ và Tối ưu hóa Tài nguyên GPU
Đối với một Sysadmin, việc quản lý tài nguyên GPU là yếu tố sống còn. Khi chạy LLM, VRAM có thể bị đầy nhanh chóng dẫn đến lỗi CUDA out of memory. vLLM cung cấp cơ chế quản lý bộ nhớ động rất tốt thông qua PagedAttention, nhưng bạn vẫn cần cấu hình đúng các tham số khởi tạo.
Các tham số quan trọng cần điều chỉnh trong vLLM bao gồm --gpu-memory-utilization. Mặc định, vLLM sẽ dùng khoảng 90% VRAM. Nếu bạn muốn chạy cùng lúc nhiều ứng dụng khác trên GPU hoặc để lại đệm an toàn, bạn có thể giảm giá trị này xuống còn 0.8 hoặc 0.9. Điều này giúp tránh việc các tiến trình khác bị kill do thiếu bộ nhớ.
vllm serve --gpu-memory-utilization 0.85 --max-num-seqs 8
Đối với Ollama, quản lý bộ nhớ thực hiện ở mức độ định dạng mô hình. Nếu bạn thấy VRAM đầy khi chạy Ollama, giải pháp là chuyển sang phiên bản mô hình có mức lượng tử hóa thấp hơn (ví dụ từ Q8_0 xuống Q4_K_M). Bạn có thể tải các model này bằng lệnh ollama pull llama3:4bit hoặc tương tự. Ollama cũng hỗ trợ tham số --keepalive để kiểm soát thời gian model nằm trong bộ nhớ sau khi không sử dụng, giúp giải phóng VRAM khi không có request.
ollama run llama3:4bit --keepalive 5m
Hơn nữa, việc giám sát (monitoring) là rất quan trọng. Bạn nên sử dụng các công cụ như nvtop hoặc nvidia-smi để theo dõi thời gian thực việc sử dụng GPU, nhiệt độ và bộ nhớ. vLLM cung cấp các metrics Prometheus sẵn có, cho phép bạn tích hợp vào hệ thống giám sát tập trung như Grafana để cảnh báo khi tài nguyên GPU đạt ngưỡng.
Kết luận
Việc lựa chọn giữa vLLM và Ollama phụ thuộc vào bài toán cụ thể của bạn. Nếu bạn cần một hệ thống server chuyên nghiệp, có khả năng mở rộng, hỗ trợ nhiều người dùng đồng thời, và yêu cầu chất lượng mô hình cao nhất với khả năng tùy chỉnh sâu, vLLM là lựa chọn không thể thay thế. Ngược lại, nếu bạn cần tốc độ triển khai nhanh, môi trường phát triển đơn giản, hoặc chạy trên phần cứng hạn chế, Ollama cung cấp trải nghiệm mượt mà và dễ dàng vượt xa các giải pháp truyền thống.
Trong thực tế, nhiều tổ chức lớn đang sử dụng kết hợp cả hai: dùng vLLM cho các service core quan trọng cần hiệu năng cao, và dùng Ollama cho các công cụ hỗ trợ nội bộ, chatbot demo, hoặc môi trường sandbox cho các developer. Việc hiểu rõ cơ chế hoạt động, cách cấu hình và quản lý bộ nhớ của cả hai công cụ sẽ giúp bạn xây dựng được hạ tầng AI vững chắc, linh hoạt và hiệu quả chi phí. Hy vọng bài hướng dẫn này đã cung cấp cho bạn những kiến thức nền tảng và các lệnh cụ thể để bắt đầu hành trình khám phá thế giới LLM trên Linux.