22import os
33import re
44import shutil
5+ import time
56
67from huggingface_hub import HfApi
78from huggingface_hub import hf_hub_download
1819HF_BASE_URI = "hf://keras"
1920JSON_FILE_PATH = "tools/admin/hf_uploaded_presets.json"
2021HF_TOKEN = os .getenv ("HUGGINGFACE_TOKEN" )
22+ KAGGLE_API_RATE_LIMIT_DELAY = 1 # Delay between Kaggle API calls (s)
2123
2224
2325def load_latest_hf_uploads (json_file_path ):
@@ -54,7 +56,7 @@ def download_and_upload_missing_models(missing_in_hf_uploads):
5456 uploaded_handles .append (kaggle_handle )
5557 except Exception as e :
5658 print (
57- "Error in downloading and uploading preset "
59+ "Error in downloading and uploading preset "
5860 f"{ kaggle_handle } : { e } "
5961 )
6062 errored_uploads .append (kaggle_handle )
@@ -73,18 +75,46 @@ def update_hf_uploads_json(json_file_path, latest_kaggle_handles):
7375def update_model_cards_on_hugging_face (presets ):
7476 kaggle_api = KaggleApi ()
7577 kaggle_api .authenticate ()
78+ updated_count = 0
79+ skipped_count = 0
80+
7681 for model , data in presets .items ():
7782 try :
7883 kaggle_handle = data ["kaggle_handle" ].removeprefix ("kaggle://" )
7984 owner = "keras"
8085 repo_id = f"keras/{ model } "
8186 readme_path = "README.md"
8287 model_slug = kaggle_handle .split ("/" )[1 ]
83- model_metadata = kaggle_api .get_model_with_http_info (
84- owner , model_slug
85- )
86- description = model_metadata [0 ]["description" ]
87- usage = model_metadata [0 ]["instances" ][0 ]["usage" ].replace (
88+
89+ # Skip Gemma models
90+ if "gemma" in kaggle_handle :
91+ print (f"Skipping Gemma model preset: { kaggle_handle } " )
92+ continue
93+ # for rate limiting
94+ max_retries = 3
95+ retry_delay = 2
96+ for attempt in range (max_retries ):
97+ try :
98+ model_metadata = kaggle_api .model_get (
99+ f"{ owner } /{ model_slug } "
100+ )
101+ time .sleep (KAGGLE_API_RATE_LIMIT_DELAY ) # Rate limit delay
102+ break
103+ except Exception as e :
104+ status_code = getattr (e , "status" , None )
105+ if status_code == 429 and attempt < max_retries - 1 :
106+ wait_time = retry_delay ** (attempt + 1 )
107+ print (
108+ f"Rate limited (429). Retrying in "
109+ f"{ wait_time } s... (Attempt "
110+ f"{ attempt + 1 } /{ max_retries } )"
111+ )
112+ time .sleep (wait_time )
113+ else :
114+ raise
115+
116+ description = model_metadata .description
117+ usage = model_metadata .instances [0 ].usage .replace (
88118 "${VARIATION_SLUG}" , model
89119 )
90120 usage = re .sub (
@@ -96,6 +126,7 @@ def update_model_cards_on_hugging_face(presets):
96126
97127 # --- Construct Model Card Markup ---
98128 initial_markup = "---\n library_name: keras-hub\n ---\n "
129+ existing_content = None
99130 try :
100131 readme_path = hf_hub_download (
101132 repo_id = repo_id ,
@@ -104,17 +135,17 @@ def update_model_cards_on_hugging_face(presets):
104135 local_dir = "." ,
105136 )
106137 with open (readme_path , "r" ) as readme_file :
107- readme_content = readme_file .read ()
138+ existing_content = readme_file .read ()
108139 # Extract existing markup between ---\n and ---\n
109140 match = re .search (
110- r"^(---\n.*?\n---\n)" , readme_content , re .DOTALL
141+ r"^(---\n.*?\n---\n)" , existing_content , re .DOTALL
111142 )
112143 if match :
113144 initial_markup = match .group (1 )
114145 except Exception as e :
115146 print (
116147 f"README.md not found on HF for { repo_id } : { e } . "
117- "Writing new README.md"
148+ "Will write new README.md"
118149 )
119150
120151 model_card_markup = (
@@ -136,6 +167,12 @@ def update_model_cards_on_hugging_face(presets):
136167 .replace (">=" , ">=" )
137168 )
138169
170+ # --- Check if content has changed ---
171+ if existing_content == model_card_markup :
172+ print (f"No changes detected for { model } , skipping upload" )
173+ skipped_count += 1
174+ continue
175+
139176 # --- Save Model Card Content to README.md ---
140177
141178 with open (readme_path , "w" ) as readme_file :
@@ -150,9 +187,10 @@ def update_model_cards_on_hugging_face(presets):
150187 path_in_repo = "README.md" ,
151188 repo_id = repo_id ,
152189 token = HF_TOKEN ,
153- commit_message = "Update README.md with new model card content" ,
190+ commit_message = ( "Update README.md with new model card content" ) ,
154191 )
155- print (f"Uploaded README.md to Hugging Face repository: { repo_id } " )
192+ print (f"✓ Uploaded README.md to Hugging Face repository: { repo_id } " )
193+ updated_count += 1
156194
157195 # --- Clean up the README.md file after upload ---
158196 os .remove (readme_path )
@@ -162,6 +200,10 @@ def update_model_cards_on_hugging_face(presets):
162200 print (f"Error updating model card for { model } : { e } " )
163201 continue
164202
203+ print ("\n Model card update summary:" )
204+ print (f"Updated: { updated_count } " )
205+ print (f"Skipped (no changes): { skipped_count } " )
206+
165207
166208def main ():
167209 print ("Starting the model presets mirroring on HF" )
@@ -191,7 +233,7 @@ def main():
191233 JSON_FILE_PATH ,
192234 sorted (list (set (latest_kaggle_handles ) - set (errored_uploads ))),
193235 )
194- print ("uploads for the following models failed: " , errored_uploads )
236+ print ("Uploads for the following models failed: " , errored_uploads )
195237 print ("Rest of the models up to date on HuggingFace" )
196238
197239 # Step 6: Update HuggingFace model card
0 commit comments