Bỏ qua điều hướng
CÔNG TY CỔ PHẦN GIẢI PHÁP CÔNG NGHỆ HQG
Giai đoạn 6 · Triển khaiTrung cấp

Triển khai suy luận LLM: vLLM, Ollama, llama.cpp, Open WebUI và bảo mật endpoint

Dựng API tương thích OpenAI bằng vLLM (tensor parallel, AWQ/GPTQ/FP8, LoRA), chạy Ollama và llama.cpp cho máy nhỏ, tổng quan SGLang/TGI, giao diện chat nội bộ Open WebUI, reverse proxy, API key và đo tải.

Khoảng 7 phút đọcCập nhật: 09/20267 bước
Mục tiêu

Có endpoint LLM nội bộ chạy ổn định, chỉ người được phép truy cập, có giao diện chat cho nhân viên và số liệu đo tải của chính hệ thống.

Dành cho ai
  • Kỹ sư triển khai AI cho doanh nghiệp
  • Trưởng phòng IT cần chatbot nội bộ không gửi dữ liệu ra ngoài
Yêu cầu
  • vLLM/SGLang: máy chủ GPU NVIDIA đủ VRAM cho mô hình + KV cache — ước lượng tại /ai/tinh-cau-hinh
  • Ollama/llama.cpp: workstation hoặc máy nhỏ, chạy được cả CPU (chậm hơn)
  • Docker + NVIDIA Container Toolkit theo bài Docker & GPU
  • Tên miền nội bộ hoặc IP cố định cho máy phục vụ
Mục lục bài

Chọn engine phục vụ

EngineĐiểm mạnhHợp với
vLLMAPI tương thích OpenAI, batching liên tục, tensor parallel, nhiều định dạng lượng tử hoá, nạp LoRAMáy chủ GPU phục vụ nhiều người dùng
SGLangEngine phục vụ hiệu năng cao, tối ưu cho chia sẻ prefix, API tương thích OpenAITương tự vLLM; nên thử cả hai trên tải thật
TGI (Hugging Face)Tích hợp hệ sinh thái Hugging FaceHệ thống đã dùng TGI; kiểm tra trạng thái phát triển trên repo trước khi chọn cho dự án mới
OllamaCài một lệnh, quản lý mô hình GGUF đơn giảnMáy trạm, thử nghiệm, nhóm nhỏ
llama.cpp (llama-server)Nhẹ, chạy GGUF trên CPU/GPU, API tương thích OpenAIMáy nhỏ, edge, mô hình lượng tử hoá

Các bước thực hiện

Tiến độ của bạn
0/7

Tiến độ chỉ lưu trên trình duyệt này.

  1. Bước 1: Chạy vLLM với API tương thích OpenAI

    Bash
    uv pip install vllm
    export VLLM_API_KEY=$(openssl rand -hex 32)
    echo "$VLLM_API_KEY" > ~/.vllm_api_key && chmod 600 ~/.vllm_api_key
    
    vllm serve Qwen/Qwen2.5-7B-Instruct \
      --host 127.0.0.1 --port 8000 \
      --api-key "$VLLM_API_KEY" \
      --max-model-len 8192 \
      --gpu-memory-utilization 0.90

    --host 127.0.0.1 giữ API chỉ nghe trên máy; ra ngoài đi qua reverse proxy ở bước 6. --max-model-len giới hạn độ dài ngữ cảnh để kiểm soát KV cache.

    Gọi thử
    curl http://127.0.0.1:8000/v1/chat/completions \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer $VLLM_API_KEY" \
      -d '{"model": "Qwen/Qwen2.5-7B-Instruct", "messages": [{"role": "user", "content": "Tóm tắt lợi ích của máy chủ GPU on-prem trong 3 ý."}], "max_tokens": 200}'
  2. Bước 2: Tensor parallel, lượng tử hoá và LoRA trên vLLM

    Bash
    # Chia mô hình lên 4 GPU trong cùng máy
    vllm serve <model-lon> --tensor-parallel-size 4 --api-key "$VLLM_API_KEY"
    
    # Mô hình đã lượng tử hoá AWQ/GPTQ: vLLM đọc cấu hình từ repo mô hình
    vllm serve Qwen/Qwen2.5-7B-Instruct-AWQ --api-key "$VLLM_API_KEY"
    
    # FP8 lượng tử hoá động khi nạp (cần GPU và bản vLLM hỗ trợ)
    vllm serve Qwen/Qwen2.5-7B-Instruct --quantization fp8 --api-key "$VLLM_API_KEY"
    
    # Phục vụ adapter LoRA đã fine-tune, gọi bằng model="hqg-support"
    vllm serve Qwen/Qwen2.5-7B-Instruct --enable-lora \
      --lora-modules hqg-support=./out/qwen7b-lora/final \
      --api-key "$VLLM_API_KEY"
    • Tensor parallel nên dùng trong một node có kết nối GPU nhanh; số GPU phải chia hết cho số attention head của mô hình.
    • Mức hỗ trợ từng kiểu lượng tử hoá phụ thuộc thế hệ GPU — kiểm tra bảng tương thích trong tài liệu vLLM.
    • Lượng tử hoá có thể ảnh hưởng chất lượng; đánh giá lại bằng bộ câu hỏi nghiệp vụ.
  3. Bước 3: Ollama cho máy nhỏ

    Bash
    curl -fsSL https://ollama.com/install.sh | sh
    ollama run qwen2.5:7b
    # API mặc định chỉ nghe 127.0.0.1:11434
    curl http://127.0.0.1:11434/v1/chat/completions -H "Content-Type: application/json" \
      -d '{"model": "qwen2.5:7b", "messages": [{"role": "user", "content": "Xin chào"}]}'

    Dùng file GGUF tự xuất ở bài fine-tune:

    Modelfile
    FROM ./qwen7b-Q4_K_M.gguf
    PARAMETER temperature 0.3
    SYSTEM "Bạn là trợ lý kỹ thuật của công ty, trả lời ngắn gọn, chính xác."
    Bash
    ollama create hqg-qwen -f Modelfile
    ollama run hqg-qwen

    Cảnh báo: Ollama import GGUF có thể không tự nhận đúng chat template của mô hình đã fine-tune. Nếu câu trả lời lạ, khai báo TEMPLATE trong Modelfile theo tài liệu Ollama.

  4. Bước 4: llama.cpp server

    Bash
    # Đã build llama.cpp với -DGGML_CUDA=ON ở bài fine-tune
    ./build/bin/llama-server -m ../out/qwen7b-Q4_K_M.gguf \
      --host 127.0.0.1 --port 8080 \
      -ngl 99 -c 8192 \
      --api-key "$VLLM_API_KEY"

    -ngl 99 đẩy tối đa số lớp lên GPU; bỏ tham số này để chạy thuần CPU. API tương thích OpenAI tại /v1/chat/completions.

  5. Bước 5: Giao diện chat nội bộ với Open WebUI

    Chạy vLLM và Open WebUI trong cùng mạng Docker: vLLM không mở cổng ra máy chủ, chỉ Open WebUI truy cập được.

    compose.yaml
    services:
      vllm:
        image: vllm/vllm-openai:latest        # ghim tag cụ thể khi chạy thật
        command: ["--model", "Qwen/Qwen2.5-7B-Instruct", "--api-key", "${VLLM_API_KEY}", "--max-model-len", "8192"]
        ipc: host
        environment:
          - HF_TOKEN=${HF_TOKEN}
        volumes:
          - hf-cache:/root/.cache/huggingface
        deploy:
          resources:
            reservations:
              devices:
                - driver: nvidia
                  count: all
                  capabilities: [gpu]
        restart: unless-stopped
    
      open-webui:
        image: ghcr.io/open-webui/open-webui:main   # ghim tag cụ thể khi chạy thật
        ports:
          - "127.0.0.1:3000:8080"
        environment:
          - OPENAI_API_BASE_URL=http://vllm:8000/v1
          - OPENAI_API_KEY=${VLLM_API_KEY}
        volumes:
          - open-webui:/app/backend/data
        depends_on:
          - vllm
        restart: unless-stopped
    
    volumes:
      hf-cache:
      open-webui:
    Bash
    printf "VLLM_API_KEY=%s\nHF_TOKEN=%s\n" "$(openssl rand -hex 32)" "hf_xxx" > .env
    chmod 600 .env
    sudo docker compose up -d
    sudo docker compose logs -f vllm

    Mẹo: Tài khoản đăng ký đầu tiên trên Open WebUI trở thành quản trị viên — tạo ngay sau khi khởi động, rồi tắt tự đăng ký hoặc chuyển sang đăng nhập SSO (OIDC) trong phần cài đặt.

  6. Bước 6: Reverse proxy, HTTPS và tường lửa

    /etc/caddy/Caddyfile
    chat.congty.local {
        tls internal
        reverse_proxy 127.0.0.1:3000
    }
    
    llm-api.congty.local {
        tls internal
        @allowed remote_ip 10.0.0.0/24
        handle @allowed {
            reverse_proxy 127.0.0.1:8000
        }
        respond 403
    }
    Bash
    sudo apt install -y caddy
    sudo systemctl reload caddy
    sudo ufw allow from 10.0.0.0/24 to any port 443 proto tcp
    sudo ufw enable
    • Khối llm-api giả định vLLM nghe tại 127.0.0.1:8000 như bước 1. Nếu chạy vLLM trong compose ở bước 5 và cần mở API cho ứng dụng khác, thêm ports: ["127.0.0.1:8000:8000"] cho service vllm.
    • tls internal dùng CA nội bộ của Caddy — cần cài chứng chỉ gốc lên máy người dùng, hoặc dùng chứng chỉ của doanh nghiệp.
    • Cổng Docker publish ra 0.0.0.0 có thể vượt qua quy tắc ufw. Luôn bind 127.0.0.1: như trong compose ở trên.
    • Mỗi ứng dụng gọi API dùng key riêng qua tầng gateway khi cần thu hồi độc lập; vLLM chỉ hỗ trợ một nhóm key tĩnh.
    • Ghi log truy cập ở reverse proxy; không log nội dung prompt nếu chứa dữ liệu nhạy cảm.
  7. Bước 7: Đo tải trước khi mở cho người dùng

    Đo trên chính phần cứng, mô hình và độ dài prompt giống thực tế. Các chỉ số cần xem: thời gian ra token đầu (TTFT), thời gian mỗi token sau đó, thông lượng và tỷ lệ lỗi khi tăng số yêu cầu đồng thời.

    Bash
    export OPENAI_API_KEY="$VLLM_API_KEY"
    vllm bench serve \
      --backend openai-chat \
      --base-url http://127.0.0.1:8000 \
      --endpoint /v1/chat/completions \
      --model Qwen/Qwen2.5-7B-Instruct \
      --dataset-name random --random-input-len 1024 --random-output-len 256 \
      --num-prompts 200 --request-rate 4
    # Tham số thay đổi theo phiên bản: vllm bench serve --help

    vLLM cũng xuất số liệu Prometheus tại /metrics — nối vào hệ giám sát theo bài giám sát & vận hành.

Kiểm tra thành công

Bash
# Không có key: phải bị từ chối (401)
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8000/v1/models
# Có key: trả về danh sách mô hình
curl -s http://127.0.0.1:8000/v1/models -H "Authorization: Bearer $VLLM_API_KEY"
# Từ máy ngoài dải IP cho phép: không truy cập được API
  • Người dùng mở https://chat.congty.local, đăng nhập và chat được.
  • Gọi API không có key bị từ chối; từ ngoài dải IP cho phép bị chặn.
  • Có kết quả đo tải ở mức đồng thời dự kiến, lưu lại làm mốc.

Lỗi thường gặp & cách sửa

vLLM báo không đủ bộ nhớ cho KV cache khi khởi động

Nguyên nhân thường gặp: --max-model-len quá lớn so với VRAM còn lại sau khi nạp trọng số.

Giảm --max-model-len, tăng --gpu-memory-utilization (nếu GPU không chạy việc khác), dùng bản lượng tử hoá hoặc thêm GPU với tensor parallel.

Open WebUI không thấy mô hình

Nguyên nhân thường gặp: Sai OPENAI_API_BASE_URL, sai key, hoặc vLLM chưa nạp xong mô hình.

Bash
sudo docker compose logs vllm | tail -n 30
sudo docker compose exec open-webui curl -s http://vllm:8000/v1/models -H "Authorization: Bearer $VLLM_API_KEY"
Tải mô hình từ Hugging Face bị 401/403

Nguyên nhân thường gặp: Mô hình yêu cầu chấp nhận giấy phép hoặc token không có quyền.

Chấp nhận điều khoản trên trang mô hình bằng tài khoản của token, đặt HF_TOKEN trong .env. Máy không ra Internet: tải mô hình ở máy khác rồi chép vào volume cache.

Câu trả lời bị cắt ngang

Nguyên nhân thường gặp: max_tokens phía client quá nhỏ hoặc chạm giới hạn --max-model-len.

Tăng max_tokens trong yêu cầu, rút gọn prompt/ngữ cảnh RAG, hoặc tăng --max-model-len nếu VRAM cho phép.

Bước tiếp theo

Nguồn chính chủ

Lệnh, tên gói và tham số thay đổi theo phiên bản. Trước khi chạy trên máy thật, hãy kiểm tra phiên bản mới nhất tại trang chính chủ:

Giới hạn của bài

  • Bài không đưa số token/giây hay số người dùng một GPU phục vụ được — chạy bước 7 trên hệ thống của bạn để có số thật.
  • Tag latest/main trong compose chỉ để minh hoạ; môi trường sản xuất phải ghim phiên bản.
  • Bài không đề cập Kubernetes, autoscaling, cân bằng tải nhiều máy phục vụ.
Cần người dựng hệ thống cùng?

Kỹ sư HQG khảo sát, lên cấu hình, lắp đặt và bàn giao hạ tầng AI chạy được thật.