From 96173e639f8916fb09981908aa8832c3199a9e2f Mon Sep 17 00:00:00 2001 From: moritzlaurer Date: Fri, 14 Jun 2024 16:48:52 +0200 Subject: [PATCH 01/32] add hypothesis template like in https://huggingface.co/docs/transformers/en/main_classes/pipelines#transformers.ZeroShotClassificationPipeline.__call__ --- src/huggingface_hub/inference/_client.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index d09177249e..8bfb00f580 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -2392,7 +2392,7 @@ def visual_question_answering( return VisualQuestionAnsweringOutputElement.parse_obj_as_list(response) def zero_shot_classification( - self, text: str, labels: List[str], *, multi_label: bool = False, model: Optional[str] = None + self, text: str, labels: List[str], *, multi_label: bool = False, model: Optional[str] = None, hypothesis_template: str = "This example is {}." ) -> List[ZeroShotClassificationOutputElement]: """ Provide as input a text and a set of candidate labels to classify the input text. @@ -2455,6 +2455,7 @@ def zero_shot_classification( "parameters": { "candidate_labels": ",".join(labels), "multi_label": multi_label, + "hypothesis_template": hypothesis_template, }, }, model=model, From 884a3d94fb6a126c7cdaf2802e6a6a4f2a988791 Mon Sep 17 00:00:00 2001 From: moritzlaurer Date: Fri, 14 Jun 2024 16:57:19 +0200 Subject: [PATCH 02/32] test removal of ",".join and min 2 class requirement --- src/huggingface_hub/inference/_client.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index 8bfb00f580..57ec4d8ad7 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -2446,14 +2446,14 @@ def zero_shot_classification( ``` """ # Raise ValueError if input is less than 2 labels - if len(labels) < 2: - raise ValueError("You must specify at least 2 classes to compare.") + #if len(labels) < 2: + # raise ValueError("You must specify at least 2 classes to compare.") response = self.post( json={ "inputs": text, "parameters": { - "candidate_labels": ",".join(labels), + "candidate_labels": labels, #",".join(labels), "multi_label": multi_label, "hypothesis_template": hypothesis_template, }, From 040a18bfe61edab970db7d4ab9dbcec75e1d4179 Mon Sep 17 00:00:00 2001 From: moritzlaurer Date: Fri, 14 Jun 2024 17:05:22 +0200 Subject: [PATCH 03/32] remove references to min 2 labels --- src/huggingface_hub/inference/_client.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index 57ec4d8ad7..1c785d160a 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -2401,7 +2401,7 @@ def zero_shot_classification( text (`str`): The input text to classify. labels (`List[str]`): - List of string possible labels. There must be at least 2 labels. + List strings. Each string is a possible label for the input text. multi_label (`bool`): Boolean that is set to True if classes can overlap. model (`str`, *optional*): @@ -2445,15 +2445,12 @@ def zero_shot_classification( ] ``` """ - # Raise ValueError if input is less than 2 labels - #if len(labels) < 2: - # raise ValueError("You must specify at least 2 classes to compare.") response = self.post( json={ "inputs": text, "parameters": { - "candidate_labels": labels, #",".join(labels), + "candidate_labels": labels, "multi_label": multi_label, "hypothesis_template": hypothesis_template, }, From 73506afe158b90463899cb3cde19830fe80e8039 Mon Sep 17 00:00:00 2001 From: moritzlaurer Date: Fri, 14 Jun 2024 17:22:12 +0200 Subject: [PATCH 04/32] improved doc string and added example --- src/huggingface_hub/inference/_client.py | 27 +++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index 1c785d160a..73dffe05aa 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -2401,9 +2401,10 @@ def zero_shot_classification( text (`str`): The input text to classify. labels (`List[str]`): - List strings. Each string is a possible label for the input text. + List of strings. Each string is the verbalization of a possible label for the input text. multi_label (`bool`): - Boolean that is set to True if classes can overlap. + Boolean. If True, the probability for each label is evaluated independently and multiple labels can have a probability close to 1 simultaneously or all probabilities can be close to 0. + If False, the labels are considered mutually exclusive and the probability over all labels always sums to 1. Defaults to False. model (`str`, *optional*): The model to use for inference. Can be a model ID hosted on the Hugging Face Hub or a URL to a deployed Inference Endpoint. This parameter overrides the model defined at the instance level. Defaults to None. @@ -2417,7 +2418,7 @@ def zero_shot_classification( `HTTPError`: If the request fails with an HTTP error status code other than HTTP 503. - Example: + Example for multi_label=False: ```py >>> from huggingface_hub import InferenceClient >>> client = InferenceClient() @@ -2444,6 +2445,26 @@ def zero_shot_classification( ZeroShotClassificationOutputElement(label='robots', score=0.00030448526376858354), ] ``` + + Example for multi_label=True and custom hypothesis_template: + ```py + >>> from huggingface_hub import InferenceClient + >>> client = InferenceClient() + >>> output = client.zero_shot_classification( + ... model=endpont.url, + ... text="I really like our dinner and I'm very happy. I don't like the weather though.", + ... labels=["positive", "negative", "pessimistic", "optimistic"], + ... multi_label=True, + ... hypothesis_template="This text is {} towards the weather" + ...) + >>> print(output) + [ + ZeroShotClassificationOutputElement(label='negative', score=0.9231801629066467), + ZeroShotClassificationOutputElement(label='pessimistic', score=0.8760990500450134), + ZeroShotClassificationOutputElement(label='optimistic', score=0.0008674879791215062), + ZeroShotClassificationOutputElement(label='positive', score=0.0005250611575320363) + ] + ``` """ response = self.post( From 9a0581759d3a8f5fc2f796e11b38fa6b834850ce Mon Sep 17 00:00:00 2001 From: moritzlaurer Date: Fri, 14 Jun 2024 17:23:37 +0200 Subject: [PATCH 05/32] typo fix --- src/huggingface_hub/inference/_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index 73dffe05aa..478a3cdad9 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -2456,7 +2456,7 @@ def zero_shot_classification( ... labels=["positive", "negative", "pessimistic", "optimistic"], ... multi_label=True, ... hypothesis_template="This text is {} towards the weather" - ...) + ... ) >>> print(output) [ ZeroShotClassificationOutputElement(label='negative', score=0.9231801629066467), From 9c4b1bfee1aebe59e50ecc9188e9ac257e1c1747 Mon Sep 17 00:00:00 2001 From: moritzlaurer Date: Fri, 14 Jun 2024 17:45:52 +0200 Subject: [PATCH 06/32] remove white spaces in doc string --- src/huggingface_hub/inference/_client.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index 478a3cdad9..b676c8a09c 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -2403,7 +2403,7 @@ def zero_shot_classification( labels (`List[str]`): List of strings. Each string is the verbalization of a possible label for the input text. multi_label (`bool`): - Boolean. If True, the probability for each label is evaluated independently and multiple labels can have a probability close to 1 simultaneously or all probabilities can be close to 0. + Boolean. If True, the probability for each label is evaluated independently and multiple labels can have a probability close to 1 simultaneously or all probabilities can be close to 0. If False, the labels are considered mutually exclusive and the probability over all labels always sums to 1. Defaults to False. model (`str`, *optional*): The model to use for inference. Can be a model ID hosted on the Hugging Face Hub or a URL to a deployed @@ -2445,7 +2445,7 @@ def zero_shot_classification( ZeroShotClassificationOutputElement(label='robots', score=0.00030448526376858354), ] ``` - + Example for multi_label=True and custom hypothesis_template: ```py >>> from huggingface_hub import InferenceClient @@ -2457,7 +2457,7 @@ def zero_shot_classification( ... multi_label=True, ... hypothesis_template="This text is {} towards the weather" ... ) - >>> print(output) + >>> print(output) [ ZeroShotClassificationOutputElement(label='negative', score=0.9231801629066467), ZeroShotClassificationOutputElement(label='pessimistic', score=0.8760990500450134), From c554c61a502271cb11b292605de2d05c6c1c8305 Mon Sep 17 00:00:00 2001 From: moritzlaurer Date: Mon, 17 Jun 2024 12:23:11 +0200 Subject: [PATCH 07/32] suggestions implemented --- src/huggingface_hub/inference/_client.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index b676c8a09c..40751149bb 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -2418,7 +2418,7 @@ def zero_shot_classification( `HTTPError`: If the request fails with an HTTP error status code other than HTTP 503. - Example for multi_label=False: + Example with `multi_label=False`: ```py >>> from huggingface_hub import InferenceClient >>> client = InferenceClient() @@ -2446,18 +2446,16 @@ def zero_shot_classification( ] ``` - Example for multi_label=True and custom hypothesis_template: + Example with `multi_label=True` and a custom `hypothesis_template`: ```py >>> from huggingface_hub import InferenceClient >>> client = InferenceClient() - >>> output = client.zero_shot_classification( - ... model=endpont.url, + >>> client.zero_shot_classification( ... text="I really like our dinner and I'm very happy. I don't like the weather though.", ... labels=["positive", "negative", "pessimistic", "optimistic"], ... multi_label=True, ... hypothesis_template="This text is {} towards the weather" ... ) - >>> print(output) [ ZeroShotClassificationOutputElement(label='negative', score=0.9231801629066467), ZeroShotClassificationOutputElement(label='pessimistic', score=0.8760990500450134), From d75f3482f03830726fa621e404614b1b1f1280f7 Mon Sep 17 00:00:00 2001 From: moritzlaurer Date: Mon, 17 Jun 2024 12:28:40 +0200 Subject: [PATCH 08/32] applied make style --- src/huggingface_hub/inference/_client.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index 40751149bb..2e8989d93e 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -2392,7 +2392,13 @@ def visual_question_answering( return VisualQuestionAnsweringOutputElement.parse_obj_as_list(response) def zero_shot_classification( - self, text: str, labels: List[str], *, multi_label: bool = False, model: Optional[str] = None, hypothesis_template: str = "This example is {}." + self, + text: str, + labels: List[str], + *, + multi_label: bool = False, + model: Optional[str] = None, + hypothesis_template: str = "This example is {}.", ) -> List[ZeroShotClassificationOutputElement]: """ Provide as input a text and a set of candidate labels to classify the input text. From af829188a3deb8d00c978676937b0d302ea87801 Mon Sep 17 00:00:00 2001 From: moritzlaurer Date: Mon, 17 Jun 2024 12:39:26 +0200 Subject: [PATCH 09/32] update asyncinferenceclient --- .../inference/_generated/_async_client.py | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/huggingface_hub/inference/_generated/_async_client.py b/src/huggingface_hub/inference/_generated/_async_client.py index d7571de176..cf7098d7a8 100644 --- a/src/huggingface_hub/inference/_generated/_async_client.py +++ b/src/huggingface_hub/inference/_generated/_async_client.py @@ -2425,7 +2425,13 @@ async def visual_question_answering( return VisualQuestionAnsweringOutputElement.parse_obj_as_list(response) async def zero_shot_classification( - self, text: str, labels: List[str], *, multi_label: bool = False, model: Optional[str] = None + self, + text: str, + labels: List[str], + *, + multi_label: bool = False, + model: Optional[str] = None, + hypothesis_template: str = "This example is {}.", ) -> List[ZeroShotClassificationOutputElement]: """ Provide as input a text and a set of candidate labels to classify the input text. @@ -2434,9 +2440,10 @@ async def zero_shot_classification( text (`str`): The input text to classify. labels (`List[str]`): - List of string possible labels. There must be at least 2 labels. + List of strings. Each string is the verbalization of a possible label for the input text. multi_label (`bool`): - Boolean that is set to True if classes can overlap. + Boolean. If True, the probability for each label is evaluated independently and multiple labels can have a probability close to 1 simultaneously or all probabilities can be close to 0. + If False, the labels are considered mutually exclusive and the probability over all labels always sums to 1. Defaults to False. model (`str`, *optional*): The model to use for inference. Can be a model ID hosted on the Hugging Face Hub or a URL to a deployed Inference Endpoint. This parameter overrides the model defined at the instance level. Defaults to None. @@ -2450,7 +2457,7 @@ async def zero_shot_classification( `aiohttp.ClientResponseError`: If the request fails with an HTTP error status code other than HTTP 503. - Example: + Example with `multi_label=False`: ```py # Must be run in an async context >>> from huggingface_hub import AsyncInferenceClient @@ -2478,17 +2485,33 @@ async def zero_shot_classification( ZeroShotClassificationOutputElement(label='robots', score=0.00030448526376858354), ] ``` + + Example with `multi_label=True` and a custom `hypothesis_template`: + ```py + >>> from huggingface_hub import AsyncInferenceClient + >>> client = AsyncInferenceClient() + >>> await client.zero_shot_classification( + ... text="I really like our dinner and I'm very happy. I don't like the weather though.", + ... labels=["positive", "negative", "pessimistic", "optimistic"], + ... multi_label=True, + ... hypothesis_template="This text is {} towards the weather" + ... ) + [ + ZeroShotClassificationOutputElement(label='negative', score=0.9231801629066467), + ZeroShotClassificationOutputElement(label='pessimistic', score=0.8760990500450134), + ZeroShotClassificationOutputElement(label='optimistic', score=0.0008674879791215062), + ZeroShotClassificationOutputElement(label='positive', score=0.0005250611575320363) + ] + ``` """ - # Raise ValueError if input is less than 2 labels - if len(labels) < 2: - raise ValueError("You must specify at least 2 classes to compare.") response = await self.post( json={ "inputs": text, "parameters": { - "candidate_labels": ",".join(labels), + "candidate_labels": labels, "multi_label": multi_label, + "hypothesis_template": hypothesis_template, }, }, model=model, From 4f6398b09e5319d3b713b695de7add5e21e51800 Mon Sep 17 00:00:00 2001 From: moritzlaurer Date: Mon, 17 Jun 2024 13:00:57 +0200 Subject: [PATCH 10/32] rerun python utils/generate_async_inference_client.py --update without manual async additions --- .../inference/_generated/_async_client.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/huggingface_hub/inference/_generated/_async_client.py b/src/huggingface_hub/inference/_generated/_async_client.py index cf7098d7a8..b92555d8d5 100644 --- a/src/huggingface_hub/inference/_generated/_async_client.py +++ b/src/huggingface_hub/inference/_generated/_async_client.py @@ -2459,16 +2459,15 @@ async def zero_shot_classification( Example with `multi_label=False`: ```py - # Must be run in an async context - >>> from huggingface_hub import AsyncInferenceClient - >>> client = AsyncInferenceClient() + >>> from huggingface_hub import InferenceClient + >>> client = InferenceClient() >>> text = ( - ... "A new model offers an explanation async for how the Galilean satellites formed around the solar system's" + ... "A new model offers an explanation for how the Galilean satellites formed around the solar system's" ... "largest world. Konstantin Batygin did not set out to solve one of the solar system's most puzzling" - ... " mysteries when he went async for a run up a hill in Nice, France." + ... " mysteries when he went for a run up a hill in Nice, France." ... ) >>> labels = ["space & cosmos", "scientific discovery", "microbiology", "robots", "archeology"] - >>> await client.zero_shot_classification(text, labels) + >>> client.zero_shot_classification(text, labels) [ ZeroShotClassificationOutputElement(label='scientific discovery', score=0.7961668968200684), ZeroShotClassificationOutputElement(label='space & cosmos', score=0.18570658564567566), @@ -2476,7 +2475,7 @@ async def zero_shot_classification( ZeroShotClassificationOutputElement(label='archeology', score=0.006258360575884581), ZeroShotClassificationOutputElement(label='robots', score=0.004559356719255447), ] - >>> await client.zero_shot_classification(text, labels, multi_label=True) + >>> client.zero_shot_classification(text, labels, multi_label=True) [ ZeroShotClassificationOutputElement(label='scientific discovery', score=0.9829297661781311), ZeroShotClassificationOutputElement(label='space & cosmos', score=0.755190908908844), @@ -2488,9 +2487,9 @@ async def zero_shot_classification( Example with `multi_label=True` and a custom `hypothesis_template`: ```py - >>> from huggingface_hub import AsyncInferenceClient - >>> client = AsyncInferenceClient() - >>> await client.zero_shot_classification( + >>> from huggingface_hub import InferenceClient + >>> client = InferenceClient() + >>> client.zero_shot_classification( ... text="I really like our dinner and I'm very happy. I don't like the weather though.", ... labels=["positive", "negative", "pessimistic", "optimistic"], ... multi_label=True, From 656a99772edcb55689d0843c06d2a07fa25cae88 Mon Sep 17 00:00:00 2001 From: kallewoof Date: Mon, 17 Jun 2024 16:27:38 +0900 Subject: [PATCH 11/32] print actual error message when failing to load a submodule (#2342) --- src/huggingface_hub/__init__.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/huggingface_hub/__init__.py b/src/huggingface_hub/__init__.py index 41d64f9f1b..0b692f5b01 100644 --- a/src/huggingface_hub/__init__.py +++ b/src/huggingface_hub/__init__.py @@ -503,10 +503,18 @@ def _attach(package_name, submodules=None, submod_attrs=None): def __getattr__(name): if name in submodules: - return importlib.import_module(f"{package_name}.{name}") + try: + return importlib.import_module(f"{package_name}.{name}") + except Exception as e: + print(f"Error importing {package_name}.{name}: {e}") + raise elif name in attr_to_modules: submod_path = f"{package_name}.{attr_to_modules[name]}" - submod = importlib.import_module(submod_path) + try: + submod = importlib.import_module(submod_path) + except Exception as e: + print(f"Error importing {submod_path}: {e}") + raise attr = getattr(submod, name) # If the attribute lives in a file (module) with the same From 22a5621acb4604b1f1a00ee8a9dc6775819a1f42 Mon Sep 17 00:00:00 2001 From: Woojun Jung <46880056+jungnerd@users.noreply.github.com> Date: Mon, 17 Jun 2024 16:29:51 +0900 Subject: [PATCH 12/32] =?UTF-8?q?=F0=9F=8C=90=20[i18n-KO]=20Translated=20`?= =?UTF-8?q?package=5Freference/environment=5Fvariables.md`=20to=20Korean?= =?UTF-8?q?=20(#2311)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: ko: package_reference/environment_variables.md * feat: nmt draft * feat: manual translate * fix: manual edits * fix: a minor typo * fix: added manual translate --------- Co-authored-by: Lucain --- .../environment_variables.md | 2 +- docs/source/ko/_toctree.yml | 4 +- .../environment_variables.md | 156 ++++++++++++++++++ 3 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 docs/source/ko/package_reference/environment_variables.md diff --git a/docs/source/en/package_reference/environment_variables.md b/docs/source/en/package_reference/environment_variables.md index d22671cf21..c5c2b37916 100644 --- a/docs/source/en/package_reference/environment_variables.md +++ b/docs/source/en/package_reference/environment_variables.md @@ -85,7 +85,7 @@ as `True` if its value is one of `{"1", "ON", "YES", "TRUE"}` (case-insensitive) ### HF_HUB_OFFLINE -If set, no HTTP calls will me made to the Hugging Face Hub. If you try to download files, only the cached files will be accessed. If no cache file is detected, an error is raised This is useful in case your network is slow and you don't care about having the latest version of a file. +If set, no HTTP calls will be made to the Hugging Face Hub. If you try to download files, only the cached files will be accessed. If no cache file is detected, an error is raised This is useful in case your network is slow and you don't care about having the latest version of a file. If `HF_HUB_OFFLINE=1` is set as environment variable and you call any method of [`HfApi`], an [`~huggingface_hub.utils.OfflineModeIsEnabled`] exception will be raised. diff --git a/docs/source/ko/_toctree.yml b/docs/source/ko/_toctree.yml index 63950fc315..9144ae7641 100644 --- a/docs/source/ko/_toctree.yml +++ b/docs/source/ko/_toctree.yml @@ -50,8 +50,8 @@ title: 개요 - local: package_reference/login title: 로그인 및 로그아웃 - - local: in_translation - title: (번역 중) Environment variables + - local: package_reference/environment_variables + title: 환경 변수 - local: package_reference/repository title: 로컬 및 온라인 리포지토리 관리 - local: package_reference/hf_api diff --git a/docs/source/ko/package_reference/environment_variables.md b/docs/source/ko/package_reference/environment_variables.md new file mode 100644 index 0000000000..f669a9f8ef --- /dev/null +++ b/docs/source/ko/package_reference/environment_variables.md @@ -0,0 +1,156 @@ + + +# 환경 변수[[environment-variables]] + +`huggingface_hub`는 환경 변수를 사용해 설정할 수 있습니다. + +환경 변수에 대해 잘 알지 못하다면 그에 대한 문서인 [macOS and Linux](https://linuxize.com/post/how-to-set-and-list-environment-variables-in-linux/)와 +[Windows](https://phoenixnap.com/kb/windows-set-environment-variable)를 참고하세요. + +이 문서에서는 `huggingface_hub`와 관련된 모든 환경 변수와 그 의미에 대해 안내합니다. + +## 일반적인 변수[[generic]] + +### HF_INFERENCE_ENDPOINT[[hfinferenceendpoint]] + +추론 API 기본 URL을 구성합니다. 조직에서 추론 API를 직접 가리키는 것이 아니라 API 게이트웨이를 가리키는 경우 이 변수를 설정할 수 있습니다. + +기본값은 `"https://api-inference.huggingface.com"`입니다. + +### HF_HOME[[hfhome]] + +`huggingface_hub`가 어디에 데이터를 로컬로 저장할 지 위치를 구성합니다. 특히 토큰과 캐시가 이 폴더에 저장됩니다. + +[XDG_CACHE_HOME](#xdgcachehome)이 설정되어 있지 않다면, 기본값은 `"~/.cache/huggingface"`입니다. + +### HF_HUB_CACHE[[hfhubcache]] + +Hub의 리포지토리가 로컬로 캐시될 위치(모델, 데이터세트 및 스페이스)를 구성합니다. + +기본값은 `"$HF_HOME/hub"` (예로 들면, 기본 설정은 `"~/.cache/huggingface/hub"`)입니다. + +### HF_ASSETS_CACHE[[hfassetscache]] + +다운스트림 라이브러리에서 생성된 [assets](../guides/manage-cache#caching-assets)가 로컬로 캐시되는 위치를 구성합니다. +이 assets은 전처리된 데이터, GitHub에서 다운로드한 파일, 로그, ... 등이 될 수 있습니다. + +기본값은 `"$HF_HOME/assets"` (예로 들면, 기본 설정은 `"~/.cache/huggingface/assets"`)입니다. + +### HF_TOKEN[[hftoken]] + +Hub에 인증하기 위한 사용자 액세스 토큰을 구성합니다. 이 값을 설정하면 머신에 저장된 토큰을 덮어씁니다(`$HF_TOKEN_PATH`, 또는 `$HF_TOKEN_PATH`가 설정되지 않은 경우 `"$HF_HOME/token"`에 저장됨). + +인증에 대한 자세한 내용은 [이 섹션](../quick-start#인증)을 참조하세요. + +### HF_TOKEN_PATH[[hftokenpath]] + +`huggingface_hub`가 사용자 액세스 토큰(User Access Token)을 저장할 위치를 구성합니다. 기본값은 `"$HF_HOME/token"`(예로 들면, 기본 설정은 `~/.cache/huggingface/token`)입니다. + +### HF_HUB_VERBOSITY[[hfhubverbosity]] + +`huggingface_hub`의 로거(logger)의 상세도 수준(verbosity level)을 설정합니다. 다음 중 하나여야 합니다. +`{"debug", "info", "warning", "error", "critical"}` 중 하나여야 합니다. + +기본값은 `"warning"`입니다. + +더 자세한 정보를 알아보고 싶다면, [logging reference](../package_reference/utilities#huggingface_hub.utils.logging.get_verbosity)를 살펴보세요. + +### HF_HUB_LOCAL_DIR_AUTO_SYMLINK_THRESHOLD[[hfhublocaldirautosymlinkthreshold]] + +이 환경 변수는 더 이상 사용되지 않으며 이제 `huggingface_hub`에서 무시됩니다. 로컬 디렉터리로 파일을 다운로드할 때 더 이상 심볼릭 링크에 의존하지 않습니다. + +### HF_HUB_ETAG_TIMEOUT[[hfhubetagtimeout]] + +파일을 다운로드하기 전에 리포지토리에서 최신 메타데이터를 가져올 때 서버 응답을 기다리는 시간(초)을 정의하는 정수 값입니다. 요청 시간이 초과되면 `huggingface_hub`는 기본적으로 로컬에 캐시된 파일을 사용합니다. 값을 낮게 설정하면 이미 파일을 캐시한 연결 속도가 느린 컴퓨터의 워크플로 속도가 빨라집니다. 값이 클수록 더 많은 경우에서 메타데이터 호출이 성공할 수 있습니다. 기본값은 10초입니다. + +### HF_HUB_DOWNLOAD_TIMEOUT[[hfhubdownloadtimeout]] + +파일을 다운로드할 때 서버 응답을 기다리는 시간(초)을 정의하는 정수 값입니다. 요청 시간이 초과되면 TimeoutError가 발생합니다. 연결 속도가 느린 컴퓨터에서는 값을 높게 설정하는 것이 좋습니다. 값이 작을수록 네트워크가 완전히 중단된 경우에 프로세스가 더 빨리 실패합니다. 기본값은 10초입니다. + +## 불리언 값[[boolean-values]] + +다음 환경 변수는 불리언 값을 요구합니다. 변수는 값이 `{"1", "ON", "YES", "TRUE"}`(대소문자 구분 없음) 중 하나이면 `True`로 간주합니다. 다른 값(또는 정의되지 않음)은 `False`로 간주됩니다. + +### HF_HUB_OFFLINE[[hfhuboffline]] + +이 옵션을 설정하면 Hugging Face Hub에 HTTP 호출이 이루어지지 않습니다. 파일을 다운로드하려고 하면 캐시된 파일만 액세스됩니다. 캐시 파일이 감지되지 않으면 오류를 발생합니다. 네트워크 속도가 느리고 파일의 최신 버전이 중요하지 않은 경우에 유용합니다. + +환경 변수로 `HF_HUB_OFFLINE=1`이 설정되어 있고 [`HfApi`]의 메소드를 호출하면 [`~huggingface_hub.utils.OfflineModeIsEnabled`] 예외가 발생합니다. + +**참고:** 최신 버전의 파일이 캐시되어 있더라도 `hf_hub_download`를 호출하면 새 버전을 사용할 수 없는지 확인하기 위해 HTTP 요청이 발생합니다. `HF_HUB_OFFLINE=1`을 설정하면 이 호출을 건너뛰어 로딩 시간이 빨라집니다. + +### HF_HUB_DISABLE_IMPLICIT_TOKEN[[hfhubdisableimplicittoken]] + +Hub에 대한 모든 요청이 반드시 인증을 필요로 하는 것은 아닙니다. 예를 들어 `"gpt2"` 모델에 대한 세부 정보를 요청하는 경우에는 인증이 필요하지 않습니다. 그러나 사용자가 [로그인](../package_reference/login) 상태인 경우, 기본 동작은 사용자 경험을 편하게 하기 위해 비공개 또는 게이트 리포지토리에 액세스할 때 항상 토큰을 전송하는 것(HTTP 401 권한 없음이 표시되지 않음)입니다. 개인 정보 보호를 위해 `HF_HUB_DISABLE_IMPLICIT_TOKEN=1`로 설정하여 이 동작을 비활성화할 수 있습니다. 이 경우 토큰은 "쓰기 권한" 호출(예: 커밋 생성)에만 전송됩니다. + +**참고:** 토큰을 항상 전송하는 것을 비활성화하면 이상한 부작용이 발생할 수 있습니다. 예를 들어 Hub에 모든 모델을 나열하려는 경우 당신의 비공개 모델은 나열되지 않습니다. 사용자 스크립트에 명시적으로 `token=True` 인수를 전달해야 합니다. + +### HF_HUB_DISABLE_PROGRESS_BARS[[hfhubdisableprogressbars]] + +시간이 오래 걸리는 작업의 경우 `huggingface_hub`는 기본적으로 진행률 표시줄을 표시합니다(tqdm 사용). +모든 진행률 표시줄을 한 번에 비활성화하려면 `HF_HUB_DISABLE_PROGRESS_BARS=1`으로 설정하면 됩니다. + +### HF_HUB_DISABLE_SYMLINKS_WARNING[[hfhubdisablesymlinkswarning]] + +Windows 머신을 사용하는 경우 개발자 모드를 활성화하거나 관리자 모드에서 `huggingface_hub`를 관리자 모드로 실행하는 것이 좋습니다. 그렇지 않은 경우 `huggingface_hub`가 캐시 시스템에 심볼릭 링크를 생성할 수 없습니다. 모든 스크립트를 실행할 수 있지만 일부 대용량 파일이 하드 드라이브에 중복될 수 있으므로 사용자 경힘이 저하될 수 있습니다. 이 동작을 경고하기 위해 경고 메시지가 나타납니다. `HF_HUB_DISABLE_SYMLINKS_WARNING=1`로 설정하면 이 경고를 비활성화할 수 있습니다. + +자세한 내용은 [캐시 제한](../guides/manage-cache#limitations)을 참조하세요. + +### HF_HUB_DISABLE_EXPERIMENTAL_WARNING[[hfhubdisableexperimentalwarning]] + +`huggingface_hub`의 일부 기능은 실험 단계입니다. 즉, 사용은 가능하지만 향후 유지될 것이라고 보장할 수는 없습니다. 특히 이러한 기능의 API나 동작은 지원 중단 없이 업데이트될 수 있습니다. 실험적 기능을 사용할 때는 이에 대한 경고를 위해 경고 메시지가 나타납니다. 실험적 기능을 사용하여 잠재적인 문제를 디버깅하는 것이 편하다면 `HF_HUB_DISABLE_EXPERIMENTAL_WARNING=1`으로 설정하여 경고를 비활성화할 수 있습니다. + +실험적인 기능을 사용 중이라면 알려주세요! 여러분의 피드백은 기능을 설계하고 개선하는 데 도움이 됩니다. + +### HF_HUB_DISABLE_TELEMETRY[[hfhubdisabletelemetry]] + +기본적으로 일부 데이터는 사용량을 모니터링하고 문제를 디버그하며 기능의 우선순위를 정하는 데 도움을 주기 위해 HF 라이브러리(`transformers`, `datasets`, `gradio`,...)에서 수집합니다. 각 라이브러리는 자체 정책(즉, 모니터링할 사용량)을 정의하지만 핵심 구현은 `huggingface_hub`에서 이루어집니다([`send_telemetry`] 참조). + +환경 변수로 `HF_HUB_DISABLE_TELEMETRY=1`을 설정하여 원격 측정을 전역적으로 비활성화할 수 있습니다. + +### HF_HUB_ENABLE_HF_TRANSFER[[hfhubenablehftransfer]] + +Hub에서 `hf_transfer`를 사용하여 더 빠르게 업로드 및 다운로드하려면 `True`로 설정하세요. +기본적으로 `huggingface_hub`는 파이썬 기반 `requests.get` 및 `requests.post` 함수를 사용합니다. +이 함수들은 안정적이고 다용도로 사용할 수 있지만 대역폭이 높은 머신에서는 가장 효율적인 선택이 아닐 수 있습니다. [`hf_transfer`](https://github.com/huggingface/hf_transfer)는 대용량 파일을 작은 부분으로 분할하여 사용 대역폭을 최대화하고 +여러 스레드를 사용하여 동시에 전송함으로써 대역폭을 최대화하기 위해 개발된 Rust 기반 패키지입니다. 이 접근 방식은 전송 속도를 거의 두 배로 높일 수 있습니다. +`hf_transfer`를 사용하려면: + +1. `huggingface_hub`를 설치할 때 `hf_transfer`를 추가로 지정합니다. + (예시: `pip install huggingface_hub[hf_transfer]`). +2. 환경 변수로 `HF_HUB_ENABLE_HF_TRANSFER=1`을 설정합니다. + +`hf_transfer`를 사용하면 특정 제한 사항이 있다는 점에 유의하세요. 순수 파이썬 기반이 아니므로 오류 디버깅이 어려울 수 있습니다. 또한 `hf_transfer`에는 다운로드 재개 및 프록시와 같은 몇 가지 사용자 친화적인 기능이 없습니다. 이런 부족한 부분은 Rust 로직의 단순성과 속도를 유지하기 위해 의도한 것입니다. 이런 이유들로, `hf_transfer`는 `huggingface_hub`에서 기본적으로 활성화되지 않습니다. + +## 사용되지 않는 환경 변수[[deprecated-environment-variables]] + +Hugging Face 생태계의 모든 환경 변수를 표준화하기 위해 일부 변수는 사용되지 않는 것으로 표시되었습니다. 해당 변수는 여전히 작동하지만 더 이상 대체한 변수보다 우선하지 않습니다. 다음 표에는 사용되지 않는 변수와 해당 대체 변수가 간략하게 설명되어 있습니다: + +| 사용되지 않는 변수 | 대체 변수 | +| --- | --- | +| `HUGGINGFACE_HUB_CACHE` | `HF_HUB_CACHE` | +| `HUGGINGFACE_ASSETS_CACHE` | `HF_ASSETS_CACHE` | +| `HUGGING_FACE_HUB_TOKEN` | `HF_TOKEN` | +| `HUGGINGFACE_HUB_VERBOSITY` | `HF_HUB_VERBOSITY` | + +## 외부 도구[[from-external-tools]] + +일부 환경 변수는 `huggingface_hub`에만 특정되지는 않지만 설정 시 함께 고려됩니다. + +### DO_NOT_TRACK[[donottrack]] + +불리언 값입니다. `hf_hub_disable_telemetry`에 해당합니다. True로 설정하면 Hugging Face Python 생태계(`transformers`, `diffusers`, `gradio` 등)에서 원격 측정이 전역적으로 비활성화됩니다. 자세한 내용은 https://consoledonottrack.com/ 을 참조하세요. + +### NO_COLOR[[nocolor]] + +불리언 값입니다. 이 값을 설정하면 `huggingface-cli` 도구는 ANSI 색상을 출력하지 않습니다. [no-color.org](https://no-color.org/)를 참조하세요. + +### XDG_CACHE_HOME[[xdgcachehome]] + +`HF_HOME`이 설정되지 않은 경우에만 사용합니다! + +이것은 Linux 시스템에서 [사용자별 비필수(캐시된) 데이터](https://wiki.archlinux.org/title/XDG_Base_Directory)가 쓰여져야 하는 위치를 구성하는 기본 방법입니다. + +`HF_HOME`이 설정되지 않은 경우 기본 홈은 `"~/.cache/huggingface"`대신 `"$XDG_CACHE_HOME/huggingface"`가 됩니다. From 8f98cec234adf9a86115acbe83532d05434d09ad Mon Sep 17 00:00:00 2001 From: Lucain Date: Mon, 17 Jun 2024 10:38:54 +0200 Subject: [PATCH 13/32] Do not raise on `.resume()` if Inference Endpoint is already running (#2335) * Do not raise on .resume() if Inference Endpoints is already running * make style * fix test --- src/huggingface_hub/_inference_endpoints.py | 11 +++++++++-- src/huggingface_hub/hf_api.py | 19 +++++++++++++++++-- tests/test_inference_endpoints.py | 2 +- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/huggingface_hub/_inference_endpoints.py b/src/huggingface_hub/_inference_endpoints.py index 92e407b81a..cff348bca0 100644 --- a/src/huggingface_hub/_inference_endpoints.py +++ b/src/huggingface_hub/_inference_endpoints.py @@ -315,16 +315,23 @@ def pause(self) -> "InferenceEndpoint": self._populate_from_raw() return self - def resume(self) -> "InferenceEndpoint": + def resume(self, running_ok: bool = True) -> "InferenceEndpoint": """Resume the Inference Endpoint. This is an alias for [`HfApi.resume_inference_endpoint`]. The current object is mutated in place with the latest data from the server. + Args: + running_ok (`bool`, *optional*): + If `True`, the method will not raise an error if the Inference Endpoint is already running. Defaults to + `True`. + Returns: [`InferenceEndpoint`]: the same Inference Endpoint, mutated in place with the latest data. """ - obj = self._api.resume_inference_endpoint(name=self.name, namespace=self.namespace, token=self._token) # type: ignore [arg-type] + obj = self._api.resume_inference_endpoint( + name=self.name, namespace=self.namespace, running_ok=running_ok, token=self._token + ) # type: ignore [arg-type] self.raw = obj.raw self._populate_from_raw() return self diff --git a/src/huggingface_hub/hf_api.py b/src/huggingface_hub/hf_api.py index 54f9f79925..901bc4f4be 100644 --- a/src/huggingface_hub/hf_api.py +++ b/src/huggingface_hub/hf_api.py @@ -7489,7 +7489,12 @@ def pause_inference_endpoint( return InferenceEndpoint.from_raw(response.json(), namespace=namespace, token=token) def resume_inference_endpoint( - self, name: str, *, namespace: Optional[str] = None, token: Union[bool, str, None] = None + self, + name: str, + *, + namespace: Optional[str] = None, + running_ok: bool = True, + token: Union[bool, str, None] = None, ) -> InferenceEndpoint: """Resume an Inference Endpoint. @@ -7500,6 +7505,9 @@ def resume_inference_endpoint( The name of the Inference Endpoint to resume. namespace (`str`, *optional*): The namespace in which the Inference Endpoint is located. Defaults to the current user. + running_ok (`bool`, *optional*): + If `True`, the method will not raise an error if the Inference Endpoint is already running. Defaults to + `True`. token (Union[bool, str, None], optional): A valid user access token (string). Defaults to the locally saved token, which is the recommended method for authentication (see @@ -7515,7 +7523,14 @@ def resume_inference_endpoint( f"{INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}/{name}/resume", headers=self._build_hf_headers(token=token), ) - hf_raise_for_status(response) + try: + hf_raise_for_status(response) + except HfHubHTTPError as error: + # If already running (and it's ok), then fetch current status and return + if running_ok and error.response.status_code == 400 and "already running" in error.response.text: + return self.get_inference_endpoint(name, namespace=namespace, token=token) + # Otherwise, raise the error + raise return InferenceEndpoint.from_raw(response.json(), namespace=namespace, token=token) diff --git a/tests/test_inference_endpoints.py b/tests/test_inference_endpoints.py index 000609240f..019d04f57e 100644 --- a/tests/test_inference_endpoints.py +++ b/tests/test_inference_endpoints.py @@ -256,4 +256,4 @@ def test_resume(mock: Mock): endpoint = InferenceEndpoint.from_raw(MOCK_RUNNING, namespace="foo") mock.return_value = InferenceEndpoint.from_raw(MOCK_INITIALIZING, namespace="foo") endpoint.resume() - mock.assert_called_once_with(namespace="foo", name="my-endpoint-name", token=None) + mock.assert_called_once_with(namespace="foo", name="my-endpoint-name", token=None, running_ok=True) From 414290198a3827870b48d5de6c18309dbff3ce53 Mon Sep 17 00:00:00 2001 From: Sungmin Oh Date: Tue, 18 Jun 2024 05:54:03 +0900 Subject: [PATCH 14/32] =?UTF-8?q?=F0=9F=8C=90=20[i18n-KO]=20Translated=20`?= =?UTF-8?q?package=5Freference/webhooks=5Fserver.md`=20to=20Korean=20(#234?= =?UTF-8?q?4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: ko: package_reference/webhooks_server * feat: nmt draft * fix: manual edits --- docs/source/ko/_toctree.yml | 4 +- .../ko/package_reference/webhooks_server.md | 75 +++++++++++++++++++ 2 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 docs/source/ko/package_reference/webhooks_server.md diff --git a/docs/source/ko/_toctree.yml b/docs/source/ko/_toctree.yml index 9144ae7641..e4a9a6aee5 100644 --- a/docs/source/ko/_toctree.yml +++ b/docs/source/ko/_toctree.yml @@ -82,7 +82,7 @@ title: Space 런타임 - local: package_reference/tensorboard title: TensorBoard 로거 - - local: in_translation - title: (번역 중) Webhooks server + - local: package_reference/webhooks_server + title: 웹훅 서버 - local: package_reference/serialization title: 직렬화 \ No newline at end of file diff --git a/docs/source/ko/package_reference/webhooks_server.md b/docs/source/ko/package_reference/webhooks_server.md new file mode 100644 index 0000000000..9712c6c0be --- /dev/null +++ b/docs/source/ko/package_reference/webhooks_server.md @@ -0,0 +1,75 @@ + + +# 웹훅 서버[[webhooks-server]] + +웹훅은 MLOps 관련 기능의 기반이 됩니다. 이를 통해 특정 저장소의 새로운 변경 사항을 수신하거나, 관심 있는 특정 사용자/조직에 속한 모든 저장소의 변경 사항을 받아볼 수 있습니다. +Huggingface Hub의 웹훅에 대해 더 자세히 알아보려면 이 [가이드](https://huggingface.co/docs/hub/webhooks)를 읽어보세요. + + + +웹훅 서버를 설정하고 Space로 배포하는 방법은 이 단계별 [가이드](../guides/webhooks_server)를 확인하세요. + + + + + +이 기능은 실험적인 기능입니다. 본 API는 현재 개선 작업 중이며, 향후 사전 통지 없이 주요 변경 사항이 도입될 수 있음을 의미합니다. `requirements`에서 `huggingface_hub`의 버전을 고정하는 것을 권장합니다. 참고로 실험적 기능을 사용하면 경고가 트리거 됩니다. 이 경고 트리거를 비활성화 시키길 원한다면 환경변수 `HF_HUB_DISABLE_EXPERIMENTAL_WARNING=1`를 설정하세요. + + + +## 서버[[server]] +여기서 서버는 하나의 [Gradio](https://gradio.app/) 앱을 의미합니다. Gradio에는 사용자 또는 사용자에게 지침을 표시하는 UI와 웹훅을 수신하기 위한 API가 있습니다. 웹훅 엔드포인트를 구현하는 것은 함수에 데코레이터를 추가하는 것만큼 간단합니다. 서버를 Space에 배포하기 전에 Gradio 터널을 사용하여 웹훅을 머신으로 리디렉션하여 디버깅할 수 있습니다. + +### WebhooksServer[[huggingface_hub.WebhooksServer]] + +[[autodoc]] huggingface_hub.WebhooksServer + +### @webhook_endpoint[[huggingface_hub.webhook_endpoint]] + +[[autodoc]] huggingface_hub.webhook_endpoint + +## 페이로드[[huggingface_hub.WebhookPayload]] + +[`WebhookPayload`]는 웹훅의 페이로드를 포함하는 기본 데이터 구조입니다. 이것은 `pydantic` 클래스로서 FastAPI에서 매우 쉽게 사용할 수 있습니다. 즉 WebhookPayload를 웹후크 엔드포인트에 매개변수로 전달하면 자동으로 유효성이 검사되고 파이썬 객체로 파싱됩니다. + +웹훅 페이로드에 대한 자세한 사항은 이 [가이드](https://huggingface.co/docs/hub/webhooks#webhook-payloads)를 참고하세요. + +[[autodoc]] huggingface_hub.WebhookPayload + +### WebhookPayload[[huggingface_hub.WebhookPayload]] + +[[autodoc]] huggingface_hub.WebhookPayload + +### WebhookPayloadComment[[huggingface_hub.WebhookPayloadComment]] + +[[autodoc]] huggingface_hub.WebhookPayloadComment + +### WebhookPayloadDiscussion[[huggingface_hub.WebhookPayloadDiscussion]] + +[[autodoc]] huggingface_hub.WebhookPayloadDiscussion + +### WebhookPayloadDiscussionChanges[[huggingface_hub.WebhookPayloadDiscussionChanges]] + +[[autodoc]] huggingface_hub.WebhookPayloadDiscussionChanges + +### WebhookPayloadEvent[[huggingface_hub.WebhookPayloadEvent]] + +[[autodoc]] huggingface_hub.WebhookPayloadEvent + +### WebhookPayloadMovedTo[[huggingface_hub.WebhookPayloadMovedTo]] + +[[autodoc]] huggingface_hub.WebhookPayloadMovedTo + +### WebhookPayloadRepo[[huggingface_hub.WebhookPayloadRepo]] + +[[autodoc]] huggingface_hub.WebhookPayloadRepo + +### WebhookPayloadUrl[[huggingface_hub.WebhookPayloadUrl]] + +[[autodoc]] huggingface_hub.WebhookPayloadUrl + +### WebhookPayloadWebhook[[huggingface_hub.WebhookPayloadWebhook]] + +[[autodoc]] huggingface_hub.WebhookPayloadWebhook From e9d1acdb8866e22a199cc8df24bf7448213ef970 Mon Sep 17 00:00:00 2001 From: Lucain Date: Mon, 24 Jun 2024 13:36:19 +0200 Subject: [PATCH 15/32] Support `resource_group_id` in `create_repo` (#2324) * Support resource_group_id in create_repo * docs * as tip * typoe --- docs/source/en/guides/repository.md | 6 ++++++ src/huggingface_hub/hf_api.py | 11 ++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/source/en/guides/repository.md b/docs/source/en/guides/repository.md index a9c9d3e9be..4e6aab5b8d 100644 --- a/docs/source/en/guides/repository.md +++ b/docs/source/en/guides/repository.md @@ -61,6 +61,12 @@ When you create a repository, you can set your repository visibility with the `p If you want to change the repository visibility at a later time, you can use the [`update_repo_visibility`] function. + + +If you are part of an organization with an Enterprise plan, you can create a repo in a specific resource group by passing `resource_group_id` as parameter to [`create_repo`]. Resource groups are a security feature to control which members from your org can access a given resource. You can get the resource group ID by copying it from your org settings page url on the Hub (e.g. `"https://huggingface.co/organizations/huggingface/settings/resource-groups/66670e5163145ca562cb1988"` => `"66670e5163145ca562cb1988"`). For more details about resource group, check out this [guide](https://huggingface.co/docs/hub/en/security-resource-groups). + + + ### Delete a repository Delete a repository with [`delete_repo`]. Make sure you want to delete a repository because this is an irreversible process! diff --git a/src/huggingface_hub/hf_api.py b/src/huggingface_hub/hf_api.py index 901bc4f4be..eddaf9130f 100644 --- a/src/huggingface_hub/hf_api.py +++ b/src/huggingface_hub/hf_api.py @@ -3089,6 +3089,7 @@ def create_repo( private: bool = False, repo_type: Optional[str] = None, exist_ok: bool = False, + resource_group_id: Optional[str] = None, space_sdk: Optional[str] = None, space_hardware: Optional[SpaceHardware] = None, space_storage: Optional[SpaceStorage] = None, @@ -3115,6 +3116,11 @@ def create_repo( `None`. exist_ok (`bool`, *optional*, defaults to `False`): If `True`, do not raise an error if repo already exists. + resource_group_id (`str`, *optional*): + Resource group in which to create the repo. Resource groups is only available for organizations and + allow to define which members of the organization can access the resource. The ID of a resource group + can be found in the URL of the resource's page on the Hub (e.g. `"66670e5163145ca562cb1988"`). + To learn more about resource groups, see https://huggingface.co/docs/hub/en/security-resource-groups. space_sdk (`str`, *optional*): Choice of SDK to use if repo_type is "space". Can be "streamlit", "gradio", "docker", or "static". space_hardware (`SpaceHardware` or `str`, *optional*): @@ -3182,8 +3188,11 @@ def create_repo( # Testing purposes only. # See https://github.com/huggingface/huggingface_hub/pull/733/files#r820604472 json["lfsmultipartthresh"] = self._lfsmultipartthresh # type: ignore - headers = self._build_hf_headers(token=token) + if resource_group_id is not None: + json["resourceGroupId"] = resource_group_id + + headers = self._build_hf_headers(token=token) while True: r = get_session().post(path, headers=headers, json=json) if r.status_code == 409 and "Cannot create repo: another conflicting operation is in progress" in r.text: From ae4fed11a76cb983a06975d112388cc91f109d89 Mon Sep 17 00:00:00 2001 From: JibrilEl <141321154+JibrilEl@users.noreply.github.com> Date: Wed, 26 Jun 2024 17:52:36 +0200 Subject: [PATCH 16/32] [i18n-FR] Translated "Integrations" to french (sub PR of 1900) (#2329) * Translated toctree & git_vs_htttp * Translated the cli guide * Testing to see if user is well configured * TEsting to see if branch is well configured * Translated index * Translated quick-start * Corrected a minor error in the english doc * Reverting a wrong change * Translated installation.md * Translated community.md * Translated download.md * Translated hf_file_system.md * Translated inference_client * Translated inference_endpoints.md * Fixed a few errors in the translation * Translated integrations.md * Translated mana-cache.md. Did not find a good translfation for cache-system * Translated manage-space.md * Translated overview.md * Translated package-reference file * Translated hf_api, login, mixins, repository, space_runtime and tensorboard in the package reference * Finished the translation of package reference by translating utilities and webhooks servers * Translated model-cards.md * Translated collections.md * translated community.md * Translated download.md, corrected an error in the english version and changed a n inacurrate translation in other files * translated hf_file_system * Translated inference_endpoints.md * Translated inference.md * translated repository.md * Translated search.md * Translated webhooks_server.md * corrected webhooks * Translated upload.md * Added "fr" to .github/workflow * Deleted redirects as it is not needed * Corrected toctree.yml * Corrected errors o quick-start.md * Corrected installation.md * Changed the translation of the product "space" in the whole documentation. * Corrected git_vs_http * Corrected CLI.md * Corrected collections.md * Corrected community.md * Corrected download.md * Corrected hf_file_system * Correction of docs/source/fr/concepts/git_vs_http.md Co-authored-by: Lucain * Corrected git vs http and index.md * Finished correcting index.md * Update docs/source/fr/installation.md Co-authored-by: Lucain * Update docs/source/fr/_toctree.yml Co-authored-by: Lucain * Update docs/source/fr/installation.md Co-authored-by: Lucain * Update docs/source/fr/installation.md Co-authored-by: Lucain * Update docs/source/fr/installation.md Co-authored-by: Lucain * Update docs/source/fr/installation.md Co-authored-by: Lucain * Update docs/source/fr/installation.md Co-authored-by: Lucain * Update docs/source/fr/installation.md Co-authored-by: Lucain * Update docs/source/fr/installation.md Co-authored-by: Lucain * Update docs/source/fr/installation.md Co-authored-by: Lucain * Update docs/source/fr/installation.md Co-authored-by: Lucain * Update docs/source/fr/installation.md Co-authored-by: Lucain * Update docs/source/fr/installation.md Co-authored-by: Lucain * Update docs/source/fr/installation.md Co-authored-by: Lucain * Update docs/source/fr/installation.md Co-authored-by: Lucain * Update docs/source/fr/installation.md Co-authored-by: Lucain * Finished correcting index.md * Corrected inference endpoint, a lot of mistakes might have to look at it again * Update docs/source/fr/concepts/git_vs_http.md Co-authored-by: Lucain * Update docs/source/fr/concepts/git_vs_http.md Co-authored-by: Lucain * Update docs/source/fr/concepts/git_vs_http.md Co-authored-by: Lucain * Update docs/source/fr/_toctree.yml Co-authored-by: Lucain * Update docs/source/fr/_toctree.yml Co-authored-by: Lucain * Update docs/source/fr/_toctree.yml Co-authored-by: Lucain * Update docs/source/fr/_toctree.yml Co-authored-by: Lucain * Update docs/source/fr/_toctree.yml Co-authored-by: Lucain * Update docs/source/fr/_toctree.yml Co-authored-by: Lucain * Update docs/source/fr/_toctree.yml Co-authored-by: Lucain * Update docs/source/fr/concepts/git_vs_http.md Co-authored-by: Lucain * Update docs/source/fr/concepts/git_vs_http.md Co-authored-by: Lucain * Update docs/source/fr/concepts/git_vs_http.md Co-authored-by: Lucain * Update docs/source/fr/concepts/git_vs_http.md Co-authored-by: Lucain * Update docs/source/fr/concepts/git_vs_http.md Co-authored-by: Lucain * Update docs/source/fr/concepts/git_vs_http.md Co-authored-by: Lucain * Update docs/source/fr/concepts/git_vs_http.md Co-authored-by: Lucain * Deleted files * Revert "Deleted files" This reverts commit 34c49a7cbe74faf605621d6e96ee016a62beaa65. * Deleted files * Deleted files * Delete files * Update docs/source/fr/_toctree.yml Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain * Update docs/source/fr/guides/integrations.md Co-authored-by: Lucain --------- Co-authored-by: JibrilEl Co-authored-by: Lucain --- docs/source/fr/_toctree.yml | 5 +- docs/source/fr/guides/integrations.md | 275 ++++++++++++++++++++++++++ 2 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 docs/source/fr/guides/integrations.md diff --git a/docs/source/fr/_toctree.yml b/docs/source/fr/_toctree.yml index b42faa9b79..62137bd951 100644 --- a/docs/source/fr/_toctree.yml +++ b/docs/source/fr/_toctree.yml @@ -9,4 +9,7 @@ - title: "Concepts" sections: - local: concepts/git_vs_http - title: Git ou HTTP? \ No newline at end of file + title: Git ou HTTP? +- title: "Guides" + - local: guides/integrations + title: Intégrer dans une librarie \ No newline at end of file diff --git a/docs/source/fr/guides/integrations.md b/docs/source/fr/guides/integrations.md new file mode 100644 index 0000000000..5813707f90 --- /dev/null +++ b/docs/source/fr/guides/integrations.md @@ -0,0 +1,275 @@ + + +# Intégrez votre framework de ML avec le Hub + +Le Hugging Face Hub facilite l'hébergement et le partage de modèles et de jeux de données. +Des [dizaines de librairies](https://huggingface.co/docs/hub/models-libraries) sont intégrées à cet écosysteme. La communauté travaille constamment à en intégrer de nouvelles et contribue ainsi à faciliter la collaboration dans le milieu du machine learning. La librairie `huggingface_hub` joue un rôle clé dans ce processus puisqu'elle permet d'interagir avec le Hub depuis n'importe quel script Python. + +Il existe quatre façons principales d'intégrer une bibliothèque au Hub : +1. **Push to Hub** implémente une méthode pour upload un modèle sur le Hub. Cela inclut les paramètres du modèle, sa fiche descriptive (appelée [Model Card](https://huggingface.co/docs/huggingface_hub/how-to-model-cards)) et toute autre information pertinente lié au modèle (par exemple, les logs d'entrainement). Cette méthode est souvent appelée `push_to_hub()`. +2. **Download from Hub** implémente une méthode pour charger un modèle depuis le Hub. La méthode doit télécharger la configuration et les poids du modèle puis instancier celui-ci. Cette méthode est souvent appelée `from_pretrained` ou `load_from_hub()`. +3. **Inference API** utilise nos serveurs pour faire de l'inférence gratuitement sur des modèles supportés par votre librairie. +4. **Widgets** affiche un widget sur la page d'accueil de votre modèle dans le Hub. Les widgets permettent aux utilisateurs de rapidement tester un modèle depuis le navigateur. + +Dans ce guide, nous nous concentreront sur les deux premiers sujets. Nous présenterons les deux approches principales que vous pouvez utiliser pour intégrer une librairie, avec leurs avantages et leurs inconvénients. Tout est résumé à la fin du guide pour vous aider à choisir entre les deux. Veuillez garder à l'esprit que ce ne sont que des conseils, et vous êtes libres de les adapter à votre cas d'usage. + +Si l'Inference API et les Widgets vous intéressent, vous pouvez suivre [ce guide](https://huggingface.co/docs/hub/models-adding-libraries#set-up-the-inference-api). Dans les deux cas, vous pouvez nous contacter si vous intégrez une librairie au Hub et que vous voulez être listée [dans la documentation officielle](https://huggingface.co/docs/hub/models-libraries). + +## Une approche flexible: les helpers + +La première approche pour intégrer une librairie au Hub est d'implémenter les méthodes `push_to_hub` et `from_pretrained` +vous même. Ceci vous donne une flexibilité totale sur le choix du fichier que vous voulez upload/download et sur comment +gérer les inputs spécifiques à votre framework. Vous pouvez vous référer aux guides : [upload des fichiers](./upload) +et [télécharger des fichiers](./download) pour en savoir plus sur la manière de faire. Par example, c'est de cette manière que l'intégration +de FastAI est implémentée (voir [`push_to_hub_fastai`] et [`from_pretrained_fastai`]). + +L'implémentation peut varier entre différentes librairies, mais le workflow est souvent similaire. + +### from_pretrained + +Voici un exemple classique pour implémenter la méthode `from_pretrained`: + +```python +def from_pretrained(model_id: str) -> MyModelClass: + # Téléchargement des paramètres depuis le Hub + cached_model = hf_hub_download( + repo_id=repo_id, + filename="model.pkl", + library_name="fastai", + library_version=get_fastai_version(), + ) + + # Instanciation du modèle + return load_model(cached_model) +``` + +### push_to_hub + +La méthode `push_to_hub` demande souvent un peu plus de complexité pour gérer la création du dépôt git, générer la model card et enregistrer les paramètres. +Une approche commune est de sauvegarder tous ces fichiers dans un dossier temporaire, les transférer sur le Hub avant de les supprimer localement. + +```python +def push_to_hub(model: MyModelClass, repo_name: str) -> None: + api = HfApi() + + # Créez d'un dépôt s'il n'existe pas encore, et obtenez le repo_id associé + repo_id = api.create_repo(repo_name, exist_ok=True).repo_id + + # Sauvegardez tous les fichiers dans un chemin temporaire, et pushez les en un seul commit + with TemporaryDirectory() as tmpdir: + tmpdir = Path(tmpdir) + + # Sauvegardez les poids + save_model(model, tmpdir / "model.safetensors") + + # Générez la model card + card = generate_model_card(model) + (tmpdir / "README.md").write_text(card) + + # Sauvegardez les logs + # Sauvegardez le métriques d'évaluation + # ... + + # Pushez vers le Hub + return api.upload_folder(repo_id=repo_id, folder_path=tmpdir) +``` + +Ceci n'est qu'un exemple. Si vous êtes intéressés par des manipulations plus complexes (supprimer des fichiers distants, +upload des poids à la volée, maintenir les poids localement, etc.) consultez le guide [upload des fichiers](./upload). + +### Limitations + +Bien que très flexible, cette approche a quelques défauts, particulièrement en terme de maintenance. Les utilisateurs +d'Hugging Face sont habitués à utiliser des certaines fonctionnalités lorsqu'ils travaillent avec `huggingface_hub`. Par exemple, +lors du chargement de fichiers depuis le Hub, il est commun de passer des paramètres tels que: +- `token`: pour télécharger depuis un dépôt privé +- `revision`: pour télécharger depuis une branche spécifique +- `cache_dir`: pour paramétrer la mise en cache des fichiers +- `force_download`: pour désactiver le cache +- `api_endpoint`/`proxies`: pour configurer la session HTTP + +Lorsque vous pushez des modèles, des paramètres similaires sont utilisables: +- `commit_message`: message de commit personnalisé +- `private`: créé un dépôt privé s'il en manque un +- `create_pr`: créé un pull request au lieu de push vers `main` +- `branch`: push vers une branche au lieu de push sur `main` +- `allow_patterns`/`ignore_patterns`: filtre les fichiers à upload +- `token` +- `api_endpoint` +- ... + +Tous ces paramètres peuvent être ajoutés aux implémentations vues ci dessus et passés aux méthodes de `huggingface_hub`. +Toutefois, si un paramètre change ou qu'une nouvelle fonctionnalité est ajoutée, vous devrez mettre à jour votre package. +Supporter ces paramètres implique aussi plus de documentation à maintenir de votre côté. Dans la prochaine section, nous allons voir comment dépasser ces limitations. + +## Une approche plus complexe: l'héritage de classe + +Comme vu ci-dessus, deux méthodes principales sont à inclure dans votre librairie pour l'intégrer avec le Hub: +la méthode permettant d'upload des fichiers (`push_to_hub`) et celle pour télécharger des fichiers (`from_pretrained`). +Vous pouvez implémenter ces méthodes vous-même mais cela a des inconvénients. Pour gérer ça, `huggingface_hub` fournit +un outil qui utilise l'héritage de classe. Regardons comment ça marche ! + +Dans beaucoup de cas, une librairie définit déjà les modèles comme des classes Python. La classe contient les +propriétés du modèle et des méthodes pour charger, lancer, entrainer et évaluer le modèle. Notre approche est d'étendre +cette classe pour inclure les fonctionnalités upload et download en utilisant les mixins. Une [mixin](https://stackoverflow.com/a/547714) +est une classe qui est faite pour étendre une classe existante avec une liste de fonctionnalités spécifiques en utilisant l'héritage de classe. +`huggingface_hub` offre son propre mixin, le [`ModelHubMixin`]. La clef ici est de comprendre son comportement et comment le customiser. + +La classe [`ModelHubMixin`] implémente 3 méthodes *public* (`push_to_hub`, `save_pretrained` et `from_pretrained`). Ce +sont les méthodes que vos utilisateurs appeleront pour charger/enregistrer des modèles avec votre librairie. +[`ModelHubMixin`] définit aussi 2 méthodes *private* (`_save_pretrained` et `from_pretrained`). Ce sont celle que vous +devez implémenter. Ainsi, pour intégrer votre librairie, vous devez : + +1. Faire en sorte que votre classe Model hérite de [`ModelHubMixin`]. +2. Implémenter les méthodes privées: + - [`~ModelHubMixin._save_pretrained`]: méthode qui prend en entrée un chemin vers un directory et qui sauvegarde le modèle. + Vous devez écrire toute la logique pour dump votre modèle de cette manière: model card, poids du modèle, fichiers de configuration, + et logs d'entrainement. Toute information pertinente pour ce modèle doit être gérée par cette méthode. Les + [model cards](https://huggingface.co/docs/hub/model-cards) sont particulièrement importantes pour décrire votre modèle. Vérifiez + [notre guide d'implémentation](./model-cards) pour plus de détails. + - [`~ModelHubMixin._from_pretrained`]: **méthode de classe** prenant en entrée un `model_id` et qui retourne un modèle instancié. + Cette méthode doit télécharger un ou plusieurs fichier(s) et le(s) charger. +3. Fini! + +L'avantage d'utiliser [`ModelHubMixin`] est qu'une fois que vous vous êtes occupés de la sérialisation et du chargement du fichier, +vous êtes prêts. Vous n'avez pas besoin de vous soucier de la création du dépôt, des commits, des pull requests ou des révisions. +Tout ceci est géré par le mixin et est disponible pour vos utilisateurs. Le Mixin s'assure aussi que les méthodes publiques sont +bien documentées et que les annotations de typage sont spécifiées. + +### Un exemple concret: PyTorch + +Un bon exemple de ce que nous avons vu ci-dessus est [`PyTorchModelHubMixin`], notre intégration pour le framework PyTorch. +C'est une intégration prête à l'emploi. + +#### Comment l'utiliser ? + +Voici comment n'importe quel utilisateur peut charger/enregistrer un modèle Pytorch depuis/vers le Hub: + +```python +>>> import torch +>>> import torch.nn as nn +>>> from huggingface_hub import PyTorchModelHubMixin + +# 1. Définissez votre modèle Pytorch exactement comme vous êtes habitués à le faire +>>> class MyModel(nn.Module, PyTorchModelHubMixin): # héritage multiple +... def __init__(self): +... super().__init__() +... self.param = nn.Parameter(torch.rand(3, 4)) +... self.linear = nn.Linear(4, 5) + +... def forward(self, x): +... return self.linear(x + self.param) +>>> model = MyModel() + +# 2. (optionnel) Sauvegarder le modèle dans un chemin local +>>> model.save_pretrained("path/to/my-awesome-model") + +# 3. Pushez les poids du modèle vers le Hub +>>> model.push_to_hub("my-awesome-model") + +# 4. initialisez le modèle depuis le Hub +>>> model = MyModel.from_pretrained("username/my-awesome-model") +``` + +#### Implémentation + +L'implémentation est très succincte (voir [ici](https://github.com/huggingface/huggingface_hub/blob/main/src/huggingface_hub/hub_mixin.py)). + +1. Premièrement, faites hériter votre classe de `ModelHubMixin`: + +```python +from huggingface_hub import ModelHubMixin + +class PyTorchModelHubMixin(ModelHubMixin): + (...) +``` + +2. Implémentez la méthode `_save_pretrained`: + +```py +from huggingface_hub import ModelCard, ModelCardData + +class PyTorchModelHubMixin(ModelHubMixin): + (...) + + def _save_pretrained(self, save_directory: Path): + """Générez une model card et enregistrez les poids d'un modèle Pytroch vers un chemin local.""" + model_card = ModelCard.from_template( + card_data=ModelCardData( + license='mit', + library_name="pytorch", + ... + ), + model_summary=..., + model_type=..., + ... + ) + (save_directory / "README.md").write_text(str(model)) + torch.save(obj=self.module.state_dict(), f=save_directory / "pytorch_model.bin") +``` + +3. Implémentez la méthode `_from_pretrained`: + +```python +class PyTorchModelHubMixin(ModelHubMixin): + (...) + + @classmethod # Doit absolument être une méthode de clase ! + def _from_pretrained( + cls, + *, + model_id: str, + revision: str, + cache_dir: str, + force_download: bool, + proxies: Optional[Dict], + resume_download: bool, + local_files_only: bool, + token: Union[str, bool, None], + map_location: str = "cpu", # argument supplémentaire + strict: bool = False, # argument supplémentaire + **model_kwargs, + ): + """Chargez les poids pré-entrainés et renvoyez les au modèle chargé.""" + if os.path.isdir(model_id): # Peut être un chemin local + print("Loading weights from local directory") + model_file = os.path.join(model_id, "pytorch_model.bin") + else: # Ou un modèle du Hub + model_file = hf_hub_download( # Téléchargez depuis le Hub, en passant le mêmes arguments d'entrée + repo_id=model_id, + filename="pytorch_model.bin", + revision=revision, + cache_dir=cache_dir, + force_download=force_download, + proxies=proxies, + resume_download=resume_download, + token=token, + local_files_only=local_files_only, + ) + + # Chargez le modèle et reoutnez une logique personnalisée dépendant de votre framework + model = cls(**model_kwargs) + state_dict = torch.load(model_file, map_location=torch.device(map_location)) + model.load_state_dict(state_dict, strict=strict) + model.eval() + return model +``` + +Et c'est fini ! Votre librairie permet maintenant aux utilisateurs d'upload et de télécharger des fichiers vers et depuis le Hub. + +## Comparaison + +Résumons rapidement les deux approches que nous avons vu avec leurs avantages et leurs défauts. Le tableau ci-dessous +est purement indicatif. Votre framework aura peut-êre des spécifités à prendre en compte. Ce guide +est ici pour vous donner des indications et des idées sur comment gérer l'intégration. Dans tous les cas, +n'hésitez pas à nous contacter si vous avez une question ! + + +| Intégration | Utilisant des helpers | Utilisant [`ModelHubMixin`] | +|:---:|:---:|:---:| +| Expérience utilisateur | `model = load_from_hub(...)`
`push_to_hub(model, ...)` | `model = MyModel.from_pretrained(...)`
`model.push_to_hub(...)` | +| Flexible | Très flexible.
Vous controllez complètement l'implémentation. | Moins flexible.
Votre framework doit avoir une classe de modèle. | +| Maintenance | Plus de maintenance pour ajouter du support pour la configuration, et de nouvelles fonctionnalités. Peut aussi nécessiter de fixx des problèmes signalés par les utilisateurs.| Moins de maintenance vu que la plupart des intégrations avec le Hub sont implémentés dans `huggingface_hub` | +| Documentation / Anotation de type| A écrire à la main | Géré partiellement par `huggingface_hub`. | \ No newline at end of file From c282c95f55eff9353c0065b9b2207e8f3c68e3fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Gallou=C3=A9dec?= <45557362+qgallouedec@users.noreply.github.com> Date: Wed, 26 Jun 2024 18:26:36 +0200 Subject: [PATCH 17/32] Update _errors.py (#2354) --- src/huggingface_hub/utils/_errors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/huggingface_hub/utils/_errors.py b/src/huggingface_hub/utils/_errors.py index 70e97f0c24..6ff09bf7f1 100644 --- a/src/huggingface_hub/utils/_errors.py +++ b/src/huggingface_hub/utils/_errors.py @@ -361,7 +361,7 @@ def hf_raise_for_status(response: Response, endpoint_name: Optional[str] = None) message = ( f"\n\n{response.status_code} Forbidden: {error_message}." + f"\nCannot access content at: {response.url}." - + "\nIf you are trying to create or update content," + + "\nIf you are trying to create or update content, " + "make sure you have a token with the `write` role." ) raise HfHubHTTPError(message, response=response) from e From 7832db59547eead4679b684bf7934a47b5a0c21a Mon Sep 17 00:00:00 2001 From: Quentin Lhoest <42851186+lhoestq@users.noreply.github.com> Date: Wed, 26 Jun 2024 19:28:26 +0200 Subject: [PATCH 18/32] [HfFileSystem] Faster `fs.walk()` (#2346) * faster fs walk * add missing args --- src/huggingface_hub/hf_file_system.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/huggingface_hub/hf_file_system.py b/src/huggingface_hub/hf_file_system.py index 7518d6684d..44c5aba17d 100644 --- a/src/huggingface_hub/hf_file_system.py +++ b/src/huggingface_hub/hf_file_system.py @@ -403,6 +403,12 @@ def _ls_tree( out.append(cache_path_info) return out + def walk(self, path, *args, **kwargs): + # Set expand_info=False by default to get a x10 speed boost + kwargs = {"expand_info": kwargs.get("detail", False), **kwargs} + path = self.resolve_path(path, revision=kwargs.get("revision")).unresolve() + yield from super().walk(path, *args, **kwargs) + def glob(self, path, **kwargs): # Set expand_info=False by default to get a x10 speed boost kwargs = {"expand_info": kwargs.get("detail", False), **kwargs} From d298397ffbef29e3358e539b7fda9998dcd2ff0a Mon Sep 17 00:00:00 2001 From: Lucain Pouget Date: Thu, 27 Jun 2024 11:01:50 +0200 Subject: [PATCH 19/32] fix docs --- docs/source/fr/_toctree.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/fr/_toctree.yml b/docs/source/fr/_toctree.yml index 62137bd951..f6c76ff6f5 100644 --- a/docs/source/fr/_toctree.yml +++ b/docs/source/fr/_toctree.yml @@ -11,5 +11,6 @@ - local: concepts/git_vs_http title: Git ou HTTP? - title: "Guides" + sections: - local: guides/integrations title: Intégrer dans une librarie \ No newline at end of file From d7def91c5e16021fd68115f6326da03580b48631 Mon Sep 17 00:00:00 2001 From: noech373 <159523865+noech373@users.noreply.github.com> Date: Thu, 27 Jun 2024 11:59:31 +0200 Subject: [PATCH 20/32] Add proxy support on async client (#2350) * add proxy support on async client * modifications suggested * fix script * fix test --------- Co-authored-by: Noe_Chabanon Co-authored-by: Lucain Pouget --- src/huggingface_hub/inference/_client.py | 3 +++ src/huggingface_hub/inference/_generated/_async_client.py | 4 +++- tests/test_inference_client.py | 5 ++++- utils/generate_async_inference_client.py | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index 2e8989d93e..8dc7e135f9 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -157,6 +157,7 @@ def __init__( timeout: Optional[float] = None, headers: Optional[Dict[str, str]] = None, cookies: Optional[Dict[str, str]] = None, + proxies: Optional[Any] = None, ) -> None: self.model: Optional[str] = model self.token: Union[str, bool, None] = token @@ -165,6 +166,7 @@ def __init__( self.headers.update(headers) self.cookies = cookies self.timeout = timeout + self.proxies = proxies def __repr__(self): return f"" @@ -264,6 +266,7 @@ def post( cookies=self.cookies, timeout=self.timeout, stream=stream, + proxies=self.proxies, ) except TimeoutError as error: # Convert any `TimeoutError` to a `InferenceTimeoutError` diff --git a/src/huggingface_hub/inference/_generated/_async_client.py b/src/huggingface_hub/inference/_generated/_async_client.py index b92555d8d5..8ae3125ac8 100644 --- a/src/huggingface_hub/inference/_generated/_async_client.py +++ b/src/huggingface_hub/inference/_generated/_async_client.py @@ -142,6 +142,7 @@ def __init__( timeout: Optional[float] = None, headers: Optional[Dict[str, str]] = None, cookies: Optional[Dict[str, str]] = None, + proxies: Optional[Any] = None, ) -> None: self.model: Optional[str] = model self.token: Union[str, bool, None] = token @@ -150,6 +151,7 @@ def __init__( self.headers.update(headers) self.cookies = cookies self.timeout = timeout + self.proxies = proxies def __repr__(self): return f"" @@ -250,7 +252,7 @@ async def post( ) try: - response = await client.post(url, json=json, data=data_as_binary) + response = await client.post(url, json=json, data=data_as_binary, proxy=self.proxies) response_error_payload = None if response.status != 200: try: diff --git a/tests/test_inference_client.py b/tests/test_inference_client.py index 78595f7802..06fdc705c2 100644 --- a/tests/test_inference_client.py +++ b/tests/test_inference_client.py @@ -767,7 +767,9 @@ def test_headers_overwrite(self) -> None: @patch("huggingface_hub.inference._client.get_session") def test_mocked_post(self, get_session_mock: MagicMock) -> None: """Test that headers and cookies are correctly passed to the request.""" - client = InferenceClient(headers={"X-My-Header": "foo"}, cookies={"my-cookie": "bar"}) + client = InferenceClient( + headers={"X-My-Header": "foo"}, cookies={"my-cookie": "bar"}, proxies="custom proxies" + ) response = client.post(data=b"content", model="username/repo_name") self.assertEqual(response, get_session_mock().post.return_value.content) @@ -780,6 +782,7 @@ def test_mocked_post(self, get_session_mock: MagicMock) -> None: cookies={"my-cookie": "bar"}, timeout=None, stream=False, + proxies="custom proxies", ) @patch("huggingface_hub.inference._client._bytes_to_image") diff --git a/utils/generate_async_inference_client.py b/utils/generate_async_inference_client.py index eaa0d7f04d..ce3e5cfabd 100644 --- a/utils/generate_async_inference_client.py +++ b/utils/generate_async_inference_client.py @@ -198,7 +198,7 @@ def _rename_to_AsyncInferenceClient(code: str) -> str: ) try: - response = await client.post(url, json=json, data=data_as_binary) + response = await client.post(url, json=json, data=data_as_binary, proxy=self.proxies) response_error_payload = None if response.status != 200: try: From 0c262f7c40d17b7cfc28c36eda33659374aaa51b Mon Sep 17 00:00:00 2001 From: Sylvain Lesage Date: Fri, 28 Jun 2024 15:55:19 +0200 Subject: [PATCH 21/32] add a diagram about hf:// URLs (#2358) --- docs/source/en/guides/hf_file_system.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/source/en/guides/hf_file_system.md b/docs/source/en/guides/hf_file_system.md index a09dc87b0d..01b38c850c 100644 --- a/docs/source/en/guides/hf_file_system.md +++ b/docs/source/en/guides/hf_file_system.md @@ -45,6 +45,10 @@ The [`HfFileSystem`] can be used with any library that integrates `fsspec`, prov hf://[][@]/ ``` +
+ +
+ The `repo_type_prefix` is `datasets/` for datasets, `spaces/` for spaces, and models don't need a prefix in the URL. Some interesting integrations where [`HfFileSystem`] simplifies interacting with the Hub are listed below: From 4ba21f409f406c4665284dda1a76b4173ddf4731 Mon Sep 17 00:00:00 2001 From: "Chulhwa (Evan) Han" Date: Mon, 1 Jul 2024 17:56:50 +0900 Subject: [PATCH 22/32] =?UTF-8?q?=F0=9F=8C=90=20[i18n-KO]=20Translated=20`?= =?UTF-8?q?guides/manage-cache.md`=20to=20Korean=20(#2347)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: ko: guides/manage-cache.md * feat: nmt draft * Update docs/source/ko/_toctree.yml * Apply suggestions from code review Co-authored-by: Harheem Kim <49297157+harheem@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Kyungmin Jeon <83350060+seoulsky-field@users.noreply.github.com> Co-authored-by: Harheem Kim <49297157+harheem@users.noreply.github.com> --------- Co-authored-by: Harheem Kim <49297157+harheem@users.noreply.github.com> Co-authored-by: Kyungmin Jeon <83350060+seoulsky-field@users.noreply.github.com> Co-authored-by: Lucain --- docs/source/ko/_toctree.yml | 8 +- docs/source/ko/guides/manage-cache.md | 439 ++++++++++++++++++++++++++ 2 files changed, 443 insertions(+), 4 deletions(-) create mode 100644 docs/source/ko/guides/manage-cache.md diff --git a/docs/source/ko/_toctree.yml b/docs/source/ko/_toctree.yml index e4a9a6aee5..2c7a4da702 100644 --- a/docs/source/ko/_toctree.yml +++ b/docs/source/ko/_toctree.yml @@ -6,7 +6,7 @@ title: 둘러보기 - local: installation title: 설치 방법 -- title: "(번역 중) How-to 가이드" +- title: "How-to 가이드" sections: - local: guides/overview title: 개요 @@ -30,8 +30,8 @@ title: 커뮤니티 - local: guides/collections title: Collections - - local: in_translation - title: (번역 중) Cache + - local: guides/manage-cache + title: 캐시 관리 - local: guides/model-cards title: 모델 카드 - local: guides/manage-spaces @@ -40,7 +40,7 @@ title: 라이브러리 통합 - local: guides/webhooks_server title: 웹훅 서버 -- title: "(번역 중) 개념 가이드" +- title: "개념 가이드" sections: - local: concepts/git_vs_http title: Git 대 HTTP 패러다임 diff --git a/docs/source/ko/guides/manage-cache.md b/docs/source/ko/guides/manage-cache.md new file mode 100644 index 0000000000..9c4836432f --- /dev/null +++ b/docs/source/ko/guides/manage-cache.md @@ -0,0 +1,439 @@ + + +# `huggingface_hub` 캐시 시스템 관리하기[[manage-huggingfacehub-cache-system]] + +## 캐싱 이해하기[[understand-caching]] + +Hugging Face Hub 캐시 시스템은 Hub에 의존하는 라이브러리 간에 공유되는 중앙 캐시로 설계되었습니다. v0.8.0에서 수정한 파일 간에 다시 다운로드하는 것을 방지하도록 업데이트되었습니다. + +캐시 시스템은 다음과 같이 설계되었습니다: + +``` + +├─ +├─ +├─ +``` + +``는 보통 사용자의 홈 디렉토리입니다. 그러나 모든 메소드에서 `cache_dir` 인수를 사용하거나 `HF_HOME` 또는 `HF_HUB_CACHE` 환경 변수를 지정하여 사용자 정의할 수 있습니다. + +모델, 데이터셋, 스페이스는 공통된 루트를 공유합니다. 각 리포지토리는 리포지토리 유형과 네임스페이스(조직 또는 사용자 이름이 있을 경우), 리포지토리 이름을 포함합니다: + +``` + +├─ models--julien-c--EsperBERTo-small +├─ models--lysandrejik--arxiv-nlp +├─ models--bert-base-cased +├─ datasets--glue +├─ datasets--huggingface--DataMeasurementsFiles +├─ spaces--dalle-mini--dalle-mini +``` + +Hub로부터 모든 파일이 이 폴더들 안에 다운로드됩니다. 캐싱은 파일이 이미 존재하고 업데이트되지 않은 경우, 파일을 두 번 다운로드하지 않도록 해줍니다. +하지만 파일이 업데이트되었고 최신 파일을 요청하면, 최신 파일을 다운로드합니다 (이전 파일은 그대로 유지되어 필요할 때 다시 사용할 수 있습니다). + +이를 위해 모든 폴더는 동일한 구조를 가집니다: + +``` + +├─ datasets--glue +│ ├─ refs +│ ├─ blobs +│ ├─ snapshots +... +``` + +각 폴더는 다음과 같은 내용을 포함하도록 구성되었습니다: + +### Refs[[refs]] + +`refs` 폴더에는 주어진 참조의 최신 수정 버전을 나타내는 파일이 포함되어 있습니다. 예를 들어, 이전에 리포지토리의 `main` 브랜치에서 파일을 가져온 경우, `refs` 폴더에는 `main`이라는 이름의 파일이 포함되며, 이 파일 자체에는 현재 헤드의 커밋 식별자가 들어 있습니다. + +만약 `main`의 최신 커밋 식별자가 `aaaaaa`라면, 그 파일에는 `aaaaaa`가 들어 있습니다. + +같은 브랜치가 새로운 커밋으로 업데이트되어 `bbbbbb`라는 식별자를 갖게 되면, 해당 참조에서 파일을 다시 다운로드할 때 `refs/main` 파일은 `bbbbbb`로 업데이트됩니다. + +### Blobs[[blobs]] + +`blobs` 폴더에는 실제로 다운로드된 파일이 포함되어 있습니다. 각 파일의 이름은 해당 파일의 해시값입니다. + +### Snapshots[[snapshots]] + +`snapshots` 폴더에는 위에서 언급한 blobs에 대한 심볼릭 링크가 포함되어 있습니다. 이 폴더는 여러 개의 하위 폴더로 구성되어 있으며, 각 폴더는 알려진 수정 버전을 나타냅니다. + +위 설명에서, 처음에 `aaaaaa` 버전에서 파일을 가져왔고, 그 후에 `bbbbbb` 버전에서 파일을 가져왔습니다. 이 상황에서 `snapshots` 폴더에는 `aaaaaa`와 `bbbbbb`라는 두 개의 폴더가 있습니다. + +이 폴더들 각각에는 다운로드한 파일의 이름을 가진 심볼릭 링크가 있습니다. 예를 들어, `aaaaaa` 버전에서 `README.md` 파일을 다운로드했다면, 다음과 같은 경로가 생깁니다: + +``` +//snapshots/aaaaaa/README.md +``` + +그 `README.md` 파일은 실제로 해당 파일의 해시를 가진 blob에 대한 심볼릭 링크입니다. + +이와 같은 구조를 생성함으로써 파일 공유 메커니즘이 열리게 됩니다. 동일한 파일을 `bbbbbb` 버전에서 가져온 경우, 동일한 해시를 가지게 되어 파일을 다시 다운로드할 필요가 없습니다. + +### .no_exist (advanced)[[noexist-advanced]] + +`blobs`, `refs`, `snapshots` 폴더 외에도 캐시에서 `.no_exist` 폴더를 찾을 수 있습니다. 이 폴더는 한 번 다운로드하려고 시도했지만 Hub에 존재하지 않는 파일을 기록합니다. 이 폴더의 구조는 `snapshots` 폴더와 동일하며, 알려진 각 수정 버전에 대해 하나의 하위 폴더를 갖습니다: + +``` +//.no_exist/aaaaaa/config_that_does_not_exist.json +``` +`snapshots` 폴더와 달리, 파일은 단순히 빈 파일입니다 (심볼릭 링크가 아님). 이 예에서 `"config_that_does_not_exist.json"` 파일은 `"aaaaaa"` 버전에 대해 Hub에 존재하지 않습니다. 빈 파일만 저장하므로, 이 폴더는 디스크 사용량을 크게 차지하지 않기에 무시할 수 있습니다. + +그렇다면 이제 여러분은 왜 이 정보가 관련이 있는지 궁금해 할지도 모릅니다. 몇몇 경우에서는 프레임워크가 모델에 대한 옵션 파일들을 불러오려고 시도합니다. 존재하지 않는 옵션 파일들을 저장하면 가능한 옵션 파일당 1개의 HTTP 호출을 절약할 수 있어 모델을 더 빠르게 불러올 수 있습니다. 이는 예를 들어 각 토크나이저가 추가 파일을 지원하는 `transformers`에서 발생합니다. 처음으로 토크나이저를 로드할 때, 다음 초기화를 위해 로딩 시간을 더 빠르게 하기 위해 옵션 파일이 존재하는지 여부를 캐시합니다. + +HTTP 요청을 만들지 않고 로컬로 캐시된 파일이 있는지 테스트하려면, [`try_to_load_from_cache`] 헬퍼를 사용할 수 있습니다. 이것은 파일이 존재하고 캐시된 경우에는 파일 경로를, 존재하지 않음이 캐시된 경우에는 `_CACHED_NO_EXIST` 객체를, 알 수 없는 경우에는 `None`을 반환합니다. + +```python +from huggingface_hub import try_to_load_from_cache, _CACHED_NO_EXIST + +filepath = try_to_load_from_cache() +if isinstance(filepath, str): + # 파일이 존재하고 캐시됩니다 + ... +elif filepath is _CACHED_NO_EXIST: + # 파일의 존재여부가 캐시됩니다 + ... +else: + # 파일은 캐시되지 않습니다 + ... +``` + +### 캐시 구조 예시[[in-practice]] + +실제로는 캐시는 다음과 같은 트리 구조를 가질 것입니다: + +```text + [ 96] . + └── [ 160] models--julien-c--EsperBERTo-small + ├── [ 160] blobs + │ ├── [321M] 403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd + │ ├── [ 398] 7cb18dc9bafbfcf74629a4b760af1b160957a83e + │ └── [1.4K] d7edf6bd2a681fb0175f7735299831ee1b22b812 + ├── [ 96] refs + │ └── [ 40] main + └── [ 128] snapshots + ├── [ 128] 2439f60ef33a0d46d85da5001d52aeda5b00ce9f + │ ├── [ 52] README.md -> ../../blobs/d7edf6bd2a681fb0175f7735299831ee1b22b812 + │ └── [ 76] pytorch_model.bin -> ../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd + └── [ 128] bbc77c8132af1cc5cf678da3f1ddf2de43606d48 + ├── [ 52] README.md -> ../../blobs/7cb18dc9bafbfcf74629a4b760af1b160957a83e + └── [ 76] pytorch_model.bin -> ../../blobs/403450e234d65943a7dcf7e05a771ce3c92faa84dd07db4ac20f592037a1e4bd +``` + +### 제한사항[[limitations]] + +효율적인 캐시 시스템을 갖기 위해 `huggingface-hub`은 심볼릭 링크를 사용합니다. 그러나 모든 기기에서 심볼릭 링크를 지원하지는 않습니다. 특히 Windows에서 이러한 한계가 있다는 것이 알려져 있습니다. 이런 경우에는 `huggingface_hub`이 `blobs/` 디렉터리를 사용하지 않고 대신 파일을 직접 `snapshots/` 디렉터리에 저장합니다. 이 해결책을 통해 사용자는 Hub에서 파일을 다운로드하고 캐시하는 방식을 정확히 동일하게 사용할 수 있습니다. 캐시를 검사하고 삭제하는 도구들도 지원됩니다. 그러나 캐시 시스템은 동일한 리포지토리의 여러 수정 버전을 다운로드하는 경우 같은 파일이 여러 번 다운로드될 수 있기 때문에 효율적이지 않을 수 있습니다. + +Windows 기기에서 심볼릭 링크 기반 캐시 시스템의 이점을 누리려면, [개발자 모드를 활성화](https://docs.microsoft.com/ko-kr/windows/apps/get-started/enable-your-device-for-development)하거나 Python을 관리자 권한으로 실행해야 합니다. + +심볼릭 링크가 지원되지 않는 경우, 사용자에게 캐시 시스템의 낮은 버전을 사용 중임을 알리는 경고 메시지가 표시됩니다. 이 경고는 `HF_HUB_DISABLE_SYMLINKS_WARNING` 환경 변수를 true로 설정하여 비활성화할 수 있습니다. + +## 캐싱 자산[[caching-assets]] + +Hub에서 파일을 캐시하는 것 외에도, 하위 라이브러리들은 종종 `huggingface_hub`에 직접 처리되지 않는 HF와 관련된 다른 파일을 캐시해야 할 때가 있습니다 (예: GitHub에서 다운로드한 파일, 전처리된 데이터, 로그 등). 이러한 파일, 즉 '자산(assets)'을 캐시하기 위해 [`cached_assets_path`]를 사용할 수 있습니다. 이 헬퍼는 요청한 라이브러리의 이름과 선택적으로 네임스페이스 및 하위 폴더 이름을 기반으로 HF 캐시의 경로를 통일된 방식으로 생성합니다. 목표는 모든 하위 라이브러리가 자산을 자체 방식대로(예: 구조에 대한 규칙 없음) 관리할 수 있도록 하는 것입니다. 그러나 올바른 자산 폴더 내에 있어야 합니다. 그러한 라이브러리는 `huggingface_hub`의 도구를 활용하여 캐시를 관리할 수 있으며, 특히 CLI 명령을 통해 자산의 일부를 스캔하고 삭제할 수 있습니다. + +```py +from huggingface_hub import cached_assets_path + +assets_path = cached_assets_path(library_name="datasets", namespace="SQuAD", subfolder="download") +something_path = assets_path / "something.json" # 자산 폴더에서 원하는 대로 작업하세요! +``` + + +[`cached_assets_path`]는 자산을 저장하는 권장 방법이지만 필수는 아닙니다. 이미 라이브러리가 자체 캐시를 사용하는 경우 해당 캐시를 자유롭게 사용하세요! + + +### 자산 캐시 구조 예시[[assets-in-practice]] + +실제로는 자산 캐시는 다음과 같은 트리 구조를 가질 것입니다: + +```text + assets/ + └── datasets/ + │ ├── SQuAD/ + │ │ ├── downloaded/ + │ │ ├── extracted/ + │ │ └── processed/ + │ ├── Helsinki-NLP--tatoeba_mt/ + │ ├── downloaded/ + │ ├── extracted/ + │ └── processed/ + └── transformers/ + ├── default/ + │ ├── something/ + ├── bert-base-cased/ + │ ├── default/ + │ └── training/ + hub/ + └── models--julien-c--EsperBERTo-small/ + ├── blobs/ + │ ├── (...) + │ ├── (...) + ├── refs/ + │ └── (...) + └── [ 128] snapshots/ + ├── 2439f60ef33a0d46d85da5001d52aeda5b00ce9f/ + │ ├── (...) + └── bbc77c8132af1cc5cf678da3f1ddf2de43606d48/ + └── (...) +``` + +## 캐시 스캔하기[[scan-your-cache]] + +현재 캐시된 파일은 로컬 디렉토리에서 삭제되지 않습니다. 브랜치의 새로운 수정 버전을 다운로드할 때 이전 파일은 다시 필요할 경우를 대비하여 보관됩니다. 따라서 디스크 공간을 많이 차지하는 리포지토리와 수정 버전을 파악하기 위해 캐시 디렉토리를 스캔하는 것이 유용할 수 있습니다. `huggingface_hub`은 이를 수행할 수 있는 헬퍼를 제공하며, `huggingface-cli`를 통해 또는 Python 스크립트에서 사용할 수 있습니다. + +### 터미널에서 캐시 스캔하기[[scan-cache-from-the-terminal]] + +HF 캐시 시스템을 스캔하는 가장 쉬운 방법은 `huggingface-cli` 도구의 `scan-cache` 명령을 사용하는 것입니다. 이 명령은 캐시를 스캔하고 리포지토리 ID, 리포지토리 유형, 디스크 사용량, 참조 및 전체 로컬 경로와 같은 정보가 포함된 보고서를 출력합니다. + +아래 코드 조각은 4개의 모델과 2개의 데이터셋이 캐시된 폴더에서의 스캔 보고서를 보여줍니다. + +```text +➜ huggingface-cli scan-cache +REPO ID REPO TYPE SIZE ON DISK NB FILES LAST_ACCESSED LAST_MODIFIED REFS LOCAL PATH +--------------------------- --------- ------------ -------- ------------- ------------- ------------------- ------------------------------------------------------------------------- +glue dataset 116.3K 15 4 days ago 4 days ago 2.4.0, main, 1.17.0 /home/wauplin/.cache/huggingface/hub/datasets--glue +google/fleurs dataset 64.9M 6 1 week ago 1 week ago refs/pr/1, main /home/wauplin/.cache/huggingface/hub/datasets--google--fleurs +Jean-Baptiste/camembert-ner model 441.0M 7 2 weeks ago 16 hours ago main /home/wauplin/.cache/huggingface/hub/models--Jean-Baptiste--camembert-ner +bert-base-cased model 1.9G 13 1 week ago 2 years ago /home/wauplin/.cache/huggingface/hub/models--bert-base-cased +t5-base model 10.1K 3 3 months ago 3 months ago main /home/wauplin/.cache/huggingface/hub/models--t5-base +t5-small model 970.7M 11 3 days ago 3 days ago refs/pr/1, main /home/wauplin/.cache/huggingface/hub/models--t5-small + +Done in 0.0s. Scanned 6 repo(s) for a total of 3.4G. +Got 1 warning(s) while scanning. Use -vvv to print details. +``` +더 자세한 보고서를 얻으려면 `--verbose` 옵션을 사용하세요. 각 리포지토리에 대해 다운로드된 모든 수정 버전의 목록을 얻게 됩니다. 위에서 설명한대로, 2개의 수정 버전 사이에 변경되지 않는 파일들은 심볼릭 링크를 통해 공유됩니다. 이는 디스크 상의 리포지토리 크기가 각 수정 버전의 크기의 합보다 작을 것으로 예상됨을 의미합니다. 예를 들어, 여기서 `bert-base-cased`는 1.4G와 1.5G의 두 가지 수정 버전이 있지만 총 디스크 사용량은 단 1.9G입니다. + +```text +➜ huggingface-cli scan-cache -v +REPO ID REPO TYPE REVISION SIZE ON DISK NB FILES LAST_MODIFIED REFS LOCAL PATH +--------------------------- --------- ---------------------------------------- ------------ -------- ------------- ----------- ---------------------------------------------------------------------------------------------------------------------------- +glue dataset 9338f7b671827df886678df2bdd7cc7b4f36dffd 97.7K 14 4 days ago main, 2.4.0 /home/wauplin/.cache/huggingface/hub/datasets--glue/snapshots/9338f7b671827df886678df2bdd7cc7b4f36dffd +glue dataset f021ae41c879fcabcf823648ec685e3fead91fe7 97.8K 14 1 week ago 1.17.0 /home/wauplin/.cache/huggingface/hub/datasets--glue/snapshots/f021ae41c879fcabcf823648ec685e3fead91fe7 +google/fleurs dataset 129b6e96cf1967cd5d2b9b6aec75ce6cce7c89e8 25.4K 3 2 weeks ago refs/pr/1 /home/wauplin/.cache/huggingface/hub/datasets--google--fleurs/snapshots/129b6e96cf1967cd5d2b9b6aec75ce6cce7c89e8 +google/fleurs dataset 24f85a01eb955224ca3946e70050869c56446805 64.9M 4 1 week ago main /home/wauplin/.cache/huggingface/hub/datasets--google--fleurs/snapshots/24f85a01eb955224ca3946e70050869c56446805 +Jean-Baptiste/camembert-ner model dbec8489a1c44ecad9da8a9185115bccabd799fe 441.0M 7 16 hours ago main /home/wauplin/.cache/huggingface/hub/models--Jean-Baptiste--camembert-ner/snapshots/dbec8489a1c44ecad9da8a9185115bccabd799fe +bert-base-cased model 378aa1bda6387fd00e824948ebe3488630ad8565 1.5G 9 2 years ago /home/wauplin/.cache/huggingface/hub/models--bert-base-cased/snapshots/378aa1bda6387fd00e824948ebe3488630ad8565 +bert-base-cased model a8d257ba9925ef39f3036bfc338acf5283c512d9 1.4G 9 3 days ago main /home/wauplin/.cache/huggingface/hub/models--bert-base-cased/snapshots/a8d257ba9925ef39f3036bfc338acf5283c512d9 +t5-base model 23aa4f41cb7c08d4b05c8f327b22bfa0eb8c7ad9 10.1K 3 1 week ago main /home/wauplin/.cache/huggingface/hub/models--t5-base/snapshots/23aa4f41cb7c08d4b05c8f327b22bfa0eb8c7ad9 +t5-small model 98ffebbb27340ec1b1abd7c45da12c253ee1882a 726.2M 6 1 week ago refs/pr/1 /home/wauplin/.cache/huggingface/hub/models--t5-small/snapshots/98ffebbb27340ec1b1abd7c45da12c253ee1882a +t5-small model d0a119eedb3718e34c648e594394474cf95e0617 485.8M 6 4 weeks ago /home/wauplin/.cache/huggingface/hub/models--t5-small/snapshots/d0a119eedb3718e34c648e594394474cf95e0617 +t5-small model d78aea13fa7ecd06c29e3e46195d6341255065d5 970.7M 9 1 week ago main /home/wauplin/.cache/huggingface/hub/models--t5-small/snapshots/d78aea13fa7ecd06c29e3e46195d6341255065d5 + +Done in 0.0s. Scanned 6 repo(s) for a total of 3.4G. +Got 1 warning(s) while scanning. Use -vvv to print details. +``` + +#### Grep 예시[[grep-example]] + +출력이 테이블 형식으로 되어 있기 때문에 `grep`과 유사한 도구를 사용하여 항목을 필터링할 수 있습니다. 여기에는 Unix 기반 머신에서 "t5-small" 모델의 수정 버전만 필터링하는 예제가 있습니다. + +```text +➜ eval "huggingface-cli scan-cache -v" | grep "t5-small" +t5-small model 98ffebbb27340ec1b1abd7c45da12c253ee1882a 726.2M 6 1 week ago refs/pr/1 /home/wauplin/.cache/huggingface/hub/models--t5-small/snapshots/98ffebbb27340ec1b1abd7c45da12c253ee1882a +t5-small model d0a119eedb3718e34c648e594394474cf95e0617 485.8M 6 4 weeks ago /home/wauplin/.cache/huggingface/hub/models--t5-small/snapshots/d0a119eedb3718e34c648e594394474cf95e0617 +t5-small model d78aea13fa7ecd06c29e3e46195d6341255065d5 970.7M 9 1 week ago main /home/wauplin/.cache/huggingface/hub/models--t5-small/snapshots/d78aea13fa7ecd06c29e3e46195d6341255065d5 +``` + +### 파이썬에서 캐시 스캔하기[[scan-cache-from-python]] + +보다 고급 기능을 사용하려면, CLI 도구에서 호출되는 파이썬 유틸리티인 [`scan_cache_dir`]을 사용할 수 있습니다. + +이를 사용하여 4가지 데이터 클래스를 중심으로 구조화된 자세한 보고서를 얻을 수 있습니다: + +- [`HFCacheInfo`]: [`scan_cache_dir`]에 의해 반환되는 완전한 보고서 +- [`CachedRepoInfo`]: 캐시된 리포지토리에 관한 정보 +- [`CachedRevisionInfo`]: 리포지토리 내의 캐시된 수정 버전(예: "snapshot")에 관한 정보 +- [`CachedFileInfo`]: 스냅샷 내의 캐시된 파일에 관한 정보 + +다음은 간단한 사용 예시입니다. 자세한 내용은 참조 문서를 참고하세요. + +```py +>>> from huggingface_hub import scan_cache_dir + +>>> hf_cache_info = scan_cache_dir() +HFCacheInfo( + size_on_disk=3398085269, + repos=frozenset({ + CachedRepoInfo( + repo_id='t5-small', + repo_type='model', + repo_path=PosixPath(...), + size_on_disk=970726914, + nb_files=11, + last_accessed=1662971707.3567169, + last_modified=1662971107.3567169, + revisions=frozenset({ + CachedRevisionInfo( + commit_hash='d78aea13fa7ecd06c29e3e46195d6341255065d5', + size_on_disk=970726339, + snapshot_path=PosixPath(...), + # 수정 버전 간에 blobs가 공유되기 때문에 `last_accessed`가 없습니다. + last_modified=1662971107.3567169, + files=frozenset({ + CachedFileInfo( + file_name='config.json', + size_on_disk=1197 + file_path=PosixPath(...), + blob_path=PosixPath(...), + blob_last_accessed=1662971707.3567169, + blob_last_modified=1662971107.3567169, + ), + CachedFileInfo(...), + ... + }), + ), + CachedRevisionInfo(...), + ... + }), + ), + CachedRepoInfo(...), + ... + }), + warnings=[ + CorruptedCacheException("Snapshots dir doesn't exist in cached repo: ..."), + CorruptedCacheException(...), + ... + ], +) +``` + +## 캐시 정리하기[[clean-your-cache]] + +캐시를 스캔하는 것은 흥미로울 수 있지만 실제로 해야 할 다음 작업은 일반적으로 드라이브의 일부 공간을 확보하기 위해 일부를 삭제하는 것입니다. 이는 `delete-cache` CLI 명령을 사용하여 가능합니다. 또한 캐시를 스캔할 때 반환되는 [`HFCacheInfo`] 객체에서 [`~HFCacheInfo.delete_revisions`] 헬퍼를 사용하여 프로그래밍 방식으로도 사용할 수 있습니다. + +### 전략적으로 삭제하기[[delete-strategy]] + + +캐시를 삭제하려면 삭제할 수정 버전 목록을 전달해야 합니다. 이 도구는 이 목록을 기반으로 공간을 확보하기 위한 전략을 정의합니다. 이는 어떤 파일과 폴더가 삭제될지를 설명하는 [`DeleteCacheStrategy`] 객체를 반환합니다. [`DeleteCacheStrategy`]를 통해 사용 가능한 공간을 확보 할 수 있습니다. 삭제에 동의하면 삭제를 실행하여 삭제를 유효하게 만들어야 합니다. 불일치를 피하기 위해 전략 객체를 수동으로 편집할 수 없습니다. + +수정 버전을 삭제하기 위한 전략은 다음과 같습니다: + +- 수정 버전 심볼릭 링크가 있는 `snapshot` 폴더가 삭제됩니다. +- 삭제할 수정 버전에만 대상이 되는 blobs 파일도 삭제됩니다. +- 수정 버전이 1개 이상의 `refs`에 연결되어 있는 경우, 참조가 삭제됩니다. +- 리포지토리의 모든 수정 버전이 삭제되는 경우 전체 캐시된 리포지토리가 삭제됩니다. + + +수정 버전 해시는 모든 리포지토리를 통틀어 고유합니다. 이는 수정 버전을 제거할 때 `repo_id`나 `repo_type`을 제공할 필요가 없음을 의미합니다. + + + +캐시에서 수정 버전을 찾을 수 없는 경우 무시됩니다. 또한 삭제 중에 파일 또는 폴더를 찾을 수 없는 경우 경고가 기록되지만 오류가 발생하지 않습니다. [`DeleteCacheStrategy`] 객체에 포함된 다른 경로에 대해 삭제가 계속됩니다. + + +### 터미널에서 캐시 정리하기[[clean-cache-from-the-terminal]] + +HF 캐시 시스템에서 일부 수정 버전을 삭제하는 가장 쉬운 방법은 `huggingface-cli` 도구의 `delete-cache` 명령을 사용하는 것입니다. 이 명령에는 두 가지 모드가 있습니다. 기본적으로 사용자에게 삭제할 수정 버전을 선택하도록 TUI(터미널 사용자 인터페이스)가 표시됩니다. 이 TUI는 현재 베타 버전으로, 모든 플랫폼에서 테스트되지 않았습니다. 만약 TUI가 작동하지 않는다면 `--disable-tui` 플래그를 사용하여 비활성화할 수 있습니다. + +#### TUI 사용하기[[using-the-tui]] + +이것은 기본 모드입니다. 이를 사용하려면 먼저 다음 명령을 실행하여 추가 종속성을 설치해야 합니다: + +``` +pip install huggingface_hub["cli"] +``` + +그러고 명령어를 실행합니다: + +``` +huggingface-cli delete-cache +``` +이제 선택/해제할 수 있는 수정 버전 목록이 표시됩니다: + +
+ +
+사용방법: + - `` 및 `` 키를 사용하여 커서를 이동합니다. + - `` 키를 눌러 항목을 토글(선택/해제)합니다. + - 수정 버전이 선택된 경우 첫 번째 줄이 업데이트되어 얼마나 많은 공간이 해제될지 표시됩니다. + - 선택을 확인하려면 `` 키를 누릅니다. + - 작업을 취소하고 종료하려면 첫 번째 항목("None of the following")을 선택합니다. 이 항목이 선택된 경우, 다른 항목이 선택되었는지 여부에 관계없이 삭제 프로세스가 취소됩니다. 그렇지 않으면 ``를 눌러 TUI를 종료할 수도 있습니다. + +삭제할 수정 버전을 선택하고 ``를 누르면 마지막 확인 메시지가 표시됩니다. 다시 ``를 누르면 삭제됩니다. 취소하려면 `n`을 입력하세요. + +```txt +✗ huggingface-cli delete-cache --dir ~/.cache/huggingface/hub +? Select revisions to delete: 2 revision(s) selected. +? 2 revisions selected counting for 3.1G. Confirm deletion ? Yes +Start deletion. +Done. Deleted 1 repo(s) and 0 revision(s) for a total of 3.1G. +``` + +#### TUI 없이 작업하기[[without-tui]] + +위에서 언급한대로, TUI 모드는 현재 베타 버전이며 선택 사항입니다. 사용 중인 기기에서 작동하지 않을 수도 있거나 편리하지 않을 수 있습니다. + +다른 방법은 `--disable-tui` 플래그를 사용하는 것입니다. 이 프로세스는 TUI 모드와 매우 유사하게 삭제할 수정 버전 목록을 수동으로 검토하라는 요청이 표시됩니다. 그러나 이 수동 단계는 터미널에서 직접 발생하는 것이 아니라 임시 파일에 자동으로 생성되며, 이를 수동으로 편집할 수 있습니다. + +이 파일에는 헤더에 필요한 모든 사용방법이 포함되어 있습니다. 텍스트 편집기에서 이 파일을 열어 `#`으로 주석 처리/해제하면 수정 버전을 쉽게 선택/해제 할 수 있습니다. 검토를 완료하고 파일 편집이 완료되었다면 터미널로 돌아가 ``를 눌러 파일을 저장하세요. 기본적으로 업데이트된 수정 버전 목록으로 확보될 공간의 양을 계산합니다. 파일을 계속 편집할 수도 있고, `"y"`를 눌러 변경 사항을 확정할 수 있습니다. + +```sh +huggingface-cli delete-cache --disable-tui +``` + +Example of command file: + +```txt +# INSTRUCTIONS +# ------------ +# This is a temporary file created by running `huggingface-cli delete-cache` with the +# `--disable-tui` option. It contains a set of revisions that can be deleted from your +# local cache directory. +# +# Please manually review the revisions you want to delete: +# - Revision hashes can be commented out with '#'. +# - Only non-commented revisions in this file will be deleted. +# - Revision hashes that are removed from this file are ignored as well. +# - If `CANCEL_DELETION` line is uncommented, the all cache deletion is cancelled and +# no changes will be applied. +# +# Once you've manually reviewed this file, please confirm deletion in the terminal. This +# file will be automatically removed once done. +# ------------ + +# KILL SWITCH +# ------------ +# Un-comment following line to completely cancel the deletion process +# CANCEL_DELETION +# ------------ + +# REVISIONS +# ------------ +# Dataset chrisjay/crowd-speech-africa (761.7M, used 5 days ago) + ebedcd8c55c90d39fd27126d29d8484566cd27ca # Refs: main # modified 5 days ago + +# Dataset oscar (3.3M, used 4 days ago) +# 916f956518279c5e60c63902ebdf3ddf9fa9d629 # Refs: main # modified 4 days ago + +# Dataset wikiann (804.1K, used 2 weeks ago) + 89d089624b6323d69dcd9e5eb2def0551887a73a # Refs: main # modified 2 weeks ago + +# Dataset z-uo/male-LJSpeech-italian (5.5G, used 5 days ago) +# 9cfa5647b32c0a30d0adfca06bf198d82192a0d1 # Refs: main # modified 5 days ago +``` + +### 파이썬에서 캐시 정리하기[[clean-cache-from-python]] + +더 유연하게 사용하려면, 프로그래밍 방식으로 [`~HFCacheInfo.delete_revisions`] 메소드를 사용할 수도 있습니다. 간단한 예제를 살펴보겠습니다. 자세한 내용은 참조 문서를 확인하세요. + +```py +>>> from huggingface_hub import scan_cache_dir + +>>> delete_strategy = scan_cache_dir().delete_revisions( +... "81fd1d6e7847c99f5862c9fb81387956d99ec7aa" +... "e2983b237dccf3ab4937c97fa717319a9ca1a96d", +... "6c0e6080953db56375760c0471a8c5f2929baf11", +... ) +>>> print("Will free " + delete_strategy.expected_freed_size_str) +Will free 8.6G + +>>> delete_strategy.execute() +Cache deletion done. Saved 8.6G. +``` From 85ffd0e4d40f0692113e0c3da2cae8d81d857463 Mon Sep 17 00:00:00 2001 From: Lucain Date: Mon, 1 Jul 2024 18:33:46 +0200 Subject: [PATCH 23/32] Update ruff in CI (#2365) * Fix updat eruff to 0.5.0 in dev * setup.py --- setup.py | 2 +- src/huggingface_hub/repocard_data.py | 2 +- utils/check_static_imports.py | 2 +- utils/generate_async_inference_client.py | 2 +- utils/generate_inference_types.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index 040abb20b4..4ecbb42e66 100644 --- a/setup.py +++ b/setup.py @@ -92,7 +92,7 @@ def get_version() -> str: ] extras["quality"] = [ - "ruff>=0.3.0", + "ruff>=0.5.0", "mypy==1.5.1", ] diff --git a/src/huggingface_hub/repocard_data.py b/src/huggingface_hub/repocard_data.py index dc79a1bc50..b9b93aac70 100644 --- a/src/huggingface_hub/repocard_data.py +++ b/src/huggingface_hub/repocard_data.py @@ -350,7 +350,7 @@ def __init__( super().__init__(**kwargs) if self.eval_results: - if type(self.eval_results) == EvalResult: + if isinstance(self.eval_results, EvalResult): self.eval_results = [self.eval_results] if self.model_name is None: raise ValueError("Passing `eval_results` requires `model_name` to be set.") diff --git a/utils/check_static_imports.py b/utils/check_static_imports.py index fe594690e9..4ea3a026aa 100644 --- a/utils/check_static_imports.py +++ b/utils/check_static_imports.py @@ -80,7 +80,7 @@ def check_static_imports(update: bool) -> NoReturn: reordered_content_before_static_checks + IF_TYPE_CHECKING_LINE + "\n".join(static_imports) + "\n" ) ruff_bin = find_ruff_bin() - os.spawnv(os.P_WAIT, ruff_bin, ["ruff", str(filepath), "--fix", "--quiet"]) + os.spawnv(os.P_WAIT, ruff_bin, ["ruff", "check", str(filepath), "--fix", "--quiet"]) os.spawnv(os.P_WAIT, ruff_bin, ["ruff", "format", str(filepath), "--quiet"]) expected_init_content = filepath.read_text() diff --git a/utils/generate_async_inference_client.py b/utils/generate_async_inference_client.py index ce3e5cfabd..f10d87c2e5 100644 --- a/utils/generate_async_inference_client.py +++ b/utils/generate_async_inference_client.py @@ -77,7 +77,7 @@ def format_source_code(code: str) -> str: filepath = Path(tmpdir) / "async_client.py" filepath.write_text(code) ruff_bin = find_ruff_bin() - os.spawnv(os.P_WAIT, ruff_bin, ["ruff", str(filepath), "--fix", "--quiet"]) + os.spawnv(os.P_WAIT, ruff_bin, ["ruff", "check", str(filepath), "--fix", "--quiet"]) os.spawnv(os.P_WAIT, ruff_bin, ["ruff", "format", str(filepath), "--quiet"]) return filepath.read_text() diff --git a/utils/generate_inference_types.py b/utils/generate_inference_types.py index 7508808a62..fe5223426f 100644 --- a/utils/generate_inference_types.py +++ b/utils/generate_inference_types.py @@ -233,7 +233,7 @@ def format_source_code(code: str) -> str: filepath = Path(tmpdir) / "tmp.py" filepath.write_text(code) ruff_bin = find_ruff_bin() - os.spawnv(os.P_WAIT, ruff_bin, ["ruff", str(filepath), "--fix", "--quiet"]) + os.spawnv(os.P_WAIT, ruff_bin, ["ruff", "check", str(filepath), "--fix", "--quiet"]) os.spawnv(os.P_WAIT, ruff_bin, ["ruff", "format", str(filepath), "--quiet"]) return filepath.read_text() From 11d4257400b301a7cb534dd4f1a70afca7007acb Mon Sep 17 00:00:00 2001 From: Lucain Date: Tue, 2 Jul 2024 12:27:21 +0200 Subject: [PATCH 24/32] Promote chat_completion in inference guide (#2366) * Promote chat_completion in inference guide * fix KO docs * update example + list conversational models * feedback * fix KO? * fix fix KO * ko * fix fix fix --- docs/source/en/guides/inference.md | 44 ++++++++++++++++--- docs/source/ko/guides/manage-cache.md | 10 ++--- docs/source/ko/in_translation.md | 5 --- src/huggingface_hub/inference/_client.py | 21 +++++++-- .../inference/_generated/_async_client.py | 21 +++++++-- 5 files changed, 78 insertions(+), 23 deletions(-) delete mode 100644 docs/source/ko/in_translation.md diff --git a/docs/source/en/guides/inference.md b/docs/source/en/guides/inference.md index 849afe7ce3..c2e2ffbd5b 100644 --- a/docs/source/en/guides/inference.md +++ b/docs/source/en/guides/inference.md @@ -38,13 +38,47 @@ Let's get started with a text-to-image task: >>> client = InferenceClient() >>> image = client.text_to_image("An astronaut riding a horse on the moon.") ->>> image.save("astronaut.png") +>>> image.save("astronaut.png") # 'image' is a PIL.Image object +``` + +In the example above, we initialized an [`InferenceClient`] with the default parameters. The only thing you need to know is the [task](#supported-tasks) you want to perform. By default, the client will connect to the Inference API and select a model to complete the task. In our example, we generated an image from a text prompt. The returned value is a `PIL.Image` object that can be saved to a file. For more details, check out the [`~InferenceClient.text_to_image`] documentation. + +Let's now see an example using the `chat_completion` API. This task uses an LLM to generate a response from a list of messages: + +```python +>>> from huggingface_hub import InferenceClient +>>> messages = [{"role": "user", "content": "What is the capital of France?"}] +>>> client = InferenceClient("meta-llama/Meta-Llama-3-8B-Instruct") +>>> client.chat_completion(messages, max_tokens=100) +ChatCompletionOutput( + choices=[ + ChatCompletionOutputComplete( + finish_reason='eos_token', + index=0, + message=ChatCompletionOutputMessage( + role='assistant', + content='The capital of France is Paris.', + name=None, + tool_calls=None + ), + logprobs=None + ) + ], + created=1719907176, + id='', + model='meta-llama/Meta-Llama-3-8B-Instruct', + object='text_completion', + system_fingerprint='2.0.4-sha-f426a33', + usage=ChatCompletionOutputUsage( + completion_tokens=8, + prompt_tokens=17, + total_tokens=25 + ) +) ``` -We initialized an [`InferenceClient`] with the default parameters. The only thing you need to know is the [task](#supported-tasks) you want -to perform. By default, the client will connect to the Inference API and select a model to complete the task. In our -example, we generated an image from a text prompt. The returned value is a `PIL.Image` object that can be saved to a -file. +In this example, we specified which model we want to use (`"meta-llama/Meta-Llama-3-8B-Instruct"`). You can find a list of compatible models [on this page](https://huggingface.co/models?other=conversational&sort=likes). We then gave a list of messages to complete (here, a single question) and passed an additional parameter to API (`max_token=100`). The output is a `ChatCompletionOutput` object that follows the OpenAI specification. The generated content can be access with `output.choices[0].message.content`. For more details, check out the [`~InferenceClient.chat_completion`] documentation. + diff --git a/docs/source/ko/guides/manage-cache.md b/docs/source/ko/guides/manage-cache.md index 9c4836432f..9e5c1a674f 100644 --- a/docs/source/ko/guides/manage-cache.md +++ b/docs/source/ko/guides/manage-cache.md @@ -350,13 +350,13 @@ huggingface-cli delete-cache 사용방법: - - `` 및 `` 키를 사용하여 커서를 이동합니다. - - `` 키를 눌러 항목을 토글(선택/해제)합니다. + - `up` 및 `down` 키를 사용하여 커서를 이동합니다. + - `space` 키를 눌러 항목을 토글(선택/해제)합니다. - 수정 버전이 선택된 경우 첫 번째 줄이 업데이트되어 얼마나 많은 공간이 해제될지 표시됩니다. - - 선택을 확인하려면 `` 키를 누릅니다. - - 작업을 취소하고 종료하려면 첫 번째 항목("None of the following")을 선택합니다. 이 항목이 선택된 경우, 다른 항목이 선택되었는지 여부에 관계없이 삭제 프로세스가 취소됩니다. 그렇지 않으면 ``를 눌러 TUI를 종료할 수도 있습니다. + - 선택을 확인하려면 `enter` 키를 누릅니다. + - 작업을 취소하고 종료하려면 첫 번째 항목("None of the following")을 선택합니다. 이 항목이 선택된 경우, 다른 항목이 선택되었는지 여부에 관계없이 삭제 프로세스가 취소됩니다. 그렇지 않으면 `ctrl+c` 를 눌러 TUI를 종료할 수도 있습니다. -삭제할 수정 버전을 선택하고 ``를 누르면 마지막 확인 메시지가 표시됩니다. 다시 ``를 누르면 삭제됩니다. 취소하려면 `n`을 입력하세요. +삭제할 수정 버전을 선택하고 `enter` 를 누르면 마지막 확인 메시지가 표시됩니다. 다시 `enter` 를 누르면 삭제됩니다. 취소하려면 `n` 을 입력하세요. ```txt ✗ huggingface-cli delete-cache --dir ~/.cache/huggingface/hub diff --git a/docs/source/ko/in_translation.md b/docs/source/ko/in_translation.md deleted file mode 100644 index 1a8497db3e..0000000000 --- a/docs/source/ko/in_translation.md +++ /dev/null @@ -1,5 +0,0 @@ - - -# 열심히 번역 중입니다. 조금 이따 만나요! diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index 8dc7e135f9..ebaeffb6f0 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -601,7 +601,7 @@ def chat_completion( # Chat example >>> from huggingface_hub import InferenceClient >>> messages = [{"role": "user", "content": "What is the capital of France?"}] - >>> client = InferenceClient("HuggingFaceH4/zephyr-7b-beta") + >>> client = InferenceClient("meta-llama/Meta-Llama-3-8B-Instruct") >>> client.chat_completion(messages, max_tokens=100) ChatCompletionOutput( choices=[ @@ -609,11 +609,24 @@ def chat_completion( finish_reason='eos_token', index=0, message=ChatCompletionOutputMessage( - content='The capital of France is Paris. The official name of the city is Ville de Paris (City of Paris) and the name of the country governing body, which is located in Paris, is La République française (The French Republic). \nI hope that helps! Let me know if you need any further information.' - ) + role='assistant', + content='The capital of France is Paris.', + name=None, + tool_calls=None + ), + logprobs=None ) ], - created=1710498360 + created=1719907176, + id='', + model='meta-llama/Meta-Llama-3-8B-Instruct', + object='text_completion', + system_fingerprint='2.0.4-sha-f426a33', + usage=ChatCompletionOutputUsage( + completion_tokens=8, + prompt_tokens=17, + total_tokens=25 + ) ) >>> for token in client.chat_completion(messages, max_tokens=10, stream=True): diff --git a/src/huggingface_hub/inference/_generated/_async_client.py b/src/huggingface_hub/inference/_generated/_async_client.py index 8ae3125ac8..527d93e973 100644 --- a/src/huggingface_hub/inference/_generated/_async_client.py +++ b/src/huggingface_hub/inference/_generated/_async_client.py @@ -603,7 +603,7 @@ async def chat_completion( # Chat example >>> from huggingface_hub import AsyncInferenceClient >>> messages = [{"role": "user", "content": "What is the capital of France?"}] - >>> client = AsyncInferenceClient("HuggingFaceH4/zephyr-7b-beta") + >>> client = AsyncInferenceClient("meta-llama/Meta-Llama-3-8B-Instruct") >>> await client.chat_completion(messages, max_tokens=100) ChatCompletionOutput( choices=[ @@ -611,11 +611,24 @@ async def chat_completion( finish_reason='eos_token', index=0, message=ChatCompletionOutputMessage( - content='The capital of France is Paris. The official name of the city is Ville de Paris (City of Paris) and the name of the country governing body, which is located in Paris, is La République française (The French Republic). \nI hope that helps! Let me know if you need any further information.' - ) + role='assistant', + content='The capital of France is Paris.', + name=None, + tool_calls=None + ), + logprobs=None ) ], - created=1710498360 + created=1719907176, + id='', + model='meta-llama/Meta-Llama-3-8B-Instruct', + object='text_completion', + system_fingerprint='2.0.4-sha-f426a33', + usage=ChatCompletionOutputUsage( + completion_tokens=8, + prompt_tokens=17, + total_tokens=25 + ) ) >>> async for token in await client.chat_completion(messages, max_tokens=10, stream=True): From 00dc59943be930538788643d7c0bc5995ad30627 Mon Sep 17 00:00:00 2001 From: Lucain Date: Tue, 2 Jul 2024 14:10:12 +0200 Subject: [PATCH 25/32] Add `prompt_name` to feature-extraction + update types (#2363) * Add to feature-extraction + update types * add truncation_direction to feature-extraction --- src/huggingface_hub/inference/_client.py | 14 ++++++++++++++ .../inference/_generated/_async_client.py | 14 ++++++++++++++ .../_generated/types/feature_extraction.py | 19 +++++++++++++++++-- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index ebaeffb6f0..fa55be9ccb 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -953,7 +953,9 @@ def feature_extraction( text: str, *, normalize: Optional[bool] = None, + prompt_name: Optional[str] = None, truncate: Optional[bool] = None, + truncation_direction: Optional[Literal["Left", "Right"]] = None, model: Optional[str] = None, ) -> "np.ndarray": """ @@ -969,9 +971,17 @@ def feature_extraction( normalize (`bool`, *optional*): Whether to normalize the embeddings or not. Defaults to None. Only available on server powered by Text-Embedding-Inference. + prompt_name (`str`, *optional*): + The name of the prompt that should be used by for encoding. If not set, no prompt will be applied. + Must be a key in the `Sentence Transformers` configuration `prompts` dictionary. + For example if ``prompt_name`` is "query" and the ``prompts`` is {"query": "query: ",...}, + then the sentence "What is the capital of France?" will be encoded as "query: What is the capital of France?" + because the prompt text will be prepended before any text to encode. truncate (`bool`, *optional*): Whether to truncate the embeddings or not. Defaults to None. Only available on server powered by Text-Embedding-Inference. + truncation_direction (`Literal["Left", "Right"]`, *optional*): + Which side of the input should be truncated when `truncate=True` is passed. Returns: `np.ndarray`: The embedding representing the input text as a float32 numpy array. @@ -996,8 +1006,12 @@ def feature_extraction( payload: Dict = {"inputs": text} if normalize is not None: payload["normalize"] = normalize + if prompt_name is not None: + payload["prompt_name"] = prompt_name if truncate is not None: payload["truncate"] = truncate + if truncation_direction is not None: + payload["truncation_direction"] = truncation_direction response = self.post(json=payload, model=model, task="feature-extraction") np = _import_numpy() return np.array(_bytes_to_dict(response), dtype="float32") diff --git a/src/huggingface_hub/inference/_generated/_async_client.py b/src/huggingface_hub/inference/_generated/_async_client.py index 527d93e973..dd2238d114 100644 --- a/src/huggingface_hub/inference/_generated/_async_client.py +++ b/src/huggingface_hub/inference/_generated/_async_client.py @@ -957,7 +957,9 @@ async def feature_extraction( text: str, *, normalize: Optional[bool] = None, + prompt_name: Optional[str] = None, truncate: Optional[bool] = None, + truncation_direction: Optional[Literal["Left", "Right"]] = None, model: Optional[str] = None, ) -> "np.ndarray": """ @@ -973,9 +975,17 @@ async def feature_extraction( normalize (`bool`, *optional*): Whether to normalize the embeddings or not. Defaults to None. Only available on server powered by Text-Embedding-Inference. + prompt_name (`str`, *optional*): + The name of the prompt that should be used by for encoding. If not set, no prompt will be applied. + Must be a key in the `Sentence Transformers` configuration `prompts` dictionary. + For example if ``prompt_name`` is "query" and the ``prompts`` is {"query": "query: ",...}, + then the sentence "What is the capital of France?" will be encoded as "query: What is the capital of France?" + because the prompt text will be prepended before any text to encode. truncate (`bool`, *optional*): Whether to truncate the embeddings or not. Defaults to None. Only available on server powered by Text-Embedding-Inference. + truncation_direction (`Literal["Left", "Right"]`, *optional*): + Which side of the input should be truncated when `truncate=True` is passed. Returns: `np.ndarray`: The embedding representing the input text as a float32 numpy array. @@ -1001,8 +1011,12 @@ async def feature_extraction( payload: Dict = {"inputs": text} if normalize is not None: payload["normalize"] = normalize + if prompt_name is not None: + payload["prompt_name"] = prompt_name if truncate is not None: payload["truncate"] = truncate + if truncation_direction is not None: + payload["truncation_direction"] = truncation_direction response = await self.post(json=payload, model=model, task="feature-extraction") np = _import_numpy() return np.array(_bytes_to_dict(response), dtype="float32") diff --git a/src/huggingface_hub/inference/_generated/types/feature_extraction.py b/src/huggingface_hub/inference/_generated/types/feature_extraction.py index ef87953ac4..e706269de1 100644 --- a/src/huggingface_hub/inference/_generated/types/feature_extraction.py +++ b/src/huggingface_hub/inference/_generated/types/feature_extraction.py @@ -4,11 +4,14 @@ # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. from dataclasses import dataclass -from typing import List, Optional, Union +from typing import Literal, Optional from .base import BaseInferenceType +FeatureExtractionInputTruncationDirection = Literal["Left", "Right"] + + @dataclass class FeatureExtractionInput(BaseInferenceType): """Feature Extraction Input. @@ -17,6 +20,18 @@ class FeatureExtractionInput(BaseInferenceType): https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-tei-import.ts. """ - inputs: Union[List[str], str] + inputs: str + """The text to embed.""" normalize: Optional[bool] = None + prompt_name: Optional[str] = None + """The name of the prompt that should be used by for encoding. If not set, no prompt + will be applied. + Must be a key in the `Sentence Transformers` configuration `prompts` dictionary. + For example if ``prompt_name`` is "query" and the ``prompts`` is {"query": "query: ", + ...}, + then the sentence "What is the capital of France?" will be encoded as + "query: What is the capital of France?" because the prompt text will be prepended before + any text to encode. + """ truncate: Optional[bool] = None + truncation_direction: Optional["FeatureExtractionInputTruncationDirection"] = None From 9a1aa570750c8fdaac70d8bbf42f64c3dceb4d49 Mon Sep 17 00:00:00 2001 From: moritzlaurer Date: Wed, 3 Jul 2024 09:53:58 +0200 Subject: [PATCH 26/32] put model arg at the end --- src/huggingface_hub/inference/_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index fa55be9ccb..15ccd71135 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -2427,8 +2427,8 @@ def zero_shot_classification( labels: List[str], *, multi_label: bool = False, - model: Optional[str] = None, hypothesis_template: str = "This example is {}.", + model: Optional[str] = None, ) -> List[ZeroShotClassificationOutputElement]: """ Provide as input a text and a set of candidate labels to classify the input text. From 59fd9b07a345eadebeff81b1f0c1459bbc286925 Mon Sep 17 00:00:00 2001 From: moritzlaurer Date: Wed, 3 Jul 2024 10:08:18 +0200 Subject: [PATCH 27/32] added doc strings for hypothesis_template and made it optional --- src/huggingface_hub/inference/_client.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index 15ccd71135..69a1fc28b3 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -2427,7 +2427,7 @@ def zero_shot_classification( labels: List[str], *, multi_label: bool = False, - hypothesis_template: str = "This example is {}.", + hypothesis_template: Optional[str] = "This example is {}.", model: Optional[str] = None, ) -> List[ZeroShotClassificationOutputElement]: """ @@ -2441,6 +2441,11 @@ def zero_shot_classification( multi_label (`bool`): Boolean. If True, the probability for each label is evaluated independently and multiple labels can have a probability close to 1 simultaneously or all probabilities can be close to 0. If False, the labels are considered mutually exclusive and the probability over all labels always sums to 1. Defaults to False. + hypothesis_template (`str`, *optional*): + A template sentence string with curly brackets to which the label strings are added. The label strings are added at the position of the curly brackets "{}". + Zero-shot classifiers are based on NLI models, which evaluate if a hypothesis is entailed in another text or not. + For example, with hypothesis_template="This text is about {}." and labels=["economics", "politics"], the system internally creates the two hypotheses "This text is about economics." and "This text is about politics.". + The model then evaluates for both hypotheses if they are entailed in the provided `text` or not. model (`str`, *optional*): The model to use for inference. Can be a model ID hosted on the Hugging Face Hub or a URL to a deployed Inference Endpoint. This parameter overrides the model defined at the instance level. Defaults to None. From 37577b1faef27990406a9f39ae84a12bae06b327 Mon Sep 17 00:00:00 2001 From: moritzlaurer Date: Wed, 3 Jul 2024 10:25:46 +0200 Subject: [PATCH 28/32] ran make style --- src/huggingface_hub/inference/_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index 69a1fc28b3..5ee48df4b6 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -2442,7 +2442,7 @@ def zero_shot_classification( Boolean. If True, the probability for each label is evaluated independently and multiple labels can have a probability close to 1 simultaneously or all probabilities can be close to 0. If False, the labels are considered mutually exclusive and the probability over all labels always sums to 1. Defaults to False. hypothesis_template (`str`, *optional*): - A template sentence string with curly brackets to which the label strings are added. The label strings are added at the position of the curly brackets "{}". + A template sentence string with curly brackets to which the label strings are added. The label strings are added at the position of the curly brackets "{}". Zero-shot classifiers are based on NLI models, which evaluate if a hypothesis is entailed in another text or not. For example, with hypothesis_template="This text is about {}." and labels=["economics", "politics"], the system internally creates the two hypotheses "This text is about economics." and "This text is about politics.". The model then evaluates for both hypotheses if they are entailed in the provided `text` or not. From e76105d1fff52b32e229dad526be3968a3501846 Mon Sep 17 00:00:00 2001 From: moritzlaurer Date: Wed, 3 Jul 2024 10:27:18 +0200 Subject: [PATCH 29/32] ran python utils/generate_async_inference_client.py --update --- src/huggingface_hub/inference/_generated/_async_client.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/huggingface_hub/inference/_generated/_async_client.py b/src/huggingface_hub/inference/_generated/_async_client.py index dd2238d114..6a8b830574 100644 --- a/src/huggingface_hub/inference/_generated/_async_client.py +++ b/src/huggingface_hub/inference/_generated/_async_client.py @@ -2459,8 +2459,8 @@ async def zero_shot_classification( labels: List[str], *, multi_label: bool = False, + hypothesis_template: Optional[str] = "This example is {}.", model: Optional[str] = None, - hypothesis_template: str = "This example is {}.", ) -> List[ZeroShotClassificationOutputElement]: """ Provide as input a text and a set of candidate labels to classify the input text. @@ -2473,6 +2473,11 @@ async def zero_shot_classification( multi_label (`bool`): Boolean. If True, the probability for each label is evaluated independently and multiple labels can have a probability close to 1 simultaneously or all probabilities can be close to 0. If False, the labels are considered mutually exclusive and the probability over all labels always sums to 1. Defaults to False. + hypothesis_template (`str`, *optional*): + A template sentence string with curly brackets to which the label strings are added. The label strings are added at the position of the curly brackets "{}". + Zero-shot classifiers are based on NLI models, which evaluate if a hypothesis is entailed in another text or not. + For example, with hypothesis_template="This text is about {}." and labels=["economics", "politics"], the system internally creates the two hypotheses "This text is about economics." and "This text is about politics.". + The model then evaluates for both hypotheses if they are entailed in the provided `text` or not. model (`str`, *optional*): The model to use for inference. Can be a model ID hosted on the Hugging Face Hub or a URL to a deployed Inference Endpoint. This parameter overrides the model defined at the instance level. Defaults to None. From 0f45cad91f5aa0e599d23a19b39faef983f08d71 Mon Sep 17 00:00:00 2001 From: moritzlaurer Date: Wed, 3 Jul 2024 11:10:46 +0200 Subject: [PATCH 30/32] hypothesis_template default to None --- src/huggingface_hub/inference/_client.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index 5ee48df4b6..2cb767871b 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -2427,7 +2427,7 @@ def zero_shot_classification( labels: List[str], *, multi_label: bool = False, - hypothesis_template: Optional[str] = "This example is {}.", + hypothesis_template: Optional[str] = None, model: Optional[str] = None, ) -> List[ZeroShotClassificationOutputElement]: """ @@ -2505,18 +2505,18 @@ def zero_shot_classification( ] ``` """ + + parameters = {"candidate_labels": labels, "multi_label": multi_label} + if hypothesis_template is not None: + parameters["hypothesis_template"] = hypothesis_template response = self.post( json={ "inputs": text, - "parameters": { - "candidate_labels": labels, - "multi_label": multi_label, - "hypothesis_template": hypothesis_template, - }, + "parameters": parameters, }, - model=model, task="zero-shot-classification", + model=model, ) output = _bytes_to_dict(response) return [ From b1d59f56b0fa751757ff24cbcc1c0110e1fcb51c Mon Sep 17 00:00:00 2001 From: moritzlaurer Date: Wed, 3 Jul 2024 11:11:27 +0200 Subject: [PATCH 31/32] make style and update async_client --- src/huggingface_hub/inference/_client.py | 2 +- .../inference/_generated/_async_client.py | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index 2cb767871b..fe3fc79cdc 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -2505,7 +2505,7 @@ def zero_shot_classification( ] ``` """ - + parameters = {"candidate_labels": labels, "multi_label": multi_label} if hypothesis_template is not None: parameters["hypothesis_template"] = hypothesis_template diff --git a/src/huggingface_hub/inference/_generated/_async_client.py b/src/huggingface_hub/inference/_generated/_async_client.py index 6a8b830574..2fcdb2adf9 100644 --- a/src/huggingface_hub/inference/_generated/_async_client.py +++ b/src/huggingface_hub/inference/_generated/_async_client.py @@ -2459,7 +2459,7 @@ async def zero_shot_classification( labels: List[str], *, multi_label: bool = False, - hypothesis_template: Optional[str] = "This example is {}.", + hypothesis_template: Optional[str] = None, model: Optional[str] = None, ) -> List[ZeroShotClassificationOutputElement]: """ @@ -2538,17 +2538,17 @@ async def zero_shot_classification( ``` """ + parameters = {"candidate_labels": labels, "multi_label": multi_label} + if hypothesis_template is not None: + parameters["hypothesis_template"] = hypothesis_template + response = await self.post( json={ "inputs": text, - "parameters": { - "candidate_labels": labels, - "multi_label": multi_label, - "hypothesis_template": hypothesis_template, - }, + "parameters": parameters, }, - model=model, task="zero-shot-classification", + model=model, ) output = _bytes_to_dict(response) return [ From f479f089a587e3938d170ad92f7c35d1568840f3 Mon Sep 17 00:00:00 2001 From: Lucain Pouget Date: Wed, 3 Jul 2024 13:50:47 +0200 Subject: [PATCH 32/32] fix generate_async_inference_client --- .../inference/_generated/_async_client.py | 22 ++++++++++--------- utils/generate_async_inference_client.py | 4 ++-- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/huggingface_hub/inference/_generated/_async_client.py b/src/huggingface_hub/inference/_generated/_async_client.py index 6e35499ad4..502e79155b 100644 --- a/src/huggingface_hub/inference/_generated/_async_client.py +++ b/src/huggingface_hub/inference/_generated/_async_client.py @@ -633,7 +633,7 @@ async def chat_completion( >>> messages = [ ... { ... "role": "system", - ... "content": "Don't make assumptions about what values to plug into functions. Ask async for clarification if a user request is ambiguous.", + ... "content": "Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous.", ... }, ... { ... "role": "user", @@ -877,7 +877,7 @@ async def conversational( >>> client = AsyncInferenceClient() >>> output = await client.conversational("Hi, who are you?") >>> output - {'generated_text': 'I am the one who knocks.', 'conversation': {'generated_responses': ['I am the one who knocks.'], 'past_user_inputs': ['Hi, who are you?']}, 'warnings': ['Setting `pad_token_id` to `eos_token_id`:50256 async for open-end generation.']} + {'generated_text': 'I am the one who knocks.', 'conversation': {'generated_responses': ['I am the one who knocks.'], 'past_user_inputs': ['Hi, who are you?']}, 'warnings': ['Setting `pad_token_id` to `eos_token_id`:50256 for open-end generation.']} >>> await client.conversational( ... "Wow, that's scary!", ... generated_responses=output["conversation"]["generated_responses"], @@ -1960,7 +1960,7 @@ async def text_generation( >>> await client.text_generation("The huggingface_hub library is ", max_new_tokens=12) '100% open source and built to be easy to use.' - # Case 2: iterate over the generated tokens. Useful async for large generation. + # Case 2: iterate over the generated tokens. Useful for large generation. >>> async for token in await client.text_generation("The huggingface_hub library is ", max_new_tokens=12, stream=True): ... print(token) 100 @@ -2483,15 +2483,16 @@ async def zero_shot_classification( Example with `multi_label=False`: ```py - >>> from huggingface_hub import InferenceClient - >>> client = InferenceClient() + # Must be run in an async context + >>> from huggingface_hub import AsyncInferenceClient + >>> client = AsyncInferenceClient() >>> text = ( ... "A new model offers an explanation for how the Galilean satellites formed around the solar system's" ... "largest world. Konstantin Batygin did not set out to solve one of the solar system's most puzzling" ... " mysteries when he went for a run up a hill in Nice, France." ... ) >>> labels = ["space & cosmos", "scientific discovery", "microbiology", "robots", "archeology"] - >>> client.zero_shot_classification(text, labels) + >>> await client.zero_shot_classification(text, labels) [ ZeroShotClassificationOutputElement(label='scientific discovery', score=0.7961668968200684), ZeroShotClassificationOutputElement(label='space & cosmos', score=0.18570658564567566), @@ -2499,7 +2500,7 @@ async def zero_shot_classification( ZeroShotClassificationOutputElement(label='archeology', score=0.006258360575884581), ZeroShotClassificationOutputElement(label='robots', score=0.004559356719255447), ] - >>> client.zero_shot_classification(text, labels, multi_label=True) + >>> await client.zero_shot_classification(text, labels, multi_label=True) [ ZeroShotClassificationOutputElement(label='scientific discovery', score=0.9829297661781311), ZeroShotClassificationOutputElement(label='space & cosmos', score=0.755190908908844), @@ -2511,9 +2512,10 @@ async def zero_shot_classification( Example with `multi_label=True` and a custom `hypothesis_template`: ```py - >>> from huggingface_hub import InferenceClient - >>> client = InferenceClient() - >>> client.zero_shot_classification( + # Must be run in an async context + >>> from huggingface_hub import AsyncInferenceClient + >>> client = AsyncInferenceClient() + >>> await client.zero_shot_classification( ... text="I really like our dinner and I'm very happy. I don't like the weather though.", ... labels=["positive", "negative", "pessimistic", "optimistic"], ... multi_label=True, diff --git a/utils/generate_async_inference_client.py b/utils/generate_async_inference_client.py index f10d87c2e5..d9b40c427c 100644 --- a/utils/generate_async_inference_client.py +++ b/utils/generate_async_inference_client.py @@ -377,7 +377,7 @@ def _update_example_code_block(code_block: str) -> str: code_block = "\n # Must be run in an async context" + code_block code_block = code_block.replace("InferenceClient", "AsyncInferenceClient") code_block = code_block.replace("client.", "await client.") - code_block = code_block.replace(" for ", " async for ") + code_block = code_block.replace(">>> for ", ">>> async for ") return code_block @@ -385,7 +385,7 @@ def _update_examples_in_public_methods(code: str) -> str: for match in re.finditer( r""" \n\s* - Example:\n\s* # example section + Example.*?:\n\s* # example section ```py # start (.*?) # code block ``` # end