Skip to main content

smart-llm-router

Provider-agnostic LLM router. Pick the cheapest capable model per prompt with rule-based scoring. Wraps LiteLLM for format conversion, streaming, tool calls, and 100+ provider integrations.

Why

Every LLM proxy today routes based on a model name you pick. This one picks the model for you — locally, in <1ms, with zero ML — by scoring the prompt across 14 dimensions (code presence, reasoning markers, multi-step patterns, multilingual keywords, etc.) and mapping to one of four tiers (SIMPLE / MEDIUM / COMPLEX / REASONING).

You bring an upstream (OpenRouter, Together, Fireworks, Groq, Anthropic direct, vLLM, Ollama — anything OpenAI-compatible). It does the rest.

Install

pip install smart-llm-router

Two console scripts ship with the package: smart-llm-router (full name) and slr (short alias).

Quick start with OpenRouter (default upstream)

# 1. Get an OpenRouter key at https://openrouter.ai/keys
export OPENROUTER_API_KEY=sk-or-v1-...
export LITELLM_MASTER_KEY=sk-anything    # gates the proxy itself

# 2. Start the proxy on :4000 (uses bundled OpenRouter config by default)
smart-llm-router start

In another terminal — any OpenAI-compatible client works:

from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:4000/v1", api_key="sk-anything")

# Smart routing — rule-based scorer picks the cheapest capable model
resp = client.chat.completions.create(
    model="smart/auto",
    messages=[{"role": "user", "content": "prove that sqrt(2) is irrational step by step"}],
)
# → routed to REASONING tier (e.g. deepseek/deepseek-r1)

Or curl:

curl http://127.0.0.1:4000/v1/chat/completions \
  -H "Authorization: Bearer sk-anything" \
  -H "Content-Type: application/json" \
  -d '{"model":"smart/auto","messages":[{"role":"user","content":"hi"}]}'

Inspect routing without dispatching

slr test "what is the capital of france"
# → SIMPLE / google/gemini-2.5-flash-lite / 100% savings vs claude-sonnet-4.6

slr test "Prove that sqrt(2) is irrational step by step"
# → REASONING / deepseek/deepseek-r1 / 90% savings

slr test "design a high-availability microservices architecture" --profile premium
# → COMPLEX / anthropic/claude-opus-4.7

slr models --profile auto    # show the tier→model table

Pointing at a different upstream

The bundled config targets OpenRouter, but anything OpenAI-compatible works (Together, Fireworks, Groq, DeepInfra, vLLM, Ollama, OpenAI direct). Copy the bundled YAML and edit api_base / api_key:

# Copy the bundled config to your working directory
python -c "from importlib.resources import files; import shutil; shutil.copy(files('smart_llm_router') / 'default_config.yaml', './smart-llm-router.yaml')"

# Edit smart-llm-router.yaml — swap api_base / api_key per model_list entry
# Then start with --config
smart-llm-router start --config smart-llm-router.yaml

Available routing profiles

model value Behavior
smart/auto Rule-based scoring → cheapest capable model
smart/eco Rule-based scoring → cheapest tier table (free + lite models)
smart/premium Rule-based scoring → quality-first tier table (Claude Sonnet/Opus, GPT-4o, o1)
smart/agentic Rule-based scoring → tool-use-friendly tier table (auto-engaged when tools[] present)
smart/free Forces only free/local models
<provider>/<model> Bypasses routing, dispatches directly

Pin a specific model (no routing)

Pass a concrete model ID and the router leaves it alone:

client.chat.completions.create(
    model="anthropic/claude-sonnet-4.6",   # always Sonnet
    messages=[...]
)

client.chat.completions.create(
    model="anthropic/claude-opus-4.7",     # always Opus
    messages=[...]
)

client.chat.completions.create(
    model="openai/gpt-4o",                 # always GPT-4o
    messages=[...]
)

Models pre-wired in the bundled config: anthropic/claude-haiku-4.5, anthropic/claude-sonnet-4.6, anthropic/claude-opus-4.6, anthropic/claude-opus-4.7, openai/gpt-4o, openai/gpt-4o-mini, openai/o1, openai/o3, openai/o3-mini, openai/o4-mini, google/gemini-2.5-flash-lite, google/gemini-2.5-flash, google/gemini-2.5-pro, google/gemini-2.0-flash-lite-001, deepseek/deepseek-chat, deepseek/deepseek-r1, meta-llama/llama-3.3-70b-instruct. Add more by editing the model_list in your config YAML.

Use with Claude Code

Claude Code respects ANTHROPIC_BASE_URL. Point it at the proxy:

export ANTHROPIC_BASE_URL=http://127.0.0.1:4000
export ANTHROPIC_AUTH_TOKEN=sk-anything   # the proxy's master key
claude

Then inside Claude Code: /model anthropic/claude-opus-4.7 to pin Opus, or /model smart/premium to let the router pick the best Claude per request.

How it works

  1. Client sends OpenAI/Anthropic/Gemini-format request to localhost:4000.
  2. LiteLLM Proxy parses; SmartRouterHook.async_pre_call_hook intercepts.
  3. If model is a smart/* profile, the rule-based router scores the prompt and picks a concrete upstream model ID.
  4. LiteLLM dispatches to the configured upstream — handling format conversion, streaming, tool calls, retries, etc.

Routing internals

The classifier (smart_llm_router/router/rules.py) scores each prompt across 14 weighted dimensions:

Dimension Weight Detects
reasoningMarkers 0.18 prove, theorem, step by step, 证明, теорема, ...
codePresence 0.15 ```, function, class, SELECT, 异步, ...
multiStepPatterns 0.12 "first ... then", "step 1", "1. "
technicalTerms 0.10 algorithm, architecture, kubernetes, ...
tokenCount 0.08 <50 tok ⇒ -1, >500 ⇒ +1
creativeMarkers 0.05 "write a story/poem"
questionComplexity 0.05 count of ?
constraintCount 0.04 "must", "exactly", "at most"
agenticTask 0.04 "edit file", "deploy", "install", "verify"
imperativeVerbs 0.03 "implement", "build", "fix"
outputFormat 0.03 json, yaml, table, schema
referenceComplexity 0.02 "above", "below", "the docs"
domainSpecificity 0.02 quantum, fpga, homomorphic, ...
simpleIndicators 0.02 "what is", "hello" → negative
negationComplexity 0.01 "not", "without", "except"

Keyword sets are multilingual — EN + ZH + JA + RU + DE + ES + PT + KO + AR — so the same scorer works across 9 languages without translation.

The score maps to a tier through three boundaries:

< 0.0   → SIMPLE        0.3-0.5 → COMPLEX
0.0-0.3 → MEDIUM        > 0.5   → REASONING

Plus three hard overrides: 2+ reasoning keywords ⇒ force REASONING; >100k tokens ⇒ force COMPLEX; system prompt mentioning json/schema ⇒ floor at MEDIUM.

Attribution

The 14-dimension rule-based router in smart_llm_router/router/ is ported from ClawRouter (MIT). Format conversion and streaming come from LiteLLM (MIT).

License

MIT

Metadata

Release files for smart-llm-router 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for smart-llm-router 0.1.2
File Size Uploaded
smart_llm_router-0.1.2.tar.gz 31.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for smart-llm-router 0.1.2
File Interpreter ABI Platform
smart_llm_router-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 61.6 kB

Release files / smart_llm_router-0.1.2.tar.gz

Download URL smart_llm_router-0.1.2.tar.gz
Size 31.8 kB
Tags Source
SHA-256 checksum
How to use checksums
cdfc88c2cdb1a22bf0caa167e0c7660ba7878d685f756ebfe4b694c78b8b2f0e
BLAKE2b-256 checksum
How to use checksums
851fc7c6a99ea8a3dbfb034af3ea823df3b7cabbcb559221e15c94c090a2b5f2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.14

Release files / smart_llm_router-0.1.2-py3-none-any.whl

Download URL smart_llm_router-0.1.2-py3-none-any.whl
Size 29.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3e5461c723a282e9a502dfa8962e21e636488b3b76059ea1bc0be21b9894dac2
BLAKE2b-256 checksum
How to use checksums
3fa3bd8e74956367bdf73bccb79fe273d7e425d2696826caeda68e97780805b6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.14

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page