| ---
|
| license: apache-2.0
|
| language:
|
| - en
|
| tags:
|
| - text-classification
|
| - distilbert
|
| - thinking-budget
|
| - reasoning-budget
|
| - agent-routing
|
| - llm-routing
|
| - qwen3
|
| - deepseek-r1
|
| - extended-thinking
|
| - ai-agents
|
| pipeline_tag: text-classification
|
| ---
|
|
|
| # ThinkingBudgetRouter
|
|
|
| A fast, lightweight 3-class classifier that decides **how many thinking tokens a query needs** — before you spend them.
|
|
|
| Built on DistilBERT (66M params), fine-tuned to classify any user message into one of three thinking budget tiers:
|
|
|
| | Label | Budget | Meaning |
|
| |---|---|---|
|
| | `no_thinking` | 0 tokens | Direct lookup or trivial — answer immediately |
|
| | `brief_thinking` | ~512 tokens | Structured reasoning needed, but not exhaustive |
|
| | `deep_thinking` | 8192+ tokens | Full chain-of-thought required |
|
|
|
| ## Why This Exists
|
|
|
| Modern reasoning models — **Qwen3**, **DeepSeek-R1**, **Claude 3.7 Sonnet** (extended thinking), **Gemini 2.0 Flash Thinking** — all support a configurable thinking budget. But most users either always use maximum thinking (slow, expensive) or never use it (misses hard problems).
|
|
|
| **ThinkingBudgetRouter** makes this decision in **~10ms on CPU**, before any tokens are spent reasoning.
|
|
|
| ## Quick Start
|
|
|
| ```python
|
| from transformers import pipeline
|
|
|
| router = pipeline("text-classification", model="tripathyShaswata/ThinkingBudgetRouter")
|
|
|
| # Single prediction
|
| result = router("What is the capital of France?")
|
| print(result)
|
| # [{'label': 'no_thinking', 'score': 0.97}]
|
|
|
| # Batch
|
| queries = [
|
| "What is 15 + 27?", # no_thinking
|
| "What does HTTP stand for?", # no_thinking
|
| "Write a Python function to merge two sorted arrays.", # brief_thinking
|
| "Explain how Dijkstra's algorithm works step by step.", # brief_thinking
|
| "Design a distributed rate limiter for 1 billion users.", # deep_thinking
|
| "Prove there are infinitely many prime numbers.", # deep_thinking
|
| "Debug this race condition in async code: ...", # deep_thinking
|
| ]
|
| results = router(queries)
|
| for q, r in zip(queries, results):
|
| print(f" {r['label']:>16} ({r['score']:.2f}) — {q}")
|
| ```
|
|
|
| ## Use With Qwen3 (Thinking Budget Control)
|
|
|
| ```python
|
| from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM
|
|
|
| budget_router = pipeline("text-classification", model="tripathyShaswata/ThinkingBudgetRouter")
|
|
|
| BUDGET_MAP = {
|
| "no_thinking": 0,
|
| "brief_thinking": 512,
|
| "deep_thinking": 8192,
|
| }
|
|
|
| def call_with_budget(user_message: str, model, tokenizer):
|
| label = budget_router(user_message)[0]["label"]
|
| budget = BUDGET_MAP[label]
|
|
|
| messages = [{"role": "user", "content": user_message}]
|
| text = tokenizer.apply_chat_template(
|
| messages,
|
| tokenize=False,
|
| add_generation_prompt=True,
|
| # Qwen3 thinking budget parameter
|
| thinking_budget=budget,
|
| )
|
| inputs = tokenizer([text], return_tensors="pt")
|
| output = model.generate(**inputs, max_new_tokens=2048)
|
| return tokenizer.decode(output[0], skip_special_tokens=True)
|
| ```
|
|
|
| ## Full 3-Stage Agent Pipeline
|
|
|
| Pair with [AgentIntentRouter](https://huggingface.co/tripathyShaswata/AgentIntentRouter) and [QueryComplexityRouter](https://huggingface.co/tripathyShaswata/QueryComplexityRouter) for a complete routing stack:
|
|
|
| ```python
|
| from transformers import pipeline
|
|
|
| intent_router = pipeline("text-classification", model="tripathyShaswata/AgentIntentRouter")
|
| complexity_router = pipeline("text-classification", model="tripathyShaswata/QueryComplexityRouter")
|
| budget_router = pipeline("text-classification", model="tripathyShaswata/ThinkingBudgetRouter")
|
|
|
| BUDGET_MAP = {"no_thinking": 0, "brief_thinking": 512, "deep_thinking": 8192}
|
|
|
| def route(user_message: str):
|
| intent = intent_router(user_message)[0]
|
| complexity = complexity_router(user_message)[0]
|
| budget = budget_router(user_message)[0]
|
|
|
| print(f"Intent: {intent['label']} ({intent['score']:.2f})")
|
| print(f"Complexity: {complexity['label']} ({complexity['score']:.2f})")
|
| print(f"Budget: {budget['label']} → {BUDGET_MAP[budget['label']]} tokens")
|
|
|
| if complexity["label"] == "no_llm":
|
| return handle_with_rules(user_message)
|
|
|
| thinking_tokens = BUDGET_MAP[budget["label"]]
|
|
|
| if complexity["label"] == "small_llm":
|
| return call_small_model(user_message, thinking_budget=thinking_tokens)
|
| else:
|
| return call_large_model(user_message, thinking_budget=thinking_tokens)
|
| ```
|
|
|
| ```
|
| User Message
|
| │
|
| ▼
|
| AgentIntentRouter ← WHAT: code / search / chat / math / ...
|
| │
|
| ▼
|
| QueryComplexityRouter ← WHICH MODEL: no_llm / small_llm / large_llm
|
| │
|
| ▼
|
| ThinkingBudgetRouter ← HOW MUCH THINKING: 0 / 512 / 8192 tokens
|
| │
|
| ▼
|
| Model call with exact budget
|
| ```
|
|
|
| ## Budget Labels
|
|
|
| ### `no_thinking` — 0 tokens
|
| Answer immediately, no chain-of-thought needed:
|
| - *"What is the capital of France?"*
|
| - *"What does HTTP stand for?"*
|
| - *"Is 17 divisible by 3?"*
|
| - *"Convert 100 km to miles."*
|
| - *"What HTTP status code means Not Found?"*
|
|
|
| ### `brief_thinking` — ~512 tokens
|
| Structured reasoning, but not exhaustive:
|
| - *"Write a Python function to binary search a sorted list."*
|
| - *"What is the difference between REST and GraphQL?"*
|
| - *"Fix this off-by-one error: for i in range(len(arr)): total += arr[i+1]"*
|
| - *"How would you detect a cycle in a linked list?"*
|
| - *"Prove that the sum of two even numbers is even."*
|
|
|
| ### `deep_thinking` — 8192+ tokens
|
| Full extended chain-of-thought required:
|
| - *"Design a distributed rate limiter for 1 billion users."*
|
| - *"Prove there are infinitely many prime numbers."*
|
| - *"Debug this race condition: two asyncio coroutines sharing a counter."*
|
| - *"Solve: given a matrix of costs, find the minimum-cost path from top-left to bottom-right."*
|
| - *"Compare PostgreSQL, MongoDB, and Cassandra across consistency, latency, and cost."*
|
|
|
| ## Model Details
|
|
|
| | Property | Value |
|
| |---|---|
|
| | Base model | `distilbert-base-uncased` |
|
| | Parameters | ~66M |
|
| | Inference (CPU) | ~10ms |
|
| | Inference (GPU) | ~2ms |
|
| | Input max length | 128 tokens |
|
| | Task | 3-class sequence classification |
|
|
|
| ## Compatible Reasoning Models
|
|
|
| | Model | Thinking control param |
|
| |---|---|
|
| | Qwen3 (all sizes) | `thinking_budget` in chat template |
|
| | DeepSeek-R1 | `/think` token budget |
|
| | Claude 3.7 Sonnet | `thinking.budget_tokens` in API |
|
| | Gemini 2.0 Flash Thinking | `thinkingConfig.thinkingBudget` |
|
|
|