huggingface-hub 0.33.5__py3-none-any.whl → 0.35.0rc0__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 (68) hide show
  1. huggingface_hub/__init__.py +487 -525
  2. huggingface_hub/_commit_api.py +21 -28
  3. huggingface_hub/_jobs_api.py +145 -0
  4. huggingface_hub/_local_folder.py +7 -1
  5. huggingface_hub/_login.py +5 -5
  6. huggingface_hub/_oauth.py +1 -1
  7. huggingface_hub/_snapshot_download.py +11 -6
  8. huggingface_hub/_upload_large_folder.py +46 -23
  9. huggingface_hub/cli/__init__.py +27 -0
  10. huggingface_hub/cli/_cli_utils.py +69 -0
  11. huggingface_hub/cli/auth.py +210 -0
  12. huggingface_hub/cli/cache.py +405 -0
  13. huggingface_hub/cli/download.py +181 -0
  14. huggingface_hub/cli/hf.py +66 -0
  15. huggingface_hub/cli/jobs.py +522 -0
  16. huggingface_hub/cli/lfs.py +198 -0
  17. huggingface_hub/cli/repo.py +243 -0
  18. huggingface_hub/cli/repo_files.py +128 -0
  19. huggingface_hub/cli/system.py +52 -0
  20. huggingface_hub/cli/upload.py +316 -0
  21. huggingface_hub/cli/upload_large_folder.py +132 -0
  22. huggingface_hub/commands/_cli_utils.py +5 -0
  23. huggingface_hub/commands/delete_cache.py +3 -1
  24. huggingface_hub/commands/download.py +4 -0
  25. huggingface_hub/commands/env.py +3 -0
  26. huggingface_hub/commands/huggingface_cli.py +2 -0
  27. huggingface_hub/commands/repo.py +4 -0
  28. huggingface_hub/commands/repo_files.py +4 -0
  29. huggingface_hub/commands/scan_cache.py +3 -1
  30. huggingface_hub/commands/tag.py +3 -1
  31. huggingface_hub/commands/upload.py +4 -0
  32. huggingface_hub/commands/upload_large_folder.py +3 -1
  33. huggingface_hub/commands/user.py +11 -1
  34. huggingface_hub/commands/version.py +3 -0
  35. huggingface_hub/constants.py +1 -0
  36. huggingface_hub/file_download.py +16 -5
  37. huggingface_hub/hf_api.py +519 -7
  38. huggingface_hub/hf_file_system.py +8 -16
  39. huggingface_hub/hub_mixin.py +3 -3
  40. huggingface_hub/inference/_client.py +38 -39
  41. huggingface_hub/inference/_common.py +38 -11
  42. huggingface_hub/inference/_generated/_async_client.py +50 -51
  43. huggingface_hub/inference/_generated/types/__init__.py +1 -0
  44. huggingface_hub/inference/_generated/types/image_to_video.py +60 -0
  45. huggingface_hub/inference/_mcp/cli.py +36 -18
  46. huggingface_hub/inference/_mcp/constants.py +8 -0
  47. huggingface_hub/inference/_mcp/types.py +3 -0
  48. huggingface_hub/inference/_providers/__init__.py +4 -1
  49. huggingface_hub/inference/_providers/_common.py +3 -6
  50. huggingface_hub/inference/_providers/fal_ai.py +85 -42
  51. huggingface_hub/inference/_providers/hf_inference.py +17 -9
  52. huggingface_hub/inference/_providers/replicate.py +19 -1
  53. huggingface_hub/keras_mixin.py +2 -2
  54. huggingface_hub/repocard.py +1 -1
  55. huggingface_hub/repository.py +2 -2
  56. huggingface_hub/utils/_auth.py +1 -1
  57. huggingface_hub/utils/_cache_manager.py +2 -2
  58. huggingface_hub/utils/_dotenv.py +51 -0
  59. huggingface_hub/utils/_headers.py +1 -1
  60. huggingface_hub/utils/_runtime.py +1 -1
  61. huggingface_hub/utils/_xet.py +6 -2
  62. huggingface_hub/utils/_xet_progress_reporting.py +141 -0
  63. {huggingface_hub-0.33.5.dist-info → huggingface_hub-0.35.0rc0.dist-info}/METADATA +7 -8
  64. {huggingface_hub-0.33.5.dist-info → huggingface_hub-0.35.0rc0.dist-info}/RECORD +68 -51
  65. {huggingface_hub-0.33.5.dist-info → huggingface_hub-0.35.0rc0.dist-info}/entry_points.txt +1 -0
  66. {huggingface_hub-0.33.5.dist-info → huggingface_hub-0.35.0rc0.dist-info}/LICENSE +0 -0
  67. {huggingface_hub-0.33.5.dist-info → huggingface_hub-0.35.0rc0.dist-info}/WHEEL +0 -0
  68. {huggingface_hub-0.33.5.dist-info → huggingface_hub-0.35.0rc0.dist-info}/top_level.txt +0 -0
@@ -367,7 +367,6 @@ class HfFileSystem(fsspec.AbstractFileSystem):
367
367
  """
368
368
  resolved_path = self.resolve_path(path, revision=revision)
369
369
  path = resolved_path.unresolve()
370
- kwargs = {"expand_info": detail, **kwargs}
371
370
  try:
372
371
  out = self._ls_tree(path, refresh=refresh, revision=revision, **kwargs)
373
372
  except EntryNotFoundError:
@@ -386,7 +385,7 @@ class HfFileSystem(fsspec.AbstractFileSystem):
386
385
  recursive: bool = False,
387
386
  refresh: bool = False,
388
387
  revision: Optional[str] = None,
389
- expand_info: bool = True,
388
+ expand_info: bool = False,
390
389
  ):
391
390
  resolved_path = self.resolve_path(path, revision=revision)
392
391
  path = resolved_path.unresolve()
@@ -497,8 +496,6 @@ class HfFileSystem(fsspec.AbstractFileSystem):
497
496
  Returns:
498
497
  `Iterator[Tuple[str, List[str], List[str]]]`: An iterator of (path, list of directory names, list of file names) tuples.
499
498
  """
500
- # Set expand_info=False by default to get a x10 speed boost
501
- kwargs = {"expand_info": kwargs.get("detail", False), **kwargs}
502
499
  path = self.resolve_path(path, revision=kwargs.get("revision")).unresolve()
503
500
  yield from super().walk(path, *args, **kwargs)
504
501
 
@@ -515,8 +512,6 @@ class HfFileSystem(fsspec.AbstractFileSystem):
515
512
  Returns:
516
513
  `List[str]`: List of paths matching the pattern.
517
514
  """
518
- # Set expand_info=False by default to get a x10 speed boost
519
- kwargs = {"expand_info": kwargs.get("detail", False), **kwargs}
520
515
  path = self.resolve_path(path, revision=kwargs.get("revision")).unresolve()
521
516
  return super().glob(path, **kwargs)
522
517
 
@@ -558,7 +553,6 @@ class HfFileSystem(fsspec.AbstractFileSystem):
558
553
  )
559
554
  resolved_path = self.resolve_path(path, revision=revision)
560
555
  path = resolved_path.unresolve()
561
- kwargs = {"expand_info": detail, **kwargs}
562
556
  try:
563
557
  out = self._ls_tree(path, recursive=True, refresh=refresh, revision=resolved_path.revision, **kwargs)
564
558
  except EntryNotFoundError:
@@ -653,7 +647,7 @@ class HfFileSystem(fsspec.AbstractFileSystem):
653
647
  Returns:
654
648
  `datetime`: Last commit date of the file.
655
649
  """
656
- info = self.info(path, **kwargs)
650
+ info = self.info(path, **{**kwargs, "expand_info": True})
657
651
  return info["last_commit"]["date"]
658
652
 
659
653
  def info(self, path: str, refresh: bool = False, revision: Optional[str] = None, **kwargs) -> Dict[str, Any]:
@@ -683,7 +677,7 @@ class HfFileSystem(fsspec.AbstractFileSystem):
683
677
  resolved_path = self.resolve_path(path, revision=revision)
684
678
  path = resolved_path.unresolve()
685
679
  expand_info = kwargs.get(
686
- "expand_info", True
680
+ "expand_info", False
687
681
  ) # don't expose it as a parameter in the public API to follow the spec
688
682
  if not resolved_path.path_in_repo:
689
683
  # Path is the root directory
@@ -691,6 +685,7 @@ class HfFileSystem(fsspec.AbstractFileSystem):
691
685
  "name": path,
692
686
  "size": 0,
693
687
  "type": "directory",
688
+ "last_commit": None,
694
689
  }
695
690
  if expand_info:
696
691
  last_commit = self._api.list_repo_commits(
@@ -708,7 +703,7 @@ class HfFileSystem(fsspec.AbstractFileSystem):
708
703
  parent_path = self._parent(path)
709
704
  if not expand_info and parent_path not in self.dircache:
710
705
  # Fill the cache with cheap call
711
- self.ls(parent_path, expand_info=False)
706
+ self.ls(parent_path)
712
707
  if parent_path in self.dircache:
713
708
  # Check if the path is in the cache
714
709
  out1 = [o for o in self.dircache[parent_path] if o["name"] == path]
@@ -779,7 +774,7 @@ class HfFileSystem(fsspec.AbstractFileSystem):
779
774
  if kwargs.get("refresh", False):
780
775
  self.invalidate_cache(path)
781
776
 
782
- self.info(path, **{**kwargs, "expand_info": False})
777
+ self.info(path, **kwargs)
783
778
  return True
784
779
  except: # noqa: E722
785
780
  return False
@@ -798,7 +793,7 @@ class HfFileSystem(fsspec.AbstractFileSystem):
798
793
  `bool`: True if path is a directory, False otherwise.
799
794
  """
800
795
  try:
801
- return self.info(path, expand_info=False)["type"] == "directory"
796
+ return self.info(path)["type"] == "directory"
802
797
  except OSError:
803
798
  return False
804
799
 
@@ -816,7 +811,7 @@ class HfFileSystem(fsspec.AbstractFileSystem):
816
811
  `bool`: True if path is a file, False otherwise.
817
812
  """
818
813
  try:
819
- return self.info(path, expand_info=False)["type"] == "file"
814
+ return self.info(path)["type"] == "file"
820
815
  except: # noqa: E722
821
816
  return False
822
817
 
@@ -942,9 +937,6 @@ class HfFileSystemFile(fsspec.spec.AbstractBufferedFile):
942
937
  f"{e}.\nMake sure the repository and revision exist before writing data."
943
938
  ) from e
944
939
  raise
945
- # avoid an unnecessary .info() call with expensive expand_info=True to instantiate .details
946
- if kwargs.get("mode", "rb") == "rb":
947
- self.details = fs.info(self.resolved_path.unresolve(), expand_info=False)
948
940
  super().__init__(fs, self.resolved_path.unresolve(), **kwargs)
949
941
  self.fs: HfFileSystem
950
942
 
@@ -491,7 +491,7 @@ class ModelHubMixin:
491
491
  'http://hostname': 'foo.bar:4012'}`. The proxies are used on every request.
492
492
  token (`str` or `bool`, *optional*):
493
493
  The token to use as HTTP bearer authorization for remote files. By default, it will use the token
494
- cached when running `huggingface-cli login`.
494
+ cached when running `hf auth login`.
495
495
  cache_dir (`str`, `Path`, *optional*):
496
496
  Path to the folder where cached files are stored.
497
497
  local_files_only (`bool`, *optional*, defaults to `False`):
@@ -619,7 +619,7 @@ class ModelHubMixin:
619
619
  'http://hostname': 'foo.bar:4012'}`).
620
620
  token (`str` or `bool`, *optional*):
621
621
  The token to use as HTTP bearer authorization for remote files. By default, it will use the token
622
- cached when running `huggingface-cli login`.
622
+ cached when running `hf auth login`.
623
623
  cache_dir (`str`, `Path`, *optional*):
624
624
  Path to the folder where cached files are stored.
625
625
  local_files_only (`bool`, *optional*, defaults to `False`):
@@ -664,7 +664,7 @@ class ModelHubMixin:
664
664
  If `None` (default), the repo will be public unless the organization's default is private.
665
665
  token (`str`, *optional*):
666
666
  The token to use as HTTP bearer authorization for remote files. By default, it will use the token
667
- cached when running `huggingface-cli login`.
667
+ cached when running `hf auth login`.
668
668
  branch (`str`, *optional*):
669
669
  The git branch on which to push the model. This defaults to `"main"`.
670
670
  create_pr (`boolean`, *optional*):
@@ -130,9 +130,7 @@ class InferenceClient:
130
130
  or a URL to a deployed Inference Endpoint. Defaults to None, in which case a recommended model is
131
131
  automatically selected for the task.
132
132
  Note: for better compatibility with OpenAI's client, `model` has been aliased as `base_url`. Those 2
133
- arguments are mutually exclusive. If using `base_url` for chat completion, the `/chat/completions` suffix
134
- path will be appended to the base URL (see the [TGI Messages API](https://huggingface.co/docs/text-generation-inference/en/messages_api)
135
- documentation for details). When passing a URL as `model`, the client will not append any suffix path to it.
133
+ arguments are mutually exclusive. If a URL is passed as `model` or `base_url` for chat completion, the `(/v1)/chat/completions` suffix path will be appended to the URL.
136
134
  provider (`str`, *optional*):
137
135
  Name of the provider to use for inference. Can be `"black-forest-labs"`, `"cerebras"`, `"cohere"`, `"fal-ai"`, `"featherless-ai"`, `"fireworks-ai"`, `"groq"`, `"hf-inference"`, `"hyperbolic"`, `"nebius"`, `"novita"`, `"nscale"`, `"openai"`, `"replicate"`, "sambanova"` or `"together"`.
138
136
  Defaults to "auto" i.e. the first of the providers available for the model, sorted by the user's order in https://hf.co/settings/inference-providers.
@@ -947,8 +945,8 @@ class InferenceClient:
947
945
  Answer questions on document images.
948
946
 
949
947
  Args:
950
- image (`Union[str, Path, bytes, BinaryIO, PIL.Image.Image]`):
951
- The input image for the context. It can be raw bytes, an image file, a URL to an online image, or a PIL Image.
948
+ image (`Union[str, Path, bytes, BinaryIO]`):
949
+ The input image for the context. It can be raw bytes, an image file, or a URL to an online image.
952
950
  question (`str`):
953
951
  Question to be answered.
954
952
  model (`str`, *optional*):
@@ -1338,6 +1336,7 @@ class InferenceClient:
1338
1336
  api_key=self.token,
1339
1337
  )
1340
1338
  response = self._inner_post(request_parameters)
1339
+ response = provider_helper.get_response(response, request_parameters)
1341
1340
  return _bytes_to_image(response)
1342
1341
 
1343
1342
  def image_to_text(self, image: ContentT, *, model: Optional[str] = None) -> ImageToTextOutput:
@@ -1858,23 +1857,23 @@ class InferenceClient:
1858
1857
  return TextClassificationOutputElement.parse_obj_as_list(response)[0] # type: ignore [return-value]
1859
1858
 
1860
1859
  @overload
1861
- def text_generation( # type: ignore
1860
+ def text_generation(
1862
1861
  self,
1863
1862
  prompt: str,
1864
1863
  *,
1865
- details: Literal[False] = ...,
1866
- stream: Literal[False] = ...,
1864
+ details: Literal[True],
1865
+ stream: Literal[True],
1867
1866
  model: Optional[str] = None,
1868
1867
  # Parameters from `TextGenerationInputGenerateParameters` (maintained manually)
1869
1868
  adapter_id: Optional[str] = None,
1870
1869
  best_of: Optional[int] = None,
1871
1870
  decoder_input_details: Optional[bool] = None,
1872
- do_sample: Optional[bool] = False, # Manual default value
1871
+ do_sample: Optional[bool] = None,
1873
1872
  frequency_penalty: Optional[float] = None,
1874
1873
  grammar: Optional[TextGenerationInputGrammarType] = None,
1875
1874
  max_new_tokens: Optional[int] = None,
1876
1875
  repetition_penalty: Optional[float] = None,
1877
- return_full_text: Optional[bool] = False, # Manual default value
1876
+ return_full_text: Optional[bool] = None,
1878
1877
  seed: Optional[int] = None,
1879
1878
  stop: Optional[List[str]] = None,
1880
1879
  stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead
@@ -1885,26 +1884,26 @@ class InferenceClient:
1885
1884
  truncate: Optional[int] = None,
1886
1885
  typical_p: Optional[float] = None,
1887
1886
  watermark: Optional[bool] = None,
1888
- ) -> str: ...
1887
+ ) -> Iterable[TextGenerationStreamOutput]: ...
1889
1888
 
1890
1889
  @overload
1891
- def text_generation( # type: ignore
1890
+ def text_generation(
1892
1891
  self,
1893
1892
  prompt: str,
1894
1893
  *,
1895
- details: Literal[True] = ...,
1896
- stream: Literal[False] = ...,
1894
+ details: Literal[True],
1895
+ stream: Optional[Literal[False]] = None,
1897
1896
  model: Optional[str] = None,
1898
1897
  # Parameters from `TextGenerationInputGenerateParameters` (maintained manually)
1899
1898
  adapter_id: Optional[str] = None,
1900
1899
  best_of: Optional[int] = None,
1901
1900
  decoder_input_details: Optional[bool] = None,
1902
- do_sample: Optional[bool] = False, # Manual default value
1901
+ do_sample: Optional[bool] = None,
1903
1902
  frequency_penalty: Optional[float] = None,
1904
1903
  grammar: Optional[TextGenerationInputGrammarType] = None,
1905
1904
  max_new_tokens: Optional[int] = None,
1906
1905
  repetition_penalty: Optional[float] = None,
1907
- return_full_text: Optional[bool] = False, # Manual default value
1906
+ return_full_text: Optional[bool] = None,
1908
1907
  seed: Optional[int] = None,
1909
1908
  stop: Optional[List[str]] = None,
1910
1909
  stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead
@@ -1918,23 +1917,23 @@ class InferenceClient:
1918
1917
  ) -> TextGenerationOutput: ...
1919
1918
 
1920
1919
  @overload
1921
- def text_generation( # type: ignore
1920
+ def text_generation(
1922
1921
  self,
1923
1922
  prompt: str,
1924
1923
  *,
1925
- details: Literal[False] = ...,
1926
- stream: Literal[True] = ...,
1924
+ details: Optional[Literal[False]] = None,
1925
+ stream: Literal[True],
1927
1926
  model: Optional[str] = None,
1928
1927
  # Parameters from `TextGenerationInputGenerateParameters` (maintained manually)
1929
1928
  adapter_id: Optional[str] = None,
1930
1929
  best_of: Optional[int] = None,
1931
1930
  decoder_input_details: Optional[bool] = None,
1932
- do_sample: Optional[bool] = False, # Manual default value
1931
+ do_sample: Optional[bool] = None,
1933
1932
  frequency_penalty: Optional[float] = None,
1934
1933
  grammar: Optional[TextGenerationInputGrammarType] = None,
1935
1934
  max_new_tokens: Optional[int] = None,
1936
1935
  repetition_penalty: Optional[float] = None,
1937
- return_full_text: Optional[bool] = False, # Manual default value
1936
+ return_full_text: Optional[bool] = None, # Manual default value
1938
1937
  seed: Optional[int] = None,
1939
1938
  stop: Optional[List[str]] = None,
1940
1939
  stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead
@@ -1948,23 +1947,23 @@ class InferenceClient:
1948
1947
  ) -> Iterable[str]: ...
1949
1948
 
1950
1949
  @overload
1951
- def text_generation( # type: ignore
1950
+ def text_generation(
1952
1951
  self,
1953
1952
  prompt: str,
1954
1953
  *,
1955
- details: Literal[True] = ...,
1956
- stream: Literal[True] = ...,
1954
+ details: Optional[Literal[False]] = None,
1955
+ stream: Optional[Literal[False]] = None,
1957
1956
  model: Optional[str] = None,
1958
1957
  # Parameters from `TextGenerationInputGenerateParameters` (maintained manually)
1959
1958
  adapter_id: Optional[str] = None,
1960
1959
  best_of: Optional[int] = None,
1961
1960
  decoder_input_details: Optional[bool] = None,
1962
- do_sample: Optional[bool] = False, # Manual default value
1961
+ do_sample: Optional[bool] = None,
1963
1962
  frequency_penalty: Optional[float] = None,
1964
1963
  grammar: Optional[TextGenerationInputGrammarType] = None,
1965
1964
  max_new_tokens: Optional[int] = None,
1966
1965
  repetition_penalty: Optional[float] = None,
1967
- return_full_text: Optional[bool] = False, # Manual default value
1966
+ return_full_text: Optional[bool] = None,
1968
1967
  seed: Optional[int] = None,
1969
1968
  stop: Optional[List[str]] = None,
1970
1969
  stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead
@@ -1975,26 +1974,26 @@ class InferenceClient:
1975
1974
  truncate: Optional[int] = None,
1976
1975
  typical_p: Optional[float] = None,
1977
1976
  watermark: Optional[bool] = None,
1978
- ) -> Iterable[TextGenerationStreamOutput]: ...
1977
+ ) -> str: ...
1979
1978
 
1980
1979
  @overload
1981
1980
  def text_generation(
1982
1981
  self,
1983
1982
  prompt: str,
1984
1983
  *,
1985
- details: Literal[True] = ...,
1986
- stream: bool = ...,
1984
+ details: Optional[bool] = None,
1985
+ stream: Optional[bool] = None,
1987
1986
  model: Optional[str] = None,
1988
1987
  # Parameters from `TextGenerationInputGenerateParameters` (maintained manually)
1989
1988
  adapter_id: Optional[str] = None,
1990
1989
  best_of: Optional[int] = None,
1991
1990
  decoder_input_details: Optional[bool] = None,
1992
- do_sample: Optional[bool] = False, # Manual default value
1991
+ do_sample: Optional[bool] = None,
1993
1992
  frequency_penalty: Optional[float] = None,
1994
1993
  grammar: Optional[TextGenerationInputGrammarType] = None,
1995
1994
  max_new_tokens: Optional[int] = None,
1996
1995
  repetition_penalty: Optional[float] = None,
1997
- return_full_text: Optional[bool] = False, # Manual default value
1996
+ return_full_text: Optional[bool] = None,
1998
1997
  seed: Optional[int] = None,
1999
1998
  stop: Optional[List[str]] = None,
2000
1999
  stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead
@@ -2005,25 +2004,25 @@ class InferenceClient:
2005
2004
  truncate: Optional[int] = None,
2006
2005
  typical_p: Optional[float] = None,
2007
2006
  watermark: Optional[bool] = None,
2008
- ) -> Union[TextGenerationOutput, Iterable[TextGenerationStreamOutput]]: ...
2007
+ ) -> Union[str, TextGenerationOutput, Iterable[str], Iterable[TextGenerationStreamOutput]]: ...
2009
2008
 
2010
2009
  def text_generation(
2011
2010
  self,
2012
2011
  prompt: str,
2013
2012
  *,
2014
- details: bool = False,
2015
- stream: bool = False,
2013
+ details: Optional[bool] = None,
2014
+ stream: Optional[bool] = None,
2016
2015
  model: Optional[str] = None,
2017
2016
  # Parameters from `TextGenerationInputGenerateParameters` (maintained manually)
2018
2017
  adapter_id: Optional[str] = None,
2019
2018
  best_of: Optional[int] = None,
2020
2019
  decoder_input_details: Optional[bool] = None,
2021
- do_sample: Optional[bool] = False, # Manual default value
2020
+ do_sample: Optional[bool] = None,
2022
2021
  frequency_penalty: Optional[float] = None,
2023
2022
  grammar: Optional[TextGenerationInputGrammarType] = None,
2024
2023
  max_new_tokens: Optional[int] = None,
2025
2024
  repetition_penalty: Optional[float] = None,
2026
- return_full_text: Optional[bool] = False, # Manual default value
2025
+ return_full_text: Optional[bool] = None,
2027
2026
  seed: Optional[int] = None,
2028
2027
  stop: Optional[List[str]] = None,
2029
2028
  stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead
@@ -2101,7 +2100,7 @@ class InferenceClient:
2101
2100
  typical_p (`float`, *optional`):
2102
2101
  Typical Decoding mass
2103
2102
  See [Typical Decoding for Natural Language Generation](https://arxiv.org/abs/2202.00666) for more information
2104
- watermark (`bool`, *optional`):
2103
+ watermark (`bool`, *optional*):
2105
2104
  Watermarking with [A Watermark for Large Language Models](https://arxiv.org/abs/2301.10226)
2106
2105
 
2107
2106
  Returns:
@@ -2251,7 +2250,7 @@ class InferenceClient:
2251
2250
  "repetition_penalty": repetition_penalty,
2252
2251
  "return_full_text": return_full_text,
2253
2252
  "seed": seed,
2254
- "stop": stop if stop is not None else [],
2253
+ "stop": stop,
2255
2254
  "temperature": temperature,
2256
2255
  "top_k": top_k,
2257
2256
  "top_n_tokens": top_n_tokens,
@@ -2305,7 +2304,7 @@ class InferenceClient:
2305
2304
 
2306
2305
  # Handle errors separately for more precise error messages
2307
2306
  try:
2308
- bytes_output = self._inner_post(request_parameters, stream=stream)
2307
+ bytes_output = self._inner_post(request_parameters, stream=stream or False)
2309
2308
  except HTTPError as e:
2310
2309
  match = MODEL_KWARGS_NOT_USED_REGEX.search(str(e))
2311
2310
  if isinstance(e, BadRequestError) and match:
@@ -18,6 +18,7 @@ import base64
18
18
  import io
19
19
  import json
20
20
  import logging
21
+ import mimetypes
21
22
  from contextlib import contextmanager
22
23
  from dataclasses import dataclass
23
24
  from pathlib import Path
@@ -160,9 +161,9 @@ def _open_as_binary(
160
161
 
161
162
  @contextmanager # type: ignore
162
163
  def _open_as_binary(content: Optional[ContentT]) -> Generator[Optional[BinaryT], None, None]:
163
- """Open `content` as a binary file, either from a URL, a local path, or raw bytes.
164
+ """Open `content` as a binary file, either from a URL, a local path, raw bytes, or a PIL Image.
164
165
 
165
- Do nothing if `content` is None,
166
+ Do nothing if `content` is None.
166
167
 
167
168
  TODO: handle base64 as input
168
169
  """
@@ -184,15 +185,21 @@ def _open_as_binary(content: Optional[ContentT]) -> Generator[Optional[BinaryT],
184
185
  logger.debug(f"Opening content from {content}")
185
186
  with content.open("rb") as f:
186
187
  yield f
187
- elif hasattr(content, "save"): # PIL Image
188
- logger.debug("Converting PIL Image to bytes")
189
- buffer = io.BytesIO()
190
- content.save(buffer, format="PNG")
191
- buffer.seek(0)
192
- yield buffer
193
- else:
194
- # Otherwise: already a file-like object or None
195
- yield content
188
+ return
189
+
190
+ # If content is a PIL Image => convert to bytes
191
+ if is_pillow_available():
192
+ from PIL import Image
193
+
194
+ if isinstance(content, Image.Image):
195
+ logger.debug("Converting PIL Image to bytes")
196
+ buffer = io.BytesIO()
197
+ content.save(buffer, format=content.format or "PNG")
198
+ yield buffer.getvalue()
199
+ return
200
+
201
+ # Otherwise: already a file-like object or None
202
+ yield content # type: ignore
196
203
 
197
204
 
198
205
  def _b64_encode(content: ContentT) -> str:
@@ -202,6 +209,26 @@ def _b64_encode(content: ContentT) -> str:
202
209
  return base64.b64encode(data_as_bytes).decode()
203
210
 
204
211
 
212
+ def _as_url(content: ContentT, default_mime_type: str) -> str:
213
+ if isinstance(content, str) and (content.startswith("https://") or content.startswith("http://")):
214
+ return content
215
+
216
+ # Handle MIME type detection for different content types
217
+ mime_type = None
218
+ if isinstance(content, (str, Path)):
219
+ mime_type = mimetypes.guess_type(content, strict=False)[0]
220
+ elif is_pillow_available():
221
+ from PIL import Image
222
+
223
+ if isinstance(content, Image.Image):
224
+ # Determine MIME type from PIL Image format, in sync with `_open_as_binary`
225
+ mime_type = f"image/{(content.format or 'PNG').lower()}"
226
+
227
+ mime_type = mime_type or default_mime_type
228
+ encoded_data = _b64_encode(content)
229
+ return f"data:{mime_type};base64,{encoded_data}"
230
+
231
+
205
232
  def _b64_to_image(encoded_image: str) -> "Image":
206
233
  """Parse a base64-encoded string into a PIL Image."""
207
234
  Image = _import_pil_image()