burtenshaw commited on
Commit
8ac80b5
·
1 Parent(s): f178a31
.claude/skills/hf-space-sandbox/scripts/example_uv_script.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env -S uv run --script
2
+ # /// script
3
+ # requires-python = ">=3.11"
4
+ # dependencies = [
5
+ # "transformers>=4.40.0",
6
+ # "torch>=2.0.0",
7
+ # "rich>=13.0.0",
8
+ # ]
9
+ # ///
10
+ """
11
+ Example uv script with inline dependencies.
12
+
13
+ This script demonstrates the PEP 723 inline metadata format for uv scripts.
14
+ Dependencies are declared in the script header and installed automatically.
15
+
16
+ Usage:
17
+ # Run locally
18
+ uv run example_uv_script.py
19
+
20
+ # Run on remote HF Space via SSH
21
+ scp example_uv_script.py user@SPACE.hf.space:/app/
22
+ ssh user@SPACE.hf.space "cd /app && uv run example_uv_script.py"
23
+
24
+ # Make executable and run directly
25
+ chmod +x example_uv_script.py
26
+ ./example_uv_script.py
27
+ """
28
+
29
+ from rich.console import Console
30
+ from rich.table import Table
31
+ import torch
32
+
33
+
34
+ def check_cuda() -> dict:
35
+ """Check CUDA availability and device info."""
36
+ info = {
37
+ "cuda_available": torch.cuda.is_available(),
38
+ "device_count": torch.cuda.device_count() if torch.cuda.is_available() else 0,
39
+ "device_name": None,
40
+ "cuda_version": None,
41
+ }
42
+
43
+ if info["cuda_available"]:
44
+ info["device_name"] = torch.cuda.get_device_name(0)
45
+ info["cuda_version"] = torch.version.cuda
46
+
47
+ return info
48
+
49
+
50
+ def run_inference():
51
+ """Run a simple inference example."""
52
+ from transformers import pipeline
53
+
54
+ # Use CPU if CUDA not available
55
+ device = 0 if torch.cuda.is_available() else -1
56
+
57
+ console = Console()
58
+ console.print("\n[bold blue]Running sentiment analysis...[/bold blue]\n")
59
+
60
+ classifier = pipeline("sentiment-analysis", device=device)
61
+ texts = [
62
+ "I love using Hugging Face!",
63
+ "This is a challenging problem.",
64
+ "The weather is nice today.",
65
+ ]
66
+
67
+ results = classifier(texts)
68
+
69
+ # Display results in a table
70
+ table = Table(title="Sentiment Analysis Results")
71
+ table.add_column("Text", style="cyan")
72
+ table.add_column("Label", style="green")
73
+ table.add_column("Score", style="magenta")
74
+
75
+ for text, result in zip(texts, results):
76
+ table.add_row(text, result["label"], f"{result['score']:.4f}")
77
+
78
+ console.print(table)
79
+ return results
80
+
81
+
82
+ def main():
83
+ console = Console()
84
+
85
+ # Header
86
+ console.print("\n[bold green]HF Space Sandbox - Example Script[/bold green]")
87
+ console.print("=" * 50)
88
+
89
+ # Check CUDA
90
+ cuda_info = check_cuda()
91
+
92
+ info_table = Table(title="System Information")
93
+ info_table.add_column("Property", style="cyan")
94
+ info_table.add_column("Value", style="yellow")
95
+
96
+ info_table.add_row("CUDA Available", str(cuda_info["cuda_available"]))
97
+ info_table.add_row("Device Count", str(cuda_info["device_count"]))
98
+ if cuda_info["device_name"]:
99
+ info_table.add_row("GPU", cuda_info["device_name"])
100
+ info_table.add_row("CUDA Version", cuda_info["cuda_version"])
101
+
102
+ console.print(info_table)
103
+
104
+ # Run inference
105
+ run_inference()
106
+
107
+ console.print("\n[bold green]Done![/bold green]\n")
108
+
109
+
110
+ if __name__ == "__main__":
111
+ main()
.claude/skills/hf-space-sandbox/scripts/sandbox.py ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # /// script
3
+ # requires-python = ">=3.10"
4
+ # dependencies = ["huggingface_hub>=0.20.0"]
5
+ # ///
6
+ """
7
+ HF Space Sandbox Manager - Create and manage dev mode Spaces.
8
+
9
+ Creates sandboxes by duplicating burtenshaw/sandbox (a dev-mode ready template).
10
+
11
+ Usage:
12
+ uv run sandbox.py create user/my-sandbox
13
+ uv run sandbox.py create user/my-sandbox --hardware t4-small --sleep-time 3600
14
+ uv run sandbox.py create user/my-sandbox --from other/template --private
15
+ uv run sandbox.py status user/my-sandbox
16
+ uv run sandbox.py start user/my-sandbox
17
+ uv run sandbox.py stop user/my-sandbox
18
+ uv run sandbox.py hardware user/my-sandbox t4-medium
19
+ uv run sandbox.py wait user/my-sandbox
20
+
21
+ Environment:
22
+ HF_TOKEN - Hugging Face API token (or use cached credentials)
23
+ """
24
+
25
+ import argparse
26
+ import os
27
+ import sys
28
+ import time
29
+
30
+ from huggingface_hub import HfApi, SpaceHardware
31
+
32
+ TEMPLATE_SPACE = "burtenshaw/sandbox"
33
+
34
+ HARDWARE_MAP = {
35
+ "cpu-basic": SpaceHardware.CPU_BASIC,
36
+ "cpu-upgrade": SpaceHardware.CPU_UPGRADE,
37
+ "t4-small": SpaceHardware.T4_SMALL,
38
+ "t4-medium": SpaceHardware.T4_MEDIUM,
39
+ "a10g-small": SpaceHardware.A10G_SMALL,
40
+ "a10g-large": SpaceHardware.A10G_LARGE,
41
+ "a100-large": SpaceHardware.A100_LARGE,
42
+ }
43
+
44
+
45
+ def get_api():
46
+ token = os.environ.get("HF_TOKEN")
47
+ return HfApi(token=token)
48
+
49
+
50
+ def cmd_create(args):
51
+ api = get_api()
52
+ hw = args.hardware or "cpu-basic"
53
+ source = args.source or TEMPLATE_SPACE
54
+
55
+ print(f"Duplicating {source} to {args.space_id}...")
56
+ kwargs = {
57
+ "from_id": source,
58
+ "to_id": args.space_id,
59
+ "private": args.private,
60
+ "hardware": hw,
61
+ }
62
+ if args.sleep_time:
63
+ kwargs["sleep_time"] = args.sleep_time
64
+ result = api.duplicate_space(**kwargs)
65
+
66
+ print(f"Created: {result}")
67
+ print(f"SSH: ssh user@{args.space_id.replace('/', '-')}.hf.space")
68
+
69
+
70
+ def cmd_status(args):
71
+ api = get_api()
72
+ runtime = api.get_space_runtime(args.space_id)
73
+ print(f"space: {args.space_id}")
74
+ print(f"stage: {runtime.stage}")
75
+ print(f"hardware: {runtime.hardware}")
76
+ if runtime.requested_hardware:
77
+ print(f"requested: {runtime.requested_hardware}")
78
+ print(f"ssh: user@{args.space_id.replace('/', '-')}.hf.space")
79
+ sys.exit(0 if runtime.stage == "RUNNING" else 1)
80
+
81
+
82
+ def cmd_start(args):
83
+ api = get_api()
84
+ print(f"Starting {args.space_id}...")
85
+ api.restart_space(args.space_id)
86
+ print("Done")
87
+
88
+
89
+ def cmd_stop(args):
90
+ api = get_api()
91
+ print(f"Stopping {args.space_id}...")
92
+ api.pause_space(args.space_id)
93
+ print("Done")
94
+
95
+
96
+ def cmd_hardware(args):
97
+ api = get_api()
98
+ hw = HARDWARE_MAP.get(args.hardware_type.lower())
99
+ if not hw:
100
+ sys.exit(f"Unknown hardware: {args.hardware_type}")
101
+
102
+ print(f"Requesting {args.hardware_type} for {args.space_id}...")
103
+ kwargs = {"repo_id": args.space_id, "hardware": hw}
104
+ if args.sleep_time:
105
+ kwargs["sleep_time"] = args.sleep_time
106
+ api.request_space_hardware(**kwargs)
107
+ print("Done")
108
+
109
+
110
+ def cmd_wait(args):
111
+ api = get_api()
112
+ deadline = time.time() + args.timeout
113
+
114
+ print(f"Waiting for {args.space_id}...")
115
+ while time.time() < deadline:
116
+ runtime = api.get_space_runtime(args.space_id)
117
+ if runtime.stage == "RUNNING":
118
+ print(f"Running (hardware: {runtime.hardware})")
119
+ return
120
+ if runtime.stage in ["RUNTIME_ERROR", "BUILD_ERROR"]:
121
+ sys.exit(f"Failed: {runtime.stage}")
122
+ print(f" {runtime.stage}...")
123
+ time.sleep(args.interval)
124
+ sys.exit("Timeout")
125
+
126
+
127
+ def main():
128
+ parser = argparse.ArgumentParser(description="HF Space Sandbox Manager")
129
+ sub = parser.add_subparsers(dest="cmd", required=True)
130
+
131
+ # create
132
+ p = sub.add_parser("create", help="Create a sandbox by duplicating template")
133
+ p.add_argument("space_id", help="Space ID (user/name)")
134
+ p.add_argument("--from", dest="source", help=f"Source Space (default: {TEMPLATE_SPACE})")
135
+ p.add_argument("--hardware", default="cpu-basic", help="Hardware tier")
136
+ p.add_argument("--sleep-time", type=int, help="Auto-sleep seconds")
137
+ p.add_argument("--private", action="store_true")
138
+ p.set_defaults(func=cmd_create)
139
+
140
+ # status
141
+ p = sub.add_parser("status", help="Get Space status")
142
+ p.add_argument("space_id")
143
+ p.set_defaults(func=cmd_status)
144
+
145
+ # start
146
+ p = sub.add_parser("start", help="Start Space")
147
+ p.add_argument("space_id")
148
+ p.set_defaults(func=cmd_start)
149
+
150
+ # stop
151
+ p = sub.add_parser("stop", help="Stop Space")
152
+ p.add_argument("space_id")
153
+ p.set_defaults(func=cmd_stop)
154
+
155
+ # hardware
156
+ p = sub.add_parser("hardware", help="Request hardware")
157
+ p.add_argument("space_id")
158
+ p.add_argument("hardware_type", help="Hardware tier")
159
+ p.add_argument("--sleep-time", type=int, help="Auto-sleep seconds")
160
+ p.set_defaults(func=cmd_hardware)
161
+
162
+ # wait
163
+ p = sub.add_parser("wait", help="Wait for Space to be running")
164
+ p.add_argument("space_id")
165
+ p.add_argument("--timeout", type=int, default=300)
166
+ p.add_argument("--interval", type=int, default=5)
167
+ p.set_defaults(func=cmd_wait)
168
+
169
+ args = parser.parse_args()
170
+ args.func(args)
171
+
172
+
173
+ if __name__ == "__main__":
174
+ main()