Proposal: load an FTW with fp16 NVFP4 global scales (upcast with a warning) instead of refusing it after #739
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 48/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
調査の方向性
Start with python/freetoken/checkpoint/ftw.py and trace iter_ftw_weights, load_ftw_banks, and load_ftw_banks_to_device, including the bank allocation and read paths. Read the existing NVFP4 dtype checks and the scripts/ftw_hotfix.py and docs/models.md guidance. Add coverage for loading fp16 global scales as fp32, including the warning and inference-mode behavior; done means the load succeeds with the stated values and the docs describe when to reconvert.
索引モデルが issue の本文から書いたものです。
説明
Proposal
Since #739, FTWReader refuses every NVFP4 FTW that stores its global scales as fp16, which is every NVFP4 FTW converted before #739. The only fix it offers is a full reconversion from the source checkpoint. Not every user still has that checkpoint. For Qwen3.8-Flash-Next-NVFP4 a reconversion means downloading about 120 GB again and converting it, and until then the server will not start at all.
The fp16 rounding cannot be undone (as #739 says), but it does not have to block loading. Upcasting the stored fp16 values to fp32 at load gives exactly the numerics every pre-#739 build served from the same file. Proposal:
FTWReaderlogs a one-time warning ("this FTW stores NVFP4 global scales as fp16 (converted before #739); serving them upcast to fp32, which keeps the old precision; reconvert withft checkpointto get the fp32 globals"), not aValueError.- The dense, host-bank and device-bank read paths read an fp16 global entry into a staging buffer and copy it into the fp32 destination.
scripts/ftw_hotfix.pyanddocs/models.mddescribe the warning and the reason to reconvert, not a hard failure.
Users get the precision fix by reconverting when they can, and their existing checkpoints keep working until they do.
Minimal reproduction of the refusal (CPU only, PYTHONPATH=python):
import json, os, tempfile
from freetoken.checkpoint.ftw import FTWReader, INDEX_NAME, FORMAT_TAG
d = tempfile.mkdtemp()
with open(os.path.join(d, INDEX_NAME), "w") as f: # index of an NVFP4 FTW written before #739
json.dump({"format": FORMAT_TAG, "shards": [], "tensors": [
{"name": "gate_up_global#L00000", "dtype": "float16", "shape": [256, 1024]}]}, f)
try:
FTWReader(d)
except ValueError as e:
print("ValueError:", e)
ValueError: '/tmp/user/1000/tmps9e9_aju' stores NVFP4 global scales as fp16 (e.g. 'gate_up_global#L00000') but FreeToken reads them as fp32; reconvert it from the source checkpoint with `ft checkpoint`
Cause (current main, cc56b6bd)
python/freetoken/checkpoint/ftw.py:229-234:FTWReader.__init__raises on any fp16 entry that_is_nvfp4_global(:105-107) matches.- The readers copy raw bytes into banks sized from the index dtype:
iter_ftw_weights(:376), andload_ftw_banks_read_row/_read_layer(:614-625), which usereader.read_into(bank.memoryview(), ...).load_ftw_banks_to_device(:707) does the same. So an upcast needs an fp32 destination plus an fp16 staging read for these entries. It cannot just change the dtype the reader reports.
Proposed fix
- Replace the
ValueErrorwith a one-timelogger.warning. Record which global entries are fp16. - In the three read paths, allocate fp32 for those entries, read the fp16 bytes into a transient buffer, and
copy_(upcast) into the bank. The scheduler builds the engine, and with it the host banks, undertorch.inference_mode()(server/launch.py:79-81), and theThreadPoolExecutorreader threads inload_ftw_banksdo not inherit that mode. The in-place copy in those threads must therefore run insidewith torch.inference_mode():, or it raises on inference tensors. - A test: write a small FTW with fp16 globals, load it under
torch.inference_mode()the way the engine does, and check that the warning appears once and that the globals come back as fp32, equal to the fp16 values.
Environment
Seen serving nvidia/Qwen3.8-Flash-Next-NVFP4 from an FTW converted before #739, on an RTX 5080 16 GB (sm_120, driver 615.78.08), torch 2.14.1+cu130; reproduction CPU-only on main cc56b6bd.
- 主要言語
- Python
- スター
- 14.2k
- フォーク
- 1.4k
- 平均マージ
- 21時間 39分
- マージ済み PR(30日)
- 100
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
FlashML-org/FreeToken のほかの issue
-
Desktop feature
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
FlashML-org/FreeToken#800 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
FlashML-org/FreeToken#767 ·
メンテナーはふだん 1 日以内に返信
-
test_gemv_path_matches_the_transcription fails on sm_120 (bf16 rounding tie exceeds the tolerance)対応中かも @void-mckenzie が 17 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 77/100
FlashML-org/FreeToken#649 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
FlashML-org/FreeToken#648 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
FlashML-org/FreeToken#646 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
FlashML-org/FreeToken の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
pytest-dev/pytest-html#1085 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 90/100
pollen-robotics/reachy_mini#1527 ·
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 66/100
メンテナーはふだん 2 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 1 日以内に返信
-
A seed and its negative give the same run, so realizations of a negative seed repeat each otherオープン
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
メンテナーはふだん 1 日以内に返信