codekingpro/portable-devtools
114k
1# Copyright 2019-present, the HuggingFace Inc. team.2#3# Licensed under the Apache License, Version 2.0 (the "License");4# you may not use this file except in compliance with the License.5# You may obtain a copy of the License at6#7# http://www.apache.org/licenses/LICENSE-2.08#9# Unless required by applicable law or agreed to in writing, software10# distributed under the License is distributed on an "AS IS" BASIS,11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12# See the License for the specific language governing permissions and13# limitations under the License.14from dataclasses import dataclass15from datetime import datetime16from enum import Enum17from typing import Literal18 19from huggingface_hub.utils import parse_datetime20 21 22class SpaceStage(str, Enum):23 """24 Enumeration of possible stage of a Space on the Hub.25 26 Value can be compared to a string:27 ```py28 assert SpaceStage.BUILDING == "BUILDING"29 ```30 31 Taken from https://github.com/huggingface/moon-landing/blob/main/server/repo_types/SpaceInfo.ts#L61 (private url).32 """33 34 # Copied from moon-landing > server > repo_types > SpaceInfo.ts (private repo)35 NO_APP_FILE = "NO_APP_FILE"36 CONFIG_ERROR = "CONFIG_ERROR"37 BUILDING = "BUILDING"38 BUILD_ERROR = "BUILD_ERROR"39 RUNNING = "RUNNING"40 RUNNING_BUILDING = "RUNNING_BUILDING"41 RUNTIME_ERROR = "RUNTIME_ERROR"42 DELETING = "DELETING"43 STOPPED = "STOPPED"44 PAUSED = "PAUSED"45 APP_STARTING = "APP_STARTING"46 RUNNING_APP_STARTING = "RUNNING_APP_STARTING"47 48 49class SpaceHardware(str, Enum):50 """51 Enumeration of hardwares available to run your Space on the Hub.52 53 Value can be compared to a string:54 ```py55 assert SpaceHardware.CPU_BASIC == "cpu-basic"56 ```57 58 Taken from https://github.com/huggingface-internal/moon-landing/blob/main/server/repo_types/SpaceHardwareFlavor.ts (private url).59 """60 61 # CPU62 CPU_BASIC = "cpu-basic"63 CPU_UPGRADE = "cpu-upgrade"64 CPU_PERFORMANCE = "cpu-performance"65 CPU_XL = "cpu-xl"66 SPRX8 = "sprx8"67 68 # ZeroGPU69 ZERO_A10G = "zero-a10g"70 71 # GPU72 T4_SMALL = "t4-small"73 T4_MEDIUM = "t4-medium"74 L4X1 = "l4x1"75 L4X4 = "l4x4"76 L40SX1 = "l40sx1"77 L40SX4 = "l40sx4"78 L40SX8 = "l40sx8"79 A10G_SMALL = "a10g-small"80 A10G_LARGE = "a10g-large"81 A10G_LARGEX2 = "a10g-largex2"82 A10G_LARGEX4 = "a10g-largex4"83 A100_LARGE = "a100-large"84 A100X4 = "a100x4"85 A100X8 = "a100x8"86 H200 = "h200"87 H200X2 = "h200x2"88 H200X4 = "h200x4"89 H200X8 = "h200x8"90 91 # Neuron92 INF2X6 = "inf2x6"93 94 95class SpaceStorage(str, Enum):96 """97 Enumeration of persistent storage available for your Space on the Hub.98 99 Value can be compared to a string:100 ```py101 assert SpaceStorage.SMALL == "small"102 ```103 104 Taken from https://github.com/huggingface/moon-landing/blob/main/server/repo_types/SpaceHardwareFlavor.ts#L24 (private url).105 """106 107 SMALL = "small"108 MEDIUM = "medium"109 LARGE = "large"110 111 112@dataclass113class Volume:114 """115 Describes a volume to mount in a Space or Job container.116 117 Args:118 type (`str`):119 Type of volume: `"bucket"`, `"model"`, `"dataset"`, or `"space"`.120 source (`str`):121 Source identifier, e.g. `"username/my-bucket"` or `"username/my-model"`.122 mount_path (`str`):123 Mount path inside the container, e.g. `"/data"`. Must start with `/`.124 revision (`str` or `None`):125 Git revision (only for repos, defaults to `"main"`).126 read_only (`bool` or `None`):127 Read-only mount. Forced `True` for repos, defaults to `False` for buckets.128 path (`str` or `None`):129 Subfolder prefix inside the bucket/repo to mount, e.g. `"path/to/dir"`.130 """131 132 type: Literal["bucket", "model", "dataset", "space"]133 source: str134 mount_path: str135 revision: str | None = None136 read_only: bool | None = None137 path: str | None = None138 139 def __init__(self, **kwargs) -> None:140 self.type = kwargs.get("type", "model")141 self.source = kwargs["source"]142 mount_path = kwargs.get("mountPath")143 self.mount_path = mount_path if mount_path is not None else kwargs["mount_path"]144 self.revision = kwargs.get("revision")145 read_only = kwargs.get("readOnly")146 self.read_only = read_only if read_only is not None else kwargs.get("read_only")147 self.path = kwargs.get("path")148 149 def to_dict(self) -> dict:150 """Serialize to the JSON payload expected by the Hub API."""151 data: dict = {152 "type": self.type,153 "source": self.source,154 "mountPath": self.mount_path,155 }156 if self.revision is not None:157 data["revision"] = self.revision158 if self.read_only is not None:159 data["readOnly"] = self.read_only160 if self.path is not None:161 data["path"] = self.path162 return data163 164 def to_hf_handle(self) -> str:165 """Return the volume as an HF handle in the format expected by the CLI."""166 path = f"/{self.path}" if self.path else ""167 revision = f"@{self.revision}" if self.revision else ""168 ro = {True: ":ro", False: ":rw", None: ""}.get(self.read_only, "")169 return f"hf://{self.type}s/{self.source}{revision}{path}:{self.mount_path}{ro}"170 171 172@dataclass173class SpaceHotReloading:174 status: Literal["created", "canceled"]175 replica_statuses: list[tuple[str, str | None]] # See _hot_reloading_types.ApiCreateReloadResponse.res.status176 raw: dict177 178 def __init__(self, data: dict) -> None:179 self.status = data["status"]180 self.replica_statuses = data["replicaStatuses"]181 self.raw = data182 183 184@dataclass185class SpaceRuntime:186 """187 Contains information about the current runtime of a Space.188 189 Args:190 stage (`str`):191 Current stage of the space. Example: RUNNING.192 hardware (`str` or `None`):193 Current hardware of the space. Example: "cpu-basic". Can be `None` if Space194 is `BUILDING` for the first time.195 requested_hardware (`str` or `None`):196 Requested hardware. Can be different from `hardware` especially if the request197 has just been made. Example: "t4-medium". Can be `None` if no hardware has198 been requested yet.199 sleep_time (`int` or `None`):200 Number of seconds the Space will be kept alive after the last request. By default (if value is `None`), the201 Space will never go to sleep if it's running on an upgraded hardware, while it will go to sleep after 48202 hours on a free 'cpu-basic' hardware. For more details, see https://huggingface.co/docs/hub/spaces-gpus#sleep-time.203 volumes (`list[Volume]` or `None`):204 List of volumes mounted in the Space. Each volume is a [`Volume`] object describing its type, source,205 mount path, and optional settings. `None` if no volumes are attached.206 raw (`dict`):207 Raw response from the server. Contains more information about the Space208 runtime like number of replicas, number of cpu, memory size,...209 """210 211 stage: SpaceStage212 hardware: SpaceHardware | None213 requested_hardware: SpaceHardware | None214 sleep_time: int | None215 storage: SpaceStorage | None216 hot_reloading: SpaceHotReloading | None217 volumes: list[Volume] | None218 raw: dict219 220 def __init__(self, data: dict) -> None:221 self.stage = data["stage"]222 self.hardware = data.get("hardware", {}).get("current")223 self.requested_hardware = data.get("hardware", {}).get("requested")224 self.sleep_time = data.get("gcTimeout")225 self.storage = data.get("storage")226 self.hot_reloading = SpaceHotReloading(raw_hr) if (raw_hr := data.get("hotReloading")) is not None else None227 raw_volumes = data.get("volumes")228 self.volumes = [Volume(**v) for v in raw_volumes] if raw_volumes is not None else None229 self.raw = data230 231 232@dataclass233class SpaceSecret:234 """235 Contains information about a secret of a Space.236 237 Secret values are write-only and cannot be read back. Only the key, description,238 and last update time are returned by the API.239 240 Args:241 key (`str`):242 Secret key. Example: `"GITHUB_API_KEY"`243 description (`str` or None):244 Description of the secret. Example: `"Github API key to access the Github API"`.245 updated_at (`datetime` or None):246 datetime of the last update of the secret (if the secret has been updated at least once).247 """248 249 key: str250 description: str | None251 updated_at: datetime | None252 253 def __init__(self, key: str, values: dict) -> None:254 self.key = key255 self.description = values.get("description")256 updated_at = values.get("updatedAt")257 self.updated_at = parse_datetime(updated_at) if updated_at is not None else None258 259 260@dataclass261class SpaceVariable:262 """263 Contains information about the current variables of a Space.264 265 Args:266 key (`str`):267 Variable key. Example: `"MODEL_REPO_ID"`268 value (`str`):269 Variable value. Example: `"the_model_repo_id"`.270 description (`str` or None):271 Description of the variable. Example: `"Model Repo ID of the implemented model"`.272 updatedAt (`datetime` or None):273 datetime of the last update of the variable (if the variable has been updated at least once).274 """275 276 key: str277 value: str278 description: str | None279 updated_at: datetime | None280 281 def __init__(self, key: str, values: dict) -> None:282 self.key = key283 self.value = values["value"]284 self.description = values.get("description")285 updated_at = values.get("updatedAt")286 self.updated_at = parse_datetime(updated_at) if updated_at is not None else None287 288 289@dataclass290class SpaceSearchResult:291 """A single result from the Spaces semantic search API.292 293 Returned by [`HfApi.search_spaces`].294 295 Attributes:296 id (`str`):297 ID of the Space (e.g. `"username/repo-name"`).298 author (`str`):299 Author of the Space.300 title (`str`):301 Display title of the Space.302 emoji (`str` or `None`):303 Emoji icon of the Space.304 sdk (`str` or `None`):305 SDK used by the Space (e.g. `"gradio"`, `"docker"`, `"static"`).306 likes (`int`):307 Number of likes.308 private (`bool`):309 Whether the Space is private.310 tags (`list[str]` or `None`):311 List of tags.312 runtime ([`SpaceRuntime`] or `None`):313 Runtime information (stage, hardware, etc.).314 ai_short_description (`str` or `None`):315 AI-generated short description.316 ai_category (`str` or `None`):317 AI-generated category (e.g. `"Image Generation"`).318 semantic_relevancy_score (`float` or `None`):319 Semantic relevancy score (0-1) relative to the search query.320 trending_score (`int` or `None`):321 Trending score.322 """323 324 id: str325 author: str326 title: str327 emoji: str | None328 sdk: str | None329 likes: int330 private: bool331 tags: list[str] | None332 runtime: SpaceRuntime | None333 ai_short_description: str | None334 ai_category: str | None335 semantic_relevancy_score: float | None336 trending_score: int | None337 338 def __init__(self, data: dict) -> None:339 runtime = data.get("runtime")340 self.id = data["id"]341 self.author = data.get("author", "")342 self.title = data.get("title", "")343 self.emoji = data.get("emoji")344 self.sdk = data.get("sdk")345 self.likes = data.get("likes", 0)346 self.private = data.get("private", False)347 self.tags = data.get("tags")348 self.runtime = SpaceRuntime(runtime) if runtime else None349 self.ai_short_description = data.get("ai_short_description")350 self.ai_category = data.get("ai_category")351 self.semantic_relevancy_score = data.get("semanticRelevancyScore")352 self.trending_score = data.get("trendingScore")353 