fix: reconcile merged runtime behavior
This commit is contained in:
@@ -36,7 +36,6 @@ from .capability import (
|
|||||||
CapabilityReport,
|
CapabilityReport,
|
||||||
build_capability_report,
|
build_capability_report,
|
||||||
)
|
)
|
||||||
from .native_backend import NativeWorkerBackendAdapter
|
|
||||||
from .recipe_manifest import (
|
from .recipe_manifest import (
|
||||||
DEFAULT_RECIPE_ID,
|
DEFAULT_RECIPE_ID,
|
||||||
Recipe,
|
Recipe,
|
||||||
@@ -450,9 +449,11 @@ def _validate_recipe(
|
|||||||
category: str | None = None
|
category: str | None = None
|
||||||
error: BaseException | None = None
|
error: BaseException | None = None
|
||||||
diagnostics: list[str] = []
|
diagnostics: list[str] = []
|
||||||
|
detail: dict = {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
backend = load_backend(selection, recipe)
|
backend = load_backend(selection, recipe)
|
||||||
probe_forward(backend)
|
detail = probe_forward(backend)
|
||||||
except DoctorError as exc:
|
except DoctorError as exc:
|
||||||
category, error = exc.category, exc
|
category, error = exc.category, exc
|
||||||
diagnostics = [str(exc), exc.hint]
|
diagnostics = [str(exc), exc.hint]
|
||||||
@@ -463,48 +464,23 @@ def _validate_recipe(
|
|||||||
duration_ms = int((time.monotonic() - started) * 1000)
|
duration_ms = int((time.monotonic() - started) * 1000)
|
||||||
|
|
||||||
device = _backend_device(backend, selection)
|
device = _backend_device(backend, selection)
|
||||||
# Only the native adapter has an authoritative immutable GGUF report and
|
|
||||||
# deployment pin. The Transformers path deliberately remains dark: a
|
|
||||||
# model/config fingerprint is not an exact ArtifactIdentity.
|
|
||||||
identity = backend.identity if isinstance(backend, NativeWorkerBackendAdapter) else None
|
|
||||||
model_id = selection.model_id if identity is None else identity.artifact.artifact_id
|
|
||||||
shard_start = selection.shard_start if identity is None else identity.shard_start
|
|
||||||
shard_end = selection.shard_end if identity is None else identity.shard_end - 1
|
|
||||||
recipe_id = recipe.id if identity is None else identity.recipe.recipe_id
|
|
||||||
recipe_version = recipe.version if identity is None else identity.recipe.recipe_version
|
|
||||||
catalogue_version = (
|
|
||||||
manifest.catalogue_version if identity is None else identity.recipe.catalogue_version
|
|
||||||
)
|
|
||||||
backend_id = recipe.backend_id if identity is None else identity.recipe.backend_id
|
|
||||||
quantization = (
|
|
||||||
selection.quantization if identity is None else identity.recipe.weight_quantization
|
|
||||||
)
|
|
||||||
runtime = _runtime_versions()
|
|
||||||
model_config = _model_config(backend)
|
|
||||||
revision = None
|
|
||||||
if identity is not None:
|
|
||||||
revision = identity.artifact.revision
|
|
||||||
model_config = "sha256:" + identity.artifact.architecture_digest
|
|
||||||
runtime = {**runtime, "native_runtime": identity.recipe.runtime_version}
|
|
||||||
report = build_capability_report(
|
report = build_capability_report(
|
||||||
model_id=model_id,
|
model_id=selection.model_id,
|
||||||
shard_start=shard_start,
|
shard_start=selection.shard_start,
|
||||||
shard_end=shard_end,
|
shard_end=selection.shard_end,
|
||||||
recipe_id=recipe_id,
|
recipe_id=recipe.id,
|
||||||
recipe_version=recipe_version,
|
recipe_version=recipe.version,
|
||||||
catalogue_version=catalogue_version,
|
catalogue_version=manifest.catalogue_version,
|
||||||
backend_id=backend_id,
|
backend_id=recipe.backend_id,
|
||||||
device=device,
|
device=device,
|
||||||
device_name=_backend_device_name(device),
|
device_name=_backend_device_name(device),
|
||||||
quantization=quantization,
|
quantization=selection.quantization,
|
||||||
runtime=runtime,
|
runtime=_runtime_versions(),
|
||||||
revision=revision,
|
model_config=_model_config(backend),
|
||||||
model_config=model_config,
|
|
||||||
status=STATUS_FAILED if category else STATUS_PASSED,
|
status=STATUS_FAILED if category else STATUS_PASSED,
|
||||||
duration_ms=duration_ms,
|
duration_ms=duration_ms,
|
||||||
diagnostics=[d for d in diagnostics if d] or None,
|
diagnostics=[d for d in diagnostics if d] or None,
|
||||||
validated_at=clock(),
|
validated_at=clock(),
|
||||||
identity=identity,
|
|
||||||
)
|
)
|
||||||
if category:
|
if category:
|
||||||
return RecipeResult(
|
return RecipeResult(
|
||||||
|
|||||||
@@ -1576,19 +1576,24 @@ class TorchNodeServer:
|
|||||||
if drop_directive is not None:
|
if drop_directive is not None:
|
||||||
model_id = str(drop_directive.get("model") or "")
|
model_id = str(drop_directive.get("model") or "")
|
||||||
removed = self._backends.pop(model_id, None)
|
removed = self._backends.pop(model_id, None)
|
||||||
if removed is None:
|
if removed is not None:
|
||||||
return None
|
if self._backends:
|
||||||
if self._backends:
|
self._backend = next(iter(self._backends.values()))
|
||||||
self._backend = next(iter(self._backends.values()))
|
self._tracker_mode = self._backend.shard_start == 0
|
||||||
self._tracker_mode = self._backend.shard_start == 0
|
else:
|
||||||
else:
|
self._backend = None
|
||||||
self._backend = None
|
self._tracker_mode = False
|
||||||
self._tracker_mode = False
|
if self._server is not None:
|
||||||
if self._server is not None:
|
self._server.backends = dict(self._backends)
|
||||||
self._server.backends = dict(self._backends)
|
self._server.backend = self._backend
|
||||||
self._server.backend = self._backend
|
self._server.tracker_mode = self._tracker_mode
|
||||||
self._server.tracker_mode = self._tracker_mode
|
# A DROP_SHARD may be paired with a subsequent LOAD_SHARD in the
|
||||||
return {"action": "DROP_SHARD", "model": model_id}
|
# same heartbeat; continue so the replacement is applied atomically.
|
||||||
|
if not any(
|
||||||
|
directive.get("action") in {"ADD_SHARD", "LOAD_SHARD"}
|
||||||
|
for directive in directives
|
||||||
|
):
|
||||||
|
return {"action": "DROP_SHARD", "model": model_id} if removed is not None else None
|
||||||
add_directive = next(
|
add_directive = next(
|
||||||
(directive for directive in reversed(directives) if directive.get("action") == "ADD_SHARD"),
|
(directive for directive in reversed(directives) if directive.get("action") == "ADD_SHARD"),
|
||||||
None,
|
None,
|
||||||
@@ -1602,8 +1607,11 @@ class TorchNodeServer:
|
|||||||
return None
|
return None
|
||||||
shard_start = int(directive["shard_start"])
|
shard_start = int(directive["shard_start"])
|
||||||
shard_end = int(directive["shard_end"])
|
shard_end = int(directive["shard_end"])
|
||||||
quantization = str(directive.get("quantization") or self._backend.quantization)
|
quantization = str(
|
||||||
model_id = str(directive.get("model") or self._backend.model_id)
|
directive.get("quantization")
|
||||||
|
or (self._backend.quantization if self._backend is not None else "auto")
|
||||||
|
)
|
||||||
|
model_id = str(directive.get("model") or (self._backend.model_id if self._backend is not None else ""))
|
||||||
replacing = directive.get("action") == "LOAD_SHARD"
|
replacing = directive.get("action") == "LOAD_SHARD"
|
||||||
if not replacing and len(self._backends) >= self._max_loaded_shards:
|
if not replacing and len(self._backends) >= self._max_loaded_shards:
|
||||||
print(
|
print(
|
||||||
|
|||||||
@@ -3295,12 +3295,15 @@ class _TrackerHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
node.hf_repo or node.model
|
node.hf_repo or node.model
|
||||||
for node in alive
|
for node in alive
|
||||||
if node.model is not None
|
if node.model is not None
|
||||||
# The same model can be registered under its HF repository while
|
# Explicit HF repositories are emitted as stable identifiers even
|
||||||
# the catalogue exposes its short preset id. Do not emit a second
|
# when they also resolve to a short-name preset; clients may use
|
||||||
# repo-keyed entry when either node identifier resolves to a preset.
|
# either identifier when selecting a model.
|
||||||
and _resolve_model_preset(
|
and (
|
||||||
server.model_presets, node.hf_repo or node.model,
|
node.hf_repo is not None
|
||||||
)[1] is None
|
or _resolve_model_preset(
|
||||||
|
server.model_presets, node.model,
|
||||||
|
)[1] is None
|
||||||
|
)
|
||||||
and node.shard_start is not None
|
and node.shard_start is not None
|
||||||
and node.shard_end is not None
|
and node.shard_end is not None
|
||||||
and node.num_layers is not None
|
and node.num_layers is not None
|
||||||
|
|||||||
Reference in New Issue
Block a user