Download build_data.py from phamluan/itschool: direct link, hf CLI and curl.
- Browser
- Download file 10.8 kB
-
https://huggingface.co/spaces/phamluan/itschool/resolve/main/build_data.py
- Command line
-
hf download hf://spaces/phamluan/itschool/build_data.py
-
curl -L -o build_data.py https://huggingface.co/spaces/phamluan/itschool/resolve/main/build_data.py
10.8 kB
| """Sinh toan bo file du lieu cho Space tu du an goc. | |
| python build_data.py "/duong/dan/Thom Paper" | |
| Ghi ra space/data/: | |
| dataset.json 10.961 cap hoi dap (train + dev + test) | |
| facets.json gia tri cho cac bo loc | |
| lessons.json cay lop > chu de > bai hoc | |
| metrics.json chi so thuc nghiem + bao cao ro ri du lieu | |
| testset.json 1.073 cau test kem du doan cua 6 mo hinh | |
| errors.json vi du phan tich loi, nhom theo kieu | |
| recorded.jsonl du doan da ghi — dung khi chua co checkpoint fine-tune | |
| built.json thoi diem build | |
| """ | |
| import csv | |
| import json | |
| import re | |
| import sys | |
| from datetime import datetime, timezone | |
| from pathlib import Path | |
| HERE = Path(__file__).parent | |
| OUT = HERE / "data" | |
| MODELS = [ | |
| ("phobert", "PhoBERT", "extractive"), | |
| ("mbert", "mBERT", "extractive"), | |
| ("xlmr", "XLM-RoBERTa", "extractive"), | |
| ("vit5", "ViT5", "generative"), | |
| ("bartpho", "BARTpho", "generative"), | |
| ("gpt", "GPT", "generative"), | |
| ] | |
| LABELS = [label for _, label, _ in MODELS] | |
| NEEDED = [ | |
| "data/processed/train.csv", | |
| "data/processed/dev.csv", | |
| "data/processed/test.csv", | |
| "results/final_results.json", | |
| "results/results_by_grade.csv", | |
| "results/du_doan_6_mo_hinh.csv", | |
| "results/vi_du_phan_tich_loi.csv", | |
| "results/data_split_report.json", | |
| ] | |
| def desegment(value): | |
| """Du lieu PhoBERT duoc tach tu nen co dau gach duoi — bo di khi hien thi.""" | |
| return re.sub(r"\s+", " ", str(value or "").replace("_", " ")).strip() | |
| def num(value): | |
| if value in ("", None): | |
| return None | |
| try: | |
| return float(value) | |
| except ValueError: | |
| return None | |
| def read_csv(root: Path, rel: str): | |
| with (root / rel).open(encoding="utf-8-sig", newline="") as fh: | |
| return list(csv.DictReader(fh)) | |
| def read_json(root: Path, rel: str): | |
| return json.loads((root / rel).read_text(encoding="utf-8")) | |
| def write(name: str, value) -> None: | |
| path = OUT / name | |
| path.write_text(json.dumps(value, ensure_ascii=False), encoding="utf-8") | |
| print(f" {name:<16} {path.stat().st_size / 1024:,.0f} KB") | |
| # ----------------------------------------------------------------- dataset | |
| def build_dataset(root: Path): | |
| items = [] | |
| for split in ("train", "dev", "test"): | |
| for r in read_csv(root, f"data/processed/{split}.csv"): | |
| items.append( | |
| { | |
| "id": r["id"], | |
| "grade": int(r["grade"]), | |
| "topic": r["topic"], | |
| "lesson": r["lesson"], | |
| "page": r["page"], | |
| "section": r["section"], | |
| "contextId": r["context_id"], | |
| "context": r["context"], | |
| "question": r["question"], | |
| "answer": r["answer"], | |
| "answerStart": int(r["answer_start"]) if r["answer_start"] else None, | |
| "answerEnd": int(r["answer_end"]) if r["answer_end"] else None, | |
| "intent": r["intent"], | |
| "difficulty": r["difficulty"], | |
| "questionType": r["question_type"], | |
| "source": r["source"], | |
| "split": split, | |
| } | |
| ) | |
| return items | |
| def build_lessons(items): | |
| grades = {} | |
| for it in items: | |
| topics = grades.setdefault(it["grade"], {}) | |
| lessons = topics.setdefault(it["topic"], {}) | |
| entry = lessons.setdefault( | |
| it["lesson"], {"lesson": it["lesson"], "page": it["page"], "questions": 0, "contexts": set()} | |
| ) | |
| entry["questions"] += 1 | |
| entry["contexts"].add(it["contextId"]) | |
| out = [] | |
| for grade in sorted(grades): | |
| topics = [] | |
| for topic in sorted(grades[grade]): | |
| lessons = sorted(grades[grade][topic].values(), key=lambda l: l["lesson"]) | |
| topics.append( | |
| { | |
| "topic": topic, | |
| "lessons": [ | |
| {"lesson": l["lesson"], "page": l["page"], "questions": l["questions"], "contexts": len(l["contexts"])} | |
| for l in lessons | |
| ], | |
| } | |
| ) | |
| out.append({"grade": grade, "topics": topics}) | |
| return out | |
| def build_facets(items): | |
| uniq = lambda key: sorted({it[key] for it in items if it[key]}) | |
| return { | |
| "grades": sorted({it["grade"] for it in items}), | |
| "topics": uniq("topic"), | |
| "difficulties": uniq("difficulty"), | |
| "questionTypes": uniq("questionType"), | |
| "splits": ["train", "dev", "test"], | |
| "total": len(items), | |
| } | |
| def build_stats(items): | |
| def count(key): | |
| out = {} | |
| for it in items: | |
| out[str(it[key])] = out.get(str(it[key]), 0) + 1 | |
| return out | |
| contexts = {it["contextId"]: it["context"] for it in items} | |
| return { | |
| "total": len(items), | |
| "contexts": len(contexts), | |
| "byGrade": count("grade"), | |
| "bySplit": count("split"), | |
| "byDifficulty": count("difficulty"), | |
| "byQuestionType": count("questionType"), | |
| "answerLengthAvg": round(sum(len(it["answer"] or "") for it in items) / len(items), 1), | |
| "contextLengthAvg": round(sum(len(c) for c in contexts.values()) / len(contexts)), | |
| } | |
| # ------------------------------------------------------------------ metrics | |
| def build_metrics(root: Path): | |
| final = read_json(root, "results/final_results.json") | |
| split = read_json(root, "results/data_split_report.json") | |
| models = [] | |
| for key, label, kind in MODELS: | |
| block = final.get("extractive", {}).get(label) or final.get("generative", {}).get(label) or {} | |
| models.append( | |
| { | |
| "key": key, | |
| "label": label, | |
| "kind": kind, | |
| "em": round(block["EM"], 2) if "EM" in block else None, | |
| "f1": round(block["F1"], 2) if "F1" in block else None, | |
| "bleu": round(block["BLEU"], 2) if "BLEU" in block else None, | |
| "rougeL": round(block["ROUGE-L"], 2) if "ROUGE-L" in block else None, | |
| } | |
| ) | |
| per_grade = [ | |
| { | |
| "label": r["Mô hình"], | |
| "grade": int(r["Lớp"]), | |
| "em": num(r["EM"]), | |
| "f1": num(r["F1"]), | |
| "bleu": num(r["BLEU"]), | |
| "rougeL": num(r["ROUGE-L"]), | |
| } | |
| for r in read_csv(root, "results/results_by_grade.csv") | |
| ] | |
| return { | |
| "models": models, | |
| "perGrade": per_grade, | |
| "counts": {"train": final["n_train"], "dev": final["n_dev"], "test": final["n_test"]}, | |
| "split": { | |
| "rowsRaw": split["rows_raw"], | |
| "rowsClean": split["rows_after_cleaning"], | |
| "contextClusters": split["context_clusters"], | |
| "uniqueContexts": split["unique_context_texts"], | |
| "seed": split["seed"], | |
| "jaccard": split["jaccard_threshold"], | |
| "leakage": split["leakage_checks"], | |
| }, | |
| } | |
| # ---------------------------------------------- testset + du doan da ghi | |
| def build_testset_and_recorded(root: Path): | |
| rows = read_csv(root, "results/du_doan_6_mo_hinh.csv") | |
| testset = [] | |
| recorded = [] | |
| for r in rows: | |
| preds = {} | |
| for key, label, _ in MODELS: | |
| preds[key] = { | |
| "answer": desegment(r.get(label)), | |
| "em": num(r.get(f"{label}_em")), | |
| "f1": num(r.get(f"{label}_f1")), | |
| } | |
| testset.append( | |
| { | |
| "id": r["id"], | |
| "grade": int(r["grade"]), | |
| "topic": r.get("topic", ""), | |
| "lesson": r.get("lesson", ""), | |
| "question": r["question"], | |
| "context": r["context"], | |
| "gold": desegment(r["gold"]), | |
| "preds": preds, | |
| "extCorrect": num(r.get("n_ext_dung")), | |
| "genF1Avg": num(r.get("gen_f1_tb")), | |
| } | |
| ) | |
| recorded.append( | |
| { | |
| "id": r["id"], | |
| "grade": r["grade"], | |
| "question": r["question"], | |
| "context": r["context"], | |
| "gold": r["gold"], | |
| "lesson": r.get("lesson", ""), | |
| "topic": r.get("topic", ""), | |
| "predictions": {label: (r.get(label) or "").strip() for label in LABELS}, | |
| "f1": {label: round(float(r[f"{label}_f1"]), 4) for label in LABELS if num(r.get(f"{label}_f1")) is not None}, | |
| } | |
| ) | |
| return testset, recorded | |
| def build_errors(root: Path): | |
| groups = {} | |
| for r in read_csv(root, "results/vi_du_phan_tich_loi.csv"): | |
| name = r["nhóm"] | |
| group = groups.setdefault(name, {"group": name, "items": []}) | |
| group["items"].append( | |
| { | |
| "id": r["id"], | |
| "grade": int(r["lớp"]), | |
| "lesson": r["bài"], | |
| "question": r["câu hỏi"], | |
| "gold": desegment(r["đáp án"]), | |
| "context": r["ngữ cảnh"], | |
| "preds": { | |
| key: {"answer": desegment(r.get(label)), "f1": num(r.get(f"{label}_F1"))} | |
| for key, label, _ in MODELS | |
| }, | |
| } | |
| ) | |
| return list(groups.values()) | |
| # -------------------------------------------------------------------- main | |
| def main() -> int: | |
| root = Path(sys.argv[1] if len(sys.argv) > 1 else HERE.parent.parent).expanduser().resolve() | |
| missing = [f for f in NEEDED if not (root / f).exists()] | |
| if missing: | |
| print(f"Khong tim thay trong {root}:") | |
| for f in missing: | |
| print(f" - {f}") | |
| print('\nChay lai voi duong dan goc, vi du:\n python build_data.py "/Volumes/MyData/paper/Thom Paper"') | |
| return 1 | |
| OUT.mkdir(exist_ok=True) | |
| print(f"Doc tu: {root}") | |
| items = build_dataset(root) | |
| testset, recorded = build_testset_and_recorded(root) | |
| write("dataset.json", items) | |
| write("facets.json", build_facets(items)) | |
| write("stats.json", build_stats(items)) | |
| write("lessons.json", build_lessons(items)) | |
| write("metrics.json", build_metrics(root)) | |
| write("testset.json", testset) | |
| write("errors.json", build_errors(root)) | |
| path = OUT / "recorded.jsonl" | |
| with path.open("w", encoding="utf-8") as fh: | |
| for row in recorded: | |
| fh.write(json.dumps(row, ensure_ascii=False) + "\n") | |
| print(f" {'recorded.jsonl':<16} {path.stat().st_size / 1024:,.0f} KB") | |
| write( | |
| "built.json", | |
| {"builtAt": datetime.now(timezone.utc).isoformat(), "source": str(root), "items": len(items)}, | |
| ) | |
| print(f"\nXong — {len(items):,} cap hoi dap, {len(testset):,} cau test.") | |
| return 0 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |