Skip to content

fix(model-normalize): pass DeepSeek V-series IDs through instead of folding to deepseek-chat#15119

Closed
0xbyt4 wants to merge 1 commit into
NousResearch:mainfrom
0xbyt4:fix/deepseek-v4-normalize
Closed

fix(model-normalize): pass DeepSeek V-series IDs through instead of folding to deepseek-chat#15119
0xbyt4 wants to merge 1 commit into
NousResearch:mainfrom
0xbyt4:fix/deepseek-v4-normalize

Conversation

@0xbyt4

@0xbyt4 0xbyt4 commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Summary

_normalize_for_deepseek was folding every non-reasoner DeepSeek input into deepseek-chat on the assumption that DeepSeek's API accepts only two model IDs. That's no longer true — deepseek-v4-pro and deepseek-v4-flash are first-class IDs accepted by the direct API, and on aggregators deepseek-chat routes explicitly to V3. So a user picking V4 Pro through the model picker was silently downgraded to V3.

Reported by @UFOnik and @Don-Piedro on Discord (/model > Deepseek > deepseek-v4-pro surfaced Normalized 'deepseek-v4-pro' to 'deepseek-chat', and the picker listing then rejected the post-normalize deepseek-chat as "not in provider listing" because live /v1/models returns v4 names, not canonical ones — that's the contradictory message users saw).

Empirical verification (2026-04-24)

End-to-end simulation against an OpenAI-compat endpoint (Nous portal's surface, /v1/chat/completions) with identical user input deepseek-v4-flash and provider=deepseek:

BEFORE fix (main) AFTER fix
User picked deepseek-v4-flash deepseek-v4-flash
Normalize emits deepseek-chat deepseek-v4-flash
API request deepseek/deepseek-chat deepseek/deepseek-v4-flash
response.model deepseek/deepseek-chat-v3 deepseek/deepseek-v4-flash-20260423
response.provider Novita (aggregator) DeepSeek (direct)

V-series names are real model IDs, not aliases of deepseek-chat. Aggregator routing even flips — deepseek-chat lands on a cheaper Novita/DeepInfra backend, deepseek-v4-flash goes direct to DeepSeek.

Fix

  • Add deepseek-v4-pro / deepseek-v4-flash to _DEEPSEEK_CANONICAL_MODELS (exact-match pass-through).
  • Add _DEEPSEEK_V_SERIES_RE (^deepseek-v\d+(...)?$) so future V-series IDs (deepseek-v5-*, dated variants like deepseek-v4-flash-20260423) pass through without another code change.
  • Update module docstring + function docstring.

Tests

  • New TestDeepseekVSeriesPassThrough — 8 parametrized + 2 end-to-end cases (bare, vendor-prefixed, case-variant, dated, future V-series).
  • New TestDeepseekCanonicalAndReasonerMapping — regressions for canonical pass-through, reasoner-keyword folding, chat fallback.
  • 77/77 pass in tests/hermes_cli/test_model_normalize.py.

…olding to deepseek-chat

`_normalize_for_deepseek` was mapping every non-reasoner input into
`deepseek-chat` on the assumption that DeepSeek's API accepts only two
model IDs. That assumption no longer holds — `deepseek-v4-pro` and
`deepseek-v4-flash` are first-class IDs accepted by the direct API,
and on aggregators `deepseek-chat` routes explicitly to V3 (DeepInfra
backend returns `deepseek-chat-v3`). So a user picking V4 Pro through
the model picker was being silently downgraded to V3.

Verified 2026-04-24 against Nous portal's OpenAI-compat surface:
  - `deepseek/deepseek-v4-flash` → provider: DeepSeek,
    model: deepseek-v4-flash-20260423
  - `deepseek/deepseek-chat`     → provider: DeepInfra,
    model: deepseek/deepseek-chat-v3

Fix:
- Add `deepseek-v4-pro` and `deepseek-v4-flash` to
  `_DEEPSEEK_CANONICAL_MODELS` so exact matches pass through.
- Add `_DEEPSEEK_V_SERIES_RE` (`^deepseek-v\d+(...)?$`) so future
  V-series IDs (`deepseek-v5-*`, dated variants) keep passing through
  without another code change.
- Update docstring + module header to reflect the new rule.

Tests:
- New `TestDeepseekVSeriesPassThrough` — 8 parametrized cases covering
  bare, vendor-prefixed, case-variant, dated, and future V-series IDs
  plus end-to-end `normalize_model_for_provider(..., "deepseek")`.
- New `TestDeepseekCanonicalAndReasonerMapping` — regression coverage
  for canonical pass-through, reasoner-keyword folding, and
  fall-back-to-chat behaviour.
- 77/77 pass.

Reported on Discord (Ufonik, Don Piedro): `/model > Deepseek >
deepseek-v4-pro` surfaced
`Normalized 'deepseek-v4-pro' to 'deepseek-chat'`. Picker listing
showed the v4 names, so validation also rejected the post-normalize
`deepseek-chat` as "not in provider listing" — the contradiction
users saw. Normalizer now respects the picker's choice.
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard provider/deepseek DeepSeek API labels Apr 24, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related to #14946 and #14947 — all three fix DeepSeek V4 model ID normalization. This PR adds a future-proof regex for V-series IDs.

@teknium1

Copy link
Copy Markdown
Contributor

Merged via #15123 — your commit (f03f836) was cherry-picked onto current main with authorship preserved in git log. Thanks for the fast turnaround on V4 release day!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists provider/deepseek DeepSeek API type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants