Files
cmhub/apps/ai/aliases.py
T

56 lines
1.8 KiB
Python
Raw Normal View History

2026-07-02 11:07:44 +08:00
from __future__ import annotations
from apps.ai.providers import ResolvedModel
from .models import AiModel, ModelAlias
class AliasResolutionError(RuntimeError):
"""Base error for alias resolution failures."""
class AliasNotFoundError(AliasResolutionError):
"""Raised when an active alias cannot be found."""
class ModelCapabilityError(AliasResolutionError):
"""Raised when an alias points to a model without the required capability."""
REQUIRED_CAPABILITIES = {
ModelAlias.OperationType.TITLE: "text",
ModelAlias.OperationType.IMAGE: "image",
}
def resolve_alias(operation_type: str, alias: str | None = None) -> ResolvedModel:
"""Resolve an external capability alias to a provider-ready model config."""
required_capability = REQUIRED_CAPABILITIES.get(operation_type)
if required_capability is None:
raise AliasResolutionError(f"unsupported operation_type: {operation_type}")
queryset = ModelAlias.objects.select_related("ai_model").filter(
operation_type=operation_type,
is_active=True,
ai_model__is_active=True,
)
if alias:
queryset = queryset.filter(alias=alias)
else:
queryset = queryset.filter(is_default=True)
model_alias = queryset.order_by("id").first()
if model_alias is None:
if alias:
raise AliasNotFoundError(f"alias not found: {operation_type}:{alias}")
raise AliasNotFoundError(f"default alias not found: {operation_type}")
ai_model: AiModel = model_alias.ai_model
capabilities = ai_model.capabilities_set()
if required_capability not in capabilities:
raise ModelCapabilityError(
f"alias {model_alias.alias} maps to model {ai_model.name} without "
f"{required_capability} capability"
)
return ai_model.to_resolved_model()