Commit a3c476ec authored by Your Name's avatar Your Name

Add --alias support for model names

- CLI (coder): Add --alias argument to create model aliases
- Config: Add model_aliases dict and resolve_model() method
- Server (coderai): Add server-side alias support with --model-alias
- Aliases are resolved in both client and server when making API calls
- Aliases appear in /v1/models endpoint
- Aliases are persisted in config file
parent aafd41eb
...@@ -149,6 +149,7 @@ class Config: ...@@ -149,6 +149,7 @@ class Config:
token: Optional[str] = None token: Optional[str] = None
system_prompt: str = DEFAULT_SYSTEM_PROMPT system_prompt: str = DEFAULT_SYSTEM_PROMPT
model: str = "default" model: str = "default"
model_aliases: Dict[str, str] = None # Alias -> Model mapping
small: bool = False # Use small model optimizations small: bool = False # Use small model optimizations
tiny: bool = False # Use tiny model optimizations (minimal) tiny: bool = False # Use tiny model optimizations (minimal)
micro: bool = False # Use micro model optimizations (ultra-minimal) micro: bool = False # Use micro model optimizations (ultra-minimal)
...@@ -163,6 +164,12 @@ class Config: ...@@ -163,6 +164,12 @@ class Config:
def __post_init__(self): def __post_init__(self):
if self.confirm_commands is None: if self.confirm_commands is None:
self.confirm_commands = {} self.confirm_commands = {}
if self.model_aliases is None:
self.model_aliases = {}
def resolve_model(self, model: str) -> str:
"""Resolve model alias to actual model name."""
return self.model_aliases.get(model, model)
@classmethod @classmethod
def load(cls, config_path: Optional[str] = None) -> "Config": def load(cls, config_path: Optional[str] = None) -> "Config":
...@@ -180,6 +187,7 @@ class Config: ...@@ -180,6 +187,7 @@ class Config:
config.token = data.get('token') config.token = data.get('token')
config.system_prompt = data.get('system_prompt', config.system_prompt) config.system_prompt = data.get('system_prompt', config.system_prompt)
config.model = data.get('model', config.model) config.model = data.get('model', config.model)
config.model_aliases = data.get('model_aliases', config.model_aliases)
config.small = data.get('small', config.small) config.small = data.get('small', config.small)
config.tiny = data.get('tiny', config.tiny) config.tiny = data.get('tiny', config.tiny)
config.micro = data.get('micro', config.micro) config.micro = data.get('micro', config.micro)
...@@ -206,6 +214,7 @@ class Config: ...@@ -206,6 +214,7 @@ class Config:
'token': self.token, 'token': self.token,
'system_prompt': self.system_prompt, 'system_prompt': self.system_prompt,
'model': self.model, 'model': self.model,
'model_aliases': self.model_aliases,
'small': self.small, 'small': self.small,
'tiny': self.tiny, 'tiny': self.tiny,
'micro': self.micro, 'micro': self.micro,
...@@ -556,7 +565,7 @@ class CoderClient: ...@@ -556,7 +565,7 @@ class CoderClient:
# Build payload, conditionally including tools # Build payload, conditionally including tools
payload = { payload = {
"model": self.config.model, "model": self.config.resolve_model(self.config.model),
"messages": messages, "messages": messages,
"stream": stream "stream": stream
} }
...@@ -1040,7 +1049,7 @@ class CoderClient: ...@@ -1040,7 +1049,7 @@ class CoderClient:
# Build payload, conditionally including tools # Build payload, conditionally including tools
payload = { payload = {
"model": self.config.model, "model": self.config.resolve_model(self.config.model),
"messages": messages, "messages": messages,
"stream": True "stream": True
} }
...@@ -1372,6 +1381,11 @@ Examples: ...@@ -1372,6 +1381,11 @@ Examples:
help='Model name to use (default: "default", temporary override)' help='Model name to use (default: "default", temporary override)'
) )
parser.add_argument(
'--alias',
help='Create an alias for the model (alias -> model mapping)'
)
parser.add_argument( parser.add_argument(
'--config', '--config',
help='Path to config file (default: ~/.config/coderai/cli.json)' help='Path to config file (default: ~/.config/coderai/cli.json)'
...@@ -1459,6 +1473,7 @@ Examples: ...@@ -1459,6 +1473,7 @@ Examples:
'token': config.token, 'token': config.token,
'system_prompt': config.system_prompt, 'system_prompt': config.system_prompt,
'model': config.model, 'model': config.model,
'model_aliases': config.model_aliases,
'small': config.small, 'small': config.small,
'tiny': config.tiny, 'tiny': config.tiny,
'max_context': config.max_context, 'max_context': config.max_context,
...@@ -1478,6 +1493,12 @@ Examples: ...@@ -1478,6 +1493,12 @@ Examples:
config.token = args.token config.token = args.token
if args.model: if args.model:
config.model = args.model config.model = args.model
if args.alias:
# Register alias: alias -> model mapping
# If model not specified, alias points to "default"
target_model = args.model if args.model else config.model
config.model_aliases[args.alias] = target_model
print(f"[Alias registered: {args.alias} -> {target_model}]")
if args.small: if args.small:
config.small = True config.small = True
if args.tiny: if args.tiny:
......
...@@ -1969,6 +1969,8 @@ class MultiModelManager: ...@@ -1969,6 +1969,8 @@ class MultiModelManager:
# Load mode settings # Load mode settings
self.load_mode: str = "ondemand" # "ondemand", "loadall", "loadswap" self.load_mode: str = "ondemand" # "ondemand", "loadall", "loadswap"
self.active_in_vram: Optional[str] = None # Which model is currently in VRAM self.active_in_vram: Optional[str] = None # Which model is currently in VRAM
# Model aliases: alias -> actual model name mapping
self.model_aliases: Dict[str, str] = {}
@property @property
def audio_model(self) -> Optional[str]: def audio_model(self) -> Optional[str]:
...@@ -2006,6 +2008,10 @@ class MultiModelManager: ...@@ -2006,6 +2008,10 @@ class MultiModelManager:
self.image_models.append(model_name) self.image_models.append(model_name)
self.config[f"image:{model_name}"] = config or {} self.config[f"image:{model_name}"] = config or {}
def set_model_alias(self, alias: str, model_name: str):
"""Register an alias for a model."""
self.model_aliases[alias] = model_name
def get_model_for_request(self, requested_model: str) -> Optional[ModelManager]: def get_model_for_request(self, requested_model: str) -> Optional[ModelManager]:
""" """
Get the appropriate model manager for a request based on model name. Get the appropriate model manager for a request based on model name.
...@@ -2018,8 +2024,13 @@ class MultiModelManager: ...@@ -2018,8 +2024,13 @@ class MultiModelManager:
- "vision:modelname" or "image:modelname" -> use specific image model - "vision:modelname" or "image:modelname" -> use specific image model
- "tts" -> use TTS model - "tts" -> use TTS model
- "tts:modelname" -> use specific TTS model - "tts:modelname" -> use specific TTS model
- Custom aliases -> resolve to actual model name
- Otherwise match by model ID in multi_model_manager.models - Otherwise match by model ID in multi_model_manager.models
""" """
# Resolve custom aliases first
if requested_model in self.model_aliases:
requested_model = self.model_aliases[requested_model]
# Handle empty or "default" model names # Handle empty or "default" model names
if not requested_model or requested_model == "default": if not requested_model or requested_model == "default":
if self.default_model and self.default_model in self.models: if self.default_model and self.default_model in self.models:
...@@ -2175,6 +2186,10 @@ class MultiModelManager: ...@@ -2175,6 +2186,10 @@ class MultiModelManager:
continue continue
models.append(ModelInfo(id=key)) models.append(ModelInfo(id=key))
# Add custom model aliases
for alias in self.model_aliases:
models.append(ModelInfo(id=alias))
return models if models else [ModelInfo(id="default")] return models if models else [ModelInfo(id="default")]
def swap_model_to_vram(self, model_key: str) -> bool: def swap_model_to_vram(self, model_key: str) -> bool:
...@@ -3735,6 +3750,16 @@ def parse_args(): ...@@ -3735,6 +3750,16 @@ def parse_args():
default=None, default=None,
help="Model name, path, or URL for text-to-text LLM. Can be specified multiple times for multiple models.", help="Model name, path, or URL for text-to-text LLM. Can be specified multiple times for multiple models.",
) )
parser.add_argument(
"--model-alias",
type=str,
action="append",
default=None,
dest="model_aliases",
nargs=2,
metavar=("ALIAS", "MODEL"),
help="Register an alias for a model. Format: --model-alias <alias_name> <actual_model>",
)
parser.add_argument( parser.add_argument(
"--backend", "--backend",
type=str, type=str,
...@@ -4388,6 +4413,12 @@ def main(): ...@@ -4388,6 +4413,12 @@ def main():
if model_name is None and not audio_models and not args.tts_model: if model_name is None and not audio_models and not args.tts_model:
print(f"Pre-loading image model...") print(f"Pre-loading image model...")
# Register model aliases if specified
if args.model_aliases:
print(f"\nRegistering model aliases:")
for alias, model in args.model_aliases:
multi_model_manager.set_model_alias(alias, model)
print(f" {alias} -> {model}")
# Start the server # Start the server
import uvicorn import uvicorn
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment