Models & Providers
dsh-smart-router
rouyiemei/dsh-smart-router · ★ 0
Automatic model routing for DeepSeek Harness: three difficulty tiers (hard/normal/easy) plus vision routing, picking models you already configured under Settings ? Models. ???? + ?????????
Manifest details
安装
dsh plugin --profile web add github:rouyiemei/dsh-smart-routerGitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试
For install and environment setup, plus plugin development tutorials, see DSH community docs ↗
README
Table of contents
English · 简体中文
Why this exists
In August 2026, DeepSeek raised prices across the V4 family and introduced peak/off-peak pricing. Flash output tokens jumped from ¥2 to ¥4.5 (¥9 at peak); Pro went up 3–5×. My monthly bill went from ¥120 to ¥700+.
I tried everything. OpenCode Go's "affordable subscription" turned out to be the same official price with a monthly cap. MiMo-V2.5 was cheap but too weak for real coding. GLM-5.1 and Kimi K3 cost more than Flash. Subscription plans didn't help either — Xiaomi's Token Plan Pro covered my usage but couldn't match the quality; Zhipu's Coding Plan was too tight; Google AI Pro and ChatGPT subscriptions don't offer API access.
No single option could deliver both "no quality loss" and "affordable price."
887M tokens/month, 80% cached input — that was my usage profile with DS Flash. The price hike hit output tokens hardest, and most of my output was thinking tokens I couldn't just turn off.
Then it clicked: instead of finding one cheaper model to replace everything, let the same system call different models for different tasks. Simple file operations, formatting, and Q&A go to the cheap model; real reasoning and complex coding stay on Flash. Distribute on demand, not one-size-fits-all.
That's how dsh-smart-router was born. It's not an architectural breakthrough — just a practical tool born from sticker shock, routing each request to the best-fit model so you can find your own balance between capability and cost.
If AI API bills have ever stung you, hopefully this small tool saves you some money.
What it solves
- Performance tiering: hard tasks (architecture, refactoring, tricky debugging) go to a strong model; easy tasks (small talk, wrap-ups, tiny edits) go to a cheap fast model; everything else hits the middle tier — like cc-switch's per-tier model slots for Claude Code, but for DSH.
- Vision built in: many users add a separate vision plugin; this router integrates vision routing into itself. Requests with images → vision tier automatically; plain text → difficulty tiers. Out of the box it ships a free anonymous vision model (OVHcloud Qwen2.5-VL-72B-Instruct, no API key), replaceable with any vision-capable model you configured.
- Cache friendly: pick all three tiers from the same vendor family (e.g. pro and flash editions of one series) for higher prefix-cache hit rates and lower cost (hint shown in the settings card).
Install
dsh plugin --profile web add dsh-smart-router
Restart dsh web, then:
- Open Settings → Smart Router: pick a model for each of the four rows (hard / normal / easy / vision). Dropdowns list the models you already configured; the vision row only lists models that declare image input.
- Back in chat, open the model picker and choose Smart Router (auto route).
- Chat normally — every request is classified and routed automatically.
Zero configuration also works: requests fall back to your default model (fail-open, never silently broken).
How it works
You pick the virtual model "smart" (declares text+image, passes DSH image admission)
│
▼
SmartRouterAdapter.stream(request)
│
├─ has image? ──────→ vision tier (free anonymous OVH by default) ──┐
│ │
└─ else: classify ──→ hard → hard tier │
(heuristic by → normal → normal tier │
default / LLM) → easy → easy tier │
│ │
▼ ▼
ctx.llm.prepareCall({provider, model}).stream(request) ← passthrough stream
│
└─ missing tier → hard→normal→easy→default ladder; error only when all fail
- Routing happens at the LLM adapter layer (architecture from llm-adaptive / dsh-vision-mix): a virtual provider is registered;
stream()decides per request and delegates viaprepareCall().stream()— no host patches, no conflicts with other vision plugins. - Classifier modes: heuristic (default; zero cost — keywords + code volume + file references) or LLM (more accurate; one small call on the easy-tier model, 120s cache).
- Image admission: the virtual model declares
inputModalities: ['text', 'image'], so DSH's preflight (MODEL_DOES_NOT_SUPPORT_IMAGES) lets images through — no host patching (compare dsh-easyvision's patch approach).
Settings (Settings → Smart Router)
| Setting | Meaning |
|---|---|
| Enable routing | Off = requests go to the session default model unchanged |
| Classifier | heuristic (default) / llm |
| Hard / Normal / Easy | { provider, model, effort } per tier; empty = unconfigured (ladder fallback) |
| Vision | Default ovh-vision / Qwen2.5-VL-72B-Instruct (free, anonymous); replace with any configured vision model |
| Default fallback | Empty = the session default model |
| LLM classifier | Optional; defaults to the easy-tier model |
Reasoning effort two-tier hierarchy: The reasoning effort in the chat input model selector (Off / High) is the master switch:
- Off: reasoning disabled for all tiers (no extended thinking)
- High: each tier uses the effort configured above (e.g. hardEffort=high, normalEffort=max, etc.)
A hint explaining this is shown in the tier models section of the settings page.
Manual config (~/.dsh/profiles/web/settings.yaml):
smart-router:
enabled: true
classifier: heuristic # heuristic | llm
hardProvider: deepseek-official
hardModel: deepseek-v4-pro
normalProvider: deepseek-official
normalModel: deepseek-chat
easyProvider: deepseek-official
easyModel: deepseek-flash
visionProvider: zhipu-vision # free quota; add GLM_API_KEY under Settings → Models
visionModel: glm-4v-flash
visionFallbacks: []
fallbackProvider: ''
fallbackModel: ''
On install the plugin idempotently seeds two free vision routes into llm-pi-ai (missing keys only, your config is never touched):
| Route | Model | Cost |
|---|---|---|
ovh-vision |
OVHcloud Qwen2.5-VL-72B-Instruct (anonymous endpoint) | Free, no key (~2 req/min/IP) |
zhipu-vision |
Zhipu GLM-4V-Flash | Free quota; set GLM_API_KEY in Settings → Models |
The vision default works out of the box; for more stable/stronger vision, point the vision row at any vision model you configured.
Coexistence with other vision plugins
The router only participates when the session model is smart; it never takes over existing provider routes and never touches the host, so modlens, dsh-vision-router and friends can stay installed side by side.
Development
npm test # node --test tests/ (80 cases: classifier / chain / vision sidecar / config API / seed idempotency / schema)
Local install for debugging:
dsh plugin --profile web add C:\path\to\dsh-smart-router
dsh --profile web --dump-config | grep smart-router
Acknowledgements (References)
This plugin directly references the following open-source projects and DSH internals:
| Project | What was referenced |
|---|---|
| farion1231/cc-switch | The per-tier model slot product shape (Claude Code's main/fast/thinking/vision tiers) |
| dylan121322/llm-adaptive | Adapter-level routing: registerAdapter + prepareCall().stream() passthrough; LLM classifier rubric |
| BruceLanLan/dsh-tier-router | Tier config schema shape and fallback/escalation trade-offs |
| haiziyao/dsh-vision-mix | Declaring inputModalities: ['text','image'] at the adapter to pass DSH image admission (zero host patches) |
| liustack/modlens | Structured vision evidence: summary/OCR/layout/semantics/visual/uncertainty template and the "vision parsing engine" prompt (source-level reference) |
| gloryxpnv/dsh-tool-vision | Same structured JSON evidence template; the vision-bridge image→text replacement and fail-open pattern |
| ysr666/dsh-vision-router | Free vision chain: anonymous OVHcloud endpoint (no key); image-admission analysis; per-image caching |
| s3yf1337/dsh-easyvision | Reading model vision capability via resolveModelInfo().inputModalities |
| akqwpeter-prog/dsh-media-skills | Idempotent free-vision route seeding into llm-pi-ai (zhipu-vision) |
| DeepSeek Harness internals | dsh-llm (LlmAdapter / llm service / prepareCall contract), dsh-settings (installSettingsSection), dsh-agent-loop (agent/request waterfall), dsh-client-modules (client bundle contract) |
License
MIT