Spaces:
Runtime error
Runtime error
| """Pull a balanced scientific-domain human-vs-machine corpus from MAGE | |
| (yaful/MAGE) via the HF datasets-server filter API — no full download. | |
| MAGE: text / label (1=human, 0=machine) / src (domain+model). The 'sci_gen_*' | |
| rows are scientific/academic text; the model name lives in src, giving us | |
| leave-one-MODEL-out groups for honest validation. Length-filtered so every | |
| doc has enough sentences for the burstiness/diversity features. | |
| Output: data/calibration/mage_sci.jsonl ({text, y, src_model}) | |
| Run: python scripts/build_mage_corpus.py [per_model] (default 120) | |
| """ | |
| import json, os, sys, time, urllib.parse, urllib.request | |
| ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
| OUT = os.path.join(ROOT, "data", "calibration", "mage_sci.jsonl") | |
| DS, CONFIG = "yaful/MAGE", "default" | |
| MIN_CHARS = 800 # need a real document, not a snippet | |
| PER_MODEL = int(sys.argv[1]) if len(sys.argv) > 1 else 120 | |
| def _get(url, tries=4): | |
| for t in range(tries): | |
| try: | |
| return json.load(urllib.request.urlopen(url, timeout=40)) | |
| except Exception as e: | |
| if t == tries - 1: | |
| raise | |
| time.sleep(2 * (t + 1)) | |
| def filt(where, split, offset, length=100): | |
| u = (f"https://datasets-server.huggingface.co/filter?dataset={urllib.parse.quote(DS)}" | |
| f"&config={CONFIG}&split={split}&where={urllib.parse.quote(where)}" | |
| f"&offset={offset}&length={length}") | |
| return _get(u) | |
| def collect(where, split, cap, by_model): | |
| """Page through a filtered view, bucket by src, length-filter, cap/model.""" | |
| offset, total = 0, None | |
| while True: | |
| d = filt(where, split, offset) | |
| total = d.get("num_rows_total", 0) | |
| rows = d.get("rows", []) | |
| if not rows: | |
| break | |
| for r in rows: | |
| row = r["row"] | |
| txt, src = row.get("text", ""), row.get("src", "") | |
| if len(txt) < MIN_CHARS: | |
| continue | |
| bucket = by_model.setdefault(src, []) | |
| if len(bucket) < cap: | |
| bucket.append(txt) | |
| offset += len(rows) | |
| got = sum(min(len(v), cap) for v in by_model.values()) | |
| print(f" {split} offset={offset}/{total} collected={got}", end="\r") | |
| if offset >= total or offset > 40000: | |
| break | |
| print() | |
| def main(): | |
| os.makedirs(os.path.dirname(OUT), exist_ok=True) | |
| human, machine = {}, {} | |
| for split in ("test", "validation", "train"): | |
| print(f"[human] {split}") | |
| collect("\"src\"='sci_gen_human'", split, PER_MODEL * 6, human) | |
| print(f"[machine] {split}") | |
| collect("\"src\" LIKE 'sci_gen_machine%'", split, PER_MODEL, machine) | |
| h = sum(len(v) for v in human.values()) | |
| m = sum(len(v) for v in machine.values()) | |
| if h >= PER_MODEL * 6 and len(machine) >= 3: | |
| break | |
| rows = [] | |
| for txts in human.values(): | |
| for t in txts[:PER_MODEL * 6]: | |
| rows.append({"text": t, "y": 1, "src_model": "human"}) | |
| for src, txts in machine.items(): | |
| model = src.replace("sci_gen_machine_continuation_", "").replace( | |
| "sci_gen_machine_", "") | |
| for t in txts: | |
| rows.append({"text": t, "y": 0, "src_model": "ai_" + model}) | |
| with open(OUT, "w", encoding="utf-8") as f: | |
| for r in rows: | |
| f.write(json.dumps(r) + "\n") | |
| from collections import Counter | |
| c = Counter(r["src_model"] for r in rows) | |
| print(f"\nwrote {len(rows)} docs -> {OUT}") | |
| for k, v in sorted(c.items()): | |
| print(f" {k:28s} {v}") | |
| if __name__ == "__main__": | |
| main() | |