Spaces:
Sleeping
Sleeping
| """Upload Pak Angels AI Tutor to a Hugging Face Space. | |
| Required environment variables: | |
| HF_TOKEN: A Hugging Face access token with write access to the Space. | |
| HF_SPACE_ID: The Space repo id, for example "your-username/pak-angels-ai-tutor". | |
| Optional environment variables: | |
| HF_COMMIT_MESSAGE: Custom commit message for the upload. | |
| HF_PRIVATE_SPACE: Set to "true" to create a private Space when using --create. | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import os | |
| import sys | |
| from pathlib import Path | |
| from huggingface_hub import HfApi | |
| from huggingface_hub.utils import HfHubHTTPError | |
| PROJECT_ROOT = Path(__file__).resolve().parent | |
| DEFAULT_IGNORE_PATTERNS = [ | |
| ".env", | |
| ".env.local", | |
| ".env.*.local", | |
| ".git/", | |
| ".git/**", | |
| ".venv/", | |
| ".venv/**", | |
| "venv/", | |
| "venv/**", | |
| "__pycache__/", | |
| "__pycache__/**", | |
| "*.pyc", | |
| ".DS_Store", | |
| ".pytest_cache/", | |
| ".pytest_cache/**", | |
| ".ruff_cache/", | |
| ".ruff_cache/**", | |
| ".mypy_cache/", | |
| ".mypy_cache/**", | |
| "dist/", | |
| "dist/**", | |
| "build/", | |
| "build/**", | |
| "*.egg-info/", | |
| "*.egg-info/**", | |
| "*.log", | |
| "tmp/", | |
| "tmp/**", | |
| "temp/", | |
| "temp/**", | |
| ] | |
| def parse_args() -> argparse.Namespace: | |
| parser = argparse.ArgumentParser( | |
| description="Upload the current Pak Angels AI Tutor project to Hugging Face Spaces." | |
| ) | |
| parser.add_argument( | |
| "--space-id", | |
| default=os.getenv("HF_SPACE_ID", "").strip(), | |
| help='Hugging Face Space id, for example "username/pak-angels-ai-tutor".', | |
| ) | |
| parser.add_argument( | |
| "--token", | |
| default=os.getenv("HF_TOKEN", "").strip(), | |
| help="Hugging Face write token. Prefer setting HF_TOKEN instead of passing this flag.", | |
| ) | |
| parser.add_argument( | |
| "--commit-message", | |
| default=os.getenv("HF_COMMIT_MESSAGE", "Deploy Pak Angels AI Tutor"), | |
| help="Commit message shown in the Hugging Face Space repository.", | |
| ) | |
| parser.add_argument( | |
| "--repo-type", | |
| default="space", | |
| choices=["space"], | |
| help="Repository type. Spaces deployments use 'space'.", | |
| ) | |
| parser.add_argument( | |
| "--create", | |
| action="store_true", | |
| help="Create the Gradio Space if it does not already exist.", | |
| ) | |
| parser.add_argument( | |
| "--private", | |
| action="store_true", | |
| default=os.getenv("HF_PRIVATE_SPACE", "").lower() in {"1", "true", "yes"}, | |
| help="Create the Space as private when --create is used.", | |
| ) | |
| return parser.parse_args() | |
| def validate_inputs(space_id: str, token: str) -> None: | |
| missing = [] | |
| if not space_id: | |
| missing.append("HF_SPACE_ID") | |
| if not token: | |
| missing.append("HF_TOKEN") | |
| if missing: | |
| joined = ", ".join(missing) | |
| raise ValueError( | |
| f"Missing required setting(s): {joined}. Set them as environment variables " | |
| "or pass --space-id and --token." | |
| ) | |
| if "/" not in space_id: | |
| raise ValueError('HF_SPACE_ID should look like "username/space-name".') | |
| placeholder_values = { | |
| "your_hugging_face_write_token_here", | |
| "your-token", | |
| "your_token", | |
| } | |
| placeholder_space_ids = { | |
| "your-username/your-space-name", | |
| "username/space-name", | |
| "your-username/pak-angels-ai-tutor", | |
| } | |
| if token in placeholder_values: | |
| raise ValueError("HF_TOKEN is still a placeholder. Use a real Hugging Face write token.") | |
| if space_id in placeholder_space_ids: | |
| raise ValueError( | |
| "HF_SPACE_ID is still a placeholder. Use your real Space id, such as " | |
| '"mohammadanwarkhan/pak-angels-ai-tutor".' | |
| ) | |
| def ensure_space_exists(api: HfApi, args: argparse.Namespace) -> None: | |
| if not args.create: | |
| return | |
| api.create_repo( | |
| repo_id=args.space_id, | |
| repo_type=args.repo_type, | |
| private=args.private, | |
| space_sdk="gradio", | |
| exist_ok=True, | |
| ) | |
| def preflight_check(api: HfApi, args: argparse.Namespace) -> None: | |
| whoami = api.whoami() | |
| account_name = whoami.get("name") or whoami.get("fullname") or "authenticated account" | |
| print(f"Authenticated with Hugging Face as: {account_name}") | |
| try: | |
| api.repo_info(repo_id=args.space_id, repo_type=args.repo_type) | |
| print(f"Space is accessible: {args.space_id}") | |
| except HfHubHTTPError as error: | |
| if args.create: | |
| raise | |
| raise RuntimeError( | |
| f"The token cannot access the Space '{args.space_id}'. Check that the Space id " | |
| "is exact and that this Hugging Face token has write access to that Space. " | |
| "If the Space does not exist, rerun with --create." | |
| ) from error | |
| def upload_project(args: argparse.Namespace) -> str: | |
| api = HfApi(token=args.token) | |
| ensure_space_exists(api, args) | |
| preflight_check(api, args) | |
| api.upload_folder( | |
| folder_path=str(PROJECT_ROOT), | |
| repo_id=args.space_id, | |
| repo_type=args.repo_type, | |
| commit_message=args.commit_message, | |
| ignore_patterns=DEFAULT_IGNORE_PATTERNS, | |
| ) | |
| return f"https://huggingface.co/spaces/{args.space_id}" | |
| def main() -> int: | |
| args = parse_args() | |
| try: | |
| validate_inputs(args.space_id, args.token) | |
| url = upload_project(args) | |
| except ValueError as error: | |
| print(f"Configuration error: {error}", file=sys.stderr) | |
| return 2 | |
| except HfHubHTTPError as error: | |
| print(f"Hugging Face upload failed: {error}", file=sys.stderr) | |
| print( | |
| "Check that HF_SPACE_ID is your real Space id, HF_TOKEN is a real write token, " | |
| "and the Space exists. If it does not exist, rerun with --create.", | |
| file=sys.stderr, | |
| ) | |
| return 1 | |
| except Exception as error: | |
| print(f"Deployment failed: {error}", file=sys.stderr) | |
| return 1 | |
| print("Deployment upload complete.") | |
| print(f"Space URL: {url}") | |
| print("Remember to set OPENAI_API_KEY in the Space secrets before testing the tutor.") | |
| return 0 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |