2026-08-12 08:02:51 +08:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
from collections.abc import Iterable
|
|
|
|
|
from typing import Any
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EXPLICIT_ARCHITECTURE_FAILURE_CATEGORY = "framework_architecture_unsupported"
|
|
|
|
|
EXPLICIT_ARCHITECTURE_FAILURE_ACTION = "block_gpu_framework_architecture"
|
|
|
|
|
EXPLICIT_ARCHITECTURE_FAILURE_REASON = "explicit_framework_model_unsupported"
|
|
|
|
|
DEFAULT_ARCHITECTURE_BLOCK_TTL_DAYS = 30
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def architecture_profile(
|
|
|
|
|
model_type: Any,
|
|
|
|
|
architectures: Any,
|
|
|
|
|
) -> dict[str, Any] | None:
|
|
|
|
|
"""Build a stable, conservative architecture identity for feedback matching."""
|
2026-08-12 08:19:53 +08:00
|
|
|
profiles = architecture_profiles(model_type, architectures)
|
|
|
|
|
return profiles[0] if profiles else None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def architecture_profiles(
|
|
|
|
|
model_type: Any,
|
|
|
|
|
architectures: Any,
|
|
|
|
|
) -> list[dict[str, Any]]:
|
|
|
|
|
"""Return exact architecture identity first, followed by model-type fallback."""
|
2026-08-12 08:02:51 +08:00
|
|
|
normalized_architectures = _normalize_architectures(architectures)
|
|
|
|
|
normalized_model_type = _normalize(model_type)
|
2026-08-12 08:19:53 +08:00
|
|
|
profiles: list[dict[str, Any]] = []
|
2026-08-12 08:02:51 +08:00
|
|
|
if normalized_architectures:
|
2026-08-12 08:19:53 +08:00
|
|
|
profiles.append(
|
|
|
|
|
{
|
|
|
|
|
"matchType": "architectures",
|
|
|
|
|
"signature": "architectures:" + ",".join(normalized_architectures),
|
|
|
|
|
"architectures": normalized_architectures,
|
|
|
|
|
"modelType": normalized_model_type or None,
|
|
|
|
|
}
|
|
|
|
|
)
|
2026-08-12 08:02:51 +08:00
|
|
|
if normalized_model_type:
|
2026-08-12 08:19:53 +08:00
|
|
|
profiles.append(
|
|
|
|
|
{
|
|
|
|
|
"matchType": "model_type",
|
|
|
|
|
"signature": f"model_type:{normalized_model_type}",
|
|
|
|
|
"architectures": [],
|
|
|
|
|
"modelType": normalized_model_type,
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
return profiles
|
2026-08-12 08:02:51 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def architecture_compatibility_key(
|
|
|
|
|
target_gpu: Any,
|
|
|
|
|
framework: Any,
|
|
|
|
|
task_type: Any,
|
|
|
|
|
signature: Any,
|
|
|
|
|
) -> str | None:
|
|
|
|
|
parts = (
|
|
|
|
|
_normalize(target_gpu),
|
|
|
|
|
_normalize(framework),
|
|
|
|
|
_normalize(task_type),
|
|
|
|
|
_normalize(signature),
|
|
|
|
|
)
|
|
|
|
|
if not all(parts):
|
|
|
|
|
return None
|
|
|
|
|
return "|".join(parts)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _normalize_architectures(value: Any) -> list[str]:
|
|
|
|
|
if isinstance(value, str):
|
|
|
|
|
values: Iterable[Any] = [value]
|
|
|
|
|
elif isinstance(value, (list, tuple, set)):
|
|
|
|
|
values = value
|
|
|
|
|
else:
|
|
|
|
|
values = []
|
|
|
|
|
return sorted({_normalize(item) for item in values if _normalize(item)})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _normalize(value: Any) -> str:
|
|
|
|
|
return str(value or "").strip().casefold()
|