from __future__ import annotations
import logging
from pathlib import Path
from .. import model_prefetch, model_snapshot
from ..adapter import EngineAdapter, StrategyFailed
from .base import LoadContext, LoadStrategy, _as_load_result, register_tensors
from .context import LoadResult
logger = logging.getLogger("modelexpress.strategy_server_cache")
class ServerCacheStrategy(LoadStrategy):
name = "server-cache"
requires = (EngineAdapter.load_via_native,)
def is_available(self, ctx: LoadContext) -> bool:
if not super().is_available(ctx):
return False
if not model_prefetch.is_enabled():
return False
if _repo_id(ctx) is None:
logger.info(
f"[Worker {ctx.global_rank}] No Hugging Face repo id for "
f"{ctx.identity.model_name!r}, skipping server cache"
)
return False
return True
def load(self, result: LoadResult, ctx: LoadContext) -> LoadResult:
result = _as_load_result(result)
if ctx.adapter is None:
raise StrategyFailed(
"ModelExpress Server cache requires an engine adapter", mutated=False
)
repo_id = _repo_id(ctx)
if repo_id is None:
raise StrategyFailed("No Hugging Face repo id for this model", mutated=False)
try:
snapshot_path, cache_root = self._snapshot_path(ctx, repo_id)
logger.info(
f"[Worker {ctx.global_rank}] Fetching {repo_id} weights from "
f"ModelExpress Server into {snapshot_path}"
)
self._install_weights(repo_id, snapshot_path, cache_root)
except StrategyFailed:
raise
except Exception as exc:
raise StrategyFailed(
f"ModelExpress Server cache failed: {exc}", mutated=False
) from exc
try:
result = ctx.adapter.load_via_native(result)
result = ctx.adapter.after_native_load(result)
except Exception as exc:
raise StrategyFailed(str(exc), mutated=True) from exc
register_tensors(result, ctx)
return result
def _snapshot_path(
self, ctx: LoadContext, repo_id: str
) -> tuple[Path, Path | None]:
engine_path = getattr(ctx.model_config, "model", None)
if engine_path:
candidate = Path(str(engine_path))
location = model_snapshot.snapshot_location(repo_id, candidate)
if location is not None:
cache_root, commit = location
if candidate.is_dir():
return candidate, cache_root
return self._install_metadata(repo_id, commit, cache_root), cache_root
if candidate.is_dir():
return candidate, None
revision = getattr(ctx.model_config, "revision", None)
return self._install_metadata(repo_id, revision, None), None
@staticmethod
def _install_metadata(
repo_id: str, revision: str | None, cache_root: Path | None
) -> Path:
snapshot_path = model_prefetch.ensure_metadata(
repo_id, revision, cache_directory=cache_root
)
if snapshot_path is None:
raise StrategyFailed(
f"No local snapshot for {repo_id} and metadata prefetch did not apply",
mutated=False,
)
return snapshot_path
@staticmethod
def _install_weights(
repo_id: str, snapshot_path: Path, cache_root: Path | None = None
) -> None:
from ..model_client import ModelCacheClient
with ModelCacheClient(
cache_directory=cache_root,
chunk_size=model_prefetch.configured_chunk_size(),
) as client:
client.install_weight_files(repo_id, snapshot_path)
def _repo_id(ctx: LoadContext) -> str | None:
return model_prefetch.repo_id_for(ctx.identity.model_name)