跳到主要内容
AI教程

使用 TensorFold 在单台 DGX Spark 上运行 Qwen3.8 Flash Next

了解如何在单台 NVIDIA DGX Spark 上安装、启动、测试和调优 Qwen3.8 Flash Next。本教程涵盖 TensorFold 部署脚本、兼容 OpenAI 的聊天请求、图像和视频输入、推理控制、内存配置、监控以及性能检查。

使用 TensorFold 在单台 DGX Spark 上运行 Qwen3.8 Flash Next

概览

本项目通过 OpenAI 兼容 API,使用一台 NVIDIA DGX Spark 提供 Qwen3.8 Flash Next 服务。项目使用 TensorFold v0.3.6.3、带有 MTP 草稿头的 MLX 4-bit 检查点,以及一组旨在加速提示词处理且不改变生成文本的补丁。

默认配置支持五个并发请求,每个请求都使用模型完整的 262,144 token 上下文窗口。项目还会在 CUDA 上加载模型自带的视觉塔,因此聊天消息可以包含图像和视频。

  • API 模型 ID: Qwen3.8-Flash-Next
  • 默认端点: http://<spark-address>:8888/v1
  • 并行流: 5
  • 每个流的上下文: 262,144 tokens
  • KV 池总量: 1,310,720 tokens
  • KV 缓存: 默认为 int8
  • 输入模式: 文本、图像和视频

主要功能

长上下文并发推理

TensorFold 为每个流分配独立的完整上下文缓存。在默认设置下,五个流各自获得一个 262,144 token 的提示词与回复窗口。生成的 int8 KV 池约占用 23.4 GiB。

OpenAI 兼容服务

服务器提供 /v1/models 和 /v1/chat/completions 等端点。OpenAI 兼容客户端只需修改基础 URL,并选择模型 ID Qwen3.8-Flash-Next 即可连接。

多模态提示词

用户消息可以包含 OpenAI 风格的 image_url 和 video_url 内容部分。支持的图像格式包括 JPEG、PNG 和 WebP。视频可以使用 MP4、WebM、MOV、MKV,或其他 FFmpeg 能够解码的格式。

经过补丁优化的提示词处理

随附的 TensorFold 补丁增加了 SSD 预读、原生多线程读取、改进的稀疏注意力块选择、可配置的提示词分块、复制草稿、实时 token 计数器以及 Flash Next 视觉支持。根据仓库中的测量结果,提示词处理速度约为对比的未打补丁版本的 1.7 倍,同时经过测试的文本回复保持字节级一致。

系统要求

克隆仓库前,请先准备主机:

  • NVIDIA DGX Spark,或其他配备 128 GB 统一内存的 GB10 系统。
  • 启动默认配置时约需要 115 GiB 可用内存。
  • 支持 NVIDIA 容器运行时的 Docker。
  • 属于 docker 组的用户账户。
  • 全新系统约需要 160 GB 可用磁盘空间。
  • 可选:用于更快、可断点续传下载的 Hugging Face hf CLI。
  • 可选:位于 ~/.cache/huggingface/token 中的 Hugging Face token,或 HF_TOKEN 环境变量。

默认部署适用于基本处于空闲状态的 DGX Spark。在统一内存系统上,耗尽内存可能会导致机器冻结,而不是产生常规的分配错误。

安装与首次启动

1. 克隆仓库

git clone https://github.com/MiaAI-Lab/Qwen3.8-Flash-Next-Single-DGX-Spark-TensorFold.git
cd Qwen3.8-Flash-Next-Single-DGX-Spark-TensorFold

2. 启动服务器

./start.sh

首次启动会完成完整设置。脚本会在可用时拉取预构建容器镜像,下载约 106 GiB 的检查点,验证该检查点,并为 GB10 编译 CUDA 内核。预构建镜像约为 11 GB,而检查点在 Hugging Face 缓存中约占 114 GB。

启动期间,脚本会显示设置进度、服务器日志、权重加载进度和内存估算,随后运行冒烟测试。成功启动后,最后会显示一条消息,说明 Qwen3.8-Flash-Next 已在端口 8888 上运行。

根据 README,后续启动会跳过已完成的设置步骤,加载权重大约需要 2.5 分钟。

3. 在不启动服务的情况下完成准备

如果想提前下载并构建所有内容,请运行:

scripts/prepare.sh

要从头重新构建容器镜像:

scripts/prepare.sh --rebuild

准备脚本会检查 Docker、NVIDIA 运行时和磁盘空间。随后,它会获取或构建 TensorFold 镜像,将检查点下载到 Hugging Face 缓存,并使用 tensorfold info 验证模型。

基本 API 用法

检查可用模型

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

将 <spark-address> 替换为 DGX Spark 的主机名或 IP 地址。如果从 Spark 本机调用,可以使用 127.0.0.1。

发送聊天补全请求

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

模型默认会在回答前进行思考,且推理过程会占用响应 token 配额。请将 max_tokens 设置得足够高,以同时容纳推理内容和最终答案。推理内容会返回在 reasoning_content 中,最终响应则出现在 content 中。

连接 OpenAI 兼容客户端

请使用以下值配置客户端:

  • 基础 URL: http://<spark-address>:8888/v1
  • 模型: Qwen3.8-Flash-Next

API 支持流式传输、类型化工具调用、推理内容、图像输入和视频输入。数组等工具参数会使用对应的 JSON 类型返回。

发送图像

默认情况下,媒体必须以数据 URL 的形式提供。以下 shell 示例会对 JPEG 进行编码,并要求模型描述它:

IMG=$(base64 -w0 photo.jpg)
curl -s http://<spark-address>:8888/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "Qwen3.8-Flash-Next",
    "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
  }'

单个请求最多可包含四张图像。每张图像最大为 10 MB,总大小上限为 20 MB。所有图像合计最多可使用 4,096 个 token。设置 "detail": "low" 可将单张图像限制为 256 个 token。

发送视频

视频使用 video_url 内容部分:

{
  "type": "video_url",
  "video_url": {
    "url": "data:video/mp4;base64,..."
  }
}

单个请求最多可包含两个视频。单个视频最大为 64 MB,请求总大小上限为 96 MB,视频时长最多为一小时。默认情况下,服务器每秒采样两帧,整个视频最多采样 256 帧,并允许每个请求使用最多 16,384 个视频 token。

图像和视频提示不会保留用于前缀复用。启用视觉功能不会影响普通文本请求。

允许使用公开的 HTTPS 媒体 URL

默认使用数据 URL。若要让服务器获取公开的 HTTPS 图像和视频 URL,请使用以下命令重启:

VISION_URLS=1 ./start.sh restart

只有在符合部署的安全要求和网络策略时,才应启用远程获取。

以纯文本模式运行

禁用视觉塔以仅提供文本服务:

VISION=0 ./start.sh restart

纯文本模式不会加载 0.84 GiB 的视觉塔,并使用 4,096 行的提示分块,而启用视觉功能时默认使用 2,048 行。

管理服务器

日常操作请使用仓库提供的封装脚本:

./start.sh restart
./stop.sh
docker logs -f qwen38-flash-next-tf
curl -s http://<spark-address>:8888/health
  • ./start.sh restart 会在替换正在运行的服务器前验证设置和参数。
  • ./stop.sh 会停止容器并释放 GPU 内存。活动请求会被中断。
  • docker logs -f 会持续跟踪 TensorFold 服务器日志。
  • /health 会报告繁忙状态和实时 token 总数。

如果服务器已经在运行,直接执行 ./start.sh 不会对其进行任何操作。对于 systemd 等进程管理器,请使用前台模式:

FOREGROUND=1 ./start.sh

配置上下文、并发和 KV 精度

默认值存储在 scripts/config.sh 中。可使用环境变量覆盖这些值,或在 start.sh 后传入 TensorFold 标志。

降低并发以获得更多余量

PARALLEL=4 ./start.sh restart

四个 int8 流可提供 1,048,576 个 token 的 KV 池,报告的启动估算值约为 97.7 GiB。

使用更短的上下文窗口

./start.sh restart --context 131072

额外的命令行参数会在默认参数之后传递给 tensorfold serve,因此具有更高优先级。运行 ./start.sh --help 可查看可用选项。

选择其他 KV 缓存类型

KV_DTYPE 接受 bf16、int8 或 int4:

PARALLEL=6 KV_DTYPE=int4 ./start.sh restart

README 说明,int4 会使输出略有变化,但未提供质量测量结果。需要项目默认的平衡时,请使用 int8。当完整精度 KV 存储比流数量更重要时,请使用 bf16。

了解启动保护机制

TensorFold 会根据可用内存计算预算,并扣除相当于 RAM 十分之一的主机预留内存。如果请求的配置无法容纳,系统会在加载权重前拒绝启动,并在错误信息中指出一个应当能够容纳的上下文窗口。

控制思考和采样

思考模式的默认采样值为温度 1.0、top-p 0.95 和 top-k 20。请求可以覆盖 temperature、top_p、top_k 和 seed。温度设为 0 可启用贪心解码。

为单个请求禁用思考

{
  "model": "Qwen3.8-Flash-Next",
  "messages": [
    {"role": "user", "content": "Answer in one sentence."}
  ],
  "chat_template_kwargs": {
    "enable_thinking": false
  },
  "max_tokens": 200
}

设置推理强度

{
  "chat_template_kwargs": {
    "reasoning_effort": "low"
  }
}

该模板还接受 "xhigh"。如果省略推理强度,模板会使用中等强度作为默认值。顶层的 OpenAI 风格 reasoning_effort 字段会被忽略,因此请将其放在 chat_template_kwargs 中。

高级性能提示

将 n-gram 表保存在 SSD 上

默认的 PLE_ON_SSD=1 会将 29.8 GiB 的 n-gram 表保存在 SSD 上,而不是放入统一内存。这会为 KV 缓存保留更多内存。因此,默认配置需要快速的本地存储。

谨慎调整提示分块大小

启用视觉功能时,TENSORFOLD_PREFILL_ROWS默认为2048,以便为视觉塔预留空间。纯文本模式默认为4096。README指出,对于约3,000个令牌的提示词,4,096行可将提示词处理速度提高约2–5%,但需要额外约0.94 GiB内存。

TENSORFOLD_PREFILL_ROWS=4096 ./start.sh restart

仅在有足够内存余量时增加此值。

控制 MTP 和复制草稿

默认的 MTP 配置每轮最多生成六个草稿,并在某个草稿的置信度低于60%时停止链式生成。复制草稿优化通过TENSORFOLD_MTP_COPY=1启用,并且至少需要两个并行流。它旨在改善引用或编辑较早提示词文本的回复。

请求串行参考解码

要绕过单个请求的草稿生成,并使用 TensorFold 一次一个令牌的参考路径,请添加:

{
  "draft": false
}

在将推测解码与串行参考进行比较时,这一选项很有用。

强制执行或跳过准备

PREPARE=1 ./start.sh restart
PREPARE=0 ./start.sh restart
PULL=0 scripts/prepare.sh
  • PREPARE=1会在重启前强制执行准备检查。
  • PREPARE=0会跳过准备步骤。
  • PULL=0会在本地构建镜像,而不是尝试使用预构建的镜像仓库镜像。

修改patches/中的文件后,请重新构建镜像,以便将这些补丁写入 TensorFold。

验证与基准测试

该仓库包含用于调用运行中服务器的工具。其 API URL 默认为http://127.0.0.1:8888。

tools/bench.py local-test
tools/needle.py
tools/toolcheck.py
tools/visioncheck.py
  • tools/bench.py会测量多种提示词大小,并执行简短的解码检查。
  • tools/needle.py会在约195,000个令牌的提示词中隐藏一段口令,并验证其检索结果。
  • tools/toolcheck.py会检查数组类型的工具参数是否以 JSON 数组形式返回。
  • tools/visioncheck.py会发送一张包含红色圆形和蓝色方形的生成图像,然后检查两者是否都能被识别。

要从另一台机器进行测试,请设置API_URL:

API_URL=http://<spark-address>:8888 tools/bench.py remote-test

预期性能

该仓库报告了以下解码结果,测试环境为一台启用 int8 KV 缓存、由 SSD 支持的 n-gram 表和 MTP 草稿生成的 DGX Spark:

  • 一个请求:每秒62.4个令牌,首个令牌耗时152毫秒。
  • 两个请求:聚合速度为每秒90.5个令牌。
  • 四个请求:聚合速度为每秒106.7个令牌。
  • 五个请求:聚合速度为每秒119.3个令牌,即每个请求每秒27.0个令牌。

报告的预填充速度范围为:对于包含8,229个令牌的提示词,约每秒2,503个令牌;对于包含131,110个令牌的提示词,每秒2,200个令牌。这些数据是项目测量结果,并非性能保证,实际表现可能因配置、提示词结构、媒体输入、存储和可用内存而异。

结论

该仓库整合了在一台 DGX Spark 上运行 Qwen3.8 Flash Next 所需的模型、TensorFold 运行时、CUDA 专用设置、性能补丁和运维脚本。建议从默认的 int8、五流配置开始,通过兼容 OpenAI 的 API 验证服务,然后根据工作负载和内存余量调整并发数、上下文大小、视觉功能和 KV 精度。