Download scripts/check_skill_usage_labels.py from weideyouni/holoaeon: direct link, hf CLI and curl.
- Browser
- Download file 4.92 kB
-
https://huggingface.co/weideyouni/holoaeon/resolve/main/scripts/check_skill_usage_labels.py
- Command line
-
hf download hf://weideyouni/holoaeon/scripts/check_skill_usage_labels.py
-
curl -L -o check_skill_usage_labels.py https://huggingface.co/weideyouni/holoaeon/resolve/main/scripts/check_skill_usage_labels.py
4.92 kB
| # -*- coding: utf-8 -*- | |
| """B3 判据校验器:1229 行用途分类 + 抽样 40 复核,判据 U1–U7。 | |
| 用法:python scripts/check_skill_usage_labels.py → 退出码 0/1 | |
| python scripts/check_skill_usage_labels.py --json → 输出回执 JSON | |
| U1 行数 1229 且与索引 count / name 集合逐一对应(不许多、不许少、不许重名混淆) | |
| U2 label 只取 K/M/T/X/U 五值,无空值("全有值"= 每行 label 非空且合法) | |
| U3 五类计数相加 == 1229,且 U(待判)≤ 20 | |
| U4 stage1 判定的行 score ≥ TH;stage2 行必须有 domain/weak 依据(reason 非空) | |
| U5 抽样 40:条数 40、agree ≥ 36(90%),且失败项必须写明改判理由 | |
| U6 复跑字节一致(--check 由 classify_skill_usage.py 提供,这里做二次比对) | |
| U7 CSV 自身 sha256 与 generation 回执一致(防手工改表后没重跑) | |
| """ | |
| import csv | |
| import hashlib | |
| import io | |
| import json | |
| import os | |
| import sys | |
| ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
| INDEX = os.path.join(ROOT, "data", "skill_matrix_index.json") | |
| CSV_F = os.path.join(ROOT, "data", "skill_usage_labels.csv") | |
| VERDICT_F = os.path.join(ROOT, "data", "b3_sample_verdicts.json") | |
| OUT = os.path.join(ROOT, "reports", "b3_usage_labels_check.json") | |
| LABELS = ("K", "M", "T", "X", "U") | |
| def main(): | |
| checks = [] | |
| def add(cid, ok, detail): | |
| checks.append({"id": cid, "ok": bool(ok), "detail": detail}) | |
| missing = [os.path.basename(p) for p in (INDEX, CSV_F, VERDICT_F) if not os.path.isfile(p)] | |
| if missing: | |
| add("U0", False, "missing={}".format(missing)) | |
| print(json.dumps({"verdict": "FAIL", "checks": checks}, ensure_ascii=False, indent=2)) | |
| return 1 | |
| with open(INDEX, encoding="utf-8") as f: | |
| idx = json.load(f) | |
| with open(CSV_F, encoding="utf-8") as f: | |
| text = f.read() | |
| rows = list(csv.DictReader(io.StringIO(text))) | |
| with open(VERDICT_F, encoding="utf-8") as f: | |
| sample = json.load(f) | |
| names_idx = [x.get("name") for x in idx["skills"]] | |
| names_csv = [r["name"] for r in rows] | |
| add("U1", len(rows) == 1229 and len(names_csv) == idx["count"] and names_csv == names_idx, | |
| "rows={} index_count={} order_identical={}".format(len(rows), idx["count"], | |
| names_csv == names_idx)) | |
| bad = [r["name"] for r in rows if r.get("label", "") not in LABELS] | |
| add("U2", not bad, "invalid_or_empty={}".format(bad[:5] + (["..."] if len(bad) > 5 else []))) | |
| counts = {k: 0 for k in LABELS} | |
| for r in rows: | |
| counts[r["label"]] += 1 | |
| total = sum(counts.values()) | |
| add("U3", total == 1229 and counts["U"] <= 20, | |
| "sum={} counts={} undecided={}".format(total, counts, counts["U"])) | |
| weak = [r["name"] for r in rows | |
| if r["stage"] == "stage1" and float(r["score"]) < 0.80 | |
| or r["stage"] not in ("stage1", "stage2", "stage2-weak", "undecided") | |
| or not r["reason"]] | |
| add("U4", not weak, "bad_stage_or_reason={}".format(weak[:5])) | |
| agree = sample.get("agree", 0) | |
| dis = [x["name"] for x in sample.get("items", []) if x["verdict"] == "disagree"] | |
| all_noted = all(x.get("note") for x in sample.get("items", []) if x["verdict"] == "disagree") | |
| add("U5", len(sample.get("items", [])) == 40 and agree >= 36 and all_noted and len(dis) == sample.get("disagree"), | |
| "sample={} agree={}/40 disagree={} notes_complete={}".format( | |
| len(sample.get("items", [])), agree, len(dis), all_noted)) | |
| # U6 复跑字节一致由 classify_skill_usage.py --check 负责,这里核一次同源构建 | |
| sys.path.insert(0, ROOT) | |
| import importlib.util | |
| spec = importlib.util.spec_from_file_location( | |
| "csu", os.path.join(ROOT, "scripts", "classify_skill_usage.py")) | |
| mod = importlib.util.module_from_spec(spec) | |
| spec.loader.exec_module(mod) | |
| rebuilt, rcounts, rdigest = mod.build() | |
| same = mod.csv_text(rebuilt) == text | |
| add("U6", same and rcounts == counts, "byte_consistent={} digest={}".format(same, rdigest)) | |
| actual = hashlib.sha256(text.encode("utf-8")).hexdigest() | |
| add("U7", sample.get("csv_sha256") == actual, | |
| "csv_sha256={}".format(actual)) | |
| verdict = "PASS" if all(c["ok"] for c in checks) else "FAIL" | |
| doc = {"batch": "B3", "index_digest": idx.get("digest"), "labels_digest": rdigest, | |
| "csv_sha256": actual, "counts": counts, "sample": {"agree": agree, | |
| "disagree": len(dis), "threshold": 36}, "verdict": verdict, | |
| "failed": [c["id"] for c in checks if not c["ok"]], "checks": checks} | |
| os.makedirs(os.path.dirname(OUT), exist_ok=True) | |
| with open(OUT, "w", encoding="utf-8") as f: | |
| json.dump(doc, f, ensure_ascii=False, indent=2) | |
| print(json.dumps(doc, ensure_ascii=False, indent=2)) | |
| return 0 if verdict == "PASS" else 1 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |