راهنمای عملی روتینگ LLM: کاهش ۸۵٪ هزینه API با LiteLLM و RouteLLM در ۲۰۲۶
روتینگ هوشمند LLM با هدایت هر درخواست به مدل مناسب، هزینه API را تا ۸۵٪ کاهش میدهد. در این راهنما با LiteLLM Router، RouteLLM و ساخت روتر سفارشی همراه با کد Python و بنچمارکهای واقعی آشنا میشوید.

یادتان هست در ۲۰۲۴ تقریباً همه ما فقط یک مدل را در محیط تولید اجرا میکردیم؟ امروز اوضاع کاملاً فرق کرده. میانگین استقرار سازمانی هوش مصنوعی در ۲۰۲۶ بین ۳ تا ۷ مدل مختلف را بهطور همزمان استفاده میکند و ۳۷٪ سازمانهای بزرگ پنج مدل یا بیشتر را در تولید فعال نگه میدارند.
راستش را بخواهید، مشکل اصلی ساده است. GPT-4o برای درخواستی به سادگی «این ایمیل را خلاصه کن» ۱۰ تا ۵۰ برابر گرانتر از مدلهای کوچکتر تمام میشود. حالا اگر روزانه ۱۰٬۰۰۰ مکالمه با میانگین ۲۰۰۰ توکن داشته باشید (که برای یک محصول جدی اصلاً عدد بزرگی نیست)، فقط هزینه توکنهای ورودی بین ۶۰ تا ۳۰۰ دلار در روز میشود. روتینگ هوشمند میتواند این هزینه را تا ۸۵٪ کاهش بدهد.
در این راهنما قرار است یک لایه روتینگ بسازیم که هر درخواست را به مناسبترین مدل بفرستد — بدون اینکه کیفیت خروجی بهطور محسوسی افت کند. خب، بیایید شروع کنیم.
روتینگ LLM چیست و چطور کار میکند؟
روتر LLM یک لایه میانی بین اپلیکیشن شما و ارائهدهندگان مدل است که هر درخواست را بر اساس پیچیدگی، هزینه، تأخیر و قوانین کسبوکار به مناسبترین مدل هدایت میکند. صادقانه بگویم، بهترین تشبیهی که برایش پیدا کردهام کنترلر ترافیک هوایی است: هر پرواز (درخواست) را به بهترین باند (مدل) میفرستد.
بدون روتینگ چه اتفاقی میافتد؟ همه درخواستها — از سادهترین سوال تا پیچیدهترین تحلیل — به یک مدل گران میروند. اما با روتینگ هوشمند ماجرا فرق میکند:
- درخواستهای ساده به مدل کوچک و ارزان میروند (مثلاً Claude Haiku یا GPT-4o mini)
- درخواستهای متوسط به مدل میانی هدایت میشوند
- درخواستهای پیچیده به مدل frontier قویتر میروند (مثل Claude Opus یا GPT-4o)
نکته جالب اینجاست که پژوهشها نشان دادهاند ۶۰ تا ۸۰٪ درخواستهای واقعی را میتوان با مدلهای کوچکتر و با کیفیت کاملاً قابل قبول پاسخ داد. در پروژهای که سال پیش روی آن کار میکردم، این عدد دقیقاً ۷۲٪ بود و من واقعاً جا خوردم.
پنج استراتژی اصلی روتینگ LLM
۱. روتینگ مبتنی بر قوانین (Rule-Based)
سادهترین روش ممکن: اگر پرامپت کوتاه است یا کلمات کلیدی خاصی ندارد، به مدل ارزان بفرست؛ در غیر این صورت، به مدل قویتر. به همین سادگی.
def rule_based_router(prompt: str) -> str:
word_count = len(prompt.split())
complex_keywords = ["analyze", "reason", "compare", "debug", "explain deeply"]
if word_count < 50 and not any(kw in prompt.lower() for kw in complex_keywords):
return "gpt-4o-mini"
elif word_count < 200:
return "claude-3-5-sonnet"
else:
return "claude-opus-4-7"
مزیت بزرگش این است که صفر تأخیر اضافه دارد و هزینهای هم نمیسازد. عیبش هم همانقدر روشن است: دقت پایینتر نسبت به رویکردهای ML.
۲. روتینگ آبشاری (Cascading)
منطق این یکی خیلی شبیه عقل سلیم خودمان است. اول مدل ارزان را امتحان کن؛ اگر کیفیت کافی نبود، آن وقت به مدل قویتر ارجاع بده:
async def cascade_router(prompt: str, quality_threshold: float = 0.8) -> dict:
# مرحله اول: مدل سریع و ارزان
response = await call_model("gpt-4o-mini", prompt)
confidence = evaluate_confidence(response)
if confidence >= quality_threshold:
return {"response": response, "model": "gpt-4o-mini", "escalated": False}
# مرحله دوم: مدل قویتر
response = await call_model("gpt-4o", prompt)
return {"response": response, "model": "gpt-4o", "escalated": True}
۳. روتینگ سمانتیک (Semantic)
از embeddingها برای شناسایی domain درخواست و هدایت آن به مدل متخصص استفاده میکند. سوالات حقوقی به یک مدل fine-tuned میروند، سوالات کدنویسی به یکی دیگر، و الی آخر.
۴. روتینگ با طبقهبند ML (ML Classifier)
آموزش یک مدل سبک برای پیشبینی پیچیدگی درخواست. به نظرم بهترین دقت با کمترین overhead همینجاست — البته به شرطی که داده آموزشی خوب جمع کرده باشید.
۵. روتینگ بر اساس بودجه
به ازای هر کاربر یا تیم یک سقف هزینه تعریف کنید، و وقتی نزدیک سقف شدید بهطور خودکار به مدلهای ارزانتر سوئیچ کنید. ساده ولی شگفتانگیز موثر.
RouteLLM: رویکرد آکادمیک با نتایج چشمگیر
RouteLLM یک فریمورک متنباز از محققان UC Berkeley، Anyscale و Canva است که در ICLR 2025 معرفی شد. و خب، نتایج بنچمارکها واقعاً قابلتوجه است:
- MT Bench: کاهش ۸۵٪ هزینه در حالی که ۹۵٪ کیفیت GPT-4 حفظ شد
- MMLU: کاهش ۴۵٪ هزینه با همان سطح کیفیت
- GSM8K: کاهش ۳۵٪ هزینه
روتر Matrix Factorization بهترین عملکرد را داشت. برای رسیدن به ۹۵٪ کیفیت GPT-4 فقط ۱۴٪ از درخواستها به مدل قوی نیاز داشتند. این عدد را دوباره بخوانید — فقط ۱۴٪!
نصب و شروع سریع
pip install "routellm[serve,eval]"
import os
from routellm.controller import Controller
os.environ["OPENAI_API_KEY"] = "sk-your-key"
# مقداردهی کنترلر با روتر Matrix Factorization
client = Controller(
routers=["mf"],
strong_model="gpt-4o", # مدل قوی برای درخواستهای پیچیده
weak_model="gpt-4o-mini", # مدل سریع و ارزان
)
response = client.chat.completions.create(
# threshold=0.11 یعنی فقط ۱۱٪ به مدل قوی میرود
model="router-mf-0.11",
messages=[
{"role": "user", "content": "معادله دیفرانسیل y'' + 2y' + y = 0 را حل کن"}
]
)
print(response.choices[0].message.content)
پارامتر threshold تعیین میکند چه درصدی از درخواستها به مدل قوی بروند. با router-mf-0.11 فقط ۱۱٪ به GPT-4o میروند. میتوانید با این عدد بازی کنید تا نقطه دلخواهتان روی منحنی هزینه/کیفیت پیدا شود.
استفاده با Ollama (مدلهای محلی)
from routellm.controller import Controller
# ترکیب مدل ابری قوی با مدل محلی ارزان
client = Controller(
routers=["mf"],
strong_model="ollama_chat/qwen2.5:32b",
weak_model="ollama_chat/llama3.2:3b",
)
response = client.chat.completions.create(
model="router-mf-0.11",
messages=[{"role": "user", "content": "پایتون را توضیح بده"}]
)
LiteLLM Router: راهحل تولیدی کامل
LiteLLM یک SDK متنباز است که رابط یکپارچهای برای ۱۰۰+ ارائهدهنده LLM ارائه میدهد. روتینگ، fallback، load balancing و ردیابی هزینه — همه در یک پکیج. اگر بپرسید من از کدام در تولید استفاده میکنم، جواب همین است.
نصب
pip install litellm
پیکربندی Router با Fallback
from litellm import Router
model_list = [
{
"model_name": "fast-model",
"litellm_params": {
"model": "gpt-4o-mini",
"api_key": "sk-openai-key",
},
"rpm": 1000,
},
{
"model_name": "smart-model",
"litellm_params": {
"model": "anthropic/claude-3-5-sonnet-20241022",
"api_key": "sk-ant-key",
},
},
{
"model_name": "power-model",
"litellm_params": {
"model": "anthropic/claude-opus-4-7",
"api_key": "sk-ant-key",
},
},
]
router = Router(
model_list=model_list,
fallbacks=[
{"fast-model": ["smart-model"]},
{"smart-model": ["power-model"]},
],
num_retries=3,
timeout=30,
)
response = router.completion(
model="fast-model",
messages=[{"role": "user", "content": "سلام!"}]
)
Fallbackهای تخصصی
router = Router(
model_list=model_list,
# وقتی context window پر شد به مدل با context بیشتر برو
context_window_fallbacks=[
{"gpt-4o": ["gpt-4o-128k"]},
],
# وقتی محتوا مشکل policy داشت
content_policy_fallbacks=[
{"gpt-4o": ["claude-opus-4-7"]},
],
fallbacks=[{"gpt-4o": ["claude-3-5-sonnet"]}],
)
روتینگ مبتنی بر بودجه
def get_model_by_budget(remaining_budget: float) -> str:
if remaining_budget > 10.0:
return "power-model"
elif remaining_budget > 1.0:
return "smart-model"
else:
return "fast-model"
async def process_with_budget(user_id: str, prompt: str):
budget = get_user_remaining_budget(user_id)
model = get_model_by_budget(budget)
response = await router.acompletion(
model=model,
messages=[{"role": "user", "content": prompt}]
)
cost = response.usage.total_tokens * get_model_cost_per_token(model)
deduct_budget(user_id, cost)
return response
ساخت روتر طبقهبند سفارشی با LLM
گاهی پیش میآید که میخواهید کنترل بیشتری روی منطق روتینگ داشته باشید. در این مواقع میتوانید از یک LLM کوچک بهعنوان طبقهبند پیچیدگی استفاده کنید. آره، این کار یک تماس API اضافه میسازد، ولی ارزشش را دارد:
import asyncio
from litellm import acompletion
ROUTING_SYSTEM_PROMPT = (
"تو یک سیستم طبقهبندی هستی. "
"پیچیدگی پرامپت کاربر را در یکی از سه دسته زیر قرار بده: "
"SIMPLE (سوالات ساده، formatting، استخراج داده), "
"MODERATE (خلاصهسازی، ترجمه، تحلیل ساده), "
"COMPLEX (استدلال پیچیده، کدنویسی عمیق). "
"فقط کلمه دسته را برگردان."
)
MODEL_MAP = {
"SIMPLE": "gpt-4o-mini",
"MODERATE": "claude-3-5-haiku-20241022",
"COMPLEX": "claude-opus-4-7",
}
async def smart_route(user_prompt: str) -> str:
# طبقهبندی با مدل سریع و ارزان
clf_response = await acompletion(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": ROUTING_SYSTEM_PROMPT},
{"role": "user", "content": user_prompt}
],
max_tokens=10,
temperature=0,
)
complexity = clf_response.choices[0].message.content.strip().upper()
selected_model = MODEL_MAP.get(complexity, "claude-3-5-haiku-20241022")
# ارسال درخواست اصلی به مدل انتخابشده
response = await acompletion(
model=selected_model,
messages=[{"role": "user", "content": user_prompt}],
)
print(f"[Router] {complexity} -> {selected_model}")
return response.choices[0].message.content
async def main():
queries = [
"سلام!",
"این مقاله را در سه خط خلاصه کن.",
"یک سیستم توزیعشده با fault tolerance طراحی کن.",
]
for q in queries:
result = await smart_route(q)
print(f"Q: {q}\nA: {result[:80]}\n")
asyncio.run(main())
معماری سهسطحی: Fast / Smart / Power
تجربه من میگوید بهترین معماری در تولید یک سیستم سهسطحی است که هر سطح برای نوع خاصی از درخواستها بهینه شده باشد:
- سطح Fast — مدلهای کوچک (Claude Haiku و GPT-4o mini): پاسخ فوری، هزینه پایین. مناسب برای استخراج داده، formatting و سوالات factual ساده. حدود ۶۰٪ از کل درخواستها.
- سطح Smart — مدلهای میانی (Claude 3.5 Sonnet و GPT-4o): تعادل بین هزینه و کیفیت. مناسب برای خلاصهسازی، تحلیل و نوشتن محتوا. حدود ۳۰٪ از کل درخواستها.
- سطح Power — مدلهای frontier (Claude Opus 4.7 و GPT-4o): بهترین کیفیت ممکن. مناسب برای استدلال پیچیده، تحلیل حقوقی یا پزشکی و debugging سخت. حدود ۱۰٪ از کل درخواستها.
نتایج بنچمارک و انتظارات واقعی
جدول زیر نتایج واقعی از رویکردهای مختلف روتینگ را نشان میدهد. این اعداد را قبل از انتخاب رویکرد حتماً ببینید:
| رویکرد روتینگ | کاهش هزینه | حفظ کیفیت | تأخیر اضافه |
|---|---|---|---|
| قوانین ساده (Rule-Based) | ۳۰–۵۰٪ | ۸۵–۹۰٪ | صفر |
| RouteLLM (Matrix Factorization) | ۷۵–۸۵٪ | ۹۵٪ | حدود ۵۰ میلیثانیه |
| LiteLLM با Fallback | ۴۰–۶۰٪ | ۹۸٪ | حدود ۲۰ میلیثانیه |
| LLM Classifier سفارشی | ۵۰–۷۰٪ | ۹۲–۹۵٪ | حدود ۴۳۰ میلیثانیه* |
| Cascading Router | ۳۵–۵۵٪ | ۹۷٪ | به علاوه تأخیر مدل ضعیف |
* اگر طبقهبندی بهصورت موازی با آمادهسازی context اجرا شود، تأخیر عملی به صفر نزدیک میشود.
ملاحظات کلیدی برای استقرار در تولید
تنظیم آستانه روتینگ
یک نکته که بارها سرم آمده: آستانه روتینگ را با دادههای واقعی تنظیم کنید، نه با حدس. اگر کاربران از کیفیت شکایت میکنند، آستانه را پایین بیاورید تا درخواستهای بیشتری به مدلهای قویتر بروند. تیمهای موفق معمولاً با آستانه ۸۰٪ شروع میکنند و بر اساس feedback تنظیم میکنند.
مانیتورینگ ضروری است (نه اختیاری)
from dataclasses import dataclass
import json
@dataclass
class RoutingMetrics:
timestamp: str
selected_model: str
complexity: str
latency_ms: float
tokens_used: int
cost_usd: float
def log_routing_decision(metrics: RoutingMetrics):
print(json.dumps({
"timestamp": metrics.timestamp,
"model": metrics.selected_model,
"complexity": metrics.complexity,
"latency_ms": metrics.latency_ms,
"cost_usd": metrics.cost_usd,
}))
معیارهایی که حتماً باید چشمتان رویشان باشد:
- نرخ hit هر سطح: چه درصدی از درخواستها به هر مدل میروند؟
- نرخ escalation: چند درصد از Cascading router به سطح بالاتر ارجاع میشوند؟
- هزینه در هر کاربر و endpoint: کدام بخشها گرانترند؟
- کیفیت خروجی: نرخ رضایت کاربر به تفکیک هر سطح مدل
اجتناب از بهینهسازی بیش از حد
بهینهسازی هزینه بازده نزولی دارد. این جمله را قاب بگیرید. تجربه نشان میدهد بهینهسازی تا حدود ۷۰ تا ۸۰٪ از حداکثر تئوری، بهترین نقطه است. آن ۲۰٪ آخر اغلب بیشتر از آنچه صرفهجویی میکند به تجربه کاربری آسیب میزند.
سوالات متداول
روتینگ LLM واقعاً چقدر هزینه را کاهش میدهد؟
بر اساس دادههای پژوهشی RouteLLM و گزارشهای تولیدی، اکثر تیمها ۳۰ تا ۵۰٪ کاهش هزینه میبینند. برای workloadهایی با درخواستهای تکراری یا ساده زیاد، این عدد میتواند تا ۸۵٪ هم برسد. انتظار واقعبینانه برای یک workload متوسط: ۴۰ تا ۶۰٪ صرفهجویی.
بهترین ابزار برای شروع روتینگ LLM کدام است؟
برای اکثر تیمها LiteLLM Router بهترین نقطه شروع است: متنباز، مستندات کامل و پشتیبانی از ۱۰۰+ ارائهدهنده. اگر دنبال روترهای pre-trained آکادمیک هستید، RouteLLM را امتحان کنید.
آیا روتینگ تأخیر (Latency) را افزایش میدهد؟
بستگی به رویکرد دارد. Rule-based routing تأخیر اضافه ندارد. LLM classifier حدود ۴۳۰ میلیثانیه اضافه میکند، اما اگر بهصورت موازی با آمادهسازی context اجرا شود، در عمل تأخیر محسوسی ندارد. Cascading routing تأخیر مدل ضعیف را اضافه میکند و در صورت escalation دو برابر میشود.
آیا RouteLLM فقط برای جفت GPT-4 و Mixtral کار میکند؟
خیر. پژوهشگران ثابت کردهاند که روترهای RouteLLM به جفتهای مدل دیگر هم تعمیم مییابند. میتوانید Claude Opus را بهعنوان strong model و Claude Haiku را بهعنوان weak model استفاده کنید — یا هر ترکیب دیگری از مدلهای ابری و محلی.
چطور بفهمم آستانه روتینگ را درست تنظیم کردهام؟
دو سیگنال اصلی را دنبال کنید. اول، نرخ شکایت کاربر از کیفیت پاسخ — اگر بالا رفت، آستانه را کاهش دهید تا بیشتر به مدلهای قوی بروند. دوم، هزینه ماهانه در مقابل بودجه — اگر بیش از بودجه است، آستانه را بالا ببرید. در نهایت، با A/B testing روی ۱۰٪ ترافیک، تنظیمات را آزمایش کنید.
Article changelog (1)
- — SEO meta refreshed (title and description updated)


