Spaces:
Sleeping
Sleeping
File size: 2,950 Bytes
c25f760 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | """v1 contribution loop — predict -> confirm/correct -> writeback (PRD §18.3, §13).
Anonymous by default (D12): no login, dedup via audio_sha256, optional handle for
attribution only. Rights gate (§12): nothing is saved unless the contributor
affirms it's their own performance / they have the right to share it.
Writes {id}.flac + {id}.json into incoming/ of the dataset repo; the consolidate
cron promotes verified clips into shards (pipeline/consolidate.py).
"""
from __future__ import annotations
import datetime as dt
import hashlib
import io
import json
import os
import uuid
# Neutral org (D19). The Space holds an HF write token scoped to this dataset repo.
DATASET_REPO = "twelveswaras/twelveswaras-commons"
CONSENT_VERSION = "2026-07-01-v1"
def utcnow() -> str:
return dt.datetime.utcnow().replace(microsecond=0).isoformat() + "Z"
def pseudonym(handle: str) -> str:
# Optional, never PII (D12). Random per-clip id if no handle given.
return "u_" + hashlib.sha256(handle.encode()).hexdigest()[:8]
def submit(audio, chosen_raaga, is_own, license_, handle, instrument, form, ctx) -> str:
if not is_own:
return "❌ Not saved — you must confirm this is your own performance / you may share it."
import soundfile as sf
from huggingface_hub import CommitOperationAdd, HfApi
api = HfApi(token=os.environ["HF_WRITE_TOKEN"]) # Space secret, scoped to the dataset repo
sr, wav = audio
buf = io.BytesIO()
sf.write(buf, wav, sr, format="FLAC")
raw = buf.getvalue()
rid = uuid.uuid4().hex[:8]
meta = {
"id": rid,
"audio_file": f"{rid}.flac",
"audio_sha256": hashlib.sha256(raw).hexdigest(),
"raaga": chosen_raaga,
"tradition": "carnatic",
"contributor_id": pseudonym(handle or rid),
"is_own_performance": True,
"license": license_,
"consent_version": CONSENT_VERSION,
"created_at": utcnow(),
"label_source": "model_confirmed" if chosen_raaga == ctx.get("pred") else "contributor_declared",
"model_prediction": ctx.get("pred"),
"model_confidence": float(ctx.get("conf", 0.0)),
"verification_status": "unverified",
"split": "pending",
"votes_agree": 0,
"votes_disagree": 0,
"instrument": instrument,
"form": form,
}
api.create_commit(
repo_id=DATASET_REPO,
repo_type="dataset",
commit_message=f"contrib {rid} ({chosen_raaga})",
operations=[
CommitOperationAdd(f"incoming/{rid}.flac", raw),
CommitOperationAdd(f"incoming/{rid}.json", json.dumps(meta, ensure_ascii=False).encode()),
],
)
return f"✅ Saved as {chosen_raaga} — thank you! It enters the verification queue."
# TODO(v1): assemble the Gradio Blocks UI (predict button + confirm/correct form).
# The identify half already lives in apps/identify.py; this file owns the writeback.
|