From d5f2cf6ab1a354258a77e6d909d5cc1015e56632 Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Tue, 23 Jan 2024 07:30:18 +0530 Subject: [PATCH 01/20] feat: explicitly tag to diffusers when using push_to_hub --- src/diffusers/utils/hub_utils.py | 39 +++++++++++++++++++++++- tests/models/test_modeling_common.py | 23 +++++++++++++- tests/pipelines/test_pipelines_common.py | 15 ++++++++- 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/src/diffusers/utils/hub_utils.py b/src/diffusers/utils/hub_utils.py index d762f015a7bc..af624abdc6d0 100644 --- a/src/diffusers/utils/hub_utils.py +++ b/src/diffusers/utils/hub_utils.py @@ -21,7 +21,7 @@ import traceback import warnings from pathlib import Path -from typing import Dict, Optional, Union +from typing import Dict, List, Optional, Union from uuid import uuid4 from huggingface_hub import ( @@ -144,6 +144,36 @@ def create_model_card(args, model_name): model_card.save(card_path) +# Taken from `transformers` +def create_and_tag_model_card(repo_id: str, token: Optional[str] = None): + """ + Creates or loads an existing model card and tags it with the `library_name`. + + Args: + repo_id (`str`): + The repo_id where to look for the model card. + token (`str`, *optional*): + Authentication token, obtained with `huggingface_hub.HfApi.login` method. Will default to the stored token. + """ + if not is_jinja_available(): + raise ValueError( + "Modelcard rendering is based on Jinja templates." + " Please make sure to have `jinja` installed before using `create_and_tag_model_card`." + " To install it, please run `pip install Jinja2`." + ) + + try: + # Check if the model card is present on the remote repo + model_card = ModelCard.load(repo_id, token=token, ignore_metadata_errors=False) + except EntryNotFoundError: + # Otherwise create a simple model card from template + model_description = "This is the model card of a 🧨 diffusers model that has been pushed on the Hub. This model card has been automatically generated." + card_data = ModelCardData(library_name="diffusers") + model_card = ModelCard.from_template(card_data, model_description=model_description) + + return model_card + + def extract_commit_hash(resolved_file: Optional[str], commit_hash: Optional[str] = None): """ Extracts the commit hash from a resolved filename toward a cache file. @@ -396,6 +426,7 @@ def push_to_hub( create_pr: bool = False, safe_serialization: bool = True, variant: Optional[str] = None, + tags: Optional[List[str]] = None, ) -> str: """ Upload model, scheduler, or pipeline files to the 🤗 Hugging Face Hub. @@ -435,6 +466,9 @@ def push_to_hub( """ repo_id = create_repo(repo_id, private=private, token=token, exist_ok=True).repo_id + # Create a new empty model card and eventually tag it + model_card = create_and_tag_model_card(repo_id, tags, token=token) + # Save all files. save_kwargs = {"safe_serialization": safe_serialization} if "Scheduler" not in self.__class__.__name__: @@ -443,6 +477,9 @@ def push_to_hub( with tempfile.TemporaryDirectory() as tmpdir: self.save_pretrained(tmpdir, **save_kwargs) + # Update model card if needed: + model_card.save(os.path.join(tmpdir, "README.md")) + return self._upload_folder( tmpdir, repo_id, diff --git a/tests/models/test_modeling_common.py b/tests/models/test_modeling_common.py index 5ea0d910f3a3..60585373846c 100644 --- a/tests/models/test_modeling_common.py +++ b/tests/models/test_modeling_common.py @@ -24,7 +24,8 @@ import numpy as np import requests_mock import torch -from huggingface_hub import delete_repo +from huggingface_hub import ModelCard, delete_repo +from huggingface_hub.utils import is_jinja_available from requests.exceptions import HTTPError from diffusers.models import UNet2DConditionModel @@ -732,3 +733,23 @@ def test_push_to_hub_in_organization(self): # Reset repo delete_repo(self.org_repo_id, token=TOKEN) + + @unittest.skipIf( + not is_jinja_available(), + reason="Model card tests cannot be performed with Jinja installed.", + ) + def test_push_to_hub_library_name(self): + model = UNet2DConditionModel( + block_out_channels=(32, 64), + layers_per_block=2, + sample_size=32, + in_channels=4, + out_channels=4, + down_block_types=("DownBlock2D", "CrossAttnDownBlock2D"), + up_block_types=("CrossAttnUpBlock2D", "UpBlock2D"), + cross_attention_dim=32, + ) + model.push_to_hub(self.repo_id, token=TOKEN) + + model_card = ModelCard.load(self.repo_id).data + assert model_card.library_name == "diffusers" diff --git a/tests/pipelines/test_pipelines_common.py b/tests/pipelines/test_pipelines_common.py index ed2920cb0c73..5f143ad59b82 100644 --- a/tests/pipelines/test_pipelines_common.py +++ b/tests/pipelines/test_pipelines_common.py @@ -13,7 +13,8 @@ import numpy as np import PIL.Image import torch -from huggingface_hub import delete_repo +from huggingface_hub import ModelCard, delete_repo +from huggingface_hub.utils import is_jinja_available from transformers import CLIPTextConfig, CLIPTextModel, CLIPTokenizer import diffusers @@ -1142,6 +1143,18 @@ def test_push_to_hub_in_organization(self): # Reset repo delete_repo(self.org_repo_id, token=TOKEN) + @unittest.skipIf( + not is_jinja_available(), + reason="Model card tests cannot be performed with Jinja installed.", + ) + def test_push_to_hub_library_name(self): + components = self.get_pipeline_components() + pipeline = StableDiffusionPipeline(**components) + pipeline.push_to_hub(self.repo_id, token=TOKEN) + + model_card = ModelCard.load(self.repo_id).data + assert model_card.library_name == "diffusers" + # For SDXL and its derivative pipelines (such as ControlNet), we have the text encoders # and the tokenizers as optional components. So, we need to override the `test_save_load_optional_components()` From dc7f55d516ba31258b60f58e015497f6be3da603 Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Tue, 23 Jan 2024 07:37:21 +0530 Subject: [PATCH 02/20] remove tags. --- src/diffusers/utils/hub_utils.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/diffusers/utils/hub_utils.py b/src/diffusers/utils/hub_utils.py index af624abdc6d0..e90764589faa 100644 --- a/src/diffusers/utils/hub_utils.py +++ b/src/diffusers/utils/hub_utils.py @@ -21,7 +21,7 @@ import traceback import warnings from pathlib import Path -from typing import Dict, List, Optional, Union +from typing import Dict, Optional, Union from uuid import uuid4 from huggingface_hub import ( @@ -426,7 +426,6 @@ def push_to_hub( create_pr: bool = False, safe_serialization: bool = True, variant: Optional[str] = None, - tags: Optional[List[str]] = None, ) -> str: """ Upload model, scheduler, or pipeline files to the 🤗 Hugging Face Hub. @@ -467,7 +466,7 @@ def push_to_hub( repo_id = create_repo(repo_id, private=private, token=token, exist_ok=True).repo_id # Create a new empty model card and eventually tag it - model_card = create_and_tag_model_card(repo_id, tags, token=token) + model_card = create_and_tag_model_card(repo_id, token=token) # Save all files. save_kwargs = {"safe_serialization": safe_serialization} From 91b26fff60ac42d603ad6e6c6cc0dc87e5dbed8f Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Tue, 23 Jan 2024 07:43:38 +0530 Subject: [PATCH 03/20] reset repo. --- tests/models/test_modeling_common.py | 5 ++++- tests/pipelines/test_pipelines_common.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/models/test_modeling_common.py b/tests/models/test_modeling_common.py index 60585373846c..62a0188685cc 100644 --- a/tests/models/test_modeling_common.py +++ b/tests/models/test_modeling_common.py @@ -751,5 +751,8 @@ def test_push_to_hub_library_name(self): ) model.push_to_hub(self.repo_id, token=TOKEN) - model_card = ModelCard.load(self.repo_id).data + model_card = ModelCard.load(self.repo_id, token=TOKEN).data assert model_card.library_name == "diffusers" + + # Reset repo + delete_repo(self.repo_id, token=TOKEN) diff --git a/tests/pipelines/test_pipelines_common.py b/tests/pipelines/test_pipelines_common.py index 5f143ad59b82..8ddcf00739e0 100644 --- a/tests/pipelines/test_pipelines_common.py +++ b/tests/pipelines/test_pipelines_common.py @@ -1152,9 +1152,12 @@ def test_push_to_hub_library_name(self): pipeline = StableDiffusionPipeline(**components) pipeline.push_to_hub(self.repo_id, token=TOKEN) - model_card = ModelCard.load(self.repo_id).data + model_card = ModelCard.load(self.repo_id, token=TOKEN).data assert model_card.library_name == "diffusers" + # Reset repo + delete_repo(self.repo_id, token=TOKEN) + # For SDXL and its derivative pipelines (such as ControlNet), we have the text encoders # and the tokenizers as optional components. So, we need to override the `test_save_load_optional_components()` From 03a704a508739a47d87a47e34f6608824284a417 Mon Sep 17 00:00:00 2001 From: Sayak Paul Date: Tue, 23 Jan 2024 13:15:42 +0530 Subject: [PATCH 04/20] Apply suggestions from code review Co-authored-by: Patrick von Platen --- src/diffusers/utils/hub_utils.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/diffusers/utils/hub_utils.py b/src/diffusers/utils/hub_utils.py index e90764589faa..10bc68b1b126 100644 --- a/src/diffusers/utils/hub_utils.py +++ b/src/diffusers/utils/hub_utils.py @@ -155,13 +155,6 @@ def create_and_tag_model_card(repo_id: str, token: Optional[str] = None): token (`str`, *optional*): Authentication token, obtained with `huggingface_hub.HfApi.login` method. Will default to the stored token. """ - if not is_jinja_available(): - raise ValueError( - "Modelcard rendering is based on Jinja templates." - " Please make sure to have `jinja` installed before using `create_and_tag_model_card`." - " To install it, please run `pip install Jinja2`." - ) - try: # Check if the model card is present on the remote repo model_card = ModelCard.load(repo_id, token=token, ignore_metadata_errors=False) From d33ed6ccbacc76eddcdfe7a3e8622dd0a02ad3f3 Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Tue, 23 Jan 2024 13:17:32 +0530 Subject: [PATCH 05/20] fix: tests --- tests/models/test_modeling_common.py | 2 +- tests/pipelines/test_pipelines_common.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/models/test_modeling_common.py b/tests/models/test_modeling_common.py index 62a0188685cc..cd1cfdce0785 100644 --- a/tests/models/test_modeling_common.py +++ b/tests/models/test_modeling_common.py @@ -751,7 +751,7 @@ def test_push_to_hub_library_name(self): ) model.push_to_hub(self.repo_id, token=TOKEN) - model_card = ModelCard.load(self.repo_id, token=TOKEN).data + model_card = ModelCard.load(f"{USER}/{self.repo_id}", token=TOKEN).data assert model_card.library_name == "diffusers" # Reset repo diff --git a/tests/pipelines/test_pipelines_common.py b/tests/pipelines/test_pipelines_common.py index 8ddcf00739e0..37f02d85ba1b 100644 --- a/tests/pipelines/test_pipelines_common.py +++ b/tests/pipelines/test_pipelines_common.py @@ -1152,7 +1152,7 @@ def test_push_to_hub_library_name(self): pipeline = StableDiffusionPipeline(**components) pipeline.push_to_hub(self.repo_id, token=TOKEN) - model_card = ModelCard.load(self.repo_id, token=TOKEN).data + model_card = ModelCard.load(f"{USER}/{self.repo_id}", token=TOKEN).data assert model_card.library_name == "diffusers" # Reset repo From 2baf0d21a64381068dbded5547d2d2251d49ebf3 Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Tue, 23 Jan 2024 13:31:32 +0530 Subject: [PATCH 06/20] fix: push_to_hub behaviour for tagging from save_pretrained --- src/diffusers/models/modeling_utils.py | 7 ++++++- src/diffusers/pipelines/pipeline_utils.py | 6 ++++++ src/diffusers/utils/hub_utils.py | 7 +++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/diffusers/models/modeling_utils.py b/src/diffusers/models/modeling_utils.py index 445c3ca71caf..80068f4f2811 100644 --- a/src/diffusers/models/modeling_utils.py +++ b/src/diffusers/models/modeling_utils.py @@ -41,7 +41,7 @@ is_torch_version, logging, ) -from ..utils.hub_utils import PushToHubMixin +from ..utils.hub_utils import PushToHubMixin, create_and_tag_model_card logger = logging.get_logger(__name__) @@ -375,6 +375,11 @@ def save_pretrained( logger.info(f"Model weights saved in {os.path.join(save_directory, weights_name)}") if push_to_hub: + # Create a new empty model card and eventually tag it + model_card = create_and_tag_model_card(repo_id, token=token) + # Update model card if needed: + model_card.save(os.path.join(save_directory, "README.md")) + self._upload_folder( save_directory, repo_id, diff --git a/src/diffusers/pipelines/pipeline_utils.py b/src/diffusers/pipelines/pipeline_utils.py index de5dea679ee9..d8de78660475 100644 --- a/src/diffusers/pipelines/pipeline_utils.py +++ b/src/diffusers/pipelines/pipeline_utils.py @@ -60,6 +60,7 @@ logging, numpy_to_pil, ) +from ..utils.hub_utils import create_and_tag_model_card from ..utils.torch_utils import is_compiled_module @@ -720,6 +721,11 @@ def is_saveable_module(name, value): self.save_config(save_directory) if push_to_hub: + # Create a new empty model card and eventually tag it + model_card = create_and_tag_model_card(repo_id, token=token, is_pipeline=True) + # Update model card if needed: + model_card.save(os.path.join(save_directory, "README.md")) + self._upload_folder( save_directory, repo_id, diff --git a/src/diffusers/utils/hub_utils.py b/src/diffusers/utils/hub_utils.py index 10bc68b1b126..0477a140bb56 100644 --- a/src/diffusers/utils/hub_utils.py +++ b/src/diffusers/utils/hub_utils.py @@ -145,7 +145,7 @@ def create_model_card(args, model_name): # Taken from `transformers` -def create_and_tag_model_card(repo_id: str, token: Optional[str] = None): +def create_and_tag_model_card(repo_id: str, token: Optional[str] = None, is_pipeline=False): """ Creates or loads an existing model card and tags it with the `library_name`. @@ -154,13 +154,16 @@ def create_and_tag_model_card(repo_id: str, token: Optional[str] = None): The repo_id where to look for the model card. token (`str`, *optional*): Authentication token, obtained with `huggingface_hub.HfApi.login` method. Will default to the stored token. + is_pipeline (`bool`, *optional*): + Boolean to indicate if we're adding tag to a [`DiffusionPipeline`]. """ try: # Check if the model card is present on the remote repo model_card = ModelCard.load(repo_id, token=token, ignore_metadata_errors=False) except EntryNotFoundError: # Otherwise create a simple model card from template - model_description = "This is the model card of a 🧨 diffusers model that has been pushed on the Hub. This model card has been automatically generated." + component = "pipeline" if is_pipeline else "model" + model_description = f"This is the model card of a 🧨 diffusers {component} that has been pushed on the Hub. This model card has been automatically generated." card_data = ModelCardData(library_name="diffusers") model_card = ModelCard.from_template(card_data, model_description=model_description) From 5d9e664940bcc8b820eeaab27b101d523dd87ca5 Mon Sep 17 00:00:00 2001 From: Sayak Paul Date: Tue, 23 Jan 2024 14:42:44 +0530 Subject: [PATCH 07/20] Apply suggestions from code review Co-authored-by: Lucain --- src/diffusers/utils/hub_utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/diffusers/utils/hub_utils.py b/src/diffusers/utils/hub_utils.py index 0477a140bb56..466eec8a5a6d 100644 --- a/src/diffusers/utils/hub_utils.py +++ b/src/diffusers/utils/hub_utils.py @@ -145,7 +145,7 @@ def create_model_card(args, model_name): # Taken from `transformers` -def create_and_tag_model_card(repo_id: str, token: Optional[str] = None, is_pipeline=False): +def generate_model_card(repo_id: str, token: Optional[str] = None, is_pipeline: bool = False) -> ModelCard: """ Creates or loads an existing model card and tags it with the `library_name`. @@ -153,13 +153,13 @@ def create_and_tag_model_card(repo_id: str, token: Optional[str] = None, is_pipe repo_id (`str`): The repo_id where to look for the model card. token (`str`, *optional*): - Authentication token, obtained with `huggingface_hub.HfApi.login` method. Will default to the stored token. + Authentication token. Will default to the stored token. See https://huggingface.co/settings/token for more details. is_pipeline (`bool`, *optional*): Boolean to indicate if we're adding tag to a [`DiffusionPipeline`]. """ try: # Check if the model card is present on the remote repo - model_card = ModelCard.load(repo_id, token=token, ignore_metadata_errors=False) + model_card = ModelCard.load(repo_id, token=token) except EntryNotFoundError: # Otherwise create a simple model card from template component = "pipeline" if is_pipeline else "model" From 62ddbb831ccbc5ec7593a1ad06724cf728386f87 Mon Sep 17 00:00:00 2001 From: Sayak Paul Date: Tue, 23 Jan 2024 14:44:01 +0530 Subject: [PATCH 08/20] Apply suggestions from code review Co-authored-by: Lucain --- tests/models/test_modeling_common.py | 2 +- tests/pipelines/test_pipelines_common.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/models/test_modeling_common.py b/tests/models/test_modeling_common.py index cd1cfdce0785..4464b420ac33 100644 --- a/tests/models/test_modeling_common.py +++ b/tests/models/test_modeling_common.py @@ -736,7 +736,7 @@ def test_push_to_hub_in_organization(self): @unittest.skipIf( not is_jinja_available(), - reason="Model card tests cannot be performed with Jinja installed.", + reason="Model card tests cannot be performed without Jinja installed.", ) def test_push_to_hub_library_name(self): model = UNet2DConditionModel( diff --git a/tests/pipelines/test_pipelines_common.py b/tests/pipelines/test_pipelines_common.py index 37f02d85ba1b..e107c5772af9 100644 --- a/tests/pipelines/test_pipelines_common.py +++ b/tests/pipelines/test_pipelines_common.py @@ -1145,7 +1145,7 @@ def test_push_to_hub_in_organization(self): @unittest.skipIf( not is_jinja_available(), - reason="Model card tests cannot be performed with Jinja installed.", + reason="Model card tests cannot be performed without Jinja installed.", ) def test_push_to_hub_library_name(self): components = self.get_pipeline_components() From 0d73555eb27ebbbca915fed60081d7537d4d6235 Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Tue, 23 Jan 2024 14:45:30 +0530 Subject: [PATCH 09/20] import fixes. --- src/diffusers/models/modeling_utils.py | 4 ++-- src/diffusers/pipelines/pipeline_utils.py | 4 ++-- src/diffusers/utils/hub_utils.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/diffusers/models/modeling_utils.py b/src/diffusers/models/modeling_utils.py index 80068f4f2811..774cdd5b78b6 100644 --- a/src/diffusers/models/modeling_utils.py +++ b/src/diffusers/models/modeling_utils.py @@ -41,7 +41,7 @@ is_torch_version, logging, ) -from ..utils.hub_utils import PushToHubMixin, create_and_tag_model_card +from ..utils.hub_utils import PushToHubMixin, generate_model_card logger = logging.get_logger(__name__) @@ -376,7 +376,7 @@ def save_pretrained( if push_to_hub: # Create a new empty model card and eventually tag it - model_card = create_and_tag_model_card(repo_id, token=token) + model_card = generate_model_card(repo_id, token=token) # Update model card if needed: model_card.save(os.path.join(save_directory, "README.md")) diff --git a/src/diffusers/pipelines/pipeline_utils.py b/src/diffusers/pipelines/pipeline_utils.py index d8de78660475..bd154391f586 100644 --- a/src/diffusers/pipelines/pipeline_utils.py +++ b/src/diffusers/pipelines/pipeline_utils.py @@ -60,7 +60,7 @@ logging, numpy_to_pil, ) -from ..utils.hub_utils import create_and_tag_model_card +from ..utils.hub_utils import generate_model_card from ..utils.torch_utils import is_compiled_module @@ -722,7 +722,7 @@ def is_saveable_module(name, value): if push_to_hub: # Create a new empty model card and eventually tag it - model_card = create_and_tag_model_card(repo_id, token=token, is_pipeline=True) + model_card = generate_model_card(repo_id, token=token, is_pipeline=True) # Update model card if needed: model_card.save(os.path.join(save_directory, "README.md")) diff --git a/src/diffusers/utils/hub_utils.py b/src/diffusers/utils/hub_utils.py index 466eec8a5a6d..ae7c5548193e 100644 --- a/src/diffusers/utils/hub_utils.py +++ b/src/diffusers/utils/hub_utils.py @@ -462,7 +462,7 @@ def push_to_hub( repo_id = create_repo(repo_id, private=private, token=token, exist_ok=True).repo_id # Create a new empty model card and eventually tag it - model_card = create_and_tag_model_card(repo_id, token=token) + model_card = generate_model_card(repo_id, token=token) # Save all files. save_kwargs = {"safe_serialization": safe_serialization} From 5297ad46f747ca462585c53c1d67872953e3b62e Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Tue, 23 Jan 2024 14:46:33 +0530 Subject: [PATCH 10/20] add library name to existing model card. --- src/diffusers/utils/hub_utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/diffusers/utils/hub_utils.py b/src/diffusers/utils/hub_utils.py index ae7c5548193e..77f9d0f5d04a 100644 --- a/src/diffusers/utils/hub_utils.py +++ b/src/diffusers/utils/hub_utils.py @@ -160,6 +160,8 @@ def generate_model_card(repo_id: str, token: Optional[str] = None, is_pipeline: try: # Check if the model card is present on the remote repo model_card = ModelCard.load(repo_id, token=token) + if model_card.data.library_name is None: + model_card.data.library_name = "diffusers" except EntryNotFoundError: # Otherwise create a simple model card from template component = "pipeline" if is_pipeline else "model" From 99ce47c863c3319ce7736171d62ab8a868f31ab4 Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Tue, 23 Jan 2024 14:58:23 +0530 Subject: [PATCH 11/20] add: standalone test for generate_model_card --- tests/others/test_hub_utils.py | 66 ++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/tests/others/test_hub_utils.py b/tests/others/test_hub_utils.py index e8b8ea3a2fd9..7e1773535a10 100644 --- a/tests/others/test_hub_utils.py +++ b/tests/others/test_hub_utils.py @@ -17,35 +17,57 @@ from tempfile import TemporaryDirectory from unittest.mock import Mock, patch -import diffusers.utils.hub_utils +from diffusers.utils.hub_utils import create_model_card, generate_model_card class CreateModelCardTest(unittest.TestCase): + def create_dummy_args(self, output_dir): + # Dummy args values + args = Mock() + args.output_dir = output_dir + args.local_rank = 0 + args.hub_token = "hub_token" + args.dataset_name = "dataset_name" + args.learning_rate = 0.01 + args.train_batch_size = 100000 + args.eval_batch_size = 10000 + args.gradient_accumulation_steps = 0.01 + args.adam_beta1 = 0.02 + args.adam_beta2 = 0.03 + args.adam_weight_decay = 0.0005 + args.adam_epsilon = 0.000001 + args.lr_scheduler = 1 + args.lr_warmup_steps = 10 + args.ema_inv_gamma = 0.001 + args.ema_power = 0.1 + args.ema_max_decay = 0.2 + args.mixed_precision = True + return args + @patch("diffusers.utils.hub_utils.get_full_repo_name") def test_create_model_card(self, repo_name_mock: Mock) -> None: repo_name_mock.return_value = "full_repo_name" with TemporaryDirectory() as tmpdir: - # Dummy args values - args = Mock() - args.output_dir = tmpdir - args.local_rank = 0 - args.hub_token = "hub_token" - args.dataset_name = "dataset_name" - args.learning_rate = 0.01 - args.train_batch_size = 100000 - args.eval_batch_size = 10000 - args.gradient_accumulation_steps = 0.01 - args.adam_beta1 = 0.02 - args.adam_beta2 = 0.03 - args.adam_weight_decay = 0.0005 - args.adam_epsilon = 0.000001 - args.lr_scheduler = 1 - args.lr_warmup_steps = 10 - args.ema_inv_gamma = 0.001 - args.ema_power = 0.1 - args.ema_max_decay = 0.2 - args.mixed_precision = True + args = self.create_dummy_args(output_dir=tmpdir) + + # Model card mush be rendered and saved + create_model_card(args, model_name="model_name") + self.assertTrue((Path(tmpdir) / "README.md").is_file()) + + def test_generate_existing_model_card_with_library_name(self): + with TemporaryDirectory() as tmpdir: + args = self.create_dummy_args(output_dir=tmpdir) # Model card mush be rendered and saved - diffusers.utils.hub_utils.create_model_card(args, model_name="model_name") + create_model_card(args, model_name="model_name") self.assertTrue((Path(tmpdir) / "README.md").is_file()) + + model_card = generate_model_card(tmpdir) + assert model_card.data.library_name == "diffusers" + + def test_generate_model_card_with_library_name(self): + with TemporaryDirectory() as tmpdir: + model_card = generate_model_card(tmpdir) + + model_card = generate_model_card(tmpdir) + assert model_card.data.library_name == "diffusers" From 2b93dcc058a68ee5da1f3f59676501346bf1de47 Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Tue, 23 Jan 2024 15:24:28 +0530 Subject: [PATCH 12/20] fix tests for standalone method --- tests/others/test_hub_utils.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/others/test_hub_utils.py b/tests/others/test_hub_utils.py index 7e1773535a10..2bcb5d148844 100644 --- a/tests/others/test_hub_utils.py +++ b/tests/others/test_hub_utils.py @@ -12,6 +12,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import os import unittest from pathlib import Path from tempfile import TemporaryDirectory @@ -56,11 +57,9 @@ def test_create_model_card(self, repo_name_mock: Mock) -> None: def test_generate_existing_model_card_with_library_name(self): with TemporaryDirectory() as tmpdir: - args = self.create_dummy_args(output_dir=tmpdir) - - # Model card mush be rendered and saved - create_model_card(args, model_name="model_name") - self.assertTrue((Path(tmpdir) / "README.md").is_file()) + content = "hello" + with open(os.path.join(tmpdir, "README.md"), "w") as f: + f.write(content) model_card = generate_model_card(tmpdir) assert model_card.data.library_name == "diffusers" From 0f31032ca3654af2c683baa17c09e177323a3f3e Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Tue, 23 Jan 2024 15:38:03 +0530 Subject: [PATCH 13/20] moved library_name to a better place. --- src/diffusers/utils/hub_utils.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/diffusers/utils/hub_utils.py b/src/diffusers/utils/hub_utils.py index 618d60159903..31b43674092f 100644 --- a/src/diffusers/utils/hub_utils.py +++ b/src/diffusers/utils/hub_utils.py @@ -160,15 +160,16 @@ def generate_model_card(repo_id: str, token: Optional[str] = None, is_pipeline: try: # Check if the model card is present on the remote repo model_card = ModelCard.load(repo_id, token=token) - if model_card.data.library_name is None: - model_card.data.library_name = "diffusers" except EntryNotFoundError: # Otherwise create a simple model card from template component = "pipeline" if is_pipeline else "model" model_description = f"This is the model card of a 🧨 diffusers {component} that has been pushed on the Hub. This model card has been automatically generated." - card_data = ModelCardData(library_name="diffusers") + card_data = ModelCardData() model_card = ModelCard.from_template(card_data, model_description=model_description) + if model_card.data.library_name is None: + model_card.data.library_name = "diffusers" + return model_card From 987178bbd543f7412a262a1a50a282c72d138a15 Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Tue, 23 Jan 2024 15:50:48 +0530 Subject: [PATCH 14/20] merge create_model_card and generate_model_card. --- src/diffusers/models/modeling_utils.py | 4 +- src/diffusers/pipelines/pipeline_utils.py | 4 +- src/diffusers/utils/hub_utils.py | 131 +++++++++++----------- tests/others/test_hub_utils.py | 8 +- 4 files changed, 75 insertions(+), 72 deletions(-) diff --git a/src/diffusers/models/modeling_utils.py b/src/diffusers/models/modeling_utils.py index 8138a91114a6..13bc35239849 100644 --- a/src/diffusers/models/modeling_utils.py +++ b/src/diffusers/models/modeling_utils.py @@ -42,7 +42,7 @@ is_torch_version, logging, ) -from ..utils.hub_utils import PushToHubMixin, generate_model_card +from ..utils.hub_utils import PushToHubMixin, create_model_card logger = logging.get_logger(__name__) @@ -378,7 +378,7 @@ def save_pretrained( if push_to_hub: # Create a new empty model card and eventually tag it - model_card = generate_model_card(repo_id, token=token) + model_card = create_model_card(repo_id=repo_id, token=token, training=False, is_pipeline=False) # Update model card if needed: model_card.save(os.path.join(save_directory, "README.md")) diff --git a/src/diffusers/pipelines/pipeline_utils.py b/src/diffusers/pipelines/pipeline_utils.py index 6967ccfd681c..5ef7cbcd2cad 100644 --- a/src/diffusers/pipelines/pipeline_utils.py +++ b/src/diffusers/pipelines/pipeline_utils.py @@ -60,7 +60,7 @@ logging, numpy_to_pil, ) -from ..utils.hub_utils import generate_model_card +from ..utils.hub_utils import create_model_card from ..utils.torch_utils import is_compiled_module @@ -727,7 +727,7 @@ def is_saveable_module(name, value): if push_to_hub: # Create a new empty model card and eventually tag it - model_card = generate_model_card(repo_id, token=token, is_pipeline=True) + model_card = create_model_card(repo_id=repo_id, token=token, training=False, is_pipeline=True) # Update model card if needed: model_card.save(os.path.join(save_directory, "README.md")) diff --git a/src/diffusers/utils/hub_utils.py b/src/diffusers/utils/hub_utils.py index 31b43674092f..2d102d8c6796 100644 --- a/src/diffusers/utils/hub_utils.py +++ b/src/diffusers/utils/hub_utils.py @@ -95,61 +95,15 @@ def http_user_agent(user_agent: Union[Dict, str, None] = None) -> str: return ua -def create_model_card(args, model_name): - if not is_jinja_available(): - raise ValueError( - "Modelcard rendering is based on Jinja templates." - " Please make sure to have `jinja` installed before using `create_model_card`." - " To install it, please run `pip install Jinja2`." - ) - - if hasattr(args, "local_rank") and args.local_rank not in [-1, 0]: - return - - hub_token = args.hub_token if hasattr(args, "hub_token") else None - repo_name = get_full_repo_name(model_name, token=hub_token) - - model_card = ModelCard.from_template( - card_data=ModelCardData( # Card metadata object that will be converted to YAML block - language="en", - license="apache-2.0", - library_name="diffusers", - tags=[], - datasets=args.dataset_name, - metrics=[], - ), - template_path=MODEL_CARD_TEMPLATE_PATH, - model_name=model_name, - repo_name=repo_name, - dataset_name=args.dataset_name if hasattr(args, "dataset_name") else None, - learning_rate=args.learning_rate, - train_batch_size=args.train_batch_size, - eval_batch_size=args.eval_batch_size, - gradient_accumulation_steps=( - args.gradient_accumulation_steps if hasattr(args, "gradient_accumulation_steps") else None - ), - adam_beta1=args.adam_beta1 if hasattr(args, "adam_beta1") else None, - adam_beta2=args.adam_beta2 if hasattr(args, "adam_beta2") else None, - adam_weight_decay=args.adam_weight_decay if hasattr(args, "adam_weight_decay") else None, - adam_epsilon=args.adam_epsilon if hasattr(args, "adam_epsilon") else None, - lr_scheduler=args.lr_scheduler if hasattr(args, "lr_scheduler") else None, - lr_warmup_steps=args.lr_warmup_steps if hasattr(args, "lr_warmup_steps") else None, - ema_inv_gamma=args.ema_inv_gamma if hasattr(args, "ema_inv_gamma") else None, - ema_power=args.ema_power if hasattr(args, "ema_power") else None, - ema_max_decay=args.ema_max_decay if hasattr(args, "ema_max_decay") else None, - mixed_precision=args.mixed_precision, - ) - - card_path = os.path.join(args.output_dir, "README.md") - model_card.save(card_path) - - -# Taken from `transformers` -def generate_model_card(repo_id: str, token: Optional[str] = None, is_pipeline: bool = False) -> ModelCard: +def create_model_card( + args=None, model_name=None, repo_id=None, token=None, training=True, is_pipeline=True +) -> Union[None, ModelCard]: """ Creates or loads an existing model card and tags it with the `library_name`. Args: + args (`Namespace`): Training arguments. + model_name (`str`): Name of the model to create a repository. repo_id (`str`): The repo_id where to look for the model card. token (`str`, *optional*): @@ -157,20 +111,69 @@ def generate_model_card(repo_id: str, token: Optional[str] = None, is_pipeline: is_pipeline (`bool`, *optional*): Boolean to indicate if we're adding tag to a [`DiffusionPipeline`]. """ - try: - # Check if the model card is present on the remote repo - model_card = ModelCard.load(repo_id, token=token) - except EntryNotFoundError: - # Otherwise create a simple model card from template - component = "pipeline" if is_pipeline else "model" - model_description = f"This is the model card of a 🧨 diffusers {component} that has been pushed on the Hub. This model card has been automatically generated." - card_data = ModelCardData() - model_card = ModelCard.from_template(card_data, model_description=model_description) + if not is_jinja_available(): + raise ValueError( + "Modelcard rendering is based on Jinja templates." + " Please make sure to have `jinja` installed before using `create_model_card`." + " To install it, please run `pip install Jinja2`." + ) + + if training: + if hasattr(args, "local_rank") and args.local_rank not in [-1, 0]: + return + + hub_token = args.hub_token if hasattr(args, "hub_token") else None + repo_name = get_full_repo_name(model_name, token=hub_token) + + model_card = ModelCard.from_template( + card_data=ModelCardData( # Card metadata object that will be converted to YAML block + language="en", + license="apache-2.0", + library_name="diffusers", + tags=[], + datasets=args.dataset_name, + metrics=[], + ), + template_path=MODEL_CARD_TEMPLATE_PATH, + model_name=model_name, + repo_name=repo_name, + dataset_name=args.dataset_name if hasattr(args, "dataset_name") else None, + learning_rate=args.learning_rate, + train_batch_size=args.train_batch_size, + eval_batch_size=args.eval_batch_size, + gradient_accumulation_steps=( + args.gradient_accumulation_steps if hasattr(args, "gradient_accumulation_steps") else None + ), + adam_beta1=args.adam_beta1 if hasattr(args, "adam_beta1") else None, + adam_beta2=args.adam_beta2 if hasattr(args, "adam_beta2") else None, + adam_weight_decay=args.adam_weight_decay if hasattr(args, "adam_weight_decay") else None, + adam_epsilon=args.adam_epsilon if hasattr(args, "adam_epsilon") else None, + lr_scheduler=args.lr_scheduler if hasattr(args, "lr_scheduler") else None, + lr_warmup_steps=args.lr_warmup_steps if hasattr(args, "lr_warmup_steps") else None, + ema_inv_gamma=args.ema_inv_gamma if hasattr(args, "ema_inv_gamma") else None, + ema_power=args.ema_power if hasattr(args, "ema_power") else None, + ema_max_decay=args.ema_max_decay if hasattr(args, "ema_max_decay") else None, + mixed_precision=args.mixed_precision, + ) + + card_path = os.path.join(args.output_dir, "README.md") + model_card.save(card_path) + + else: + try: + # Check if the model card is present on the remote repo + model_card = ModelCard.load(repo_id, token=token) + except EntryNotFoundError: + # Otherwise create a simple model card from template + component = "pipeline" if is_pipeline else "model" + model_description = f"This is the model card of a 🧨 diffusers {component} that has been pushed on the Hub. This model card has been automatically generated." + card_data = ModelCardData() + model_card = ModelCard.from_template(card_data, model_description=model_description) - if model_card.data.library_name is None: - model_card.data.library_name = "diffusers" + if model_card.data.library_name is None: + model_card.data.library_name = "diffusers" - return model_card + return model_card def extract_commit_hash(resolved_file: Optional[str], commit_hash: Optional[str] = None): @@ -465,7 +468,7 @@ def push_to_hub( repo_id = create_repo(repo_id, private=private, token=token, exist_ok=True).repo_id # Create a new empty model card and eventually tag it - model_card = generate_model_card(repo_id, token=token) + model_card = create_model_card(repo_id=repo_id, token=token, training=False) # Save all files. save_kwargs = {"safe_serialization": safe_serialization} diff --git a/tests/others/test_hub_utils.py b/tests/others/test_hub_utils.py index 2bcb5d148844..0965ccc44bbc 100644 --- a/tests/others/test_hub_utils.py +++ b/tests/others/test_hub_utils.py @@ -18,7 +18,7 @@ from tempfile import TemporaryDirectory from unittest.mock import Mock, patch -from diffusers.utils.hub_utils import create_model_card, generate_model_card +from diffusers.utils.hub_utils import create_model_card class CreateModelCardTest(unittest.TestCase): @@ -61,12 +61,12 @@ def test_generate_existing_model_card_with_library_name(self): with open(os.path.join(tmpdir, "README.md"), "w") as f: f.write(content) - model_card = generate_model_card(tmpdir) + model_card = create_model_card(tmpdir) assert model_card.data.library_name == "diffusers" def test_generate_model_card_with_library_name(self): with TemporaryDirectory() as tmpdir: - model_card = generate_model_card(tmpdir) + model_card = create_model_card(tmpdir) - model_card = generate_model_card(tmpdir) + model_card = create_model_card(tmpdir) assert model_card.data.library_name == "diffusers" From 5bd864cc449ee0e171f3a92b34c736ce7c96866b Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Tue, 23 Jan 2024 15:54:16 +0530 Subject: [PATCH 15/20] fix test --- tests/others/test_hub_utils.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/others/test_hub_utils.py b/tests/others/test_hub_utils.py index 0965ccc44bbc..b07c69946c90 100644 --- a/tests/others/test_hub_utils.py +++ b/tests/others/test_hub_utils.py @@ -61,12 +61,11 @@ def test_generate_existing_model_card_with_library_name(self): with open(os.path.join(tmpdir, "README.md"), "w") as f: f.write(content) - model_card = create_model_card(tmpdir) + model_card = create_model_card(repo_id=tmpdir, training=False) assert model_card.data.library_name == "diffusers" def test_generate_model_card_with_library_name(self): with TemporaryDirectory() as tmpdir: - model_card = create_model_card(tmpdir) + model_card = create_model_card(repo_id=tmpdir, training=False) - model_card = create_model_card(tmpdir) assert model_card.data.library_name == "diffusers" From 33e2d912a602ea3a3d5c6323716e101241141179 Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Tue, 23 Jan 2024 16:23:15 +0530 Subject: [PATCH 16/20] address lucain's comments --- src/diffusers/models/modeling_utils.py | 6 +- src/diffusers/pipelines/pipeline_utils.py | 6 +- src/diffusers/utils/hub_utils.py | 80 ++++++----------------- tests/others/test_hub_utils.py | 53 ++------------- 4 files changed, 30 insertions(+), 115 deletions(-) diff --git a/src/diffusers/models/modeling_utils.py b/src/diffusers/models/modeling_utils.py index 13bc35239849..e687263f3a2d 100644 --- a/src/diffusers/models/modeling_utils.py +++ b/src/diffusers/models/modeling_utils.py @@ -42,7 +42,7 @@ is_torch_version, logging, ) -from ..utils.hub_utils import PushToHubMixin, create_model_card +from ..utils.hub_utils import PushToHubMixin, load_or_create_model_card, populate_model_card logger = logging.get_logger(__name__) @@ -378,8 +378,8 @@ def save_pretrained( if push_to_hub: # Create a new empty model card and eventually tag it - model_card = create_model_card(repo_id=repo_id, token=token, training=False, is_pipeline=False) - # Update model card if needed: + model_card = load_or_create_model_card(repo_id=repo_id, token=token) + model_card = populate_model_card(model_card) model_card.save(os.path.join(save_directory, "README.md")) self._upload_folder( diff --git a/src/diffusers/pipelines/pipeline_utils.py b/src/diffusers/pipelines/pipeline_utils.py index 5ef7cbcd2cad..7bb853f3e713 100644 --- a/src/diffusers/pipelines/pipeline_utils.py +++ b/src/diffusers/pipelines/pipeline_utils.py @@ -60,7 +60,7 @@ logging, numpy_to_pil, ) -from ..utils.hub_utils import create_model_card +from ..utils.hub_utils import load_or_create_model_card, populate_model_card from ..utils.torch_utils import is_compiled_module @@ -727,8 +727,8 @@ def is_saveable_module(name, value): if push_to_hub: # Create a new empty model card and eventually tag it - model_card = create_model_card(repo_id=repo_id, token=token, training=False, is_pipeline=True) - # Update model card if needed: + model_card = load_or_create_model_card(repo_id=repo_id, token=token, is_pipeline=True) + model_card = populate_model_card(model_card) model_card.save(os.path.join(save_directory, "README.md")) self._upload_folder( diff --git a/src/diffusers/utils/hub_utils.py b/src/diffusers/utils/hub_utils.py index 2d102d8c6796..77c0b54336d4 100644 --- a/src/diffusers/utils/hub_utils.py +++ b/src/diffusers/utils/hub_utils.py @@ -28,7 +28,6 @@ ModelCard, ModelCardData, create_repo, - get_full_repo_name, hf_hub_download, upload_folder, ) @@ -95,15 +94,11 @@ def http_user_agent(user_agent: Union[Dict, str, None] = None) -> str: return ua -def create_model_card( - args=None, model_name=None, repo_id=None, token=None, training=True, is_pipeline=True -) -> Union[None, ModelCard]: +def load_or_create_model_card(repo_id=None, token=None, is_pipeline=False) -> ModelCard: """ - Creates or loads an existing model card and tags it with the `library_name`. + Loads or creates a model card. Args: - args (`Namespace`): Training arguments. - model_name (`str`): Name of the model to create a repository. repo_id (`str`): The repo_id where to look for the model card. token (`str`, *optional*): @@ -118,62 +113,24 @@ def create_model_card( " To install it, please run `pip install Jinja2`." ) - if training: - if hasattr(args, "local_rank") and args.local_rank not in [-1, 0]: - return - - hub_token = args.hub_token if hasattr(args, "hub_token") else None - repo_name = get_full_repo_name(model_name, token=hub_token) - - model_card = ModelCard.from_template( - card_data=ModelCardData( # Card metadata object that will be converted to YAML block - language="en", - license="apache-2.0", - library_name="diffusers", - tags=[], - datasets=args.dataset_name, - metrics=[], - ), - template_path=MODEL_CARD_TEMPLATE_PATH, - model_name=model_name, - repo_name=repo_name, - dataset_name=args.dataset_name if hasattr(args, "dataset_name") else None, - learning_rate=args.learning_rate, - train_batch_size=args.train_batch_size, - eval_batch_size=args.eval_batch_size, - gradient_accumulation_steps=( - args.gradient_accumulation_steps if hasattr(args, "gradient_accumulation_steps") else None - ), - adam_beta1=args.adam_beta1 if hasattr(args, "adam_beta1") else None, - adam_beta2=args.adam_beta2 if hasattr(args, "adam_beta2") else None, - adam_weight_decay=args.adam_weight_decay if hasattr(args, "adam_weight_decay") else None, - adam_epsilon=args.adam_epsilon if hasattr(args, "adam_epsilon") else None, - lr_scheduler=args.lr_scheduler if hasattr(args, "lr_scheduler") else None, - lr_warmup_steps=args.lr_warmup_steps if hasattr(args, "lr_warmup_steps") else None, - ema_inv_gamma=args.ema_inv_gamma if hasattr(args, "ema_inv_gamma") else None, - ema_power=args.ema_power if hasattr(args, "ema_power") else None, - ema_max_decay=args.ema_max_decay if hasattr(args, "ema_max_decay") else None, - mixed_precision=args.mixed_precision, - ) - - card_path = os.path.join(args.output_dir, "README.md") - model_card.save(card_path) + try: + # Check if the model card is present on the remote repo + model_card = ModelCard.load(repo_id, token=token) + except EntryNotFoundError: + # Otherwise create a simple model card from template + component = "pipeline" if is_pipeline else "model" + model_description = f"This is the model card of a 🧨 diffusers {component} that has been pushed on the Hub. This model card has been automatically generated." + card_data = ModelCardData() + model_card = ModelCard.from_template(card_data, model_description=model_description) - else: - try: - # Check if the model card is present on the remote repo - model_card = ModelCard.load(repo_id, token=token) - except EntryNotFoundError: - # Otherwise create a simple model card from template - component = "pipeline" if is_pipeline else "model" - model_description = f"This is the model card of a 🧨 diffusers {component} that has been pushed on the Hub. This model card has been automatically generated." - card_data = ModelCardData() - model_card = ModelCard.from_template(card_data, model_description=model_description) + return model_card - if model_card.data.library_name is None: - model_card.data.library_name = "diffusers" - return model_card +def populate_model_card(model_card: ModelCard) -> ModelCard: + """Populates the `model_card` with library name.""" + if model_card.data.library_name is None: + model_card.data.library_name = "diffusers" + return model_card def extract_commit_hash(resolved_file: Optional[str], commit_hash: Optional[str] = None): @@ -468,7 +425,8 @@ def push_to_hub( repo_id = create_repo(repo_id, private=private, token=token, exist_ok=True).repo_id # Create a new empty model card and eventually tag it - model_card = create_model_card(repo_id=repo_id, token=token, training=False) + model_card = load_or_create_model_card(repo_id=repo_id, token=token) + model_card = populate_model_card(model_card) # Save all files. save_kwargs = {"safe_serialization": safe_serialization} diff --git a/tests/others/test_hub_utils.py b/tests/others/test_hub_utils.py index b07c69946c90..220f67279a8b 100644 --- a/tests/others/test_hub_utils.py +++ b/tests/others/test_hub_utils.py @@ -12,60 +12,17 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import os import unittest from pathlib import Path from tempfile import TemporaryDirectory -from unittest.mock import Mock, patch -from diffusers.utils.hub_utils import create_model_card +from diffusers.utils.hub_utils import load_or_create_model_card class CreateModelCardTest(unittest.TestCase): - def create_dummy_args(self, output_dir): - # Dummy args values - args = Mock() - args.output_dir = output_dir - args.local_rank = 0 - args.hub_token = "hub_token" - args.dataset_name = "dataset_name" - args.learning_rate = 0.01 - args.train_batch_size = 100000 - args.eval_batch_size = 10000 - args.gradient_accumulation_steps = 0.01 - args.adam_beta1 = 0.02 - args.adam_beta2 = 0.03 - args.adam_weight_decay = 0.0005 - args.adam_epsilon = 0.000001 - args.lr_scheduler = 1 - args.lr_warmup_steps = 10 - args.ema_inv_gamma = 0.001 - args.ema_power = 0.1 - args.ema_max_decay = 0.2 - args.mixed_precision = True - return args - - @patch("diffusers.utils.hub_utils.get_full_repo_name") - def test_create_model_card(self, repo_name_mock: Mock) -> None: - repo_name_mock.return_value = "full_repo_name" - with TemporaryDirectory() as tmpdir: - args = self.create_dummy_args(output_dir=tmpdir) - - # Model card mush be rendered and saved - create_model_card(args, model_name="model_name") - self.assertTrue((Path(tmpdir) / "README.md").is_file()) - - def test_generate_existing_model_card_with_library_name(self): - with TemporaryDirectory() as tmpdir: - content = "hello" - with open(os.path.join(tmpdir, "README.md"), "w") as f: - f.write(content) - - model_card = create_model_card(repo_id=tmpdir, training=False) - assert model_card.data.library_name == "diffusers" - def test_generate_model_card_with_library_name(self): with TemporaryDirectory() as tmpdir: - model_card = create_model_card(repo_id=tmpdir, training=False) - - assert model_card.data.library_name == "diffusers" + file_path = Path(tmpdir) / "README.md" + file_path.write_text("---\nlibrary_name: foo\n---\nContent\n") + model_card = load_or_create_model_card(file_path) + assert model_card.data.library_name == "foo" From 322c0e19cfb995839ece80e22abe14a9de4092bc Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Tue, 23 Jan 2024 16:34:06 +0530 Subject: [PATCH 17/20] fix return identation --- src/diffusers/utils/hub_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diffusers/utils/hub_utils.py b/src/diffusers/utils/hub_utils.py index 77c0b54336d4..f91293a2ae60 100644 --- a/src/diffusers/utils/hub_utils.py +++ b/src/diffusers/utils/hub_utils.py @@ -123,7 +123,7 @@ def load_or_create_model_card(repo_id=None, token=None, is_pipeline=False) -> Mo card_data = ModelCardData() model_card = ModelCard.from_template(card_data, model_description=model_description) - return model_card + return model_card def populate_model_card(model_card: ModelCard) -> ModelCard: From 73ea51d45cdec1865c556a67470bc5096b462e27 Mon Sep 17 00:00:00 2001 From: Sayak Paul Date: Tue, 23 Jan 2024 19:36:43 +0530 Subject: [PATCH 18/20] Apply suggestions from code review Co-authored-by: Lucain --- src/diffusers/models/modeling_utils.py | 2 +- src/diffusers/utils/hub_utils.py | 6 +++--- tests/others/test_hub_utils.py | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/diffusers/models/modeling_utils.py b/src/diffusers/models/modeling_utils.py index e687263f3a2d..aab4d16172d9 100644 --- a/src/diffusers/models/modeling_utils.py +++ b/src/diffusers/models/modeling_utils.py @@ -378,7 +378,7 @@ def save_pretrained( if push_to_hub: # Create a new empty model card and eventually tag it - model_card = load_or_create_model_card(repo_id=repo_id, token=token) + model_card = load_or_create_model_card(repo_id, token=token) model_card = populate_model_card(model_card) model_card.save(os.path.join(save_directory, "README.md")) diff --git a/src/diffusers/utils/hub_utils.py b/src/diffusers/utils/hub_utils.py index f91293a2ae60..01e4159dfffe 100644 --- a/src/diffusers/utils/hub_utils.py +++ b/src/diffusers/utils/hub_utils.py @@ -94,7 +94,7 @@ def http_user_agent(user_agent: Union[Dict, str, None] = None) -> str: return ua -def load_or_create_model_card(repo_id=None, token=None, is_pipeline=False) -> ModelCard: +def load_or_create_model_card(repo_id_or_path: Optional[str] = None, token: Optional[str] = None, is_pipeline: bool = False) -> ModelCard: """ Loads or creates a model card. @@ -115,7 +115,7 @@ def load_or_create_model_card(repo_id=None, token=None, is_pipeline=False) -> Mo try: # Check if the model card is present on the remote repo - model_card = ModelCard.load(repo_id, token=token) + model_card = ModelCard.load(repo_id_or_path, token=token) except EntryNotFoundError: # Otherwise create a simple model card from template component = "pipeline" if is_pipeline else "model" @@ -425,7 +425,7 @@ def push_to_hub( repo_id = create_repo(repo_id, private=private, token=token, exist_ok=True).repo_id # Create a new empty model card and eventually tag it - model_card = load_or_create_model_card(repo_id=repo_id, token=token) + model_card = load_or_create_model_card(repo_id, token=token) model_card = populate_model_card(model_card) # Save all files. diff --git a/tests/others/test_hub_utils.py b/tests/others/test_hub_utils.py index 220f67279a8b..23fbb35e913d 100644 --- a/tests/others/test_hub_utils.py +++ b/tests/others/test_hub_utils.py @@ -25,4 +25,5 @@ def test_generate_model_card_with_library_name(self): file_path = Path(tmpdir) / "README.md" file_path.write_text("---\nlibrary_name: foo\n---\nContent\n") model_card = load_or_create_model_card(file_path) + populate_model_card(model_card) assert model_card.data.library_name == "foo" From e32e5e1f5aaf5644375cfbe224c343b38b49d95a Mon Sep 17 00:00:00 2001 From: sayakpaul Date: Tue, 23 Jan 2024 19:39:25 +0530 Subject: [PATCH 19/20] address further comments. --- src/diffusers/utils/hub_utils.py | 5 ++- src/diffusers/utils/model_card_template.md | 50 ---------------------- tests/others/test_hub_utils.py | 2 +- 3 files changed, 4 insertions(+), 53 deletions(-) delete mode 100644 src/diffusers/utils/model_card_template.md diff --git a/src/diffusers/utils/hub_utils.py b/src/diffusers/utils/hub_utils.py index 01e4159dfffe..c6a45b569218 100644 --- a/src/diffusers/utils/hub_utils.py +++ b/src/diffusers/utils/hub_utils.py @@ -66,7 +66,6 @@ logger = get_logger(__name__) -MODEL_CARD_TEMPLATE_PATH = Path(__file__).parent / "model_card_template.md" SESSION_ID = uuid4().hex @@ -94,7 +93,9 @@ def http_user_agent(user_agent: Union[Dict, str, None] = None) -> str: return ua -def load_or_create_model_card(repo_id_or_path: Optional[str] = None, token: Optional[str] = None, is_pipeline: bool = False) -> ModelCard: +def load_or_create_model_card( + repo_id_or_path: Optional[str] = None, token: Optional[str] = None, is_pipeline: bool = False +) -> ModelCard: """ Loads or creates a model card. diff --git a/src/diffusers/utils/model_card_template.md b/src/diffusers/utils/model_card_template.md deleted file mode 100644 index f19c85b0fcf2..000000000000 --- a/src/diffusers/utils/model_card_template.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -{{ card_data }} ---- - - - -# {{ model_name | default("Diffusion Model") }} - -## Model description - -This diffusion model is trained with the [🤗 Diffusers](https://github.com/huggingface/diffusers) library -on the `{{ dataset_name }}` dataset. - -## Intended uses & limitations - -#### How to use - -```python -# TODO: add an example code snippet for running this diffusion pipeline -``` - -#### Limitations and bias - -[TODO: provide examples of latent issues and potential remediations] - -## Training data - -[TODO: describe the data used to train the model] - -### Training hyperparameters - -The following hyperparameters were used during training: -- learning_rate: {{ learning_rate }} -- train_batch_size: {{ train_batch_size }} -- eval_batch_size: {{ eval_batch_size }} -- gradient_accumulation_steps: {{ gradient_accumulation_steps }} -- optimizer: AdamW with betas=({{ adam_beta1 }}, {{ adam_beta2 }}), weight_decay={{ adam_weight_decay }} and epsilon={{ adam_epsilon }} -- lr_scheduler: {{ lr_scheduler }} -- lr_warmup_steps: {{ lr_warmup_steps }} -- ema_inv_gamma: {{ ema_inv_gamma }} -- ema_inv_gamma: {{ ema_power }} -- ema_inv_gamma: {{ ema_max_decay }} -- mixed_precision: {{ mixed_precision }} - -### Training results - -📈 [TensorBoard logs](https://huggingface.co/{{ repo_name }}/tensorboard?#scalars) - - diff --git a/tests/others/test_hub_utils.py b/tests/others/test_hub_utils.py index 23fbb35e913d..7d01172125a8 100644 --- a/tests/others/test_hub_utils.py +++ b/tests/others/test_hub_utils.py @@ -16,7 +16,7 @@ from pathlib import Path from tempfile import TemporaryDirectory -from diffusers.utils.hub_utils import load_or_create_model_card +from diffusers.utils.hub_utils import load_or_create_model_card, populate_model_card class CreateModelCardTest(unittest.TestCase): From ffc3845e9365e82db6c1a448650f1ed46587364b Mon Sep 17 00:00:00 2001 From: Sayak Paul Date: Tue, 23 Jan 2024 19:49:32 +0530 Subject: [PATCH 20/20] Update src/diffusers/pipelines/pipeline_utils.py Co-authored-by: Lucain --- src/diffusers/pipelines/pipeline_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diffusers/pipelines/pipeline_utils.py b/src/diffusers/pipelines/pipeline_utils.py index 7bb853f3e713..06187645f000 100644 --- a/src/diffusers/pipelines/pipeline_utils.py +++ b/src/diffusers/pipelines/pipeline_utils.py @@ -727,7 +727,7 @@ def is_saveable_module(name, value): if push_to_hub: # Create a new empty model card and eventually tag it - model_card = load_or_create_model_card(repo_id=repo_id, token=token, is_pipeline=True) + model_card = load_or_create_model_card(repo_id, token=token, is_pipeline=True) model_card = populate_model_card(model_card) model_card.save(os.path.join(save_directory, "README.md"))