Spaces:
Running on Zero
Running on Zero
Commit ·
9e47f62
1
Parent(s): b8216f1
Write one parquet file per inference to avoid Git LFS version bloat
Browse filesPreviously the logger downloaded and rewrote the same daily parquet file
on every inference, creating a new LFS object each time and inflating
private storage far beyond the actual data size. Now each inference writes
a uniquely-named file (data/YYYY-MM-DD-HHMMSS-{uid}.parquet) that is
committed once and never overwritten.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- logging_utils.py +31 -62
logging_utils.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
import os
|
|
|
|
| 2 |
from io import BytesIO
|
| 3 |
from datetime import datetime, timezone
|
| 4 |
|
|
@@ -6,35 +7,19 @@ HF_TOKEN = os.environ.get("HF_TOKEN")
|
|
| 6 |
DATASET_REPO = os.environ.get("LOG_DATASET_REPO")
|
| 7 |
|
| 8 |
|
| 9 |
-
def _readme_from_features(feats):
|
| 10 |
-
lines = ["---", "configs:", "- config_name: default",
|
| 11 |
-
" data_files:", " - split: train",
|
| 12 |
-
" path: data/*.parquet", " features:"]
|
| 13 |
-
for name, f in feats.items():
|
| 14 |
-
lines.append(f" - name: {name}")
|
| 15 |
-
if f.get("_type") == "Image":
|
| 16 |
-
lines.append(" dtype: image")
|
| 17 |
-
elif f.get("_type") == "Sequence" and f.get("feature", {}).get("_type") == "Image":
|
| 18 |
-
lines.append(" sequence: image")
|
| 19 |
-
else:
|
| 20 |
-
lines.append(f" dtype: {f.get('dtype', 'string')}")
|
| 21 |
-
lines.append("---")
|
| 22 |
-
return "\n".join(lines) + "\n"
|
| 23 |
-
|
| 24 |
-
|
| 25 |
def log_inference(pil_inputs, output_pil, prompt, seed, steps, guidance_scale,
|
| 26 |
input_width, input_height, duration_seconds, success, error_message=""):
|
| 27 |
if not HF_TOKEN or not DATASET_REPO:
|
| 28 |
print(f"[log] skipped — HF_TOKEN={'set' if HF_TOKEN else 'missing'}, DATASET_REPO={'set' if DATASET_REPO else 'missing'}")
|
| 29 |
return
|
|
|
|
| 30 |
try:
|
| 31 |
-
import tempfile
|
|
|
|
| 32 |
import pyarrow as pa
|
| 33 |
import pyarrow.parquet as pq
|
| 34 |
-
from huggingface_hub import HfApi
|
| 35 |
|
| 36 |
-
# Image columns need Arrow struct {bytes: binary, path: utf8} plus
|
| 37 |
-
# a 'huggingface' schema metadata key for the HF viewer to render them.
|
| 38 |
img_struct = pa.struct([("bytes", pa.binary()), ("path", pa.string())])
|
| 39 |
hf_meta = _json.dumps({"info": {"features": {
|
| 40 |
"timestamp": {"dtype": "float64", "_type": "Value"},
|
|
@@ -75,57 +60,35 @@ def log_inference(pil_inputs, output_pil, prompt, seed, steps, guidance_scale,
|
|
| 75 |
def _img(b):
|
| 76 |
return {"bytes": b, "path": None}
|
| 77 |
|
|
|
|
| 78 |
input_jpegs = [_to_jpeg(img) for img in pil_inputs]
|
| 79 |
output_jpeg = _to_jpeg(output_pil)
|
| 80 |
|
| 81 |
-
|
| 82 |
-
"timestamp": pa.array([
|
| 83 |
-
"prompt": pa.array([prompt],
|
| 84 |
-
"seed": pa.array([int(seed)],
|
| 85 |
-
"steps": pa.array([int(steps)],
|
| 86 |
-
"guidance_scale": pa.array([float(guidance_scale)],
|
| 87 |
-
"input_images": pa.array([[_img(b) for b in input_jpegs]],
|
| 88 |
"output_image": pa.array([_img(output_jpeg) if output_jpeg else None], type=img_struct),
|
| 89 |
-
"duration_seconds": pa.array([float(duration_seconds)],
|
| 90 |
-
"input_width": pa.array([int(input_width)],
|
| 91 |
-
"input_height": pa.array([int(input_height)],
|
| 92 |
-
"success": pa.array([bool(success)],
|
| 93 |
-
"error_message": pa.array([str(error_message)],
|
| 94 |
}, schema=schema)
|
| 95 |
-
print(f"[log] built row — success={success}, inputs={len(input_jpegs)}")
|
| 96 |
-
|
| 97 |
-
today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
|
| 98 |
-
path_in_repo = f"data/{today}.parquet"
|
| 99 |
-
api = HfApi(token=HF_TOKEN)
|
| 100 |
-
api.create_repo(repo_id=DATASET_REPO, repo_type="dataset", private=True, exist_ok=True)
|
| 101 |
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
hf_hub_download(repo_id=DATASET_REPO, filename="README.md",
|
| 105 |
-
repo_type="dataset", token=HF_TOKEN)
|
| 106 |
-
except Exception:
|
| 107 |
-
readme = _readme_from_features(_json.loads(hf_meta)["info"]["features"])
|
| 108 |
-
api.upload_file(path_or_fileobj=readme.encode(), path_in_repo="README.md",
|
| 109 |
-
repo_id=DATASET_REPO, repo_type="dataset")
|
| 110 |
-
print("[log] uploaded README.md with feature schema")
|
| 111 |
-
|
| 112 |
-
try:
|
| 113 |
-
local_path = hf_hub_download(
|
| 114 |
-
repo_id=DATASET_REPO, filename=path_in_repo,
|
| 115 |
-
repo_type="dataset", token=HF_TOKEN,
|
| 116 |
-
)
|
| 117 |
-
existing = pq.read_table(local_path)
|
| 118 |
-
combined = pa.concat_tables([existing, new_table])
|
| 119 |
-
combined = combined.replace_schema_metadata(schema.metadata)
|
| 120 |
-
print(f"[log] appending to existing {existing.num_rows} row(s)")
|
| 121 |
-
except Exception as dl_err:
|
| 122 |
-
print(f"[log] no existing file ({dl_err}), starting fresh")
|
| 123 |
-
combined = new_table
|
| 124 |
|
| 125 |
with tempfile.NamedTemporaryFile(suffix=".parquet", delete=False) as tmp:
|
| 126 |
tmp_path = tmp.name
|
| 127 |
-
pq.write_table(
|
| 128 |
-
|
|
|
|
|
|
|
|
|
|
| 129 |
api.upload_file(
|
| 130 |
path_or_fileobj=tmp_path, path_in_repo=path_in_repo,
|
| 131 |
repo_id=DATASET_REPO, repo_type="dataset",
|
|
@@ -134,3 +97,9 @@ def log_inference(pil_inputs, output_pil, prompt, seed, steps, guidance_scale,
|
|
| 134 |
except Exception as log_err:
|
| 135 |
import traceback as _tb
|
| 136 |
print(f"[log] WARNING: {log_err}\n{_tb.format_exc()}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import os
|
| 2 |
+
import uuid
|
| 3 |
from io import BytesIO
|
| 4 |
from datetime import datetime, timezone
|
| 5 |
|
|
|
|
| 7 |
DATASET_REPO = os.environ.get("LOG_DATASET_REPO")
|
| 8 |
|
| 9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
def log_inference(pil_inputs, output_pil, prompt, seed, steps, guidance_scale,
|
| 11 |
input_width, input_height, duration_seconds, success, error_message=""):
|
| 12 |
if not HF_TOKEN or not DATASET_REPO:
|
| 13 |
print(f"[log] skipped — HF_TOKEN={'set' if HF_TOKEN else 'missing'}, DATASET_REPO={'set' if DATASET_REPO else 'missing'}")
|
| 14 |
return
|
| 15 |
+
tmp_path = None
|
| 16 |
try:
|
| 17 |
+
import tempfile
|
| 18 |
+
import json as _json
|
| 19 |
import pyarrow as pa
|
| 20 |
import pyarrow.parquet as pq
|
| 21 |
+
from huggingface_hub import HfApi
|
| 22 |
|
|
|
|
|
|
|
| 23 |
img_struct = pa.struct([("bytes", pa.binary()), ("path", pa.string())])
|
| 24 |
hf_meta = _json.dumps({"info": {"features": {
|
| 25 |
"timestamp": {"dtype": "float64", "_type": "Value"},
|
|
|
|
| 60 |
def _img(b):
|
| 61 |
return {"bytes": b, "path": None}
|
| 62 |
|
| 63 |
+
now = datetime.now(timezone.utc)
|
| 64 |
input_jpegs = [_to_jpeg(img) for img in pil_inputs]
|
| 65 |
output_jpeg = _to_jpeg(output_pil)
|
| 66 |
|
| 67 |
+
table = pa.table({
|
| 68 |
+
"timestamp": pa.array([now.timestamp()], type=pa.float64()),
|
| 69 |
+
"prompt": pa.array([prompt], type=pa.string()),
|
| 70 |
+
"seed": pa.array([int(seed)], type=pa.int32()),
|
| 71 |
+
"steps": pa.array([int(steps)], type=pa.int32()),
|
| 72 |
+
"guidance_scale": pa.array([float(guidance_scale)], type=pa.float32()),
|
| 73 |
+
"input_images": pa.array([[_img(b) for b in input_jpegs]], type=pa.list_(img_struct)),
|
| 74 |
"output_image": pa.array([_img(output_jpeg) if output_jpeg else None], type=img_struct),
|
| 75 |
+
"duration_seconds": pa.array([float(duration_seconds)], type=pa.float32()),
|
| 76 |
+
"input_width": pa.array([int(input_width)], type=pa.int32()),
|
| 77 |
+
"input_height": pa.array([int(input_height)], type=pa.int32()),
|
| 78 |
+
"success": pa.array([bool(success)], type=pa.bool_()),
|
| 79 |
+
"error_message": pa.array([str(error_message)], type=pa.string()),
|
| 80 |
}, schema=schema)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
+
uid = uuid.uuid4().hex[:8]
|
| 83 |
+
path_in_repo = f"data/{now.strftime('%Y-%m-%d-%H%M%S')}-{uid}.parquet"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
|
| 85 |
with tempfile.NamedTemporaryFile(suffix=".parquet", delete=False) as tmp:
|
| 86 |
tmp_path = tmp.name
|
| 87 |
+
pq.write_table(table, tmp_path)
|
| 88 |
+
|
| 89 |
+
api = HfApi(token=HF_TOKEN)
|
| 90 |
+
api.create_repo(repo_id=DATASET_REPO, repo_type="dataset", private=True, exist_ok=True)
|
| 91 |
+
print(f"[log] uploading {path_in_repo} ({os.path.getsize(tmp_path)//1024}KB)")
|
| 92 |
api.upload_file(
|
| 93 |
path_or_fileobj=tmp_path, path_in_repo=path_in_repo,
|
| 94 |
repo_id=DATASET_REPO, repo_type="dataset",
|
|
|
|
| 97 |
except Exception as log_err:
|
| 98 |
import traceback as _tb
|
| 99 |
print(f"[log] WARNING: {log_err}\n{_tb.format_exc()}")
|
| 100 |
+
finally:
|
| 101 |
+
if tmp_path:
|
| 102 |
+
try:
|
| 103 |
+
os.unlink(tmp_path)
|
| 104 |
+
except Exception:
|
| 105 |
+
pass
|