[Bugfix] Fix local speculators with dots in the name from classifying as custom_class (#48754)

Signed-off-by: mgoin <mgoin64@gmail.com>

Michael Goin committed Jul 15, 2026 at 20:58 UTC 3a5e88e629d22946041378316aa81eb77d6a8750
1 file changed +14 -7
vllm/config/speculative.py
+14 -7
@@ -626,6 +626,18 @@ class SpeculativeConfig:
626 SpeculativeConfig._apply_composed_hf_override, target_hf_overrides
627 )
628
629 + @staticmethod
630 + def _is_custom_proposer_path(model: str | None) -> bool:
631 + """True if ``model`` is a dotted import path (e.g. ``pkg.MyProposer``)."""
632 + if model is None:
633 + return False
634 + if model.startswith(("http://", "https://", "file://")):
635 + return False
636 + if "/" in model:
637 + return False
638 + parts = model.split(".")
639 + return len(parts) >= 2 and all(part.isidentifier() for part in parts)
640 +
641 def __post_init__(self):
642 # Note: "method" is a new parameter that helps to extend the
643 # configuration of non-model-based proposers, and the "model" parameter
@@ -636,14 +648,9 @@ class SpeculativeConfig:
648 # default.
649
650 # infer method from user args
639 - # Check if the model field contains a custom module path (e.g., 'pkg.Mod')
640 - if (
641 - self.model is not None
642 - and "." in self.model
643 - and not self.model.startswith(("http://", "https://", "file://"))
644 - and "/" not in self.model # not a HuggingFace repo (org/model)
651 + if self.method is None and SpeculativeConfig._is_custom_proposer_path(
652 + self.model
653 ):
646 - # Treat as a custom class path
654 self.method = "custom_class"
655 elif self.method is None:
656 if self.model in ("ngram", "[ngram]"):