code2lora commited on
Commit
7bacdbf
·
verified ·
1 Parent(s): a3d7d04

Update app

Browse files
app.py CHANGED
@@ -63,6 +63,8 @@ def load_repo(safe: str) -> dict:
63
  d = json.load(f)
64
  d["ctx"] = np.load(DATA / f"{safe}.ctx.npy")
65
  d["tt_commits"] = [k for k, c in enumerate(d["commits"]) if c.get("time_travel")]
 
 
66
  return d
67
 
68
 
@@ -187,6 +189,12 @@ def repo_header(safe: str) -> str:
187
  r = INDEX_BY_SAFE[safe]
188
  stars = f"★ {r['stars']:,} · " if r.get("stars") else ""
189
  desc = f"<div class='desc'>{esc(r.get('description'))}</div>" if r.get("description") else ""
 
 
 
 
 
 
190
  return f"""
191
  <div class="repo-card">
192
  <div class="repo-title"><a href="https://github.com/{esc(r['repo_id'])}" target="_blank">{esc(r['repo_id'])}</a>
@@ -194,8 +202,7 @@ def repo_header(safe: str) -> str:
194
  {desc}
195
  <div class="repo-stats">{stars}{r['n_commits']} commits · {short_date(r['first_date'])} → {short_date(r['last_date'])}
196
  · {r['n_qnas']:,} test assertions</div>
197
- <div class="repo-em">Exact match across this repo's history:
198
- base model <b>{pct(r['base_em'])}</b> → Code2LoRA <b class="accent">{pct(r['c2l_em'])}</b></div>
199
  </div>"""
200
 
201
 
@@ -236,18 +243,22 @@ def timeline_plot(safe: str, k: int) -> Figure:
236
 
237
  fig = Figure(figsize=(9, 2.4), dpi=110)
238
  ax = fig.add_subplot(111)
239
- ax.plot(x, rolling("base_em"), color="#9aa3b5", lw=1.6, label="Base model")
240
- ax.plot(x, rolling("c2l_em"), color="#4f5bd5", lw=2.2, label="Code2LoRA (adapter at each commit)")
241
- for t in d["tt_commits"]:
242
- ax.axvline(t + 1, color="#22c3a6", alpha=0.18, lw=1)
 
 
 
 
 
 
243
  ax.axvline(k + 1, color="#ff6b8b", lw=2)
244
- ax.set_xlim(1, max(2, len(cs)))
245
- ax.set_ylim(0, 100)
246
- ax.set_ylabel("Exact match %\n(rolling)")
247
  ax.set_xlabel("Commit")
248
  for s in ("top", "right"):
249
  ax.spines[s].set_visible(False)
250
- ax.legend(loc="lower right", fontsize=8, frameon=False)
251
  fig.tight_layout()
252
  return fig
253
 
@@ -278,8 +289,13 @@ def assertion_panel(safe: str, k: int, i: Optional[int], adapted_k: Optional[int
278
  if i is None or i >= len(qs):
279
  return "", "<div class='hint'>Pick an assertion above.</div>"
280
  q = qs[i]
281
- rows = [f"""<tr class="truth"><td class="who">Ground truth</td><td><code>{esc(q['target'])}</code></td><td></td>
282
- <td class="note">what the developer actually wrote</td></tr>""",
 
 
 
 
 
283
  pred_row("Base model", "base", q["base_pred"], q["base_em"], "Qwen2.5-Coder-1.5B, no adapter")]
284
  if adapted_k == k:
285
  if q.get("prev_pred") is not None:
@@ -302,7 +318,7 @@ def assertion_panel(safe: str, k: int, i: Optional[int], adapted_k: Optional[int
302
 
303
  def default_commit(safe: str) -> int:
304
  d = load_repo(safe)
305
- return d["tt_commits"][0] if d["tt_commits"] else len(d["commits"]) - 1
306
 
307
 
308
  def on_repo(safe: str):
@@ -311,7 +327,8 @@ def on_repo(safe: str):
311
  choices = assertion_choices(safe, k)
312
  first = choices[0][1] if choices else None
313
  ctx, preds = assertion_panel(safe, k, first, None)
314
- return (repo_header(safe),
 
315
  gr.Slider(minimum=1, maximum=len(d["commits"]), value=k + 1, step=1),
316
  commit_card(safe, k, None), timeline_plot(safe, k),
317
  d["commits"][k].get("diff_preview") or "",
@@ -336,7 +353,7 @@ def step(safe: str, k1: int, delta: int) -> int:
336
 
337
 
338
  def next_star(safe: str, k1: int) -> int:
339
- tt = load_repo(safe)["tt_commits"]
340
  k = int(k1) - 1
341
  later = [t for t in tt if t > k]
342
  return (later[0] if later else (tt[0] if tt else k)) + 1
@@ -400,6 +417,13 @@ def on_live(safe: str, k1: int, i: Optional[int], adapted: Optional[Tuple[str, i
400
  q["target"]) + note
401
 
402
 
 
 
 
 
 
 
 
403
  def on_prefill(safe: str, k1: int, i: Optional[int]) -> str:
404
  qs = load_repo(safe)["qnas"][int(k1) - 1]
405
  if i is None or i >= len(qs):
@@ -496,7 +520,7 @@ adapter gets an assertion right that the adapter from one commit earlier got wro
496
  """
497
 
498
  choices = [(repo_label(r), r["safe"]) for r in INDEX]
499
- start = max(INDEX, key=lambda r: (r["c2l_em"] - r["base_em"]))["safe"]
500
 
501
  with gr.Blocks(css=CSS, title="Code2LoRA timeline demo", theme=gr.themes.Soft(primary_hue="indigo")) as demo:
502
  adapted_state = gr.State(None)
@@ -542,7 +566,7 @@ with gr.Blocks(css=CSS, title="Code2LoRA timeline demo", theme=gr.themes.Soft(pr
542
  f"{LIVE_MAX_INPUT:,} context tokens and takes roughly 10–40 s.*"
543
  if DEVICE == "cpu" else ""))
544
 
545
- repo_outputs = [repo_html, commit_slider, commit_html, plot, diff_code, pick, ctx_code, preds_html,
546
  adapted_state, adapt_html, live_html]
547
  commit_outputs = [commit_html, plot, diff_code, pick, ctx_code, preds_html, live_html]
548
 
@@ -555,9 +579,12 @@ with gr.Blocks(css=CSS, title="Code2LoRA timeline demo", theme=gr.themes.Soft(pr
555
  on_commit, [repo_dd, commit_slider, adapted_state], commit_outputs)
556
  star_btn.click(next_star, [repo_dd, commit_slider], commit_slider).then(
557
  on_commit, [repo_dd, commit_slider, adapted_state], commit_outputs)
 
558
  adapt_btn.click(on_adapt, [repo_dd, commit_slider, pick],
559
- [adapt_html, adapted_state, commit_html, ctx_code, preds_html], concurrency_limit=1)
560
- pick.change(on_pick, [repo_dd, commit_slider, pick, adapted_state], [ctx_code, preds_html, live_html])
 
 
561
  live_btn.click(on_live, [repo_dd, commit_slider, pick, adapted_state], live_html, concurrency_limit=1)
562
  prefill_btn.click(on_prefill, [repo_dd, commit_slider, pick], custom_in)
563
  custom_btn.click(on_custom, [repo_dd, commit_slider, custom_in, max_new, adapted_state], custom_out,
 
63
  d = json.load(f)
64
  d["ctx"] = np.load(DATA / f"{safe}.ctx.npy")
65
  d["tt_commits"] = [k for k, c in enumerate(d["commits"]) if c.get("time_travel")]
66
+ d["live_only"] = INDEX_BY_SAFE[safe].get("c2l_em") is None
67
+ d["jump_targets"] = d["tt_commits"] or [k for k, g in enumerate(d["qnas"]) if g]
68
  return d
69
 
70
 
 
189
  r = INDEX_BY_SAFE[safe]
190
  stars = f"★ {r['stars']:,} · " if r.get("stars") else ""
191
  desc = f"<div class='desc'>{esc(r.get('description'))}</div>" if r.get("description") else ""
192
+ if r.get("c2l_em") is None:
193
+ em = ("<div class='repo-em'>Live mode: cached GPU scores for this repository are still being computed. "
194
+ "Press <b>Adapt</b> and both models answer live on this Space.</div>")
195
+ else:
196
+ em = (f"<div class='repo-em'>Exact match across this repo's history: base model <b>{pct(r['base_em'])}</b>"
197
+ f" → Code2LoRA <b class='accent'>{pct(r['c2l_em'])}</b></div>")
198
  return f"""
199
  <div class="repo-card">
200
  <div class="repo-title"><a href="https://github.com/{esc(r['repo_id'])}" target="_blank">{esc(r['repo_id'])}</a>
 
202
  {desc}
203
  <div class="repo-stats">{stars}{r['n_commits']} commits · {short_date(r['first_date'])} → {short_date(r['last_date'])}
204
  · {r['n_qnas']:,} test assertions</div>
205
+ {em}
 
206
  </div>"""
207
 
208
 
 
243
 
244
  fig = Figure(figsize=(9, 2.4), dpi=110)
245
  ax = fig.add_subplot(111)
246
+ if d["live_only"]:
247
+ ax.bar(x, [len(g) for g in d["qnas"]], color="#c5cbf5", width=0.9, label="Test assertions added")
248
+ ax.set_ylabel("Assertions\nadded")
249
+ else:
250
+ ax.plot(x, rolling("base_em"), color="#9aa3b5", lw=1.6, label="Base model")
251
+ ax.plot(x, rolling("c2l_em"), color="#4f5bd5", lw=2.2, label="Code2LoRA (adapter at each commit)")
252
+ for t in d["tt_commits"]:
253
+ ax.axvline(t + 1, color="#22c3a6", alpha=0.18, lw=1)
254
+ ax.set_ylim(0, 100)
255
+ ax.set_ylabel("Exact match %\n(rolling)")
256
  ax.axvline(k + 1, color="#ff6b8b", lw=2)
257
+ ax.set_xlim(0.5, max(2, len(cs)) + 0.5)
 
 
258
  ax.set_xlabel("Commit")
259
  for s in ("top", "right"):
260
  ax.spines[s].set_visible(False)
261
+ ax.legend(loc="upper left" if d["live_only"] else "lower right", fontsize=8, frameon=False)
262
  fig.tight_layout()
263
  return fig
264
 
 
289
  if i is None or i >= len(qs):
290
  return "", "<div class='hint'>Pick an assertion above.</div>"
291
  q = qs[i]
292
+ truth = f"""<tr class="truth"><td class="who">Ground truth</td><td><code>{esc(q['target'])}</code></td><td></td>
293
+ <td class="note">what the developer actually wrote</td></tr>"""
294
+ if q.get("base_pred") is None:
295
+ hint = ("Both models are answering live below…" if adapted_k == k else
296
+ "Press <b>Adapt at this commit</b>: the adapter is generated and both models answer live.")
297
+ return context_tail(q["prompt"]), f"<table class='preds'>{truth}</table><div class='hint'>{hint}</div>"
298
+ rows = [truth,
299
  pred_row("Base model", "base", q["base_pred"], q["base_em"], "Qwen2.5-Coder-1.5B, no adapter")]
300
  if adapted_k == k:
301
  if q.get("prev_pred") is not None:
 
318
 
319
  def default_commit(safe: str) -> int:
320
  d = load_repo(safe)
321
+ return d["jump_targets"][0] if d["jump_targets"] else len(d["commits"]) - 1
322
 
323
 
324
  def on_repo(safe: str):
 
327
  choices = assertion_choices(safe, k)
328
  first = choices[0][1] if choices else None
329
  ctx, preds = assertion_panel(safe, k, first, None)
330
+ jump = "Jump to next commit with tests" if d["live_only"] else "Jump to next ✨ commit"
331
+ return (gr.Button(value=jump), repo_header(safe),
332
  gr.Slider(minimum=1, maximum=len(d["commits"]), value=k + 1, step=1),
333
  commit_card(safe, k, None), timeline_plot(safe, k),
334
  d["commits"][k].get("diff_preview") or "",
 
353
 
354
 
355
  def next_star(safe: str, k1: int) -> int:
356
+ tt = load_repo(safe)["jump_targets"]
357
  k = int(k1) - 1
358
  later = [t for t in tt if t > k]
359
  return (later[0] if later else (tt[0] if tt else k)) + 1
 
417
  q["target"]) + note
418
 
419
 
420
+ def on_auto_live(safe: str, k1: int, i: Optional[int], adapted: Optional[Tuple[str, int]],
421
+ progress=gr.Progress()):
422
+ if not load_repo(safe)["live_only"] or adapted != (safe, int(k1) - 1) or i is None:
423
+ return gr.update()
424
+ return on_live(safe, k1, i, adapted, progress)
425
+
426
+
427
  def on_prefill(safe: str, k1: int, i: Optional[int]) -> str:
428
  qs = load_repo(safe)["qnas"][int(k1) - 1]
429
  if i is None or i >= len(qs):
 
520
  """
521
 
522
  choices = [(repo_label(r), r["safe"]) for r in INDEX]
523
+ start = max(INDEX, key=lambda r: ((r["c2l_em"] or 0) - (r["base_em"] or 0), r.get("stars") or 0))["safe"]
524
 
525
  with gr.Blocks(css=CSS, title="Code2LoRA timeline demo", theme=gr.themes.Soft(primary_hue="indigo")) as demo:
526
  adapted_state = gr.State(None)
 
566
  f"{LIVE_MAX_INPUT:,} context tokens and takes roughly 10–40 s.*"
567
  if DEVICE == "cpu" else ""))
568
 
569
+ repo_outputs = [star_btn, repo_html, commit_slider, commit_html, plot, diff_code, pick, ctx_code, preds_html,
570
  adapted_state, adapt_html, live_html]
571
  commit_outputs = [commit_html, plot, diff_code, pick, ctx_code, preds_html, live_html]
572
 
 
579
  on_commit, [repo_dd, commit_slider, adapted_state], commit_outputs)
580
  star_btn.click(next_star, [repo_dd, commit_slider], commit_slider).then(
581
  on_commit, [repo_dd, commit_slider, adapted_state], commit_outputs)
582
+ live_inputs = [repo_dd, commit_slider, pick, adapted_state]
583
  adapt_btn.click(on_adapt, [repo_dd, commit_slider, pick],
584
+ [adapt_html, adapted_state, commit_html, ctx_code, preds_html], concurrency_limit=1).then(
585
+ on_auto_live, live_inputs, live_html, concurrency_limit=1)
586
+ pick.change(on_pick, live_inputs, [ctx_code, preds_html, live_html]).then(
587
+ on_auto_live, live_inputs, live_html, concurrency_limit=1)
588
  live_btn.click(on_live, [repo_dd, commit_slider, pick, adapted_state], live_html, concurrency_limit=1)
589
  prefill_btn.click(on_prefill, [repo_dd, commit_slider, pick], custom_in)
590
  custom_btn.click(on_custom, [repo_dd, commit_slider, custom_in, max_new, adapted_state], custom_out,
tools/build_prototype_data.py ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Build a live-only Space data directory on CPU, without the GPU cache.
3
+
4
+ GRU contexts and prompts are real; predictions are left empty, so the app
5
+ answers every assertion live. Replaced by build_space_data.py output once the
6
+ precompute job is done.
7
+
8
+ python hf_space_demo/tools/build_prototype_data.py --out-dir DATA --repos pypa/pipx msiemens/tinydb
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import argparse
14
+ import gzip
15
+ import json
16
+ import sys
17
+ from collections import defaultdict
18
+ from pathlib import Path
19
+
20
+ import numpy as np
21
+ import pyarrow.parquet as pq
22
+ import torch
23
+ from huggingface_hub import hf_hub_download
24
+ from transformers import AutoTokenizer
25
+
26
+ HERE = Path(__file__).resolve().parent
27
+ sys.path.insert(0, str(HERE.parent))
28
+ sys.path.insert(0, str(HERE))
29
+
30
+ from build_space_data import github_meta # noqa: E402
31
+ from c2l.core import CommitGRU # noqa: E402
32
+
33
+ COMMITS = "/scratch/lhotsko/REPO_DATASET/commit_parquet_hf_v2/commits/cr_test.parquet"
34
+ QNAS = "/scratch/lhotsko/REPO_DATASET/code2lora_snapshots_hf/qna/cr_test.parquet"
35
+
36
+
37
+ def load_gru() -> CommitGRU:
38
+ state = torch.load(hf_hub_download("code2lora/code2lora-gru", "code2lora_gru.pt"),
39
+ map_location="cpu", weights_only=False, mmap=True)
40
+ gc = state.get("gru_config") or {}
41
+ gru = CommitGRU(int(gc.get("diff_input_dim", 2048)), int(gc.get("repo_state_dim", 2048)),
42
+ int(gc.get("hidden_dim", 2048)))
43
+ gru.load_state_dict(state["gru_state"])
44
+ return gru.eval()
45
+
46
+
47
+ @torch.no_grad()
48
+ def build_repo(repo: str, out: Path, gru: CommitGRU, tok, max_input: int = 4096) -> dict:
49
+ safe = repo.replace("/", "__")
50
+ ct = pq.read_table(COMMITS, filters=[("repo_id", "=", repo)]).to_pylist()
51
+ ct.sort(key=lambda r: r["commit_index"])
52
+ by_sha = defaultdict(list)
53
+ for q in pq.read_table(QNAS, columns=["repo_id", "commit_sha", "test_file", "lineno", "test_function",
54
+ "prefix", "target"], filters=[("repo_id", "=", repo)]).to_pylist():
55
+ by_sha[q["commit_sha"]].append(q)
56
+
57
+ h = gru.init_hidden(torch.tensor(ct[0]["repo_state_embedding"]).unsqueeze(0))
58
+ ctx = []
59
+ for r in ct:
60
+ h = gru.step(torch.tensor(r["diff_embedding"]).unsqueeze(0), h)
61
+ ctx.append(gru.context(h).float())
62
+ np.save(out / f"{safe}.ctx.npy", torch.cat(ctx).numpy().astype(np.float32))
63
+
64
+ bos = tok.bos_token_id if tok.bos_token_id is not None else tok.eos_token_id
65
+ commits, qnas = [], []
66
+ for k, r in enumerate(ct):
67
+ group = []
68
+ for q in by_sha[r["commit_sha"]][:8]:
69
+ ids = ([bos] + tok.encode(q["prefix"], add_special_tokens=False))[-max_input:]
70
+ had_bos = ids[0] == bos
71
+ group.append({"k": k, "test_file": q["test_file"], "lineno": int(q["lineno"] or 0),
72
+ "test_function": q["test_function"] or "",
73
+ "prompt": tok.decode(ids[1:] if had_bos else ids), "had_bos": had_bos,
74
+ "n_prompt_tokens": len(ids), "target": q["target"],
75
+ "base_pred": None, "base_em": None, "c2l_pred": None, "c2l_em": None})
76
+ qnas.append(group)
77
+ commits.append({"sha": r["commit_sha"], "commit_index": r["commit_index"],
78
+ "timestamp": r["commit_timestamp"], "n_new_assertions": r["n_new_assertions"],
79
+ "diff_preview": (r["production_code_diff"] or "")[:6000],
80
+ "n_qnas": len(group), "base_em": None, "c2l_em": None, "time_travel": False})
81
+ with gzip.open(out / f"{safe}.json.gz", "wt", encoding="utf-8") as f:
82
+ json.dump({"repo_id": repo, "commits": commits, "qnas": qnas,
83
+ "max_input_tokens": max_input, "max_new_tokens": 64}, f)
84
+ print(f"[{repo}] {len(commits)} commits, {sum(map(len, qnas))} qnas", flush=True)
85
+ return {"repo_id": repo, "safe": safe, "n_commits": len(commits), "n_qnas": sum(map(len, qnas)),
86
+ "base_em": None, "c2l_em": None, "n_time_travel": 0,
87
+ "first_date": commits[0]["timestamp"], "last_date": commits[-1]["timestamp"],
88
+ **github_meta(repo)}
89
+
90
+
91
+ def main() -> None:
92
+ ap = argparse.ArgumentParser()
93
+ ap.add_argument("--out-dir", required=True)
94
+ ap.add_argument("--repos", nargs="+", required=True)
95
+ args = ap.parse_args()
96
+ out = Path(args.out_dir)
97
+ out.mkdir(parents=True, exist_ok=True)
98
+ gru = load_gru()
99
+ tok = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-Coder-1.5B")
100
+ index = [build_repo(r, out, gru, tok) for r in args.repos]
101
+ (out / "index.json").write_text(json.dumps(index, indent=1))
102
+ print(f"wrote {len(index)} repos to {out}")
103
+
104
+
105
+ if __name__ == "__main__":
106
+ main()
tools/precompute.py CHANGED
@@ -104,6 +104,8 @@ def main() -> None:
104
  ap.add_argument("--batch-size", type=int, default=8)
105
  ap.add_argument("--qnas-per-commit-limit", type=int, default=8)
106
  ap.add_argument("--repos", nargs="*", default=None)
 
 
107
  args = ap.parse_args()
108
 
109
  out_dir = Path(args.out_dir)
@@ -111,7 +113,8 @@ def main() -> None:
111
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
112
 
113
  rows_by_repo = load_commit_rows_for_gru(Path(COMMITS))
114
- repos = sorted(rows_by_repo)
 
115
  if args.repos:
116
  repos = [r for r in repos if r in set(args.repos)]
117
  repos = [r for i, r in enumerate(repos) if i % args.num_shards == args.shard_i]
 
104
  ap.add_argument("--batch-size", type=int, default=8)
105
  ap.add_argument("--qnas-per-commit-limit", type=int, default=8)
106
  ap.add_argument("--repos", nargs="*", default=None)
107
+ ap.add_argument("--min-commits", type=int, default=10)
108
+ ap.add_argument("--max-commits", type=int, default=400)
109
  args = ap.parse_args()
110
 
111
  out_dir = Path(args.out_dir)
 
113
  device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
114
 
115
  rows_by_repo = load_commit_rows_for_gru(Path(COMMITS))
116
+ repos = sorted(r for r, rows in rows_by_repo.items()
117
+ if args.min_commits <= len(rows) <= args.max_commits)
118
  if args.repos:
119
  repos = [r for r in repos if r in set(args.repos)]
120
  repos = [r for i, r in enumerate(repos) if i % args.num_shards == args.shard_i]
tools/precompute.sbatch CHANGED
@@ -1,10 +1,10 @@
1
  #!/bin/bash
2
- # Precompute the Code2LoRA timeline Space cache (cr_test, all 51 repos).
3
- # sbatch --array=0-7 hf_space_demo/tools/precompute.sbatch
4
  #SBATCH --job-name=c2l_space_cache
5
- #SBATCH --output=slurm_logs/c2l_space_cache_%A_%a.out
6
- #SBATCH --error=slurm_logs/c2l_space_cache_%A_%a.err
7
- #SBATCH --time=03:00:00
8
  #SBATCH --gres=gpu:h100:1
9
  #SBATCH --cpus-per-task=8
10
  #SBATCH --mem=80G
@@ -24,4 +24,4 @@ export HF_HUB_OFFLINE=1
24
 
25
  python hf_space_demo/tools/precompute.py \
26
  --out-dir /home/lhotsko/projects/def-yuntian/lhotsko/c2l_space/cache \
27
- --shard-i "${SLURM_ARRAY_TASK_ID:-0}" --num-shards 8
 
1
  #!/bin/bash
2
+ # Precompute the Code2LoRA timeline Space cache (cr_test repos with 10-400 commits).
3
+ # sbatch hf_space_demo/tools/precompute.sbatch
4
  #SBATCH --job-name=c2l_space_cache
5
+ #SBATCH --output=slurm_logs/c2l_space_cache_%j.out
6
+ #SBATCH --error=slurm_logs/c2l_space_cache_%j.err
7
+ #SBATCH --time=12:00:00
8
  #SBATCH --gres=gpu:h100:1
9
  #SBATCH --cpus-per-task=8
10
  #SBATCH --mem=80G
 
24
 
25
  python hf_space_demo/tools/precompute.py \
26
  --out-dir /home/lhotsko/projects/def-yuntian/lhotsko/c2l_space/cache \
27
+ --shard-i 0 --num-shards 1
tools/publish.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Push the app and a built data directory to the Space, replacing old data.
3
+
4
+ python hf_space_demo/tools/publish.py --data-dir hf_space_demo/data [--public]
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import argparse
10
+ from pathlib import Path
11
+
12
+ from huggingface_hub import HfApi
13
+
14
+ HERE = Path(__file__).resolve().parents[1]
15
+
16
+
17
+ def main() -> None:
18
+ ap = argparse.ArgumentParser()
19
+ ap.add_argument("--data-dir", required=True)
20
+ ap.add_argument("--space", default="code2lora/code2lora-gru-demo")
21
+ ap.add_argument("--public", action="store_true")
22
+ args = ap.parse_args()
23
+
24
+ data = Path(args.data_dir)
25
+ if not (data / "index.json").exists():
26
+ raise SystemExit(f"{data}/index.json not found; run build_space_data.py first")
27
+
28
+ api = HfApi()
29
+ api.upload_folder(repo_id=args.space, repo_type="space", folder_path=str(HERE),
30
+ ignore_patterns=["data/*", "**/__pycache__/*", "*.pyc"],
31
+ commit_message="Update app")
32
+ api.upload_folder(repo_id=args.space, repo_type="space", folder_path=str(data),
33
+ path_in_repo="data", delete_patterns=["*"],
34
+ commit_message="Precomputed GRU states and cached predictions")
35
+ if args.public:
36
+ api.update_repo_settings(args.space, repo_type="space", private=False)
37
+ print(f"https://huggingface.co/spaces/{args.space}", api.get_space_runtime(args.space).stage)
38
+
39
+
40
+ if __name__ == "__main__":
41
+ main()