""" Hugging Face Deployment Automation for Nova AI - ChatGPT Astra Edition. Handles automatic creation, file synchronization, metadata configuration, and status monitoring for Hugging Face Spaces and Model Hub Repositories. """ import os import sys import shutil from pathlib import Path from typing import Dict, Any, Optional from huggingface_hub import HfApi, create_repo, upload_folder, whoami from src.config import config, PROJECT_ROOT, DeploymentConfig from src.utils import console class HuggingFaceDeployer: """Automates deployment of Nova AI to Hugging Face Spaces & Model Hub.""" def __init__(self, deploy_config: Optional[DeploymentConfig] = None): self.cfg = deploy_config or config.deploy_config self.api = HfApi() def validate_token(self, token: Optional[str] = None) -> Dict[str, Any]: """Validate Hugging Face token and return user identity.""" auth_token = token or self.cfg.hf_token or os.getenv("HF_TOKEN") if not auth_token or auth_token == "your_huggingface_token_here": raise ValueError( "Hugging Face Token (HF_TOKEN) is missing or set to placeholder.\n" "Please get your free User Access Token with 'Write' permissions from:\n" "👉 https://huggingface.co/settings/tokens\n" "and set it in your .env file or pass it to this deployment script." ) try: user_info = whoami(token=auth_token) console.print(f"[bold green]✓ Authenticated as Hugging Face user:[/bold green] [cyan]{user_info.get('name')}[/cyan]") return user_info except Exception as e: raise RuntimeError(f"Authentication failed with provided Hugging Face token: {e}") def deploy_space( self, token: Optional[str] = None, username: Optional[str] = None, space_name: Optional[str] = None, hardware: Optional[str] = None ) -> Dict[str, str]: """ Deploy the Nova AI Gradio application to a Hugging Face Space with NVIDIA ZeroGPU acceleration. """ auth_token = token or self.cfg.hf_token or os.getenv("HF_TOKEN") user_info = self.validate_token(auth_token) hf_user = username or self.cfg.hf_username or user_info.get("name") target_space_name = space_name or self.cfg.hf_space_name target_hardware = hardware or self.cfg.space_hardware or "zero-a10g" repo_id = f"{hf_user}/{target_space_name}" console.print(f"\n[bold cyan]🚀 Deploying Nova AI to Hugging Face Space:[/bold cyan] [yellow]{repo_id}[/yellow]") # 1. Create or ensure Space exists console.print("[dim]Step 1/3: Checking / Creating Space repository...[/dim]") try: self.api.create_repo( repo_id=repo_id, repo_type="space", space_sdk="gradio", private=False, exist_ok=True, token=auth_token ) console.print(f"[bold green]✓ Space '{repo_id}' ready on Hugging Face.[/bold green]") except Exception as e: console.print(f"[bold red]✗ Error creating Space:[/bold red] {e}") raise # 2. Upload Project Files console.print("[dim]Step 2/3: Uploading project codebase to Hugging Face...[/dim]") ignore_patterns = [ ".venv/*", "venv/*", ".git/*", ".idea/*", "__pycache__/*", "*/__pycache__/*", "*.pyc", "models_cache/*", "checkpoints/*", "lora_output/*", "exported_model/*.safetensors", ".env", "*.tmp", "*.log" ] try: upload_result = self.api.upload_folder( folder_path=str(PROJECT_ROOT), repo_id=repo_id, repo_type="space", ignore_patterns=ignore_patterns, commit_message="Deploy Nova AI (Flagship ChatGPT Astra Edition with NVIDIA ZeroGPU)", token=auth_token ) console.print("[bold green]✓ Codebase synchronized successfully![/bold green]") except Exception as e: console.print(f"[bold red]✗ Error uploading files to Space:[/bold red] {e}") raise # 3. Request NVIDIA ZeroGPU / Target Hardware if target_hardware: try: self.api.request_space_hardware( repo_id=repo_id, hardware=target_hardware, token=auth_token ) console.print(f"[bold green]✓ Space hardware requested:[/bold green] [cyan]{target_hardware}[/cyan]") except Exception as hw_err: console.print(f"[dim]Space hardware note: {hw_err}[/dim]") space_url = f"https://huggingface.co/spaces/{repo_id}" embed_url = f"https://{repo_id.replace('/', '-')}.hf.space" console.print("\n[bold green]🎉 NOVA AI DEPLOYMENT SUCCESSFUL![/bold green]") console.print(f"👉 [bold]Public Space URL:[/bold] [link={space_url}]{space_url}[/link]") console.print(f"👉 [bold]Direct App Embed:[/bold] [link={embed_url}]{embed_url}[/link]\n") return { "status": "success", "repo_id": repo_id, "space_url": space_url, "embed_url": embed_url, "hardware": target_hardware } def deploy_model( self, model_directory: Path, repo_name: Optional[str] = None, token: Optional[str] = None, username: Optional[str] = None ) -> Dict[str, str]: """ Deploy fine-tuned Nova Astra model weights or LoRA adapters to Hugging Face Model Hub. """ auth_token = token or self.cfg.hf_token or os.getenv("HF_TOKEN") user_info = self.validate_token(auth_token) hf_user = username or self.cfg.hf_username or user_info.get("name") target_repo = repo_name or self.cfg.hf_model_repo_name repo_id = f"{hf_user}/{target_repo}" console.print(f"\n[bold cyan]📦 Uploading Nova Astra Weights to HF Hub:[/bold cyan] [yellow]{repo_id}[/yellow]") try: self.api.create_repo( repo_id=repo_id, repo_type="model", private=False, exist_ok=True, token=auth_token ) self.api.upload_folder( folder_path=str(model_directory), repo_id=repo_id, repo_type="model", commit_message="Upload Nova Astra fine-tuned model checkpoint & tokenizer", token=auth_token ) model_url = f"https://huggingface.co/{repo_id}" console.print(f"[bold green]✓ Model published successfully at:[/bold green] {model_url}") return {"status": "success", "repo_id": repo_id, "model_url": model_url} except Exception as e: console.print(f"[bold red]✗ Failed to deploy model:[/bold red] {e}") raise