Download scripts/hf_state_backup.py from Prabu17/askmydocs: direct link, hf CLI and curl.
- Browser
- Download file 3.53 kB
-
https://huggingface.co/spaces/Prabu17/askmydocs/resolve/main/scripts/hf_state_backup.py
- Command line
-
hf download hf://spaces/Prabu17/askmydocs/scripts/hf_state_backup.py
-
curl -L -o hf_state_backup.py https://huggingface.co/spaces/Prabu17/askmydocs/resolve/main/scripts/hf_state_backup.py
3.53 kB
| """Back up AskMyDocs state to a Hugging Face Storage Bucket. | |
| Creates a compressed archive of PostgreSQL data, Qdrant storage, and uploaded | |
| documents, then uploads it to the specified HF Storage Bucket. The Space's | |
| ``start.sh`` restores this archive on boot when ``RESTORE_ON_BOOT=true``. | |
| Usage: | |
| python scripts/hf_state_backup.py --bucket username/askmydocs-data | |
| python scripts/hf_state_backup.py --bucket username/askmydocs-data --data-root /home/user | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import subprocess | |
| import tempfile | |
| from pathlib import Path | |
| def create_archive(data_root: Path, output: Path) -> bool: | |
| """Create a zstd-compressed tar of the state directories.""" | |
| dirs_to_include = ["pgdata", "qdrant_storage"] | |
| uploads_dir = data_root / "app" / "data" / "uploads" | |
| if uploads_dir.exists(): | |
| dirs_to_include.append("app/data/uploads") | |
| existing = [d for d in dirs_to_include if (data_root / d).exists()] | |
| if not existing: | |
| print("No state directories found to back up.") | |
| return False | |
| cmd = [ | |
| "tar", | |
| "--zstd", | |
| "-cf", | |
| str(output), | |
| "-C", | |
| str(data_root), | |
| *existing, | |
| ] | |
| print(f"Creating archive: {' '.join(cmd)}") | |
| result = subprocess.run(cmd, capture_output=True, text=True) | |
| if result.returncode != 0: | |
| print(f"tar failed: {result.stderr}") | |
| return False | |
| size_mb = output.stat().st_size / (1024 * 1024) | |
| print(f"Archive created: {output} ({size_mb:.1f} MB)") | |
| return True | |
| def upload_to_bucket(archive: Path, bucket: str, token: str | None = None) -> bool: | |
| """Upload the archive to an HF Storage Bucket. | |
| Storage Buckets are not repos: ``upload_file(repo_type="space_storage")`` | |
| does not exist (supported repo types are model/dataset/space). The bucket | |
| API is ``batch_bucket_files(bucket_id=..., add=[(local, remote)])``. | |
| """ | |
| try: | |
| from huggingface_hub import batch_bucket_files | |
| except ImportError: | |
| print("Error: huggingface_hub is required. Install with: pip install huggingface_hub") | |
| return False | |
| print(f"Uploading {archive.name} to bucket {bucket}...") | |
| batch_bucket_files( | |
| bucket_id=bucket, | |
| add=[(archive, "state.tar.zst")], | |
| token=token, | |
| ) | |
| print(f"Uploaded to hf://buckets/{bucket}/state.tar.zst") | |
| return True | |
| def main() -> int: | |
| parser = argparse.ArgumentParser(description="Back up AskMyDocs state to HF Storage Bucket.") | |
| parser.add_argument( | |
| "--bucket", | |
| required=True, | |
| help="HF Storage Bucket name (e.g. 'username/askmydocs-data')", | |
| ) | |
| parser.add_argument( | |
| "--data-root", | |
| type=Path, | |
| default=Path("/home/user"), | |
| help="Data root directory (default: /home/user for HF Space)", | |
| ) | |
| parser.add_argument( | |
| "--token", | |
| default=None, | |
| help="HF token for private bucket access (default: HF_TOKEN env var)", | |
| ) | |
| args = parser.parse_args() | |
| import os | |
| token = args.token or os.environ.get("HF_TOKEN") | |
| with tempfile.NamedTemporaryFile(suffix=".tar.zst", delete=False) as tmp: | |
| tmp_path = Path(tmp.name) | |
| try: | |
| if not create_archive(args.data_root, tmp_path): | |
| return 1 | |
| if not upload_to_bucket(tmp_path, args.bucket, token): | |
| return 1 | |
| finally: | |
| tmp_path.unlink(missing_ok=True) | |
| print("State backup complete.") | |
| return 0 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |