# HuggingFace Authentication Integration Notes ## Purpose Allow users to save their Big RPG Scale entity databases to their own HuggingFace datasets (avoiding data collection concerns). ## Requirements - Space-level OAuth configuration - User authentication via `gr.LoginButton()` - Save/load to user's own HF datasets ## README.md Changes Required ```yaml --- title: GameConfigIdeaEditBrainstorm hf_oauth: true hf_oauth_scopes: - read-repos - write-repos --- ``` ## Gradio OAuth Integration ### Login Button ```python import gradio as gr with gr.Blocks() as demo: gr.LoginButton(variant="huggingface", size="sm") ``` ### Access User Profile ```python def my_function(profile: gr.OAuthProfile | None): if profile: username = profile.username # Can now save to user's repos else: return "Please log in first" ``` ### Access User Token ```python def save_to_user_dataset( profile: gr.OAuthProfile | None, token: gr.OAuthToken | None, data: str ): if not profile or not token: return "Login required" # Use token.token for API calls ``` ## Implementation Functions ### Save Database ```python from huggingface_hub import HfApi, create_repo def save_database_to_hf( db: EntityDatabase, profile: gr.OAuthProfile, token: gr.OAuthToken, dataset_name: str = "rpg-entity-database" ) -> str: username = profile.username repo_id = f"{username}/{dataset_name}" api = HfApi(token=token.token) # Create repo if needed create_repo(repo_id, repo_type="dataset", exist_ok=True, private=True) # Export and upload db_json = db.to_json() api.upload_file( path_or_fileobj=db_json.encode('utf-8'), path_in_repo="entity_database.json", repo_id=repo_id, repo_type="dataset" ) return f"Saved to: https://huggingface.co/datasets/{repo_id}" ``` ### Load Database ```python from huggingface_hub import hf_hub_download def load_database_from_hf( db: EntityDatabase, profile: gr.OAuthProfile, token: gr.OAuthToken, dataset_name: str = "rpg-entity-database" ) -> str: username = profile.username repo_id = f"{username}/{dataset_name}" file_path = hf_hub_download( repo_id=repo_id, filename="entity_database.json", repo_type="dataset", token=token.token ) with open(file_path, 'r') as f: json_str = f.read() success, message = db.from_json(json_str) return message ``` ## UI Integration ### Entity Database Tab Addition ```python with gr.Row(): login_btn = gr.LoginButton(variant="huggingface", size="sm") login_status = gr.Markdown("*Not logged in*") with gr.Accordion("Cloud Save/Load (HuggingFace)", open=False): gr.Markdown("Save your entity database to your HuggingFace account.") hf_dataset_name = gr.Textbox( label="Dataset Name", value="rpg-entity-database" ) with gr.Row(): save_to_hf_btn = gr.Button("Save to HuggingFace", variant="primary") load_from_hf_btn = gr.Button("Load from HuggingFace") hf_status = gr.Markdown("") ``` ## Graceful Degradation - All local features work without login - Show `gr.Info("Please log in...")` when save/load attempted without auth - Display current login status prominently ## Alternative: CommitScheduler (Auto-Save) For session logging (like D&D GM event logs): ```python from huggingface_hub import CommitScheduler scheduler = CommitScheduler( folder_path="./user_data", repo_id=f"{username}/game-sessions", token=token.token, private=True ) ``` - Runs background thread, pushes every ~1 minute - Good for append-only data (logs, feedback) - Not ideal for frequently-updated files ## Resources - [Gradio OAuth Docs](https://huggingface.co/docs/hub/spaces-oauth) - [Gradio OAuth Example Space](https://huggingface.co/spaces/gradio/oauth-example) - [HuggingFace Hub Upload Guide](https://huggingface.co/docs/huggingface_hub/guides/upload) - [Spaces Persistent Storage](https://huggingface.co/docs/hub/spaces-storage) ## TODO - [ ] Test OAuth flow locally with `huggingface-cli login` - [ ] Decide on dataset structure (single JSON vs multiple files) - [ ] Consider versioning/backup strategy - [ ] Investigate Space-level persistent storage options