From 3e030966e7d563a4fea5d71849a2482458a56a5e Mon Sep 17 00:00:00 2001 From: James Palmer Date: Sat, 22 Aug 2026 07:10:04 -0600 Subject: [PATCH] fix(deepseek_v4): resolve HF repo ids to local cache when serving ft serve --model deepseek-ai/DeepSeek-V4-Flash-0731 failed with a "config.json missing" / "safetensors index missing" error even when the checkpoint was already present in the HF cache, because DSV4's loader paths did raw os.path.join(model_path, ...) checks against model_path -- fine for a local directory, but a no-op when model_path is a bare repo id: hf_config._name_or_path (and the --model string itself) stays the literal repo id string rather than the resolved local snapshot directory, so the join produced a path relative to cwd instead of the actual HF cache location. - args.py: _config_path now resolves inference/config.json and model_args.json through huggingface_hub.hf_hub_download (offline cache-aware) when model_path isn't a local directory, mirroring the pattern utils/hf.py already uses for config.json. - weight.py: iter_weights and load_dsfp4_expert_sources now resolve model_path via download_hf_weight before reading model.safetensors.index.json / opening shards, matching every other model's weight loader (load_dsfp4_expert_sources_parallel already did this indirectly via iter_expert_tensors_parallel). Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_018DTUNGq4V1tujUvS8dqP4n --- python/freetoken/models/deepseek_v4/args.py | 30 ++++++++++++++----- python/freetoken/models/deepseek_v4/weight.py | 4 ++- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/python/freetoken/models/deepseek_v4/args.py b/python/freetoken/models/deepseek_v4/args.py index b75d2800d..611b89a9f 100644 --- a/python/freetoken/models/deepseek_v4/args.py +++ b/python/freetoken/models/deepseek_v4/args.py @@ -80,14 +80,28 @@ def nope_head_dim(self) -> int: def _config_path(model_path: str) -> str: - """Locate the authors' ModelArgs JSON inside the checkpoint directory.""" - candidates = [ - os.path.join(model_path, "inference", "config.json"), - os.path.join(model_path, "model_args.json"), - ] - for path in candidates: - if os.path.exists(path): - return path + """Locate the authors' ModelArgs JSON inside the checkpoint directory. + + ``model_path`` is either a local directory or a Hugging Face repo id (e.g. when + serving straight from ``--model deepseek-ai/DeepSeek-V4-Flash-0731``, unresolved + to a local snapshot dir). For the repo-id case, resolve each candidate filename + through the HF cache/hub the same way ``utils.hf`` does for ``config.json``. + """ + filenames = [os.path.join("inference", "config.json"), "model_args.json"] + if os.path.isdir(model_path): + for filename in filenames: + path = os.path.join(model_path, filename) + if os.path.exists(path): + return path + else: + from huggingface_hub import hf_hub_download + from huggingface_hub.utils import EntryNotFoundError + + for filename in filenames: + try: + return hf_hub_download(repo_id=model_path, filename=filename) + except EntryNotFoundError: + continue raise FileNotFoundError( f"No DeepSeek-V4 ModelArgs JSON found under {model_path} " f"(looked for inference/config.json)" diff --git a/python/freetoken/models/deepseek_v4/weight.py b/python/freetoken/models/deepseek_v4/weight.py index f5a3fd174..e98b04663 100644 --- a/python/freetoken/models/deepseek_v4/weight.py +++ b/python/freetoken/models/deepseek_v4/weight.py @@ -20,6 +20,7 @@ from tqdm import tqdm from freetoken.models.loader import drop_page_cache +from freetoken.utils import download_hf_weight from .args import DeepseekV4Args, load_args @@ -93,6 +94,7 @@ def iter_weights( if not include_non_moe: return + model_path = download_hf_weight(model_path) args = load_args(model_path, max_batch_size=1) reader = _ShardReader(model_path, _weight_map(model_path), device) @@ -189,7 +191,7 @@ def load_dsfp4_expert_sources( """ from freetoken.moe.host_banks import LayerCompletionTracker, PinPipeline, alloc_layer_banks - folder = model_path + folder = download_hf_weight(model_path) weight_map = _weight_map(folder) L, E = args.n_layers, args.n_routed_experts H, I = args.dim, args.moe_inter_dim