From 258b92c9c0339adacbec2ea6a78351a5c3537bd4 Mon Sep 17 00:00:00 2001 From: Daniel Knoodle Date: Mon, 20 Jul 2026 20:47:10 -0500 Subject: [PATCH] fix(offline): remove process-global offline guard from Qwen3 LLM loads (#924) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit force_offline_if_cached flips HF_HUB_OFFLINE (env + huggingface_hub constant + transformers._is_offline_mode) process-wide for the duration of a cached LLM load, silently switching every concurrent model download/load on other threads to offline mode. With default capture settings (whisper-turbo STT + Qwen3 refinement + auto_refine) a first run downloads several models concurrently, and a poisoned fetch surfaces as "Can't load feature extractor..." (whisper) or "Unrecognized model ... model_type" (Qwen3) rather than anything mentioning offline mode. These are the last two call sites of the guard — the same pattern was deliberately removed app-wide in #524/#530 after identical failures, and the 0.5.0 LLM backend reintroduced it. LLM loads now run with the process's default HF_HUB_OFFLINE state, matching every other backend (issue #462 precedent). Fixes #841 Claude-Session: https://claude.ai/code/session_011iwL9AyeAWgz2jpgcHxJpC Co-authored-by: Claude Fable 5 --- backend/backends/qwen_llm_backend.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/backend/backends/qwen_llm_backend.py b/backend/backends/qwen_llm_backend.py index e77a3540..5d29d892 100644 --- a/backend/backends/qwen_llm_backend.py +++ b/backend/backends/qwen_llm_backend.py @@ -19,7 +19,6 @@ from .base import ( manual_seed, model_load_progress, ) -from ..utils.hf_offline_patch import force_offline_if_cached logger = logging.getLogger(__name__) @@ -103,15 +102,19 @@ class PyTorchQwenLLMBackend: with model_load_progress(progress_model_name, is_cached): logger.info("Loading Qwen3 %s on %s...", model_size, self.device) - with force_offline_if_cached(is_cached, progress_model_name): - self.tokenizer = AutoTokenizer.from_pretrained(repo) - dtype = torch.float16 if self.device in ("cuda", "mps") else torch.float32 - self.model = AutoModelForCausalLM.from_pretrained( - repo, - dtype=dtype, - ) - self.model.to(self.device) - self.model.eval() + # Loads run with the process's default HF_HUB_OFFLINE state. + # Forcing offline for cached models flips process-global state + # and silently switches every concurrent download/load on other + # threads to offline mode (issue #841) — the same regression + # removed app-wide in #524/#530. + self.tokenizer = AutoTokenizer.from_pretrained(repo) + dtype = torch.float16 if self.device in ("cuda", "mps") else torch.float32 + self.model = AutoModelForCausalLM.from_pretrained( + repo, + dtype=dtype, + ) + self.model.to(self.device) + self.model.eval() self._current_model_size = model_size self.model_size = model_size @@ -223,8 +226,8 @@ class MLXQwenLLMBackend: with model_load_progress(progress_model_name, is_cached): logger.info("Loading Qwen3 %s via MLX...", model_size) - with force_offline_if_cached(is_cached, progress_model_name): - loaded = mlx_load(repo) + # See the PyTorch loader comment — no offline forcing (issue #841). + loaded = mlx_load(repo) # mlx_lm.load returns (model, tokenizer) by default and # (model, tokenizer, config) when return_config=True.