Skip to content

Commit f62180a

Browse files
Use server-side bucket copy when freezing Spaces (#482)
Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
1 parent e53aebc commit f62180a

8 files changed

Lines changed: 38 additions & 33 deletions

File tree

.changeset/large-ravens-decide.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"trackio": patch
3+
---
4+
5+
feat:Use server-side bucket copy when freezing Spaces

docs/source/cli_commands.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ trackio freeze --space-id "username/my-space" --project "my-project" --new-space
7676
| `--private` | Make the new static Space private |
7777

7878
> **Note:** The source must be a Gradio Space with a bucket mounted at `/data`. If the destination Space already exists and is not a Trackio static Space, `freeze` will refuse to overwrite it.
79+
> The frozen Space is a snapshot. Later metrics synced to the original Gradio Space do not appear in the frozen static Space unless you run `freeze` again.
7980
8081
## List Commands
8182

@@ -416,4 +417,3 @@ trackio list runs --project "my-project" --json | jq '.runs[] | select(startswit
416417
# Export to file
417418
trackio get run --project "my-project" --run "my-run" --json > run_summary.json
418419
```
419-

docs/source/deploy_embed.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ trackio freeze --space-id "username/my-space" --project "my-project"
6060

6161
This creates a new static Space (by default named `{space_id}_static`) containing a snapshot of the project's data from the source Space's bucket. The original Space is not modified.
6262

63+
Note that`freeze()` is a one-time snapshot. If new metrics are later uploaded to the original Gradio Space, the frozen static Space will not update automatically.
64+
6365
You can customize the destination:
6466

6567
```py

docs/source/quickstart.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,4 @@ trackio.sync(project="my-project", space_id="username/space_id")
128128
</hfoption>
129129
</hfoptions>
130130

131-
This will create the Space if it does not already exist, and upload all runs and associated data to the Space. You can also sync to a lightweight static Space with `sdk="static"`, or create a read-only snapshot of a live Space with [`freeze`](deploy_embed.md#freezing-a-space-snapshot). See the [Deploy and Embed Dashboards](deploy_embed.md) page for more details.
131+
This will create the Space if it does not already exist, and upload all runs and associated data to the Space. You can also sync to a lightweight static Space with `sdk="static"`, or create a read-only snapshot of a live Space with [`freeze`](deploy_embed.md#freezing-a-space-snapshot). A frozen Space is a point-in-time snapshot and will not pick up later metrics from the original Gradio Space unless you freeze again. See the [Deploy and Embed Dashboards](deploy_embed.md) page for more details.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ readme = "README.md"
1414
requires-python = ">=3.10"
1515
dependencies = [
1616
"pandas<3.0.0",
17-
"huggingface-hub>=1.9.2,<2",
17+
"huggingface-hub>=1.10.0,<2",
1818
"gradio[oauth]>=6.10.0,<7.0.0",
1919
"numpy<3.0.0",
2020
"pillow<12.0.0",

trackio/bucket_storage.py

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from pathlib import Path
44

55
import huggingface_hub
6-
from huggingface_hub import sync_bucket
6+
from huggingface_hub import copy_files, sync_bucket
77

88
from trackio.sqlite_storage import SQLiteStorage
99
from trackio.utils import MEDIA_DIR, TRACKIO_DIR
@@ -108,6 +108,22 @@ def _export_and_upload_static(
108108
huggingface_hub.batch_bucket_files(dest_bucket_id, add=files_to_add)
109109

110110

111+
def _copy_project_media_between_buckets(
112+
source_bucket_id: str, dest_bucket_id: str, project: str
113+
) -> None:
114+
source_media_prefix = f"trackio/media/{project}/"
115+
media_to_copy = _list_bucket_file_paths(
116+
source_bucket_id, prefix=source_media_prefix
117+
)
118+
if not media_to_copy:
119+
return
120+
121+
copy_files(
122+
f"hf://buckets/{source_bucket_id}/{source_media_prefix}",
123+
f"hf://buckets/{dest_bucket_id}/media/",
124+
)
125+
126+
111127
def upload_project_to_bucket_for_static(project: str, bucket_id: str) -> None:
112128
if not _local_db_has_data(project):
113129
_download_db_from_bucket(project, bucket_id)
@@ -131,24 +147,5 @@ def export_from_bucket_for_static(
131147
f"from bucket '{source_bucket_id}'."
132148
)
133149

134-
media_dest = work_path / "media"
135-
source_media_prefix = f"trackio/media/{project}/"
136-
media_to_download = _list_bucket_file_paths(
137-
source_bucket_id, prefix=source_media_prefix
138-
)
139-
if media_to_download:
140-
media_dest.mkdir(parents=True, exist_ok=True)
141-
dl_pairs = []
142-
for remote_path in media_to_download:
143-
rel = remote_path[len(source_media_prefix) :]
144-
local_file = media_dest / rel
145-
local_file.parent.mkdir(parents=True, exist_ok=True)
146-
dl_pairs.append((remote_path, str(local_file)))
147-
huggingface_hub.download_bucket_files(source_bucket_id, files=dl_pairs)
148-
149-
_export_and_upload_static(
150-
project,
151-
dest_bucket_id,
152-
db_path,
153-
media_dest if media_dest.exists() else None,
154-
)
150+
_export_and_upload_static(project, dest_bucket_id, db_path)
151+
_copy_project_media_between_buckets(source_bucket_id, dest_bucket_id, project)

trackio/cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ def main():
228228

229229
freeze_parser = subparsers.add_parser(
230230
"freeze",
231-
help="Create a new static Space snapshot from a project's data.",
231+
help="Create a one-time static Space snapshot from a project's data.",
232232
)
233233
freeze_parser.add_argument(
234234
"--space-id",
@@ -238,7 +238,7 @@ def main():
238238
freeze_parser.add_argument(
239239
"--project",
240240
required=True,
241-
help="The name of the project to freeze.",
241+
help="The name of the project to freeze into a static snapshot.",
242242
)
243243
freeze_parser.add_argument(
244244
"--new-space-id",

trackio/deploy.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -743,10 +743,10 @@ def sync(
743743
Syncs a local Trackio project's database to a Hugging Face Space.
744744
If the Space does not exist, it will be created. Local data is never deleted.
745745
746-
**Freezing:** Passing ``sdk="static"`` *freezes* the Space: it converts a live Gradio
747-
Space into a static Space backed by an HF Bucket (read-only dashboard, no Gradio
748-
server). You cannot log new metrics to a frozen Space; use a different ``space_id``
749-
or a new Gradio Space for further training runs.
746+
**Freezing:** Passing ``sdk="static"`` deploys a static Space backed by an HF Bucket
747+
(read-only dashboard, no Gradio server). You can sync the same project again later to
748+
refresh that static Space. If you want a one-time snapshot of an existing Gradio Space,
749+
use ``freeze()`` instead.
750750
751751
Args:
752752
project (`str`): The name of the project to upload.
@@ -863,8 +863,9 @@ def freeze(
863863
"""
864864
Creates a new static Hugging Face Space containing a read-only snapshot of
865865
the data for the specified project from the source Gradio Space. The data is
866-
read from the bucket attached to the source Space, so it always reflects the
867-
remote state. The original Space is not modified.
866+
read from the bucket attached to the source Space at freeze time. The original
867+
Space is not modified, and the new static Space does not automatically reflect
868+
metrics uploaded to the original Gradio Space after the freeze completes.
868869
869870
Args:
870871
space_id (`str`):

0 commit comments

Comments
 (0)