fix: make prefixed Qwen detection positive-only to avoid shadowing hybrid IDs

Gate review found that the broadened token-prefix check caused
deepseek-r1-distill-qwen2.5-bakeneko-32b to enter the Qwen branch
(qwen2 token), return False, and prevent the DeepSeek detector from
running — a silent regression.

Fix: split into two phases:
1. Positive-only scan: any token matching qwen(\d+) with major >= 3
   immediately returns True. No False path — Qwen 2.x in hybrid IDs
   falls through to subsequent detectors.
2. Terminal guard (original behavior): standalone "qwen" token or
   normalized.startswith("qwen") still applies the 3+ gate with
   return False for 2.x, since those ARE pure Qwen models.

Add regression test for deepseek-r1-distill-qwen2.5-bakeneko-32b.
This commit is contained in:
happy5318 2026-07-25 16:27:50 +08:00 committed by nesquena-hermes
parent 90250adfb7
commit a57d576805
2 changed files with 24 additions and 6 deletions

View file

@ -3316,12 +3316,20 @@ def _candidate_supports_reasoning(candidate: str) -> bool:
if major >= 4 or (major == 3 and minor >= 7):
return True
return False
if any(token.startswith("qwen") for token in tokens):
# Restrict to Qwen 3+ (exclude Qwen 2/2.5)
# Token-prefix matching (position-independent) so prefixed ids like
# "al-qwen3-8-max-preview" (tokens: ["al","qwen3","8",...]) still match,
# even though "qwen" is not a standalone token. The bare
# normalized.startswith("qwen") case is subsumed by this check.
# Positive-only prefixed Qwen 3+ detection (e.g. "al-qwen3-8-max-preview"
# → tokens ["al","qwen3","8",...]). Scan for any token starting with
# "qwen" followed by version >= 3 and immediately allow. Do NOT return
# False here — Qwen 2.x embedded in hybrid IDs like
# "deepseek-r1-distill-qwen2.5-bakeneko-32b" must fall through to the
# DeepSeek detector below.
for token in tokens:
m = re.match(r"qwen(\d+)", token)
if m and int(m.group(1)) >= 3:
return True
# Terminal guard for standalone/bare Qwen IDs (original behavior):
# "qwen" as a standalone token or normalized starting with "qwen" means
# this IS a Qwen model — apply the 3+ gate and block 2.x.
if "qwen" in token_set or normalized.startswith("qwen"):
match = re.search(r"qwen.*?(\d+)(?:\D+(\d+))?", normalized)
if match:
major = int(match.group(1))

View file

@ -550,4 +550,14 @@ def test_qwen_prefixed_alias_reasoning_detection():
assert cfg._candidate_supports_reasoning(model) is False, (
f"{model} must NOT be reasoning-capable (Qwen 2.x excluded)"
)
# Hybrid IDs with embedded Qwen 2.x must NOT be shadowed by the Qwen
# branch — they must fall through to the DeepSeek detector.
for model in (
"deepseek-r1-distill-qwen2.5-bakeneko-32b",
"rinna/deepseek-r1-distill-qwen2.5-bakeneko-32b",
):
assert cfg._candidate_supports_reasoning(model) is True, (
f"{model} must remain reasoning-capable (DeepSeek-R1 hybrid, "
f"Qwen 2.x must not shadow the DeepSeek detector)"
)