import os import gradio as gr from huggingface_hub import HfApi, CommitOperationAdd, create_commit import pandas as pd from datetime import datetime import tempfile from typing import Optional # Initialize Hugging Face client hf_api = HfApi(token=os.getenv("HF_TOKEN")) DATASET_REPO = "HuggingFaceTB/smolvlm2-iphone-waitlist" MAX_RETRIES = 3 def commit_signup(username: str, email: str, current_data: pd.DataFrame) -> Optional[str]: """Attempt to commit new signup atomically""" # Add new user with timestamp new_row = pd.DataFrame([{ 'userid': username, 'email': email, 'joined_at': datetime.utcnow().isoformat() }]) updated_data = pd.concat([current_data, new_row], ignore_index=True) # Save to temp file with tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False) as tmp: updated_data.to_csv(tmp.name, index=False) # Create commit operation operation = CommitOperationAdd( path_in_repo="waitlist.csv", path_or_fileobj=tmp.name, commit_message=f"Add user {username} to waitlist" ) try: # Try to create commit create_commit( repo_id=DATASET_REPO, repo_type="dataset", operations=[operation], commit_message=f"Add user {username} to waitlist" ) os.unlink(tmp.name) return None # Success except Exception as e: os.unlink(tmp.name) return str(e) # Return error message def join_waitlist( token: gr.OAuthToken | None, profile: gr.OAuthProfile | None, ) -> str: """Add user to the SmolVLM2 iPhone waitlist with retry logic for concurrent updates""" if token is None or profile is None: gr.Warning("Please log in to Hugging Face first!") return None for attempt in range(MAX_RETRIES): try: # Get current waitlist state try: current_data = pd.read_csv( f"https://huggingface.co/datasets/{DATASET_REPO}/raw/main/waitlist.csv" ) except: current_data = pd.DataFrame(columns=['userid', 'email', 'joined_at']) # Check if user already registered if profile.username in current_data['userid'].values: return "You're already on the waitlist! We'll keep you updated." # Try to commit the update error = commit_signup(profile.username, profile.email, current_data) if error is None: # Success return "Thanks for joining the waitlist! We'll keep you updated on SmolVLM2 iPhone app." # If we got a conflict error, retry if "Conflict" in str(error) and attempt < MAX_RETRIES - 1: continue # Other error or last attempt gr.Error(f"An error occurred: {str(error)}") return "Sorry, something went wrong. Please try again later." except Exception as e: if attempt == MAX_RETRIES - 1: # Last attempt gr.Error(f"An error occurred: {str(e)}") return "Sorry, something went wrong. Please try again later." # Create the interface with gr.Blocks() as demo: gr.Markdown(""" # Join SmolVLM2 iPhone Waitlist 📱 Sign up to be notified when the SmolVLM2 iPhone app and source code are released. By joining the waitlist, you'll get: - Early access to the SmolVLM2 iPhone app - Updates on development progress - First look at the source code when available """) with gr.Row(): gr.LoginButton() join_button = gr.Button("Join Waitlist", variant="primary") output = gr.Markdown(visible=False) join_button.click( fn=join_waitlist, outputs=output, ) if __name__ == "__main__": demo.launch(auth_required=True)