feat(litellm): add provider namespaces with legacy compatibility

This commit is contained in:
Codex
2026-10-26 17:38:55 -07:00
parent 6a88160e0f
commit daa907d029
7 changed files with 214 additions and 10 deletions
+64 -2
View File
@@ -1,6 +1,7 @@
"""Render only credential-ready routes; credentials remain environment references."""
import os
import json
from copy import deepcopy
from pathlib import Path
import yaml
@@ -14,7 +15,67 @@ def oauth_ready(path):
return False
def build_config(catalog, env, exists):
def namespace_config(config):
"""Add explicit provider names without removing existing client aliases."""
routes = config['model_list']
existing = {r['model_name']: r for r in routes}
fallbacks = config['router_settings']['fallbacks']
automatic = {name for group in fallbacks for name in group}
renamed = {}
def clone(route, alias):
if alias in existing:
if existing[alias]['litellm_params'] != route['litellm_params']:
raise ValueError('Conflicting namespace alias: ' + alias)
return
new = deepcopy(route)
new['model_name'] = alias
existing[alias] = new
routes.append(new)
for route in list(routes):
alias = route['model_name']
model = route['litellm_params']['model']
if alias in {'gemini-3.6-flash', 'gemini-3.5-flash-lite',
'google/gemini-embedding-2', 'google/gemini-3.8-flash'}:
continue
if alias.endswith('-openrouter'):
new = 'openrouter/' + alias.removesuffix('-openrouter')
elif alias in automatic:
new = 'auto/' + alias
clone(route, 'zenmux/' + alias)
elif model.startswith('anthropic/'):
new = ('zenmux-payg/' + alias.removesuffix('-payg')
if alias.endswith('-payg') else 'zenmux/' + alias)
elif model.startswith('openai/'):
name = model.removeprefix('openai/').split('/', 1)[-1]
new = 'zenmux/' + (name if alias.startswith('asr-') else
alias.replace('-zenmux', '-latest'))
elif model.startswith('openrouter/'):
new = 'openrouter/' + alias
elif model.startswith('gemini/'):
new = 'aistudio/' + alias.removesuffix('-studio')
elif model.startswith('vertex_ai/'):
name = {'google-rerank-default': 'rerank-default-latest',
'google-rerank-fast': 'rerank-fast-latest'}.get(alias,
alias.replace('-vertex', '-latest'))
new = 'vertex/' + name
elif model.startswith('chatgpt/'):
name = model.split('/', 1)[1] if alias in {'gpt-work-sol', 'gpt-review-5.5'} else alias
new = 'codex/' + name
elif model.startswith('xai/'):
new = 'xai/' + alias
else:
raise ValueError('Unrecognized namespace provider: ' + alias)
clone(route, new)
renamed[alias] = new
for group in list(fallbacks):
for source, targets in group.items():
fallbacks.append({renamed[source]: [renamed[target] for target in targets]})
return config
def build_config(catalog, env, exists, namespaced=True):
routes = []
fallbacks = []
@@ -73,7 +134,7 @@ def build_config(catalog, env, exists):
for alias, model in catalog[provider].items():
extra = {'use_xai_oauth': True} if provider == 'xai' else {}
add(alias, provider + '/' + model, **extra)
return {
config = {
'model_list': routes,
'general_settings': {
'master_key': 'os.environ/LITELLM_MASTER_KEY',
@@ -85,6 +146,7 @@ def build_config(catalog, env, exists):
# Only explicitly approved open-model routes have cross-provider fallbacks.
'router_settings': {'num_retries': 1, 'timeout': 180, 'fallbacks': fallbacks},
}
return namespace_config(config) if namespaced else config
if __name__ == '__main__':