huggingface-hub 0.29.3rc0__py3-none-any.whl → 0.30.0rc1__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.

Files changed (40) hide show
  1. huggingface_hub/__init__.py +16 -1
  2. huggingface_hub/_commit_api.py +142 -4
  3. huggingface_hub/_space_api.py +15 -2
  4. huggingface_hub/_webhooks_server.py +2 -0
  5. huggingface_hub/commands/delete_cache.py +66 -20
  6. huggingface_hub/commands/upload.py +16 -2
  7. huggingface_hub/constants.py +44 -7
  8. huggingface_hub/errors.py +19 -0
  9. huggingface_hub/file_download.py +163 -35
  10. huggingface_hub/hf_api.py +349 -28
  11. huggingface_hub/hub_mixin.py +19 -4
  12. huggingface_hub/inference/_client.py +50 -69
  13. huggingface_hub/inference/_generated/_async_client.py +57 -76
  14. huggingface_hub/inference/_generated/types/__init__.py +1 -0
  15. huggingface_hub/inference/_generated/types/chat_completion.py +20 -10
  16. huggingface_hub/inference/_generated/types/image_to_image.py +2 -0
  17. huggingface_hub/inference/_providers/__init__.py +7 -1
  18. huggingface_hub/inference/_providers/_common.py +9 -5
  19. huggingface_hub/inference/_providers/black_forest_labs.py +5 -5
  20. huggingface_hub/inference/_providers/cohere.py +1 -1
  21. huggingface_hub/inference/_providers/fal_ai.py +64 -7
  22. huggingface_hub/inference/_providers/fireworks_ai.py +4 -1
  23. huggingface_hub/inference/_providers/hf_inference.py +41 -4
  24. huggingface_hub/inference/_providers/hyperbolic.py +3 -3
  25. huggingface_hub/inference/_providers/nebius.py +3 -3
  26. huggingface_hub/inference/_providers/novita.py +35 -5
  27. huggingface_hub/inference/_providers/openai.py +22 -0
  28. huggingface_hub/inference/_providers/replicate.py +3 -3
  29. huggingface_hub/inference/_providers/together.py +3 -3
  30. huggingface_hub/utils/__init__.py +8 -0
  31. huggingface_hub/utils/_http.py +4 -1
  32. huggingface_hub/utils/_runtime.py +11 -0
  33. huggingface_hub/utils/_xet.py +199 -0
  34. huggingface_hub/utils/tqdm.py +30 -2
  35. {huggingface_hub-0.29.3rc0.dist-info → huggingface_hub-0.30.0rc1.dist-info}/METADATA +3 -1
  36. {huggingface_hub-0.29.3rc0.dist-info → huggingface_hub-0.30.0rc1.dist-info}/RECORD +40 -38
  37. {huggingface_hub-0.29.3rc0.dist-info → huggingface_hub-0.30.0rc1.dist-info}/LICENSE +0 -0
  38. {huggingface_hub-0.29.3rc0.dist-info → huggingface_hub-0.30.0rc1.dist-info}/WHEEL +0 -0
  39. {huggingface_hub-0.29.3rc0.dist-info → huggingface_hub-0.30.0rc1.dist-info}/entry_points.txt +0 -0
  40. {huggingface_hub-0.29.3rc0.dist-info → huggingface_hub-0.30.0rc1.dist-info}/top_level.txt +0 -0
@@ -84,7 +84,11 @@ class TaskProviderHelper:
84
84
  raise ValueError("Either payload or data must be set in the request.")
85
85
  return RequestParameters(url=url, task=self.task, model=mapped_model, json=payload, data=data, headers=headers)
86
86
 
87
- def get_response(self, response: Union[bytes, Dict]) -> Any:
87
+ def get_response(
88
+ self,
89
+ response: Union[bytes, Dict],
90
+ request_params: Optional[RequestParameters] = None,
91
+ ) -> Any:
88
92
  """
89
93
  Return the response in the expected format.
90
94
 
@@ -142,7 +146,7 @@ class TaskProviderHelper:
142
146
 
143
147
  Usually not overwritten in subclasses."""
144
148
  base_url = self._prepare_base_url(api_key)
145
- route = self._prepare_route(mapped_model)
149
+ route = self._prepare_route(mapped_model, api_key)
146
150
  return f"{base_url.rstrip('/')}/{route.lstrip('/')}"
147
151
 
148
152
  def _prepare_base_url(self, api_key: str) -> str:
@@ -157,7 +161,7 @@ class TaskProviderHelper:
157
161
  logger.info(f"Calling '{self.provider}' provider directly.")
158
162
  return self.base_url
159
163
 
160
- def _prepare_route(self, mapped_model: str) -> str:
164
+ def _prepare_route(self, mapped_model: str, api_key: str) -> str:
161
165
  """Return the route to use for the request.
162
166
 
163
167
  Override this method in subclasses for customized routes.
@@ -192,7 +196,7 @@ class BaseConversationalTask(TaskProviderHelper):
192
196
  def __init__(self, provider: str, base_url: str):
193
197
  super().__init__(provider=provider, base_url=base_url, task="conversational")
194
198
 
195
- def _prepare_route(self, mapped_model: str) -> str:
199
+ def _prepare_route(self, mapped_model: str, api_key: str) -> str:
196
200
  return "/v1/chat/completions"
197
201
 
198
202
  def _prepare_payload_as_dict(self, inputs: Any, parameters: Dict, mapped_model: str) -> Optional[Dict]:
@@ -208,7 +212,7 @@ class BaseTextGenerationTask(TaskProviderHelper):
208
212
  def __init__(self, provider: str, base_url: str):
209
213
  super().__init__(provider=provider, base_url=base_url, task="text-generation")
210
214
 
211
- def _prepare_route(self, mapped_model: str) -> str:
215
+ def _prepare_route(self, mapped_model: str, api_key: str) -> str:
212
216
  return "/v1/completions"
213
217
 
214
218
  def _prepare_payload_as_dict(self, inputs: Any, parameters: Dict, mapped_model: str) -> Optional[Dict]:
@@ -1,7 +1,7 @@
1
1
  import time
2
2
  from typing import Any, Dict, Optional, Union
3
3
 
4
- from huggingface_hub.inference._common import _as_dict
4
+ from huggingface_hub.inference._common import RequestParameters, _as_dict
5
5
  from huggingface_hub.inference._providers._common import TaskProviderHelper, filter_none
6
6
  from huggingface_hub.utils import logging
7
7
  from huggingface_hub.utils._http import get_session
@@ -15,7 +15,7 @@ POLLING_INTERVAL = 1.0
15
15
 
16
16
  class BlackForestLabsTextToImageTask(TaskProviderHelper):
17
17
  def __init__(self):
18
- super().__init__(provider="black-forest-labs", base_url="https://api.us1.bfl.ai/v1", task="text-to-image")
18
+ super().__init__(provider="black-forest-labs", base_url="https://api.us1.bfl.ai", task="text-to-image")
19
19
 
20
20
  def _prepare_headers(self, headers: Dict, api_key: str) -> Dict:
21
21
  headers = super()._prepare_headers(headers, api_key)
@@ -24,8 +24,8 @@ class BlackForestLabsTextToImageTask(TaskProviderHelper):
24
24
  headers["X-Key"] = api_key
25
25
  return headers
26
26
 
27
- def _prepare_route(self, mapped_model: str) -> str:
28
- return mapped_model
27
+ def _prepare_route(self, mapped_model: str, api_key: str) -> str:
28
+ return f"/v1/{mapped_model}"
29
29
 
30
30
  def _prepare_payload_as_dict(self, inputs: Any, parameters: Dict, mapped_model: str) -> Optional[Dict]:
31
31
  parameters = filter_none(parameters)
@@ -36,7 +36,7 @@ class BlackForestLabsTextToImageTask(TaskProviderHelper):
36
36
 
37
37
  return {"prompt": inputs, **parameters}
38
38
 
39
- def get_response(self, response: Union[bytes, Dict]) -> Any:
39
+ def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any:
40
40
  """
41
41
  Polling mechanism for Black Forest Labs since the API is asynchronous.
42
42
  """
@@ -11,5 +11,5 @@ class CohereConversationalTask(BaseConversationalTask):
11
11
  def __init__(self):
12
12
  super().__init__(provider=_PROVIDER, base_url=_BASE_URL)
13
13
 
14
- def _prepare_route(self, mapped_model: str) -> str:
14
+ def _prepare_route(self, mapped_model: str, api_key: str) -> str:
15
15
  return "/compatibility/v1/chat/completions"
@@ -1,10 +1,19 @@
1
1
  import base64
2
+ import time
2
3
  from abc import ABC
3
4
  from typing import Any, Dict, Optional, Union
5
+ from urllib.parse import urlparse
4
6
 
5
- from huggingface_hub.inference._common import _as_dict
7
+ from huggingface_hub.inference._common import RequestParameters, _as_dict
6
8
  from huggingface_hub.inference._providers._common import TaskProviderHelper, filter_none
7
- from huggingface_hub.utils import get_session
9
+ from huggingface_hub.utils import get_session, hf_raise_for_status
10
+ from huggingface_hub.utils.logging import get_logger
11
+
12
+
13
+ logger = get_logger(__name__)
14
+
15
+ # Arbitrary polling interval
16
+ _POLLING_INTERVAL = 0.5
8
17
 
9
18
 
10
19
  class FalAITask(TaskProviderHelper, ABC):
@@ -17,7 +26,7 @@ class FalAITask(TaskProviderHelper, ABC):
17
26
  headers["authorization"] = f"Key {api_key}"
18
27
  return headers
19
28
 
20
- def _prepare_route(self, mapped_model: str) -> str:
29
+ def _prepare_route(self, mapped_model: str, api_key: str) -> str:
21
30
  return f"/{mapped_model}"
22
31
 
23
32
 
@@ -41,7 +50,7 @@ class FalAIAutomaticSpeechRecognitionTask(FalAITask):
41
50
 
42
51
  return {"audio_url": audio_url, **filter_none(parameters)}
43
52
 
44
- def get_response(self, response: Union[bytes, Dict]) -> Any:
53
+ def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any:
45
54
  text = _as_dict(response)["text"]
46
55
  if not isinstance(text, str):
47
56
  raise ValueError(f"Unexpected output format from FalAI API. Expected string, got {type(text)}.")
@@ -61,7 +70,7 @@ class FalAITextToImageTask(FalAITask):
61
70
  }
62
71
  return {"prompt": inputs, **parameters}
63
72
 
64
- def get_response(self, response: Union[bytes, Dict]) -> Any:
73
+ def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any:
65
74
  url = _as_dict(response)["images"][0]["url"]
66
75
  return get_session().get(url).content
67
76
 
@@ -73,7 +82,7 @@ class FalAITextToSpeechTask(FalAITask):
73
82
  def _prepare_payload_as_dict(self, inputs: Any, parameters: Dict, mapped_model: str) -> Optional[Dict]:
74
83
  return {"lyrics": inputs, **filter_none(parameters)}
75
84
 
76
- def get_response(self, response: Union[bytes, Dict]) -> Any:
85
+ def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any:
77
86
  url = _as_dict(response)["audio"]["url"]
78
87
  return get_session().get(url).content
79
88
 
@@ -82,9 +91,57 @@ class FalAITextToVideoTask(FalAITask):
82
91
  def __init__(self):
83
92
  super().__init__("text-to-video")
84
93
 
94
+ def _prepare_base_url(self, api_key: str) -> str:
95
+ if api_key.startswith("hf_"):
96
+ return super()._prepare_base_url(api_key)
97
+ else:
98
+ logger.info(f"Calling '{self.provider}' provider directly.")
99
+ return "https://queue.fal.run"
100
+
101
+ def _prepare_route(self, mapped_model: str, api_key: str) -> str:
102
+ if api_key.startswith("hf_"):
103
+ # Use the queue subdomain for HF routing
104
+ return f"/{mapped_model}?_subdomain=queue"
105
+ return f"/{mapped_model}"
106
+
85
107
  def _prepare_payload_as_dict(self, inputs: Any, parameters: Dict, mapped_model: str) -> Optional[Dict]:
86
108
  return {"prompt": inputs, **filter_none(parameters)}
87
109
 
88
- def get_response(self, response: Union[bytes, Dict]) -> Any:
110
+ def get_response(
111
+ self,
112
+ response: Union[bytes, Dict],
113
+ request_params: Optional[RequestParameters] = None,
114
+ ) -> Any:
115
+ response_dict = _as_dict(response)
116
+
117
+ request_id = response_dict.get("request_id")
118
+ if not request_id:
119
+ raise ValueError("No request ID found in the response")
120
+ if request_params is None:
121
+ raise ValueError(
122
+ "A `RequestParameters` object should be provided to get text-to-video responses with Fal AI."
123
+ )
124
+
125
+ # extract the base url and query params
126
+ parsed_url = urlparse(request_params.url)
127
+ # a bit hacky way to concatenate the provider name without parsing `parsed_url.path`
128
+ base_url = f"{parsed_url.scheme}://{parsed_url.netloc}{'/fal-ai' if parsed_url.netloc == 'router.huggingface.co' else ''}"
129
+ query_param = f"?{parsed_url.query}" if parsed_url.query else ""
130
+
131
+ # extracting the provider model id for status and result urls
132
+ # from the response as it might be different from the mapped model in `request_params.url`
133
+ model_id = urlparse(response_dict.get("response_url")).path
134
+ status_url = f"{base_url}{str(model_id)}/status{query_param}"
135
+ result_url = f"{base_url}{str(model_id)}{query_param}"
136
+
137
+ status = response_dict.get("status")
138
+ logger.info("Generating the video.. this can take several minutes.")
139
+ while status != "COMPLETED":
140
+ time.sleep(_POLLING_INTERVAL)
141
+ status_response = get_session().get(status_url, headers=request_params.headers)
142
+ hf_raise_for_status(status_response)
143
+ status = status_response.json().get("status")
144
+
145
+ response = get_session().get(result_url, headers=request_params.headers).json()
89
146
  url = _as_dict(response)["video"]["url"]
90
147
  return get_session().get(url).content
@@ -3,4 +3,7 @@ from ._common import BaseConversationalTask
3
3
 
4
4
  class FireworksAIConversationalTask(BaseConversationalTask):
5
5
  def __init__(self):
6
- super().__init__(provider="fireworks-ai", base_url="https://api.fireworks.ai/inference")
6
+ super().__init__(provider="fireworks-ai", base_url="https://api.fireworks.ai")
7
+
8
+ def _prepare_route(self, mapped_model: str, api_key: str) -> str:
9
+ return "/inference/v1/chat/completions"
@@ -24,15 +24,16 @@ class HFInferenceTask(TaskProviderHelper):
24
24
  return api_key or get_token() # type: ignore[return-value]
25
25
 
26
26
  def _prepare_mapped_model(self, model: Optional[str]) -> str:
27
- if model is not None:
27
+ if model is not None and model.startswith(("http://", "https://")):
28
28
  return model
29
- model = _fetch_recommended_models().get(self.task)
30
- if model is None:
29
+ model_id = model if model is not None else _fetch_recommended_models().get(self.task)
30
+ if model_id is None:
31
31
  raise ValueError(
32
32
  f"Task {self.task} has no recommended model for HF Inference. Please specify a model"
33
33
  " explicitly. Visit https://huggingface.co/tasks for more info."
34
34
  )
35
- return model
35
+ _check_supported_task(model_id, self.task)
36
+ return model_id
36
37
 
37
38
  def _prepare_url(self, api_key: str, mapped_model: str) -> str:
38
39
  # hf-inference provider can handle URLs (e.g. Inference Endpoints or TGI deployment)
@@ -120,3 +121,39 @@ def _fetch_recommended_models() -> Dict[str, Optional[str]]:
120
121
  response = get_session().get(f"{constants.ENDPOINT}/api/tasks", headers=build_hf_headers())
121
122
  hf_raise_for_status(response)
122
123
  return {task: next(iter(details["widgetModels"]), None) for task, details in response.json().items()}
124
+
125
+
126
+ @lru_cache(maxsize=None)
127
+ def _check_supported_task(model: str, task: str) -> None:
128
+ from huggingface_hub.hf_api import HfApi
129
+
130
+ model_info = HfApi().model_info(model)
131
+ pipeline_tag = model_info.pipeline_tag
132
+ tags = model_info.tags or []
133
+ is_conversational = "conversational" in tags
134
+ if task in ("text-generation", "conversational"):
135
+ if pipeline_tag == "text-generation":
136
+ # text-generation + conversational tag -> both tasks allowed
137
+ if is_conversational:
138
+ return
139
+ # text-generation without conversational tag -> only text-generation allowed
140
+ if task == "text-generation":
141
+ return
142
+ raise ValueError(f"Model '{model}' doesn't support task '{task}'.")
143
+
144
+ if pipeline_tag == "text2text-generation":
145
+ if task == "text-generation":
146
+ return
147
+ raise ValueError(f"Model '{model}' doesn't support task '{task}'.")
148
+
149
+ if pipeline_tag == "image-text-to-text":
150
+ if is_conversational and task == "conversational":
151
+ return # Only conversational allowed if tagged as conversational
152
+ raise ValueError("Non-conversational image-text-to-text task is not supported.")
153
+
154
+ # For all other tasks, just check pipeline tag
155
+ if pipeline_tag != task:
156
+ raise ValueError(
157
+ f"Model '{model}' doesn't support task '{task}'. Supported tasks: '{pipeline_tag}', got: '{task}'"
158
+ )
159
+ return
@@ -1,7 +1,7 @@
1
1
  import base64
2
2
  from typing import Any, Dict, Optional, Union
3
3
 
4
- from huggingface_hub.inference._common import _as_dict
4
+ from huggingface_hub.inference._common import RequestParameters, _as_dict
5
5
  from huggingface_hub.inference._providers._common import BaseConversationalTask, TaskProviderHelper, filter_none
6
6
 
7
7
 
@@ -9,7 +9,7 @@ class HyperbolicTextToImageTask(TaskProviderHelper):
9
9
  def __init__(self):
10
10
  super().__init__(provider="hyperbolic", base_url="https://api.hyperbolic.xyz", task="text-to-image")
11
11
 
12
- def _prepare_route(self, mapped_model: str) -> str:
12
+ def _prepare_route(self, mapped_model: str, api_key: str) -> str:
13
13
  return "/v1/images/generations"
14
14
 
15
15
  def _prepare_payload_as_dict(self, inputs: Any, parameters: Dict, mapped_model: str) -> Optional[Dict]:
@@ -25,7 +25,7 @@ class HyperbolicTextToImageTask(TaskProviderHelper):
25
25
  parameters["height"] = 512
26
26
  return {"prompt": inputs, "model_name": mapped_model, **parameters}
27
27
 
28
- def get_response(self, response: Union[bytes, Dict]) -> Any:
28
+ def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any:
29
29
  response_dict = _as_dict(response)
30
30
  return base64.b64decode(response_dict["images"][0]["image"])
31
31
 
@@ -1,7 +1,7 @@
1
1
  import base64
2
2
  from typing import Any, Dict, Optional, Union
3
3
 
4
- from huggingface_hub.inference._common import _as_dict
4
+ from huggingface_hub.inference._common import RequestParameters, _as_dict
5
5
  from huggingface_hub.inference._providers._common import (
6
6
  BaseConversationalTask,
7
7
  BaseTextGenerationTask,
@@ -24,7 +24,7 @@ class NebiusTextToImageTask(TaskProviderHelper):
24
24
  def __init__(self):
25
25
  super().__init__(task="text-to-image", provider="nebius", base_url="https://api.studio.nebius.ai")
26
26
 
27
- def _prepare_route(self, mapped_model: str) -> str:
27
+ def _prepare_route(self, mapped_model: str, api_key: str) -> str:
28
28
  return "/v1/images/generations"
29
29
 
30
30
  def _prepare_payload_as_dict(self, inputs: Any, parameters: Dict, mapped_model: str) -> Optional[Dict]:
@@ -36,6 +36,6 @@ class NebiusTextToImageTask(TaskProviderHelper):
36
36
 
37
37
  return {"prompt": inputs, **parameters, "model": mapped_model}
38
38
 
39
- def get_response(self, response: Union[bytes, Dict]) -> Any:
39
+ def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any:
40
40
  response_dict = _as_dict(response)
41
41
  return base64.b64decode(response_dict["data"][0]["b64_json"])
@@ -1,26 +1,56 @@
1
+ from typing import Any, Dict, Optional, Union
2
+
3
+ from huggingface_hub.inference._common import RequestParameters, _as_dict
1
4
  from huggingface_hub.inference._providers._common import (
2
5
  BaseConversationalTask,
3
6
  BaseTextGenerationTask,
7
+ TaskProviderHelper,
8
+ filter_none,
4
9
  )
10
+ from huggingface_hub.utils import get_session
5
11
 
6
12
 
7
13
  _PROVIDER = "novita"
8
- _BASE_URL = "https://api.novita.ai/v3/openai"
14
+ _BASE_URL = "https://api.novita.ai"
9
15
 
10
16
 
11
17
  class NovitaTextGenerationTask(BaseTextGenerationTask):
12
18
  def __init__(self):
13
19
  super().__init__(provider=_PROVIDER, base_url=_BASE_URL)
14
20
 
15
- def _prepare_route(self, mapped_model: str) -> str:
21
+ def _prepare_route(self, mapped_model: str, api_key: str) -> str:
16
22
  # there is no v1/ route for novita
17
- return "/completions"
23
+ return "/v3/openai/completions"
18
24
 
19
25
 
20
26
  class NovitaConversationalTask(BaseConversationalTask):
21
27
  def __init__(self):
22
28
  super().__init__(provider=_PROVIDER, base_url=_BASE_URL)
23
29
 
24
- def _prepare_route(self, mapped_model: str) -> str:
30
+ def _prepare_route(self, mapped_model: str, api_key: str) -> str:
25
31
  # there is no v1/ route for novita
26
- return "/chat/completions"
32
+ return "/v3/openai/chat/completions"
33
+
34
+
35
+ class NovitaTextToVideoTask(TaskProviderHelper):
36
+ def __init__(self):
37
+ super().__init__(provider=_PROVIDER, base_url=_BASE_URL, task="text-to-video")
38
+
39
+ def _prepare_route(self, mapped_model: str, api_key: str) -> str:
40
+ return f"/v3/hf/{mapped_model}"
41
+
42
+ def _prepare_payload_as_dict(self, inputs: Any, parameters: Dict, mapped_model: str) -> Optional[Dict]:
43
+ return {"prompt": inputs, **filter_none(parameters)}
44
+
45
+ def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any:
46
+ response_dict = _as_dict(response)
47
+ if not (
48
+ isinstance(response_dict, dict)
49
+ and "video" in response_dict
50
+ and isinstance(response_dict["video"], dict)
51
+ and "video_url" in response_dict["video"]
52
+ ):
53
+ raise ValueError("Expected response format: { 'video': { 'video_url': string } }")
54
+
55
+ video_url = response_dict["video"]["video_url"]
56
+ return get_session().get(video_url).content
@@ -0,0 +1,22 @@
1
+ from typing import Optional
2
+
3
+ from huggingface_hub.inference._providers._common import BaseConversationalTask
4
+
5
+
6
+ class OpenAIConversationalTask(BaseConversationalTask):
7
+ def __init__(self):
8
+ super().__init__(provider="openai", base_url="https://api.openai.com")
9
+
10
+ def _prepare_api_key(self, api_key: Optional[str]) -> str:
11
+ if api_key is None:
12
+ raise ValueError("You must provide an api_key to work with OpenAI API.")
13
+ if api_key.startswith("hf_"):
14
+ raise ValueError(
15
+ "OpenAI provider is not available through Hugging Face routing, please use your own OpenAI API key."
16
+ )
17
+ return api_key
18
+
19
+ def _prepare_mapped_model(self, model: Optional[str]) -> str:
20
+ if model is None:
21
+ raise ValueError("Please provide an OpenAI model ID, e.g. `gpt-4o` or `o1`.")
22
+ return model
@@ -1,6 +1,6 @@
1
1
  from typing import Any, Dict, Optional, Union
2
2
 
3
- from huggingface_hub.inference._common import _as_dict
3
+ from huggingface_hub.inference._common import RequestParameters, _as_dict
4
4
  from huggingface_hub.inference._providers._common import TaskProviderHelper, filter_none
5
5
  from huggingface_hub.utils import get_session
6
6
 
@@ -18,7 +18,7 @@ class ReplicateTask(TaskProviderHelper):
18
18
  headers["Prefer"] = "wait"
19
19
  return headers
20
20
 
21
- def _prepare_route(self, mapped_model: str) -> str:
21
+ def _prepare_route(self, mapped_model: str, api_key: str) -> str:
22
22
  if ":" in mapped_model:
23
23
  return "/v1/predictions"
24
24
  return f"/v1/models/{mapped_model}/predictions"
@@ -30,7 +30,7 @@ class ReplicateTask(TaskProviderHelper):
30
30
  payload["version"] = version
31
31
  return payload
32
32
 
33
- def get_response(self, response: Union[bytes, Dict]) -> Any:
33
+ def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any:
34
34
  response_dict = _as_dict(response)
35
35
  if response_dict.get("output") is None:
36
36
  raise TimeoutError(
@@ -2,7 +2,7 @@ import base64
2
2
  from abc import ABC
3
3
  from typing import Any, Dict, Optional, Union
4
4
 
5
- from huggingface_hub.inference._common import _as_dict
5
+ from huggingface_hub.inference._common import RequestParameters, _as_dict
6
6
  from huggingface_hub.inference._providers._common import (
7
7
  BaseConversationalTask,
8
8
  BaseTextGenerationTask,
@@ -21,7 +21,7 @@ class TogetherTask(TaskProviderHelper, ABC):
21
21
  def __init__(self, task: str):
22
22
  super().__init__(provider=_PROVIDER, base_url=_BASE_URL, task=task)
23
23
 
24
- def _prepare_route(self, mapped_model: str) -> str:
24
+ def _prepare_route(self, mapped_model: str, api_key: str) -> str:
25
25
  if self.task == "text-to-image":
26
26
  return "/v1/images/generations"
27
27
  elif self.task == "conversational":
@@ -54,6 +54,6 @@ class TogetherTextToImageTask(TogetherTask):
54
54
 
55
55
  return {"prompt": inputs, "response_format": "base64", **parameters, "model": mapped_model}
56
56
 
57
- def get_response(self, response: Union[bytes, Dict]) -> Any:
57
+ def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any:
58
58
  response_dict = _as_dict(response)
59
59
  return base64.b64decode(response_dict["data"][0]["b64_json"])
@@ -107,4 +107,12 @@ from ._subprocess import capture_output, run_interactive_subprocess, run_subproc
107
107
  from ._telemetry import send_telemetry
108
108
  from ._typing import is_jsonable, is_simple_optional_type, unwrap_simple_optional_type
109
109
  from ._validators import smoothly_deprecate_use_auth_token, validate_hf_hub_args, validate_repo_id
110
+ from ._xet import (
111
+ XetConnectionInfo,
112
+ XetFileData,
113
+ XetTokenType,
114
+ fetch_xet_connection_info_from_repo_info,
115
+ parse_xet_file_data_from_response,
116
+ refresh_xet_connection_info,
117
+ )
110
118
  from .tqdm import are_progress_bars_disabled, disable_progress_bars, enable_progress_bars, tqdm, tqdm_stream_file
@@ -453,7 +453,8 @@ def hf_raise_for_status(response: Response, endpoint_name: Optional[str] = None)
453
453
  + f"Repository Not Found for url: {response.url}."
454
454
  + "\nPlease make sure you specified the correct `repo_id` and"
455
455
  " `repo_type`.\nIf you are trying to access a private or gated repo,"
456
- " make sure you are authenticated."
456
+ " make sure you are authenticated. For more details, see"
457
+ " https://huggingface.co/docs/huggingface_hub/authentication"
457
458
  )
458
459
  raise _format(RepositoryNotFoundError, message, response) from e
459
460
 
@@ -577,6 +578,8 @@ def _curlify(request: requests.PreparedRequest) -> str:
577
578
  body = request.body
578
579
  if isinstance(body, bytes):
579
580
  body = body.decode("utf-8", errors="ignore")
581
+ elif hasattr(body, "read"):
582
+ body = "<file-like object>" # Don't try to read it to avoid consuming the stream
580
583
  if len(body) > 1000:
581
584
  body = body[:1000] + " ... [truncated]"
582
585
  parts += [("-d", body.replace("\n", ""))]
@@ -36,6 +36,7 @@ _CANDIDATES = {
36
36
  "gradio": {"gradio"},
37
37
  "graphviz": {"graphviz"},
38
38
  "hf_transfer": {"hf_transfer"},
39
+ "hf_xet": {"hf_xet"},
39
40
  "jinja": {"Jinja2"},
40
41
  "keras": {"keras"},
41
42
  "numpy": {"numpy"},
@@ -151,6 +152,15 @@ def get_hf_transfer_version() -> str:
151
152
  return _get_version("hf_transfer")
152
153
 
153
154
 
155
+ # xet
156
+ def is_xet_available() -> bool:
157
+ return is_package_available("hf_xet")
158
+
159
+
160
+ def get_xet_version() -> str:
161
+ return _get_version("hf_xet")
162
+
163
+
154
164
  # keras
155
165
  def is_keras_available() -> bool:
156
166
  return is_package_available("keras")
@@ -357,6 +367,7 @@ def dump_environment_info() -> Dict[str, Any]:
357
367
  info["numpy"] = get_numpy_version()
358
368
  info["pydantic"] = get_pydantic_version()
359
369
  info["aiohttp"] = get_aiohttp_version()
370
+ info["hf_xet"] = get_xet_version()
360
371
 
361
372
  # Environment variables
362
373
  info["ENDPOINT"] = constants.ENDPOINT