Chuyển đến nội dung chính
Hướng dẫn AI

Chạy GLM-5.3-Flash trên Hai DGX Spark với TensorFold

Tìm hiểu cách cài đặt, cấu hình, khởi chạy, kiểm thử và tinh chỉnh GLM-5.3-Flash EXL3 trên hai NVIDIA DGX Spark. Hướng dẫn này bao gồm kết nối RoCE, thiết lập tự động, các yêu cầu tương thích với OpenAI, đầu vào hình ảnh và video, các tùy chọn suy luận, cơ chế hoạt động của bộ nhớ đệm KV dùng chung, giám sát và cấu hình nâng cao.

Chạy GLM-5.3-Flash trên Hai DGX Spark với TensorFold

Dự án này thực hiện những gì

Dự án này cung cấp GLM-5.3-Flash trên hai hệ thống NVIDIA DGX Spark bằng TensorFold v0.5.0. Mỗi Spark chạy một rank phân tán, trong đó Spark đầu tiên đồng thời lưu trữ API HTTP tương thích với OpenAI.

Cấu hình mặc định hỗ trợ bốn yêu cầu đồng thời, cửa sổ ngữ cảnh tối đa 1,048,576 token cho mỗi yêu cầu, đầu vào hình ảnh và video, gọi công cụ, đầu ra có cấu trúc, các endpoint token hóa và số liệu Prometheus. Hai hệ thống giao tiếp qua liên kết RoCE ConnectX-7 trực tiếp.

Hệ thống triển khai sử dụng checkpoint Mia-AiLab GLM-5.3-Flash EXL3. Các expert được định tuyến được lưu trữ ở mức xấp xỉ bốn bit cho mỗi trọng số, trong khi các trọng số khác của checkpoint dùng BF16. Toàn bộ checkpoint có dung lượng khoảng 176 GB.

Tính năng chính

  • API tương thích với OpenAI: Sử dụng các endpoint chat completions, completions, responses và liệt kê model.
  • Ngữ cảnh dài: Hỗ trợ tối đa 1,048,576 token prompt và phản hồi cho một yêu cầu riêng lẻ với cấu hình KV FP8 mặc định.
  • Suy luận đồng thời: Giải mã tối đa bốn yêu cầu cùng lúc với drafter DFlash2 mặc định.
  • Pool bộ nhớ đệm dùng chung: Các cuộc hội thoại đồng thời dùng chung một pool KV FP8 chứa khoảng 2,1 đến 2,7 triệu token, tùy theo bộ nhớ khả dụng.
  • Yêu cầu đa phương thức: Gửi đầu vào JPEG, PNG, WebP, MP4, WebM, MOV, MKV và các video khác có thể được FFmpeg giải mã.
  • Điều khiển suy luận: Chọn mức nỗ lực suy luận thấp, cao hoặc tối đa, hoặc tắt chế độ suy nghĩ cho một yêu cầu.
  • Tính năng agent: Sử dụng gọi công cụ và đầu ra có cấu trúc bị ràng buộc bởi schema thông qua xgrammar.
  • Endpoint vận hành: Kiểm tra tình trạng, token hóa hoặc giải token hóa đầu vào và thu thập số liệu Prometheus.
  • Triển khai tự động: Một lệnh chuẩn bị cả hai máy, khởi chạy cả hai rank, thực hiện kiểm tra nhanh và báo cáo địa chỉ API.

Yêu cầu phần cứng và phần mềm

Bạn cần hai DGX Spark hoặc hai hệ thống GB10, mỗi hệ thống có 128 GB bộ nhớ hợp nhất. Khi máy chủ khởi động, mỗi GPU cần còn trống khoảng 110 GiB, vì vậy hãy dừng các tác vụ GPU lớn khác trước.

Yêu cầu mạng

Kết nối các cổng ConnectX-7 bằng cáp QSFP và gán cho mỗi đầu cuối một địa chỉ IPv4 trong cùng subnet riêng. Ví dụ, head có thể dùng 192.0.2.1/24 và worker dùng 192.0.2.2/24. Các địa chỉ phải có thể truy cập bằng ping và phải có GID RoCE v2.

Nếu cả hai cổng CX7 đều được kết nối và gán địa chỉ, dự án có thể sử dụng cả hai rail. Theo các phép đo trong README, thao tác all-gather của một đoạn prompt nhanh hơn khoảng 1,8 lần khi dùng hai rail.

Yêu cầu SSH và hệ thống

  • Truy cập SSH bằng khóa từ Spark head đến worker.
  • Docker với NVIDIA container runtime trên cả hai hệ thống.
  • Tài khoản của bạn thuộc nhóm docker trên cả hai hệ thống.
  • Đã cài đặt rsync trên cả hai hệ thống.
  • Khoảng 205 GB dung lượng đĩa trên mỗi Spark.
  • Tùy chọn: CLI hf của Hugging Face và token Hugging Face trên head.

Tạo khóa SSH nếu cần, sao chép khóa sang worker và xác minh quyền truy cập không tương tác:

ssh-keygen -t ed25519
ssh-copy-id user@192.0.2.2
ssh -o BatchMode=yes user@192.0.2.2 true

Drafter DFlash2 được cấp phép theo CC BY-NC-ND 4.0 và chỉ được sử dụng cho mục đích phi thương mại. Nếu cần tránh tải xuống hoặc sử dụng DFlash2, hãy chọn drafter MTP của checkpoint trước lần thiết lập đầu tiên.

Cài đặt và cấu hình dự án

1. Sao chép repository trên head

git clone https://github.com/MiaAI-Lab/GLM-5.3-Flash-EXL3-2x-DGX-Sparks-TensorFold.git
cd GLM-5.3-Flash-EXL3-2x-DGX-Sparks-TensorFold
cp scripts/local.sh.example scripts/local.sh

Worker không cần bản checkout riêng. Các script thiết lập sẽ chuyển image container và các tệp model cần thiết từ head.

2. Thiết lập địa chỉ worker

Chỉnh sửa scripts/local.sh và đặt WORKER thành đích SSH của worker:

WORKER=user@192.0.2.2

Các rank phân tán giao tiếp qua route được sử dụng để kết nối đến worker. Nếu WORKER trỏ đến một địa chỉ trên mạng khác, hãy đặt FABRIC_PEER thành địa chỉ CX7 riêng của worker:

WORKER=user@worker-hostname
FABRIC_PEER=192.0.2.2

3. Chọn drafter nếu cần

Mặc định là DRAFTER=dflash2, cho phép tối đa bốn yêu cầu đồng thời và cải thiện tốc độ giải mã khoảng 5 đến 10 phần trăm theo đo lường. Để sử dụng MTP head của checkpoint, hãy cấu hình trước lần khởi động đầu tiên:

DRAFTER=mtp

MTP tránh được giấy phép và quá trình tải xuống DFlash2, nhưng mặc định chỉ phục vụ một yêu cầu mỗi lần.

4. Khởi động cả hai rank

./start.sh

Trong lần chạy đầu tiên, script kiểm tra cả hai hệ thống, lấy hoặc xây dựng image container khoảng 25 GB, tải checkpoint và drafter trên head, sao chép chúng sang worker và biên dịch các kernel CUDA vào ~/.cache/tensorfold-glm53.

Các lần khởi động tiếp theo thường mất từ hai đến sáu phút để nạp khoảng 80 GiB trọng số lên mỗi Spark. Trình khởi chạy theo dõi log của rank 0, báo cáo tiến trình nạp, chạy kiểm tra nhanh phân tán và in ra endpoint hoạt động trên cổng 8888.

Để chuẩn bị cả hai hệ thống mà không khởi động API, hãy chạy:

scripts/prepare.sh

Để buộc xây dựng lại image từ đầu, hãy sử dụng:

scripts/prepare.sh --rebuild

Thực hiện yêu cầu API đầu tiên

Mã định danh mô hình mặc định là GLM-5.3-Flash-EXL3, còn URL cơ sở là http://<head-address>:8888/v1.

Liệt kê các mô hình khả dụng

curl -s http://<head-address>:8888/v1/models

Gửi yêu cầu hoàn tất trò chuyện

curl -s http://<head-address>:8888/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "GLM-5.3-Flash-EXL3",
    "messages": [
      {"role": "user", "content": "Write a Python fibonacci function."}
    ],
    "max_tokens": 2000
  }'

The model thinks before answering by default. Reasoning is returned in reasoning_content, while the final answer appears in content. Allocate enough output tokens for both phases. If content is empty, the model probably consumed the output allowance while reasoning.

Kiểm soát suy luận và lấy mẫu

Đặt reasoning_effort thành low, high hoặc max. Sử dụng none để yêu cầu câu trả lời trực tiếp mà không suy nghĩ:

curl -s http://<head-address>:8888/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "GLM-5.3-Flash-EXL3",
    "messages": [{"role": "user", "content": "Summarize TCP in two sentences."}],
    "reasoning_effort": "low",
    "temperature": 0,
    "max_tokens": 1000
  }'

API cũng chấp nhận temperature, top_p, top_k, min_p và seed. Nếu không chỉ định seed, bộ lấy mẫu sẽ tạo khóa từ prompt, vì vậy các yêu cầu giống hệt nhau sẽ tạo ra cùng một câu trả lời.

Gửi hình ảnh và video

Vision tower của GLM mặc định chạy trên rank 0. Hình ảnh và video được biểu diễn dưới dạng các phần nội dung theo kiểu OpenAI trong tin nhắn người dùng.

Phân tích hình ảnh cục bộ

IMG=$(base64 -w0 photo.jpg)
curl -s http://<head-address>:8888/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "GLM-5.3-Flash-EXL3",
    "messages": [{
      "role": "user",
      "content": [
        {"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,'"$IMG"'"}},
        {"type": "text", "text": "What is in this picture?"}
      ]
    }],
    "max_tokens": 2000
  }'

Theo mặc định, máy chủ chấp nhận phương tiện thông qua data URL. Đặt VISION_URLS=1 nếu máy chủ cũng cần tải các URL HTTPS công khai.

Giới hạn phương tiện được hỗ trợ

  • Tối đa 50 hình ảnh mỗi yêu cầu, giới hạn 10 MB mỗi hình và tổng dữ liệu hình ảnh là 64 MB.
  • Tối đa 4 video mỗi yêu cầu, giới hạn 64 MB mỗi video và tổng dữ liệu video là 96 MB.
  • Mỗi video có thể chứa tối đa một giờ nội dung.
  • Nội dung yêu cầu có thể có kích thước tối đa 96 MiB, dành khoảng 70 MB cho phương tiện được mã hóa base64.
  • Mỗi ảnh nhận tối đa 2.048 token, trong khi tất cả ảnh trong một yêu cầu dùng chung ngân sách mặc định 16.384 token.
  • Mặc định, video được lấy mẫu ở tốc độ hai khung hình mỗi giây và tối đa 128 khung hình trong một đoạn.

Đối với video, thay phần nội dung hình ảnh bằng phần video_url chứa data URL như data:video/mp4;base64,....

Nếu chỉ cần văn bản, đặt VISION=0. Việc này tránh tải vision tower và dành thêm khoảng 1,8 GiB bộ nhớ trên rank 0 để sử dụng cho bộ nhớ đệm.

Vận hành và giám sát máy chủ

Khởi động lại và dừng

./start.sh restart
./stop.sh

Cần khởi động lại sau khi thay đổi các cài đặt lưu trữ lâu dài. Dừng dịch vụ sẽ giải phóng bộ nhớ GPU trên cả hai máy.

Kiểm tra nhật ký

docker logs -f glm53-flash-tf
ssh <worker> docker logs -f glm53-flash-tf

Lệnh đầu tiên theo dõi rank 0 trên máy head. Lệnh thứ hai theo dõi rank 1 và đặc biệt hữu ích khi worker thoát đột ngột.

Kiểm tra trạng thái và chỉ số

curl -s http://<head-address>:8888/health
curl -s http://<head-address>:8888/metrics

Phản hồi trạng thái báo cáo trạng thái bận, các luồng đang hoạt động và dung lượng pool dùng chung, bao gồm pool_tokens và pool_free_tokens. Endpoint metrics cung cấp các chỉ số Prometheus về yêu cầu, độ trễ, thời gian đến token đầu tiên và trạng thái.

Tìm hiểu về ngữ cảnh và bộ nhớ KV dùng chung

Cấu hình mặc định sử dụng bộ nhớ đệm KV FP8 và cấp cho mỗi yêu cầu một cửa sổ tối đa 1.048.576 token. Bốn yêu cầu dùng chung một pool được đo ở mức 2.684.928 token trong một lần khởi động đã ghi nhận, mặc dù dung lượng chính xác phụ thuộc vào bộ nhớ trống.

Một yêu cầu có thể sử dụng toàn bộ cửa sổ, nhưng tất cả cuộc trò chuyện đang hoạt động và được giữ lại phải vừa trong pool chung. Ví dụ, hai cuộc trò chuyện có thể đạt gần một triệu token mỗi cuộc, trong khi các cuộc trò chuyện ngắn hơn chạy đồng thời có thể chia sẻ dung lượng còn lại. Yêu cầu chưa thể được sắp xếp sẽ chờ các yêu cầu khác hoàn tất.

Sử dụng CONTEXT=0 để tính cửa sổ lớn nhất có thể chứa, nhưng lưu ý rằng tùy chọn này không chừa bộ nhớ để giữ lại trạng thái prompt của các cuộc trò chuyện khác. Chuyển sang lưu trữ KV BF16 chính xác sẽ làm giảm đáng kể cửa sổ khả dụng.

Hết bộ nhớ thống nhất có thể khiến Spark bị treo thay vì tạo ra lỗi cấp phát rõ ràng. Hãy giữ mức dự phòng mặc định trừ khi bạn hiểu rõ đánh đổi về bộ nhớ, và tăng MEMORY_RESERVE_GIB khi các máy dùng chung cho những khối lượng công việc khác.

Cấu hình nâng cao

Có thể cung cấp các cài đặt thông qua môi trường, scripts/local.sh hoặc tệp .env nằm cạnh start.sh. Thứ tự ưu tiên là môi trường, sau đó đến scripts/local.sh, .env và cuối cùng là các giá trị mặc định của kho mã.

Thay đổi mức đồng thời cho một lần chạy

PARALLEL=2 ./start.sh restart

PARALLEL có thể được đặt từ một đến bốn khi DFlash2 được bật. MTP mặc định xử lý một yêu cầu mỗi lần.

Thay đổi cửa sổ ngữ cảnh

CONTEXT=524288 ./start.sh restart

Cửa sổ ngữ cảnh nhỏ hơn có thể giảm áp lực bộ nhớ đệm khi không cần toàn bộ cửa sổ một triệu token.

Tăng giới hạn đầu ra mặc định

./start.sh restart --max-tokens 16384

Các đối số dòng lệnh bổ sung được truyền cho tensorfold serve sau các giá trị mặc định đã cấu hình, vì vậy chúng sẽ được ưu tiên. Chạy ./start.sh --help để xem các đối số được hỗ trợ.

Buộc hoặc bỏ qua bước chuẩn bị

PREPARE=1 ./start.sh restart
PREPARE=0 ./start.sh restart

Lệnh đầu tiên buộc kiểm tra thiết lập và quy trình chuẩn bị. Lệnh thứ hai bỏ qua các bước này.

Sử dụng hiệu quả việc tái sử dụng prompt

Tái sử dụng tiền tố dùng chung được bật theo mặc định với SHARED_PREFIX=1. Các system prompt lặp lại và prompt được giữ nguyên giống hệt có thể tiếp tục từ trạng thái đã lưu trong bộ nhớ đệm thay vì phải nạp trước lại. Trong các phép đo được ghi lại, prompt 64K token lặp lại giảm từ 34 giây xuống dưới 0.07 giây, trong khi việc tái sử dụng system prompt 7.9K token giảm thời gian khởi động từ 4.24 giây xuống 0.13 giây.

Chọn độ chính xác của bộ nhớ đệm và trọng số

  • KV=fp8 là mặc định và cho phép sử dụng cửa sổ ngữ cảnh lớn nhất.
  • KV=bf16 sử dụng bộ nhớ đệm chính xác nhưng làm ngắn đáng kể cửa sổ khả dụng.
  • DENSE=q4 là mặc định cho các thành phần checkpoint dense.
  • DENSE=fp8 và DENSE=bf16 là các lựa chọn thay thế, với tác động khác nhau đến bộ nhớ.

Các khả năng API bổ sung

Bên cạnh chat completions, máy chủ cung cấp /v1/completions, /v1/responses, /v1/models, /tokenize, /detokenize, /health và /metrics. Các route tokenization cũng khả dụng dưới /v1/. Máy chủ không cung cấp endpoint /v1/messages tương thích với Anthropic.

Tool calling hỗ trợ tools và tool_calls dạng stream, với các đối số được định kiểu theo schema được cung cấp. Sinh có cấu trúc hỗ trợ json_object, json_schema, JSON có hướng dẫn, biểu thức chính quy, lựa chọn, grammar và các trường đầu ra có cấu trúc khác được thực thi thông qua xgrammar sau khi hoàn tất suy luận.

Nếu prompt cộng với max_tokens vượt quá cửa sổ đã cấu hình, API sẽ trả về HTTP 400 cùng mã lỗi theo kiểu OpenAI là context_length_exceeded.

Khắc phục các sự cố khởi động thường gặp

  • Không đủ bộ nhớ: Nếu quá trình khởi động báo rằng chỉ có một lượng GiB giới hạn khả dụng, hãy kiểm tra docker ps và dừng các workload GPU khác trên cả hai Sparks.
  • Không có thiết bị hoặc route RoCE: Xác nhận các giao diện CX7 có địa chỉ IPv4 bằng ip -4 addr. Nếu SSH sử dụng mạng khác, hãy cấu hình FABRIC_PEER bằng địa chỉ CX7 của worker.
  • Không thể ghi vào bộ nhớ đệm của worker: Sửa quyền sở hữu bộ nhớ đệm Hugging Face của worker nếu một container trước đó đã để thư mục này thuộc về root.
  • Một rank thoát: Kiểm tra log trên cả hai máy. Launcher thường dừng rank còn lại nếu một trong hai phía gặp lỗi.
  • Thiết lập đã thay đổi: Sau khi sửa patch hoặc thay đổi TensorFold, base image hay các đầu vào build liên quan, hãy chạy scripts/prepare.sh --rebuild.

Kỳ vọng về hiệu năng

Trong các phép đo mặc định với hai Spark của README, giải mã văn bản dao động từ 60.4 token mỗi giây cho một yêu cầu đến 108.8 token mỗi giây tổng cộng cho bốn yêu cầu đồng thời. Sinh có cấu trúc dao động từ 114.7 đến 227.9 token mỗi giây tổng cộng. Tốc độ prefill xấp xỉ 1,952 token mỗi giây đối với prompt 8,219 token và 1,015 token mỗi giây đối với prompt needle-in-a-haystack 981,841 token, trong đó needle được tìm thấy.

Các số liệu này được đo với bốn stream, bộ nhớ đệm KV FP8, trọng số dense bốn bit, DFlash2 và copy drafts, bật vision và giới hạn xung nhịp GPU ở 2,200 MHz. Hãy xem đây là kết quả tham chiếu cho cấu hình đó, không phải bảo đảm cho mọi môi trường.

Kết luận

Triển khai này đóng gói một cấu hình TensorFold hai node phức tạp phía sau quy trình khởi động thực tế và API tương thích với OpenAI. Khi liên kết CX7, quyền truy cập SSH, runtime Docker, bộ nhớ lưu trữ và địa chỉ worker đã sẵn sàng, ./start.sh sẽ xử lý việc chuẩn bị, khởi chạy phân tán, xác thực và cung cấp dịch vụ. Từ đó, bạn có thể sử dụng các client API tiêu chuẩn, đồng thời tinh chỉnh mức đồng thời, ngữ cảnh, giới hạn suy luận, đa phương thức và cách sử dụng bộ nhớ cho workload của mình.