huggingface-hub 0.35.0rc0__py3-none-any.whl → 0.35.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of huggingface-hub might be problematic. Click here for more details.
- huggingface_hub/__init__.py +19 -1
- huggingface_hub/_jobs_api.py +168 -12
- huggingface_hub/_local_folder.py +1 -1
- huggingface_hub/_oauth.py +5 -9
- huggingface_hub/_tensorboard_logger.py +9 -10
- huggingface_hub/_upload_large_folder.py +108 -1
- huggingface_hub/cli/auth.py +4 -1
- huggingface_hub/cli/cache.py +7 -9
- huggingface_hub/cli/hf.py +2 -5
- huggingface_hub/cli/jobs.py +591 -13
- huggingface_hub/cli/repo.py +10 -4
- huggingface_hub/commands/delete_cache.py +2 -2
- huggingface_hub/commands/scan_cache.py +1 -1
- huggingface_hub/dataclasses.py +3 -0
- huggingface_hub/file_download.py +12 -10
- huggingface_hub/hf_api.py +549 -95
- huggingface_hub/hf_file_system.py +4 -10
- huggingface_hub/hub_mixin.py +5 -3
- huggingface_hub/inference/_client.py +98 -181
- huggingface_hub/inference/_common.py +72 -70
- huggingface_hub/inference/_generated/_async_client.py +116 -201
- huggingface_hub/inference/_generated/types/chat_completion.py +2 -0
- huggingface_hub/inference/_mcp/_cli_hacks.py +3 -3
- huggingface_hub/inference/_mcp/cli.py +1 -1
- huggingface_hub/inference/_mcp/constants.py +1 -1
- huggingface_hub/inference/_mcp/mcp_client.py +28 -11
- huggingface_hub/inference/_mcp/types.py +3 -0
- huggingface_hub/inference/_mcp/utils.py +7 -3
- huggingface_hub/inference/_providers/__init__.py +13 -0
- huggingface_hub/inference/_providers/_common.py +29 -4
- huggingface_hub/inference/_providers/black_forest_labs.py +1 -1
- huggingface_hub/inference/_providers/fal_ai.py +33 -2
- huggingface_hub/inference/_providers/hf_inference.py +15 -7
- huggingface_hub/inference/_providers/publicai.py +6 -0
- huggingface_hub/inference/_providers/replicate.py +1 -1
- huggingface_hub/inference/_providers/scaleway.py +28 -0
- huggingface_hub/lfs.py +2 -4
- huggingface_hub/repocard.py +2 -1
- huggingface_hub/utils/_dotenv.py +24 -20
- huggingface_hub/utils/_git_credential.py +1 -1
- huggingface_hub/utils/_http.py +3 -5
- huggingface_hub/utils/_runtime.py +1 -0
- huggingface_hub/utils/_typing.py +24 -4
- huggingface_hub/utils/_xet_progress_reporting.py +31 -10
- {huggingface_hub-0.35.0rc0.dist-info → huggingface_hub-0.35.1.dist-info}/METADATA +7 -4
- {huggingface_hub-0.35.0rc0.dist-info → huggingface_hub-0.35.1.dist-info}/RECORD +50 -48
- {huggingface_hub-0.35.0rc0.dist-info → huggingface_hub-0.35.1.dist-info}/LICENSE +0 -0
- {huggingface_hub-0.35.0rc0.dist-info → huggingface_hub-0.35.1.dist-info}/WHEEL +0 -0
- {huggingface_hub-0.35.0rc0.dist-info → huggingface_hub-0.35.1.dist-info}/entry_points.txt +0 -0
- {huggingface_hub-0.35.0rc0.dist-info → huggingface_hub-0.35.1.dist-info}/top_level.txt +0 -0
huggingface_hub/hf_api.py
CHANGED
|
@@ -67,7 +67,7 @@ from ._commit_api import (
|
|
|
67
67
|
_warn_on_overwriting_operations,
|
|
68
68
|
)
|
|
69
69
|
from ._inference_endpoints import InferenceEndpoint, InferenceEndpointType
|
|
70
|
-
from ._jobs_api import JobInfo
|
|
70
|
+
from ._jobs_api import JobInfo, ScheduledJobInfo, _create_job_spec
|
|
71
71
|
from ._space_api import SpaceHardware, SpaceRuntime, SpaceStorage, SpaceVariable
|
|
72
72
|
from ._upload_large_folder import upload_large_folder_internal
|
|
73
73
|
from .community import (
|
|
@@ -132,8 +132,12 @@ from .utils import (
|
|
|
132
132
|
validate_hf_hub_args,
|
|
133
133
|
)
|
|
134
134
|
from .utils import tqdm as hf_tqdm
|
|
135
|
-
from .utils._auth import
|
|
136
|
-
|
|
135
|
+
from .utils._auth import (
|
|
136
|
+
_get_token_from_environment,
|
|
137
|
+
_get_token_from_file,
|
|
138
|
+
_get_token_from_google_colab,
|
|
139
|
+
)
|
|
140
|
+
from .utils._deprecation import _deprecate_arguments, _deprecate_method
|
|
137
141
|
from .utils._runtime import is_xet_available
|
|
138
142
|
from .utils._typing import CallableT
|
|
139
143
|
from .utils.endpoint_helpers import _is_emission_within_threshold
|
|
@@ -1777,18 +1781,20 @@ class HfApi:
|
|
|
1777
1781
|
try:
|
|
1778
1782
|
hf_raise_for_status(r)
|
|
1779
1783
|
except HTTPError as e:
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1784
|
+
if e.response.status_code == 401:
|
|
1785
|
+
error_message = "Invalid user token."
|
|
1786
|
+
# Check which token is the effective one and generate the error message accordingly
|
|
1787
|
+
if effective_token == _get_token_from_google_colab():
|
|
1788
|
+
error_message += " The token from Google Colab vault is invalid. Please update it from the UI."
|
|
1789
|
+
elif effective_token == _get_token_from_environment():
|
|
1790
|
+
error_message += (
|
|
1791
|
+
" The token from HF_TOKEN environment variable is invalid. "
|
|
1792
|
+
"Note that HF_TOKEN takes precedence over `hf auth login`."
|
|
1793
|
+
)
|
|
1794
|
+
elif effective_token == _get_token_from_file():
|
|
1795
|
+
error_message += " The token stored is invalid. Please run `hf auth login` to update it."
|
|
1796
|
+
raise HTTPError(error_message, request=e.request, response=e.response) from e
|
|
1797
|
+
raise
|
|
1792
1798
|
return r.json()
|
|
1793
1799
|
|
|
1794
1800
|
@_deprecate_method(
|
|
@@ -1849,6 +1855,9 @@ class HfApi:
|
|
|
1849
1855
|
hf_raise_for_status(r)
|
|
1850
1856
|
return r.json()
|
|
1851
1857
|
|
|
1858
|
+
@_deprecate_arguments(
|
|
1859
|
+
version="1.0", deprecated_args=["language", "library", "task", "tags"], custom_message="Use `filter` instead."
|
|
1860
|
+
)
|
|
1852
1861
|
@validate_hf_hub_args
|
|
1853
1862
|
def list_models(
|
|
1854
1863
|
self,
|
|
@@ -1856,15 +1865,12 @@ class HfApi:
|
|
|
1856
1865
|
# Search-query parameter
|
|
1857
1866
|
filter: Union[str, Iterable[str], None] = None,
|
|
1858
1867
|
author: Optional[str] = None,
|
|
1868
|
+
apps: Optional[Union[str, List[str]]] = None,
|
|
1859
1869
|
gated: Optional[bool] = None,
|
|
1860
1870
|
inference: Optional[Literal["warm"]] = None,
|
|
1861
1871
|
inference_provider: Optional[Union[Literal["all"], "PROVIDER_T", List["PROVIDER_T"]]] = None,
|
|
1862
|
-
library: Optional[Union[str, List[str]]] = None,
|
|
1863
|
-
language: Optional[Union[str, List[str]]] = None,
|
|
1864
1872
|
model_name: Optional[str] = None,
|
|
1865
|
-
task: Optional[Union[str, List[str]]] = None,
|
|
1866
1873
|
trained_dataset: Optional[Union[str, List[str]]] = None,
|
|
1867
|
-
tags: Optional[Union[str, List[str]]] = None,
|
|
1868
1874
|
search: Optional[str] = None,
|
|
1869
1875
|
pipeline_tag: Optional[str] = None,
|
|
1870
1876
|
emissions_thresholds: Optional[Tuple[float, float]] = None,
|
|
@@ -1878,6 +1884,11 @@ class HfApi:
|
|
|
1878
1884
|
cardData: bool = False,
|
|
1879
1885
|
fetch_config: bool = False,
|
|
1880
1886
|
token: Union[bool, str, None] = None,
|
|
1887
|
+
# Deprecated arguments - use `filter` instead
|
|
1888
|
+
language: Optional[Union[str, List[str]]] = None,
|
|
1889
|
+
library: Optional[Union[str, List[str]]] = None,
|
|
1890
|
+
tags: Optional[Union[str, List[str]]] = None,
|
|
1891
|
+
task: Optional[Union[str, List[str]]] = None,
|
|
1881
1892
|
) -> Iterable[ModelInfo]:
|
|
1882
1893
|
"""
|
|
1883
1894
|
List models hosted on the Huggingface Hub, given some filters.
|
|
@@ -1885,9 +1896,13 @@ class HfApi:
|
|
|
1885
1896
|
Args:
|
|
1886
1897
|
filter (`str` or `Iterable[str]`, *optional*):
|
|
1887
1898
|
A string or list of string to filter models on the Hub.
|
|
1899
|
+
Models can be filtered by library, language, task, tags, and more.
|
|
1888
1900
|
author (`str`, *optional*):
|
|
1889
1901
|
A string which identify the author (user or organization) of the
|
|
1890
1902
|
returned models.
|
|
1903
|
+
apps (`str` or `List`, *optional*):
|
|
1904
|
+
A string or list of strings to filter models on the Hub that
|
|
1905
|
+
support the specified apps. Example values include `"ollama"` or `["ollama", "vllm"]`.
|
|
1891
1906
|
gated (`bool`, *optional*):
|
|
1892
1907
|
A boolean to filter models on the Hub that are gated or not. By default, all models are returned.
|
|
1893
1908
|
If `gated=True` is passed, only gated models are returned.
|
|
@@ -1898,23 +1913,19 @@ class HfApi:
|
|
|
1898
1913
|
A string to filter models on the Hub that are served by a specific provider.
|
|
1899
1914
|
Pass `"all"` to get all models served by at least one provider.
|
|
1900
1915
|
library (`str` or `List`, *optional*):
|
|
1901
|
-
|
|
1902
|
-
originally trained from, such as pytorch, tensorflow, or allennlp.
|
|
1916
|
+
Deprecated. Pass a library name in `filter` to filter models by library.
|
|
1903
1917
|
language (`str` or `List`, *optional*):
|
|
1904
|
-
|
|
1905
|
-
code, such as "en" or "English"
|
|
1918
|
+
Deprecated. Pass a language in `filter` to filter models by language.
|
|
1906
1919
|
model_name (`str`, *optional*):
|
|
1907
1920
|
A string that contain complete or partial names for models on the
|
|
1908
1921
|
Hub, such as "bert" or "bert-base-cased"
|
|
1909
1922
|
task (`str` or `List`, *optional*):
|
|
1910
|
-
|
|
1911
|
-
as: "fill-mask" or "automatic-speech-recognition"
|
|
1923
|
+
Deprecated. Pass a task in `filter` to filter models by task.
|
|
1912
1924
|
trained_dataset (`str` or `List`, *optional*):
|
|
1913
1925
|
A string tag or a list of string tags of the trained dataset for a
|
|
1914
1926
|
model on the Hub.
|
|
1915
1927
|
tags (`str` or `List`, *optional*):
|
|
1916
|
-
|
|
1917
|
-
as `text-generation` or `spacy`.
|
|
1928
|
+
Deprecated. Pass tags in `filter` to filter models by tags.
|
|
1918
1929
|
search (`str`, *optional*):
|
|
1919
1930
|
A string that will be contained in the returned model ids.
|
|
1920
1931
|
pipeline_tag (`str`, *optional*):
|
|
@@ -1985,7 +1996,7 @@ class HfApi:
|
|
|
1985
1996
|
if expand and (full or cardData or fetch_config):
|
|
1986
1997
|
raise ValueError("`expand` cannot be used if `full`, `cardData` or `fetch_config` are passed.")
|
|
1987
1998
|
|
|
1988
|
-
if emissions_thresholds is not None and cardData
|
|
1999
|
+
if emissions_thresholds is not None and not cardData:
|
|
1989
2000
|
raise ValueError("`emissions_thresholds` were passed without setting `cardData=True`.")
|
|
1990
2001
|
|
|
1991
2002
|
path = f"{self.endpoint}/api/models"
|
|
@@ -2017,6 +2028,10 @@ class HfApi:
|
|
|
2017
2028
|
# Handle other query params
|
|
2018
2029
|
if author:
|
|
2019
2030
|
params["author"] = author
|
|
2031
|
+
if apps:
|
|
2032
|
+
if isinstance(apps, str):
|
|
2033
|
+
apps = [apps]
|
|
2034
|
+
params["apps"] = apps
|
|
2020
2035
|
if gated is not None:
|
|
2021
2036
|
params["gated"] = gated
|
|
2022
2037
|
if inference is not None:
|
|
@@ -2068,6 +2083,7 @@ class HfApi:
|
|
|
2068
2083
|
if emissions_thresholds is None or _is_emission_within_threshold(model_info, *emissions_thresholds):
|
|
2069
2084
|
yield model_info
|
|
2070
2085
|
|
|
2086
|
+
@_deprecate_arguments(version="1.0", deprecated_args=["tags"], custom_message="Use `filter` instead.")
|
|
2071
2087
|
@validate_hf_hub_args
|
|
2072
2088
|
def list_datasets(
|
|
2073
2089
|
self,
|
|
@@ -2082,7 +2098,6 @@ class HfApi:
|
|
|
2082
2098
|
language: Optional[Union[str, List[str]]] = None,
|
|
2083
2099
|
multilinguality: Optional[Union[str, List[str]]] = None,
|
|
2084
2100
|
size_categories: Optional[Union[str, List[str]]] = None,
|
|
2085
|
-
tags: Optional[Union[str, List[str]]] = None,
|
|
2086
2101
|
task_categories: Optional[Union[str, List[str]]] = None,
|
|
2087
2102
|
task_ids: Optional[Union[str, List[str]]] = None,
|
|
2088
2103
|
search: Optional[str] = None,
|
|
@@ -2094,6 +2109,8 @@ class HfApi:
|
|
|
2094
2109
|
expand: Optional[List[ExpandDatasetProperty_T]] = None,
|
|
2095
2110
|
full: Optional[bool] = None,
|
|
2096
2111
|
token: Union[bool, str, None] = None,
|
|
2112
|
+
# Deprecated arguments - use `filter` instead
|
|
2113
|
+
tags: Optional[Union[str, List[str]]] = None,
|
|
2097
2114
|
) -> Iterable[DatasetInfo]:
|
|
2098
2115
|
"""
|
|
2099
2116
|
List datasets hosted on the Huggingface Hub, given some filters.
|
|
@@ -2128,7 +2145,7 @@ class HfApi:
|
|
|
2128
2145
|
the Hub by the size of the dataset such as `100K<n<1M` or
|
|
2129
2146
|
`1M<n<10M`.
|
|
2130
2147
|
tags (`str` or `List`, *optional*):
|
|
2131
|
-
|
|
2148
|
+
Deprecated. Pass tags in `filter` to filter datasets by tags.
|
|
2132
2149
|
task_categories (`str` or `List`, *optional*):
|
|
2133
2150
|
A string or list of strings that can be used to identify datasets on
|
|
2134
2151
|
the Hub by the designed task, such as `audio_classification` or
|
|
@@ -5315,14 +5332,18 @@ class HfApi:
|
|
|
5315
5332
|
1. (Check parameters and setup.)
|
|
5316
5333
|
2. Create repo if missing.
|
|
5317
5334
|
3. List local files to upload.
|
|
5318
|
-
4.
|
|
5335
|
+
4. Run validation checks and display warnings if repository limits might be exceeded:
|
|
5336
|
+
- Warns if the total number of files exceeds 100k (recommended limit).
|
|
5337
|
+
- Warns if any folder contains more than 10k files (recommended limit).
|
|
5338
|
+
- Warns about files larger than 20GB (recommended) or 50GB (hard limit).
|
|
5339
|
+
5. Start workers. Workers can perform the following tasks:
|
|
5319
5340
|
- Hash a file.
|
|
5320
5341
|
- Get upload mode (regular or LFS) for a list of files.
|
|
5321
5342
|
- Pre-upload an LFS file.
|
|
5322
5343
|
- Commit a bunch of files.
|
|
5323
5344
|
Once a worker finishes a task, it will move on to the next task based on the priority list (see below) until
|
|
5324
5345
|
all files are uploaded and committed.
|
|
5325
|
-
|
|
5346
|
+
6. While workers are up, regularly print a report to sys.stdout.
|
|
5326
5347
|
|
|
5327
5348
|
Order of priority:
|
|
5328
5349
|
1. Commit if more than 5 minutes since last commit attempt (and at least 1 file).
|
|
@@ -9994,7 +10015,7 @@ class HfApi:
|
|
|
9994
10015
|
|
|
9995
10016
|
```python
|
|
9996
10017
|
>>> from huggingface_hub import run_job
|
|
9997
|
-
>>> run_job("python:3.12", ["python", "-c" ,"print('Hello from HF compute!')"])
|
|
10018
|
+
>>> run_job(image="python:3.12", command=["python", "-c" ,"print('Hello from HF compute!')"])
|
|
9998
10019
|
```
|
|
9999
10020
|
|
|
10000
10021
|
Run a GPU Job:
|
|
@@ -10003,47 +10024,23 @@ class HfApi:
|
|
|
10003
10024
|
>>> from huggingface_hub import run_job
|
|
10004
10025
|
>>> image = "pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel"
|
|
10005
10026
|
>>> command = ["python", "-c", "import torch; print(f"This code ran with the following GPU: {torch.cuda.get_device_name()}")"]
|
|
10006
|
-
>>> run_job(image, command, flavor="a10g-small")
|
|
10027
|
+
>>> run_job(image=image, command=command, flavor="a10g-small")
|
|
10007
10028
|
```
|
|
10008
10029
|
|
|
10009
10030
|
"""
|
|
10010
|
-
if flavor is None:
|
|
10011
|
-
flavor = SpaceHardware.CPU_BASIC
|
|
10012
|
-
|
|
10013
|
-
# prepare payload to send to HF Jobs API
|
|
10014
|
-
input_json: Dict[str, Any] = {
|
|
10015
|
-
"command": command,
|
|
10016
|
-
"arguments": [],
|
|
10017
|
-
"environment": env or {},
|
|
10018
|
-
"flavor": flavor,
|
|
10019
|
-
}
|
|
10020
|
-
# secrets are optional
|
|
10021
|
-
if secrets:
|
|
10022
|
-
input_json["secrets"] = secrets
|
|
10023
|
-
# timeout is optional
|
|
10024
|
-
if timeout:
|
|
10025
|
-
time_units_factors = {"s": 1, "m": 60, "h": 3600, "d": 3600 * 24}
|
|
10026
|
-
if isinstance(timeout, str) and timeout[-1] in time_units_factors:
|
|
10027
|
-
input_json["timeoutSeconds"] = int(float(timeout[:-1]) * time_units_factors[timeout[-1]])
|
|
10028
|
-
else:
|
|
10029
|
-
input_json["timeoutSeconds"] = int(timeout)
|
|
10030
|
-
# input is either from docker hub or from HF spaces
|
|
10031
|
-
for prefix in (
|
|
10032
|
-
"https://huggingface.co/spaces/",
|
|
10033
|
-
"https://hf.co/spaces/",
|
|
10034
|
-
"huggingface.co/spaces/",
|
|
10035
|
-
"hf.co/spaces/",
|
|
10036
|
-
):
|
|
10037
|
-
if image.startswith(prefix):
|
|
10038
|
-
input_json["spaceId"] = image[len(prefix) :]
|
|
10039
|
-
break
|
|
10040
|
-
else:
|
|
10041
|
-
input_json["dockerImage"] = image
|
|
10042
10031
|
if namespace is None:
|
|
10043
10032
|
namespace = self.whoami(token=token)["name"]
|
|
10033
|
+
job_spec = _create_job_spec(
|
|
10034
|
+
image=image,
|
|
10035
|
+
command=command,
|
|
10036
|
+
env=env,
|
|
10037
|
+
secrets=secrets,
|
|
10038
|
+
flavor=flavor,
|
|
10039
|
+
timeout=timeout,
|
|
10040
|
+
)
|
|
10044
10041
|
response = get_session().post(
|
|
10045
10042
|
f"https://huggingface.co/api/jobs/{namespace}",
|
|
10046
|
-
json=
|
|
10043
|
+
json=job_spec,
|
|
10047
10044
|
headers=self._build_hf_headers(token=token),
|
|
10048
10045
|
)
|
|
10049
10046
|
hf_raise_for_status(response)
|
|
@@ -10076,8 +10073,8 @@ class HfApi:
|
|
|
10076
10073
|
|
|
10077
10074
|
```python
|
|
10078
10075
|
>>> from huggingface_hub import fetch_job_logs, run_job
|
|
10079
|
-
>>> job = run_job("python:3.12", ["python", "-c" ,"print('Hello from HF compute!')"])
|
|
10080
|
-
>>> for log in fetch_job_logs(job.
|
|
10076
|
+
>>> job = run_job(image="python:3.12", command=["python", "-c" ,"print('Hello from HF compute!')"])
|
|
10077
|
+
>>> for log in fetch_job_logs(job.id):
|
|
10081
10078
|
... print(log)
|
|
10082
10079
|
Hello from HF compute!
|
|
10083
10080
|
```
|
|
@@ -10200,8 +10197,8 @@ class HfApi:
|
|
|
10200
10197
|
|
|
10201
10198
|
```python
|
|
10202
10199
|
>>> from huggingface_hub import inspect_job, run_job
|
|
10203
|
-
>>> job = run_job("python:3.12", ["python", "-c" ,"print('Hello from HF compute!')"])
|
|
10204
|
-
>>> inspect_job(job.
|
|
10200
|
+
>>> job = run_job(image="python:3.12", command=["python", "-c" ,"print('Hello from HF compute!')"])
|
|
10201
|
+
>>> inspect_job(job.id)
|
|
10205
10202
|
JobInfo(
|
|
10206
10203
|
id='68780d00bbe36d38803f645f',
|
|
10207
10204
|
created_at=datetime.datetime(2025, 7, 16, 20, 35, 12, 808000, tzinfo=datetime.timezone.utc),
|
|
@@ -10276,10 +10273,10 @@ class HfApi:
|
|
|
10276
10273
|
|
|
10277
10274
|
Args:
|
|
10278
10275
|
script (`str`):
|
|
10279
|
-
Path or URL of the UV script.
|
|
10276
|
+
Path or URL of the UV script, or a command.
|
|
10280
10277
|
|
|
10281
10278
|
script_args (`List[str]`, *optional*)
|
|
10282
|
-
Arguments to pass to the script.
|
|
10279
|
+
Arguments to pass to the script or command.
|
|
10283
10280
|
|
|
10284
10281
|
dependencies (`List[str]`, *optional*)
|
|
10285
10282
|
Dependencies to use to run the UV script.
|
|
@@ -10287,7 +10284,7 @@ class HfApi:
|
|
|
10287
10284
|
python (`str`, *optional*)
|
|
10288
10285
|
Use a specific Python version. Default is 3.12.
|
|
10289
10286
|
|
|
10290
|
-
image (`str`, *optional*, defaults to "ghcr.io/astral-sh/uv:python3.12-bookworm
|
|
10287
|
+
image (`str`, *optional*, defaults to "ghcr.io/astral-sh/uv:python3.12-bookworm"):
|
|
10291
10288
|
Use a custom Docker image with `uv` installed.
|
|
10292
10289
|
|
|
10293
10290
|
env (`Dict[str, Any]`, *optional*):
|
|
@@ -10314,13 +10311,474 @@ class HfApi:
|
|
|
10314
10311
|
|
|
10315
10312
|
Example:
|
|
10316
10313
|
|
|
10314
|
+
Run a script from a URL:
|
|
10315
|
+
|
|
10317
10316
|
```python
|
|
10318
10317
|
>>> from huggingface_hub import run_uv_job
|
|
10319
10318
|
>>> script = "https://raw.githubusercontent.com/huggingface/trl/refs/heads/main/trl/scripts/sft.py"
|
|
10320
|
-
>>>
|
|
10319
|
+
>>> script_args = ["--model_name_or_path", "Qwen/Qwen2-0.5B", "--dataset_name", "trl-lib/Capybara", "--push_to_hub"]
|
|
10320
|
+
>>> run_uv_job(script, script_args=script_args, dependencies=["trl"], flavor="a10g-small")
|
|
10321
|
+
```
|
|
10322
|
+
|
|
10323
|
+
Run a local script:
|
|
10324
|
+
|
|
10325
|
+
```python
|
|
10326
|
+
>>> from huggingface_hub import run_uv_job
|
|
10327
|
+
>>> script = "my_sft.py"
|
|
10328
|
+
>>> script_args = ["--model_name_or_path", "Qwen/Qwen2-0.5B", "--dataset_name", "trl-lib/Capybara", "--push_to_hub"]
|
|
10329
|
+
>>> run_uv_job(script, script_args=script_args, dependencies=["trl"], flavor="a10g-small")
|
|
10330
|
+
```
|
|
10331
|
+
|
|
10332
|
+
Run a command:
|
|
10333
|
+
|
|
10334
|
+
```python
|
|
10335
|
+
>>> from huggingface_hub import run_uv_job
|
|
10336
|
+
>>> script = "lighteval"
|
|
10337
|
+
>>> script_args= ["endpoint", "inference-providers", "model_name=openai/gpt-oss-20b,provider=auto", "lighteval|gsm8k|0|0"]
|
|
10338
|
+
>>> run_uv_job(script, script_args=script_args, dependencies=["lighteval"], flavor="a10g-small")
|
|
10339
|
+
```
|
|
10340
|
+
"""
|
|
10341
|
+
image = image or "ghcr.io/astral-sh/uv:python3.12-bookworm"
|
|
10342
|
+
env = env or {}
|
|
10343
|
+
secrets = secrets or {}
|
|
10344
|
+
|
|
10345
|
+
# Build command
|
|
10346
|
+
command, env, secrets = self._create_uv_command_env_and_secrets(
|
|
10347
|
+
script=script,
|
|
10348
|
+
script_args=script_args,
|
|
10349
|
+
dependencies=dependencies,
|
|
10350
|
+
python=python,
|
|
10351
|
+
env=env,
|
|
10352
|
+
secrets=secrets,
|
|
10353
|
+
namespace=namespace,
|
|
10354
|
+
token=token,
|
|
10355
|
+
_repo=_repo,
|
|
10356
|
+
)
|
|
10357
|
+
# Create RunCommand args
|
|
10358
|
+
return self.run_job(
|
|
10359
|
+
image=image,
|
|
10360
|
+
command=command,
|
|
10361
|
+
env=env,
|
|
10362
|
+
secrets=secrets,
|
|
10363
|
+
flavor=flavor,
|
|
10364
|
+
timeout=timeout,
|
|
10365
|
+
namespace=namespace,
|
|
10366
|
+
token=token,
|
|
10367
|
+
)
|
|
10368
|
+
|
|
10369
|
+
def create_scheduled_job(
|
|
10370
|
+
self,
|
|
10371
|
+
*,
|
|
10372
|
+
image: str,
|
|
10373
|
+
command: List[str],
|
|
10374
|
+
schedule: str,
|
|
10375
|
+
suspend: Optional[bool] = None,
|
|
10376
|
+
concurrency: Optional[bool] = None,
|
|
10377
|
+
env: Optional[Dict[str, Any]] = None,
|
|
10378
|
+
secrets: Optional[Dict[str, Any]] = None,
|
|
10379
|
+
flavor: Optional[SpaceHardware] = None,
|
|
10380
|
+
timeout: Optional[Union[int, float, str]] = None,
|
|
10381
|
+
namespace: Optional[str] = None,
|
|
10382
|
+
token: Union[bool, str, None] = None,
|
|
10383
|
+
) -> ScheduledJobInfo:
|
|
10384
|
+
"""
|
|
10385
|
+
Create scheduled compute Jobs on Hugging Face infrastructure.
|
|
10386
|
+
|
|
10387
|
+
Args:
|
|
10388
|
+
image (`str`):
|
|
10389
|
+
The Docker image to use.
|
|
10390
|
+
Examples: `"ubuntu"`, `"python:3.12"`, `"pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel"`.
|
|
10391
|
+
Example with an image from a Space: `"hf.co/spaces/lhoestq/duckdb"`.
|
|
10392
|
+
|
|
10393
|
+
command (`List[str]`):
|
|
10394
|
+
The command to run. Example: `["echo", "hello"]`.
|
|
10395
|
+
|
|
10396
|
+
schedule (`str`):
|
|
10397
|
+
One of "@annually", "@yearly", "@monthly", "@weekly", "@daily", "@hourly", or a
|
|
10398
|
+
CRON schedule expression (e.g., '0 9 * * 1' for 9 AM every Monday).
|
|
10399
|
+
|
|
10400
|
+
suspend (`bool`, *optional*):
|
|
10401
|
+
If True, the scheduled Job is suspended (paused). Defaults to False.
|
|
10402
|
+
|
|
10403
|
+
concurrency (`bool`, *optional*):
|
|
10404
|
+
If True, multiple instances of this Job can run concurrently. Defaults to False.
|
|
10405
|
+
|
|
10406
|
+
env (`Dict[str, Any]`, *optional*):
|
|
10407
|
+
Defines the environment variables for the Job.
|
|
10408
|
+
|
|
10409
|
+
secrets (`Dict[str, Any]`, *optional*):
|
|
10410
|
+
Defines the secret environment variables for the Job.
|
|
10411
|
+
|
|
10412
|
+
flavor (`str`, *optional*):
|
|
10413
|
+
Flavor for the hardware, as in Hugging Face Spaces. See [`SpaceHardware`] for possible values.
|
|
10414
|
+
Defaults to `"cpu-basic"`.
|
|
10415
|
+
|
|
10416
|
+
timeout (`Union[int, float, str]`, *optional*):
|
|
10417
|
+
Max duration for the Job: int/float with s (seconds, default), m (minutes), h (hours) or d (days).
|
|
10418
|
+
Example: `300` or `"5m"` for 5 minutes.
|
|
10419
|
+
|
|
10420
|
+
namespace (`str`, *optional*):
|
|
10421
|
+
The namespace where the Job will be created. Defaults to the current user's namespace.
|
|
10422
|
+
|
|
10423
|
+
token `(Union[bool, str, None]`, *optional*):
|
|
10424
|
+
A valid user access token. If not provided, the locally saved token will be used, which is the
|
|
10425
|
+
recommended authentication method. Set to `False` to disable authentication.
|
|
10426
|
+
Refer to: https://huggingface.co/docs/huggingface_hub/quick-start#authentication.
|
|
10427
|
+
|
|
10428
|
+
Example:
|
|
10429
|
+
Create your first scheduled Job:
|
|
10430
|
+
|
|
10431
|
+
```python
|
|
10432
|
+
>>> from huggingface_hub import create_scheduled_job
|
|
10433
|
+
>>> create_scheduled_job(image="python:3.12", command=["python", "-c" ,"print('Hello from HF compute!')"], schedule="@hourly")
|
|
10434
|
+
```
|
|
10435
|
+
|
|
10436
|
+
Use a CRON schedule expression:
|
|
10437
|
+
|
|
10438
|
+
```python
|
|
10439
|
+
>>> from huggingface_hub import create_scheduled_job
|
|
10440
|
+
>>> create_scheduled_job(image="python:3.12", command=["python", "-c" ,"print('this runs every 5min')"], schedule="*/5 * * * *")
|
|
10441
|
+
```
|
|
10442
|
+
|
|
10443
|
+
Create a scheduled GPU Job:
|
|
10444
|
+
|
|
10445
|
+
```python
|
|
10446
|
+
>>> from huggingface_hub import create_scheduled_job
|
|
10447
|
+
>>> image = "pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel"
|
|
10448
|
+
>>> command = ["python", "-c", "import torch; print(f"This code ran with the following GPU: {torch.cuda.get_device_name()}")"]
|
|
10449
|
+
>>> create_scheduled_job(image, command, flavor="a10g-small", schedule="@hourly")
|
|
10450
|
+
```
|
|
10451
|
+
|
|
10452
|
+
"""
|
|
10453
|
+
if namespace is None:
|
|
10454
|
+
namespace = self.whoami(token=token)["name"]
|
|
10455
|
+
|
|
10456
|
+
# prepare payload to send to HF Jobs API
|
|
10457
|
+
job_spec = _create_job_spec(
|
|
10458
|
+
image=image,
|
|
10459
|
+
command=command,
|
|
10460
|
+
env=env,
|
|
10461
|
+
secrets=secrets,
|
|
10462
|
+
flavor=flavor,
|
|
10463
|
+
timeout=timeout,
|
|
10464
|
+
)
|
|
10465
|
+
input_json: Dict[str, Any] = {
|
|
10466
|
+
"jobSpec": job_spec,
|
|
10467
|
+
"schedule": schedule,
|
|
10468
|
+
}
|
|
10469
|
+
if concurrency is not None:
|
|
10470
|
+
input_json["concurrency"] = concurrency
|
|
10471
|
+
if suspend is not None:
|
|
10472
|
+
input_json["suspend"] = suspend
|
|
10473
|
+
response = get_session().post(
|
|
10474
|
+
f"https://huggingface.co/api/scheduled-jobs/{namespace}",
|
|
10475
|
+
json=input_json,
|
|
10476
|
+
headers=self._build_hf_headers(token=token),
|
|
10477
|
+
)
|
|
10478
|
+
hf_raise_for_status(response)
|
|
10479
|
+
scheduled_job_info = response.json()
|
|
10480
|
+
return ScheduledJobInfo(**scheduled_job_info)
|
|
10481
|
+
|
|
10482
|
+
def list_scheduled_jobs(
|
|
10483
|
+
self,
|
|
10484
|
+
*,
|
|
10485
|
+
timeout: Optional[int] = None,
|
|
10486
|
+
namespace: Optional[str] = None,
|
|
10487
|
+
token: Union[bool, str, None] = None,
|
|
10488
|
+
) -> List[ScheduledJobInfo]:
|
|
10489
|
+
"""
|
|
10490
|
+
List scheduled compute Jobs on Hugging Face infrastructure.
|
|
10491
|
+
|
|
10492
|
+
Args:
|
|
10493
|
+
timeout (`float`, *optional*):
|
|
10494
|
+
Whether to set a timeout for the request to the Hub.
|
|
10495
|
+
|
|
10496
|
+
namespace (`str`, *optional*):
|
|
10497
|
+
The namespace from where it lists the jobs. Defaults to the current user's namespace.
|
|
10498
|
+
|
|
10499
|
+
token `(Union[bool, str, None]`, *optional*):
|
|
10500
|
+
A valid user access token. If not provided, the locally saved token will be used, which is the
|
|
10501
|
+
recommended authentication method. Set to `False` to disable authentication.
|
|
10502
|
+
Refer to: https://huggingface.co/docs/huggingface_hub/quick-start#authentication.
|
|
10503
|
+
"""
|
|
10504
|
+
if namespace is None:
|
|
10505
|
+
namespace = self.whoami(token=token)["name"]
|
|
10506
|
+
response = get_session().get(
|
|
10507
|
+
f"{self.endpoint}/api/scheduled-jobs/{namespace}",
|
|
10508
|
+
headers=self._build_hf_headers(token=token),
|
|
10509
|
+
timeout=timeout,
|
|
10510
|
+
)
|
|
10511
|
+
hf_raise_for_status(response)
|
|
10512
|
+
return [ScheduledJobInfo(**scheduled_job_info) for scheduled_job_info in response.json()]
|
|
10513
|
+
|
|
10514
|
+
def inspect_scheduled_job(
|
|
10515
|
+
self,
|
|
10516
|
+
*,
|
|
10517
|
+
scheduled_job_id: str,
|
|
10518
|
+
namespace: Optional[str] = None,
|
|
10519
|
+
token: Union[bool, str, None] = None,
|
|
10520
|
+
) -> ScheduledJobInfo:
|
|
10521
|
+
"""
|
|
10522
|
+
Inspect a scheduled compute Job on Hugging Face infrastructure.
|
|
10523
|
+
|
|
10524
|
+
Args:
|
|
10525
|
+
scheduled_job_id (`str`):
|
|
10526
|
+
ID of the scheduled Job.
|
|
10527
|
+
|
|
10528
|
+
namespace (`str`, *optional*):
|
|
10529
|
+
The namespace where the scheduled Job is. Defaults to the current user's namespace.
|
|
10530
|
+
|
|
10531
|
+
token `(Union[bool, str, None]`, *optional*):
|
|
10532
|
+
A valid user access token. If not provided, the locally saved token will be used, which is the
|
|
10533
|
+
recommended authentication method. Set to `False` to disable authentication.
|
|
10534
|
+
Refer to: https://huggingface.co/docs/huggingface_hub/quick-start#authentication.
|
|
10535
|
+
|
|
10536
|
+
Example:
|
|
10537
|
+
|
|
10538
|
+
```python
|
|
10539
|
+
>>> from huggingface_hub import inspect_job, create_scheduled_job
|
|
10540
|
+
>>> scheduled_job = create_scheduled_job(image="python:3.12", command=["python", "-c" ,"print('Hello from HF compute!')"], schedule="@hourly")
|
|
10541
|
+
>>> inspect_scheduled_job(scheduled_job.id)
|
|
10542
|
+
```
|
|
10543
|
+
"""
|
|
10544
|
+
if namespace is None:
|
|
10545
|
+
namespace = self.whoami(token=token)["name"]
|
|
10546
|
+
response = get_session().get(
|
|
10547
|
+
f"{self.endpoint}/api/scheduled-jobs/{namespace}/{scheduled_job_id}",
|
|
10548
|
+
headers=self._build_hf_headers(token=token),
|
|
10549
|
+
)
|
|
10550
|
+
hf_raise_for_status(response)
|
|
10551
|
+
return ScheduledJobInfo(**response.json())
|
|
10552
|
+
|
|
10553
|
+
def delete_scheduled_job(
|
|
10554
|
+
self,
|
|
10555
|
+
*,
|
|
10556
|
+
scheduled_job_id: str,
|
|
10557
|
+
namespace: Optional[str] = None,
|
|
10558
|
+
token: Union[bool, str, None] = None,
|
|
10559
|
+
) -> None:
|
|
10560
|
+
"""
|
|
10561
|
+
Delete a scheduled compute Job on Hugging Face infrastructure.
|
|
10562
|
+
|
|
10563
|
+
Args:
|
|
10564
|
+
scheduled_job_id (`str`):
|
|
10565
|
+
ID of the scheduled Job.
|
|
10566
|
+
|
|
10567
|
+
namespace (`str`, *optional*):
|
|
10568
|
+
The namespace where the scheduled Job is. Defaults to the current user's namespace.
|
|
10569
|
+
|
|
10570
|
+
token `(Union[bool, str, None]`, *optional*):
|
|
10571
|
+
A valid user access token. If not provided, the locally saved token will be used, which is the
|
|
10572
|
+
recommended authentication method. Set to `False` to disable authentication.
|
|
10573
|
+
Refer to: https://huggingface.co/docs/huggingface_hub/quick-start#authentication.
|
|
10574
|
+
"""
|
|
10575
|
+
if namespace is None:
|
|
10576
|
+
namespace = self.whoami(token=token)["name"]
|
|
10577
|
+
response = get_session().delete(
|
|
10578
|
+
f"{self.endpoint}/api/scheduled-jobs/{namespace}/{scheduled_job_id}",
|
|
10579
|
+
headers=self._build_hf_headers(token=token),
|
|
10580
|
+
)
|
|
10581
|
+
hf_raise_for_status(response)
|
|
10582
|
+
|
|
10583
|
+
def suspend_scheduled_job(
|
|
10584
|
+
self,
|
|
10585
|
+
*,
|
|
10586
|
+
scheduled_job_id: str,
|
|
10587
|
+
namespace: Optional[str] = None,
|
|
10588
|
+
token: Union[bool, str, None] = None,
|
|
10589
|
+
) -> None:
|
|
10590
|
+
"""
|
|
10591
|
+
Suspend (pause) a scheduled compute Job on Hugging Face infrastructure.
|
|
10592
|
+
|
|
10593
|
+
Args:
|
|
10594
|
+
scheduled_job_id (`str`):
|
|
10595
|
+
ID of the scheduled Job.
|
|
10596
|
+
|
|
10597
|
+
namespace (`str`, *optional*):
|
|
10598
|
+
The namespace where the scheduled Job is. Defaults to the current user's namespace.
|
|
10599
|
+
|
|
10600
|
+
token `(Union[bool, str, None]`, *optional*):
|
|
10601
|
+
A valid user access token. If not provided, the locally saved token will be used, which is the
|
|
10602
|
+
recommended authentication method. Set to `False` to disable authentication.
|
|
10603
|
+
Refer to: https://huggingface.co/docs/huggingface_hub/quick-start#authentication.
|
|
10604
|
+
"""
|
|
10605
|
+
if namespace is None:
|
|
10606
|
+
namespace = self.whoami(token=token)["name"]
|
|
10607
|
+
get_session().post(
|
|
10608
|
+
f"{self.endpoint}/api/scheduled-jobs/{namespace}/{scheduled_job_id}/suspend",
|
|
10609
|
+
headers=self._build_hf_headers(token=token),
|
|
10610
|
+
).raise_for_status()
|
|
10611
|
+
|
|
10612
|
+
def resume_scheduled_job(
|
|
10613
|
+
self,
|
|
10614
|
+
*,
|
|
10615
|
+
scheduled_job_id: str,
|
|
10616
|
+
namespace: Optional[str] = None,
|
|
10617
|
+
token: Union[bool, str, None] = None,
|
|
10618
|
+
) -> None:
|
|
10619
|
+
"""
|
|
10620
|
+
Resume (unpause) a scheduled compute Job on Hugging Face infrastructure.
|
|
10621
|
+
|
|
10622
|
+
Args:
|
|
10623
|
+
scheduled_job_id (`str`):
|
|
10624
|
+
ID of the scheduled Job.
|
|
10625
|
+
|
|
10626
|
+
namespace (`str`, *optional*):
|
|
10627
|
+
The namespace where the scheduled Job is. Defaults to the current user's namespace.
|
|
10628
|
+
|
|
10629
|
+
token `(Union[bool, str, None]`, *optional*):
|
|
10630
|
+
A valid user access token. If not provided, the locally saved token will be used, which is the
|
|
10631
|
+
recommended authentication method. Set to `False` to disable authentication.
|
|
10632
|
+
Refer to: https://huggingface.co/docs/huggingface_hub/quick-start#authentication.
|
|
10633
|
+
"""
|
|
10634
|
+
if namespace is None:
|
|
10635
|
+
namespace = self.whoami(token=token)["name"]
|
|
10636
|
+
get_session().post(
|
|
10637
|
+
f"{self.endpoint}/api/scheduled-jobs/{namespace}/{scheduled_job_id}/resume",
|
|
10638
|
+
headers=self._build_hf_headers(token=token),
|
|
10639
|
+
).raise_for_status()
|
|
10640
|
+
|
|
10641
|
+
@experimental
|
|
10642
|
+
def create_scheduled_uv_job(
|
|
10643
|
+
self,
|
|
10644
|
+
script: str,
|
|
10645
|
+
*,
|
|
10646
|
+
script_args: Optional[List[str]] = None,
|
|
10647
|
+
schedule: str,
|
|
10648
|
+
suspend: Optional[bool] = None,
|
|
10649
|
+
concurrency: Optional[bool] = None,
|
|
10650
|
+
dependencies: Optional[List[str]] = None,
|
|
10651
|
+
python: Optional[str] = None,
|
|
10652
|
+
image: Optional[str] = None,
|
|
10653
|
+
env: Optional[Dict[str, Any]] = None,
|
|
10654
|
+
secrets: Optional[Dict[str, Any]] = None,
|
|
10655
|
+
flavor: Optional[SpaceHardware] = None,
|
|
10656
|
+
timeout: Optional[Union[int, float, str]] = None,
|
|
10657
|
+
namespace: Optional[str] = None,
|
|
10658
|
+
token: Union[bool, str, None] = None,
|
|
10659
|
+
_repo: Optional[str] = None,
|
|
10660
|
+
) -> ScheduledJobInfo:
|
|
10661
|
+
"""
|
|
10662
|
+
Run a UV script Job on Hugging Face infrastructure.
|
|
10663
|
+
|
|
10664
|
+
Args:
|
|
10665
|
+
script (`str`):
|
|
10666
|
+
Path or URL of the UV script, or a command.
|
|
10667
|
+
|
|
10668
|
+
script_args (`List[str]`, *optional*)
|
|
10669
|
+
Arguments to pass to the script, or a command.
|
|
10670
|
+
|
|
10671
|
+
schedule (`str`):
|
|
10672
|
+
One of "@annually", "@yearly", "@monthly", "@weekly", "@daily", "@hourly", or a
|
|
10673
|
+
CRON schedule expression (e.g., '0 9 * * 1' for 9 AM every Monday).
|
|
10674
|
+
|
|
10675
|
+
suspend (`bool`, *optional*):
|
|
10676
|
+
If True, the scheduled Job is suspended (paused). Defaults to False.
|
|
10677
|
+
|
|
10678
|
+
concurrency (`bool`, *optional*):
|
|
10679
|
+
If True, multiple instances of this Job can run concurrently. Defaults to False.
|
|
10680
|
+
|
|
10681
|
+
dependencies (`List[str]`, *optional*)
|
|
10682
|
+
Dependencies to use to run the UV script.
|
|
10683
|
+
|
|
10684
|
+
python (`str`, *optional*)
|
|
10685
|
+
Use a specific Python version. Default is 3.12.
|
|
10686
|
+
|
|
10687
|
+
image (`str`, *optional*, defaults to "ghcr.io/astral-sh/uv:python3.12-bookworm"):
|
|
10688
|
+
Use a custom Docker image with `uv` installed.
|
|
10689
|
+
|
|
10690
|
+
env (`Dict[str, Any]`, *optional*):
|
|
10691
|
+
Defines the environment variables for the Job.
|
|
10692
|
+
|
|
10693
|
+
secrets (`Dict[str, Any]`, *optional*):
|
|
10694
|
+
Defines the secret environment variables for the Job.
|
|
10695
|
+
|
|
10696
|
+
flavor (`str`, *optional*):
|
|
10697
|
+
Flavor for the hardware, as in Hugging Face Spaces. See [`SpaceHardware`] for possible values.
|
|
10698
|
+
Defaults to `"cpu-basic"`.
|
|
10699
|
+
|
|
10700
|
+
timeout (`Union[int, float, str]`, *optional*):
|
|
10701
|
+
Max duration for the Job: int/float with s (seconds, default), m (minutes), h (hours) or d (days).
|
|
10702
|
+
Example: `300` or `"5m"` for 5 minutes.
|
|
10703
|
+
|
|
10704
|
+
namespace (`str`, *optional*):
|
|
10705
|
+
The namespace where the Job will be created. Defaults to the current user's namespace.
|
|
10706
|
+
|
|
10707
|
+
token `(Union[bool, str, None]`, *optional*):
|
|
10708
|
+
A valid user access token. If not provided, the locally saved token will be used, which is the
|
|
10709
|
+
recommended authentication method. Set to `False` to disable authentication.
|
|
10710
|
+
Refer to: https://huggingface.co/docs/huggingface_hub/quick-start#authentication.
|
|
10711
|
+
|
|
10712
|
+
Example:
|
|
10713
|
+
|
|
10714
|
+
Schedule a script from a URL:
|
|
10715
|
+
|
|
10716
|
+
```python
|
|
10717
|
+
>>> from huggingface_hub import create_scheduled_uv_job
|
|
10718
|
+
>>> script = "https://raw.githubusercontent.com/huggingface/trl/refs/heads/main/trl/scripts/sft.py"
|
|
10719
|
+
>>> script_args = ["--model_name_or_path", "Qwen/Qwen2-0.5B", "--dataset_name", "trl-lib/Capybara", "--push_to_hub"]
|
|
10720
|
+
>>> create_scheduled_uv_job(script, script_args=script_args, dependencies=["trl"], flavor="a10g-small", schedule="@weekly")
|
|
10721
|
+
```
|
|
10722
|
+
|
|
10723
|
+
Schedule a local script:
|
|
10724
|
+
|
|
10725
|
+
```python
|
|
10726
|
+
>>> from huggingface_hub import create_scheduled_uv_job
|
|
10727
|
+
>>> script = "my_sft.py"
|
|
10728
|
+
>>> script_args = ["--model_name_or_path", "Qwen/Qwen2-0.5B", "--dataset_name", "trl-lib/Capybara", "--push_to_hub"]
|
|
10729
|
+
>>> create_scheduled_uv_job(script, script_args=script_args, dependencies=["trl"], flavor="a10g-small", schedule="@weekly")
|
|
10730
|
+
```
|
|
10731
|
+
|
|
10732
|
+
Schedule a command:
|
|
10733
|
+
|
|
10734
|
+
```python
|
|
10735
|
+
>>> from huggingface_hub import create_scheduled_uv_job
|
|
10736
|
+
>>> script = "lighteval"
|
|
10737
|
+
>>> script_args= ["endpoint", "inference-providers", "model_name=openai/gpt-oss-20b,provider=auto", "lighteval|gsm8k|0|0"]
|
|
10738
|
+
>>> create_scheduled_uv_job(script, script_args=script_args, dependencies=["lighteval"], flavor="a10g-small", schedule="@weekly")
|
|
10321
10739
|
```
|
|
10322
10740
|
"""
|
|
10323
|
-
image = image or "ghcr.io/astral-sh/uv:python3.12-bookworm
|
|
10741
|
+
image = image or "ghcr.io/astral-sh/uv:python3.12-bookworm"
|
|
10742
|
+
# Build command
|
|
10743
|
+
command, env, secrets = self._create_uv_command_env_and_secrets(
|
|
10744
|
+
script=script,
|
|
10745
|
+
script_args=script_args,
|
|
10746
|
+
dependencies=dependencies,
|
|
10747
|
+
python=python,
|
|
10748
|
+
env=env,
|
|
10749
|
+
secrets=secrets,
|
|
10750
|
+
namespace=namespace,
|
|
10751
|
+
token=token,
|
|
10752
|
+
_repo=_repo,
|
|
10753
|
+
)
|
|
10754
|
+
# Create RunCommand args
|
|
10755
|
+
return self.create_scheduled_job(
|
|
10756
|
+
image=image,
|
|
10757
|
+
command=command,
|
|
10758
|
+
schedule=schedule,
|
|
10759
|
+
suspend=suspend,
|
|
10760
|
+
concurrency=concurrency,
|
|
10761
|
+
env=env,
|
|
10762
|
+
secrets=secrets,
|
|
10763
|
+
flavor=flavor,
|
|
10764
|
+
timeout=timeout,
|
|
10765
|
+
namespace=namespace,
|
|
10766
|
+
token=token,
|
|
10767
|
+
)
|
|
10768
|
+
|
|
10769
|
+
def _create_uv_command_env_and_secrets(
|
|
10770
|
+
self,
|
|
10771
|
+
*,
|
|
10772
|
+
script: str,
|
|
10773
|
+
script_args: Optional[List[str]],
|
|
10774
|
+
dependencies: Optional[List[str]],
|
|
10775
|
+
python: Optional[str],
|
|
10776
|
+
env: Optional[Dict[str, Any]],
|
|
10777
|
+
secrets: Optional[Dict[str, Any]],
|
|
10778
|
+
namespace: Optional[str],
|
|
10779
|
+
token: Union[bool, str, None],
|
|
10780
|
+
_repo: Optional[str],
|
|
10781
|
+
) -> Tuple[List[str], Dict[str, Any], Dict[str, Any]]:
|
|
10324
10782
|
env = env or {}
|
|
10325
10783
|
secrets = secrets or {}
|
|
10326
10784
|
|
|
@@ -10336,8 +10794,9 @@ class HfApi:
|
|
|
10336
10794
|
if namespace is None:
|
|
10337
10795
|
namespace = self.whoami(token=token)["name"]
|
|
10338
10796
|
|
|
10339
|
-
|
|
10340
|
-
|
|
10797
|
+
is_url = script.startswith("http://") or script.startswith("https://")
|
|
10798
|
+
if is_url or not Path(script).is_file():
|
|
10799
|
+
# Direct URL execution or command - no upload needed
|
|
10341
10800
|
command = ["uv", "run"] + uv_args + [script] + script_args
|
|
10342
10801
|
else:
|
|
10343
10802
|
# Local file - upload to HF
|
|
@@ -10348,7 +10807,6 @@ class HfApi:
|
|
|
10348
10807
|
repo_id = _repo
|
|
10349
10808
|
if "/" not in repo_id:
|
|
10350
10809
|
repo_id = f"{namespace}/{repo_id}"
|
|
10351
|
-
repo_id = _repo
|
|
10352
10810
|
else:
|
|
10353
10811
|
repo_id = f"{namespace}/hf-cli-jobs-uv-run-scripts"
|
|
10354
10812
|
|
|
@@ -10365,15 +10823,15 @@ class HfApi:
|
|
|
10365
10823
|
with open(script_path, "r") as f:
|
|
10366
10824
|
script_content = f.read()
|
|
10367
10825
|
|
|
10368
|
-
self.upload_file(
|
|
10826
|
+
commit_hash = self.upload_file(
|
|
10369
10827
|
path_or_fileobj=script_content.encode(),
|
|
10370
10828
|
path_in_repo=filename,
|
|
10371
10829
|
repo_id=repo_id,
|
|
10372
10830
|
repo_type="dataset",
|
|
10373
|
-
)
|
|
10831
|
+
).oid
|
|
10374
10832
|
|
|
10375
|
-
script_url = f"
|
|
10376
|
-
repo_url = f"
|
|
10833
|
+
script_url = f"{self.endpoint}/datasets/{repo_id}/resolve/{commit_hash}/{filename}"
|
|
10834
|
+
repo_url = f"{self.endpoint}/datasets/{repo_id}"
|
|
10377
10835
|
|
|
10378
10836
|
logger.debug(f"✓ Script uploaded to: {repo_url}/blob/main/{filename}")
|
|
10379
10837
|
|
|
@@ -10430,18 +10888,7 @@ class HfApi:
|
|
|
10430
10888
|
pre_command = ["python", "-c", '"' + "; ".join(pre_command) + '"']
|
|
10431
10889
|
command = ["uv", "run"] + uv_args + ["/tmp/script.py"] + script_args
|
|
10432
10890
|
command = ["bash", "-c", " ".join(pre_command) + " && " + " ".join(command)]
|
|
10433
|
-
|
|
10434
|
-
# Create RunCommand args
|
|
10435
|
-
return self.run_job(
|
|
10436
|
-
image=image,
|
|
10437
|
-
command=command,
|
|
10438
|
-
env=env,
|
|
10439
|
-
secrets=secrets,
|
|
10440
|
-
flavor=flavor,
|
|
10441
|
-
timeout=timeout,
|
|
10442
|
-
namespace=namespace,
|
|
10443
|
-
token=token,
|
|
10444
|
-
)
|
|
10891
|
+
return command, env, secrets
|
|
10445
10892
|
|
|
10446
10893
|
|
|
10447
10894
|
def _parse_revision_from_pr_url(pr_url: str) -> str:
|
|
@@ -10607,3 +11054,10 @@ list_jobs = api.list_jobs
|
|
|
10607
11054
|
inspect_job = api.inspect_job
|
|
10608
11055
|
cancel_job = api.cancel_job
|
|
10609
11056
|
run_uv_job = api.run_uv_job
|
|
11057
|
+
create_scheduled_job = api.create_scheduled_job
|
|
11058
|
+
list_scheduled_jobs = api.list_scheduled_jobs
|
|
11059
|
+
inspect_scheduled_job = api.inspect_scheduled_job
|
|
11060
|
+
delete_scheduled_job = api.delete_scheduled_job
|
|
11061
|
+
suspend_scheduled_job = api.suspend_scheduled_job
|
|
11062
|
+
resume_scheduled_job = api.resume_scheduled_job
|
|
11063
|
+
create_scheduled_uv_job = api.create_scheduled_uv_job
|