メインコンテンツへ移動
AIチュートリアル

TensorFoldで単一のDGX Spark上でQwen3.8 Flash Nextを実行する

単一のNVIDIA DGX SparkにQwen3.8 Flash Nextをインストールし、起動、テスト、調整する方法を解説します。TensorFoldのデプロイスクリプト、OpenAI互換のチャットリクエスト、画像・動画入力、推論制御、メモリ設定、モニタリング、性能確認を取り上げます。

TensorFoldで単一のDGX Spark上でQwen3.8 Flash Nextを実行する

概要

このプロジェクトは、1台のNVIDIA DGX Spark上でQwen3.8 Flash NextをOpenAI互換API経由で提供します。TensorFold v0.3.6.3、MTPドラフトヘッド付きのMLX 4ビットチェックポイント、そして生成テキストを変更せずにプロンプト処理を高速化するための各種パッチを使用します。

デフォルト設定では、モデルの262,144トークンのコンテキストウィンドウ全体を各リクエストで利用しながら、5件のリクエストを同時に処理できます。また、モデル独自のビジョンタワーをCUDA上で読み込むため、チャットメッセージに画像や動画を含められます。

  • APIモデルID: Qwen3.8-Flash-Next
  • デフォルトエンドポイント: http://<spark-address>:8888/v1
  • 並列ストリーム数: 5
  • ストリームあたりのコンテキスト: 262,144トークン
  • KVプール合計: 1,310,720トークン
  • KVキャッシュ: デフォルトではint8
  • 入力モード: テキスト、画像、動画

主な機能

長文脈の同時推論

TensorFoldは各ストリームに完全なコンテキストキャッシュを割り当てます。デフォルト設定では、5つのストリームがそれぞれ262,144トークンのプロンプトと応答用ウィンドウを受け取ります。その結果、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の先読み、ネイティブなスレッド読み込み、スパースアテンションのブロック選択の改善、設定可能なプロンプトチャンク、コピー用ドラフト、リアルタイムのトークンカウンター、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トークン、または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回目以降の起動では完了済みのセットアップ処理が省略され、重みの読み込みに約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": "Pythonでフィボナッチ関数を書いてください。"
      }
    ],
    "max_tokens": 1000
  }'

デフォルトでは、モデルは回答前に思考し、その推論にも応答のトークン上限が使用されます。推論と最終回答の両方を収められるよう、max_tokensを十分に大きく設定してください。推論はreasoning_contentに返され、最終回答はcontentに表示されます。

OpenAI互換クライアントに接続する

クライアントを次の値で設定します。

  • ベースURL: http://<spark-address>:8888/v1
  • モデル: Qwen3.8-Flash-Next

APIはストリーミング、型付きツール呼び出し、推論コンテンツ、画像入力、動画入力に対応しています。配列などのツールパラメーターは、対応するJSON型を使用して返されます。

画像の送信

デフォルトでは、メディアをデータURLとして指定する必要があります。次のシェル例では、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
  }'

1回のリクエストには最大4枚の画像を含められます。各画像のサイズは最大10 MB、合計サイズは最大20 MBです。すべての画像で使用できるトークン数は最大4,096です。"detail": "low"を設定すると、画像のトークン数は256に制限されます。

動画の送信

動画にはvideo_urlコンテンツパートを使用します。

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

1回のリクエストには最大2本の動画を含められます。動画のサイズは最大64 MB、リクエスト全体の合計サイズは最大96 MBで、長さは最大1時間です。デフォルトでは、サーバーは1秒あたり2フレーム、動画全体に分散した最大256フレームをサンプリングし、1リクエストあたり最大16,384動画トークンを使用できます。

画像および動画のプロンプトは、プレフィックス再利用のために保持されません。通常のテキストリクエストは、ビジョン機能を有効にしても影響を受けません。

公開HTTPSメディアURLを許可する

デフォルトではデータURLを使用します。サーバーが公開HTTPSの画像URLおよび動画URLを取得できるようにするには、次のコマンドで再起動します。

VISION_URLS=1 ./start.sh restart

リモート取得は、デプロイ環境のセキュリティおよびネットワークポリシー上適切な場合にのみ有効にしてください。

テキスト専用モードで実行する

ビジョンタワーを無効にして、テキスト専用で提供します。

VISION=0 ./start.sh restart

テキスト専用モードでは、0.84 GiBのビジョンタワーを読み込まず、ビジョン有効時のデフォルトである2,048行の代わりに4,096行のプロンプトチャンクを使用します。

サーバーの管理

日常的な操作には、リポジトリのラッパースクリプトを使用します。

./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はビジー状態と現在の合計トークン数を報告します。

サーバーがすでに実行中の場合、単純な./start.shはサーバーに変更を加えません。systemdなどのプロセスマネージャーを使用する場合は、フォアグラウンドモードを使用します。

FOREGROUND=1 ./start.sh

コンテキスト、同時実行数、KV精度を設定する

デフォルト値はscripts/config.shに保存されています。環境変数で上書きするか、start.shの後にTensorFoldのフラグを渡します。

余裕を増やすために同時実行数を減らす

PARALLEL=4 ./start.sh restart

4つのint8ストリームにより、1,048,576トークンの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の10分の1に相当するホスト予約分を差し引いて予算を計算します。要求された構成が収まらない場合、重みを読み込む前に起動を拒否し、収まるはずのコンテキストウィンドウを示すエラーを出力します。

思考とサンプリングを制御する

思考モードのデフォルトのサンプリング値は、temperatureが1.0、top-pが0.95、top-kが20です。リクエストではtemperature、top_p、top_k、seedを上書きできます。temperatureに0を指定すると、貪欲デコーディングが有効になります。

1回のリクエストで思考を無効にする

{
  "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"も受け付けます。推論の強度を省略した場合、テンプレートはmediumをデフォルトとして使用します。トップレベルのOpenAI形式のreasoning_effortフィールドは無視されるため、chat_template_kwargs内に配置してください。

高度なパフォーマンスのヒント

n-gramテーブルをSSDに保持する

デフォルトのPLE_ON_SSD=1では、n-gramテーブル29.8 GiB分をユニファイドメモリに配置せず、SSD上に保持します。これによりKVキャッシュ用のメモリを確保できます。そのため、デフォルト構成では高速なローカルストレージが重要です。

プロンプトチャンクサイズを慎重に調整する

Visionを有効にすると、TENSORFOLD_PREFILL_ROWSのデフォルト値は、Visionタワー用の余裕を確保するため2048になります。テキストのみのモードではデフォルト値は4096です。READMEによると、約3,000トークンのプロンプトでは、4,096行にするとプロンプト処理が約2~5%向上する可能性がありますが、約0.94 GiB多くのメモリが必要です。

TENSORFOLD_PREFILL_ROWS=4096 ./start.sh restart

この値を増やすのは、十分なメモリの余裕がある場合に限ってください。

MTPとコピー・ドラフトを制御する

デフォルトのMTP設定では、1ラウンドあたり最大6件のドラフトを生成し、ドラフトの信頼度が60%未満になるとチェーンを停止します。コピー・ドラフト最適化はTENSORFOLD_MTP_COPY=1で有効になり、少なくとも2つの並列ストリームが必要です。これは、以前のプロンプトテキストを引用または編集する応答の改善を目的としています。

シリアルな参照デコードをリクエストする

個別のリクエストでドラフトを無効にし、TensorFoldの1トークンずつ処理する参照パスを使用するには、次を追加します。

{
  "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ドラフトを使用した1台のDGX Sparkで、次のデコード結果が報告されています。

  • 1リクエスト: 毎秒62.4トークン、初回トークンまで152ミリ秒。
  • 2リクエスト: 合計で毎秒90.5トークン。
  • 4リクエスト: 合計で毎秒106.7トークン。
  • 5リクエスト: 合計で毎秒119.3トークン、1リクエストあたり毎秒27.0トークン。

報告されているプリフィル速度は、8,229トークンのプロンプトで約毎秒2,503トークンから、131,110トークンのプロンプトで毎秒2,200トークンまでの範囲です。これらはプロジェクトでの測定値であり、保証値ではありません。設定、プロンプト構造、メディア入力、ストレージ、利用可能なメモリによって変動する場合があります。

まとめ

このリポジトリは、1台のDGX SparkでQwen3.8 Flash Nextを提供するために必要なモデル、TensorFoldランタイム、CUDA固有のセットアップ、パフォーマンスパッチ、運用スクリプトをまとめたものです。まずはデフォルトのint8・5ストリーム構成から始め、OpenAI互換APIを通じてサービスを検証したうえで、ワークロードとメモリの余裕に応じて同時実行数、コンテキストサイズ、Vision、KV精度を調整してください。