Skip to content

Commit 2ab88f1

Browse files
Blaizzyclaude
andcommitted
qwen3_vl: fetch image URLs and chat_template.jinja from Hub
README examples surfaced two gaps in the port: - Image inputs passed as https:// URLs (the embedding/reranker README examples) hit `FileNotFoundError` because `_to_numpy_image` treated every string as a local path. Detect URLs and fetch via requests. - `Qwen/Qwen3-VL-Reranker-2B` ships its chat template in chat_template.jinja, not in tokenizer_config.json. Add a `_load_qwen_vl_text` helper (local-then-Hub) and fall back to it when neither processor_config.json nor the tokenizer carries a template. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 26a4936 commit 2ab88f1

1 file changed

Lines changed: 31 additions & 1 deletion

File tree

mlx_embeddings/models/qwen3_vl/processor.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,17 @@ def _smart_resize_image(
103103

104104

105105
def _to_numpy_image(img) -> np.ndarray:
106+
from io import BytesIO
107+
106108
from PIL import Image
107109

108110
if isinstance(img, str):
109-
img = Image.open(img)
111+
if img.startswith(("http://", "https://")):
112+
import requests
113+
114+
img = Image.open(BytesIO(requests.get(img, timeout=30).content))
115+
else:
116+
img = Image.open(img)
110117
if hasattr(img, "convert"):
111118
img = img.convert("RGB")
112119
arr = np.array(img)
@@ -372,6 +379,21 @@ def _load_qwen_vl_json(pretrained_model_name_or_path, relative_name: str):
372379
return None
373380

374381

382+
def _load_qwen_vl_text(pretrained_model_name_or_path, relative_name: str):
383+
from pathlib import Path
384+
385+
local = Path(pretrained_model_name_or_path) / relative_name
386+
if local.exists():
387+
return local.read_text(encoding="utf-8")
388+
try:
389+
from huggingface_hub import hf_hub_download
390+
391+
fetched = Path(hf_hub_download(pretrained_model_name_or_path, relative_name))
392+
return fetched.read_text(encoding="utf-8")
393+
except Exception:
394+
return None
395+
396+
375397
def _qwen_vl_image_kwargs(pretrained_model_name_or_path, default_patch_size: int = 16):
376398
proc_cfg = (
377399
_load_qwen_vl_json(pretrained_model_name_or_path, "processor_config.json") or {}
@@ -639,6 +661,14 @@ def from_pretrained(cls, pretrained_model_name_or_path, **kwargs):
639661
chat_template = proc_cfg.get(
640662
"chat_template", getattr(tokenizer, "chat_template", None)
641663
)
664+
# Some checkpoints (e.g. Qwen3-VL-Reranker-2B) ship the template in
665+
# chat_template.jinja on the Hub instead of tokenizer_config.json.
666+
if chat_template is None:
667+
chat_template = _load_qwen_vl_text(
668+
pretrained_model_name_or_path, "chat_template.jinja"
669+
)
670+
if chat_template is not None:
671+
tokenizer.chat_template = chat_template
642672

643673
return cls(
644674
image_processor=image_processor,

0 commit comments

Comments
 (0)