Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/vidxp/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
ImportMediaCommand,
IndexSnapshotReference,
MediaAsset,
ModelDownloadError,
ModelUnavailableError,
PrepareModelsCommand,
PrepareModelsResult,
Expand Down Expand Up @@ -59,7 +60,10 @@
from vidxp.ports import IndexBackend, ModelRuntimePort, QueryModelPort
from vidxp.query_service import GroundedQueryService
from vidxp.search_fusion import fuse_search_results
from vidxp.model_contracts import ModelArtifactUnavailableError
from vidxp.model_contracts import (
ModelArtifactDownloadError,
ModelArtifactUnavailableError,
)
from vidxp.repository_layout import RepositoryLayout
from vidxp.settings import VidXPSettings
from vidxp.control_plane import ControlPlaneApplication
Expand Down Expand Up @@ -119,6 +123,15 @@ def _capability_dependencies(
capabilities,
self.registry.install_hint(capabilities),
) from exc
except ModelArtifactDownloadError as exc:
raise ModelDownloadError(
exc.capability,
exc.model_id,
attempts=exc.attempts,
reason=exc.reason,
resumable=exc.resumable,
retryable=exc.retryable,
) from exc
except ModelArtifactUnavailableError as exc:
raise ModelUnavailableError(exc.capability) from exc
except (ModuleNotFoundError, CapabilityDependencyError) as exc:
Expand Down
37 changes: 37 additions & 0 deletions src/vidxp/application_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,43 @@ def __init__(self, capability: str) -> None:
)


class ModelDownloadError(ApplicationError):
def __init__(
self,
capability: str,
model_id: str,
*,
attempts: int,
reason: str,
resumable: bool,
retryable: bool,
) -> None:
modality = capability.split(".", 1)[0]
remediation = f"vidxp prepare --modalities {modality}"
retry_message = (
"Partial files were kept and the next preparation attempt will "
"resume them."
if resumable
else "The next preparation attempt will restart this file."
)
super().__init__(
"model_download_failed",
ErrorCategory.unavailable,
f"Downloading {model_id} failed after {attempts} attempt(s) "
f"({reason}). {retry_message} Run "
f"`{remediation}` again when the connection is available.",
details={
"capability": capability,
"model": model_id,
"attempts": attempts,
"reason": reason,
"partial_files_preserved": resumable,
"remediation": remediation,
},
retryable=retryable,
)


class InvalidRequestError(ApplicationError):
def __init__(
self,
Expand Down
5 changes: 2 additions & 3 deletions src/vidxp/cli_commands/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,9 +471,8 @@ def prepare(
typer.confirm("Download these models?", abort=True)
show_progress = not state.quiet and output_format == OutputFormat.rich
if show_progress:
emit_progress(
"Starting model preparation for " + ", ".join(selected) + "."
)
action = "Downloading and validating" if missing else "Validating cached"
emit_progress(f"{action} models for " + ", ".join(selected) + ".")
job = state.jobs.submit_prepare_models(
PrepareModelsCommand(
modalities=selected,
Expand Down
23 changes: 23 additions & 0 deletions src/vidxp/model_contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,29 @@ def __init__(self, capability: str) -> None:
super().__init__(f"Model artifacts for {capability} are unavailable.")


class ModelArtifactDownloadError(RuntimeError):
def __init__(
self,
capability: str,
model_id: str,
*,
attempts: int,
reason: str,
resumable: bool,
retryable: bool,
) -> None:
self.capability = capability
self.model_id = model_id
self.attempts = attempts
self.reason = reason
self.resumable = resumable
self.retryable = retryable
super().__init__(
f"Downloading {model_id} failed after {attempts} attempt(s): "
f"{reason}."
)


@dataclass(frozen=True)
class ModelKey:
capability: str
Expand Down
Loading