someone-in-the-world Claude Sonnet 4.6 commited on
Commit
9e47f62
·
1 Parent(s): b8216f1

Write one parquet file per inference to avoid Git LFS version bloat

Browse files

Previously 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>

Files changed (1) hide show
  1. 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, json as _json
 
32
  import pyarrow as pa
33
  import pyarrow.parquet as pq
34
- from huggingface_hub import HfApi, hf_hub_download
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
- new_table = pa.table({
82
- "timestamp": pa.array([datetime.now(timezone.utc).timestamp()], type=pa.float64()),
83
- "prompt": pa.array([prompt], type=pa.string()),
84
- "seed": pa.array([int(seed)], type=pa.int32()),
85
- "steps": pa.array([int(steps)], type=pa.int32()),
86
- "guidance_scale": pa.array([float(guidance_scale)], type=pa.float32()),
87
- "input_images": pa.array([[_img(b) for b in input_jpegs]], type=pa.list_(img_struct)),
88
  "output_image": pa.array([_img(output_jpeg) if output_jpeg else None], type=img_struct),
89
- "duration_seconds": pa.array([float(duration_seconds)], type=pa.float32()),
90
- "input_width": pa.array([int(input_width)], type=pa.int32()),
91
- "input_height": pa.array([int(input_height)], type=pa.int32()),
92
- "success": pa.array([bool(success)], type=pa.bool_()),
93
- "error_message": pa.array([str(error_message)], type=pa.string()),
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
- # Upload README.md once so the HF viewer knows the column types.
103
- try:
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(combined, tmp_path)
128
- print(f"[log] uploading {path_in_repo} ({combined.num_rows} row(s), {os.path.getsize(tmp_path)//1024}KB)")
 
 
 
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