ldv-pilot / ldv-backend /scripts /import_datasets.py
vadhhh's picture
Upload folder using huggingface_hub
1b2d52d verified
Raw
History Blame Contribute Delete
4.23 kB
"""
scripts/import_datasets.py — Convert datasets/ CSVs into clause_training_data.csv.
Reads all clause datasets and maps their categories to MLP labels, then appends
new rows into ldv-backend/data/clause_training_data.csv, ready for train_mlp.py.
Usage
-----
cd ldv-backend
python3 scripts/import_datasets.py
Output
------
ldv-backend/data/clause_training_data.csv (appended, not overwritten)
Run train_mlp.py afterwards to retrain:
python3 scripts/train_mlp.py
Category → MLP label mapping
-----------------------------
Detection → normal
Missing → missing_mandatory
Dangerous / Abusive
Leonine / Illegal → abusive_clause
"""
from __future__ import annotations
import csv
from pathlib import Path
DATASETS_DIR = Path(__file__).parent.parent.parent / "datasets"
OUT_CSV = Path(__file__).parent.parent / "data" / "clause_training_data.csv"
# Files that have a header row
_HAS_HEADER = {
"dangerous_clauses.csv",
"contract_logic_master_sorted.csv",
"contract_logic_master .csv",
"required_clauses.csv",
}
# Column indices (0-based)
_COL_CATEGORY = 1
_COL_CLAUSE_NAME = 2
_COL_KEYWORDS = 4
# Category → MLP label
_CATEGORY_MAP: dict[str, str] = {
"detection": "normal",
"missing": "missing_mandatory",
"dangerous": "abusive_clause",
"abusive": "abusive_clause",
"leonine": "abusive_clause",
"illegal": "abusive_clause",
}
# Skip non-clause files
_SKIP_FILES = {"risk_levels.csv"}
def _rows_from_file(path: Path) -> list[tuple[str, str]]:
rows: list[tuple[str, str]] = []
has_header = path.name in _HAS_HEADER
skipped = 0
with open(path, newline="", encoding="utf-8") as f:
reader = csv.reader(f)
for i, row in enumerate(reader):
if i == 0 and has_header:
continue
if len(row) <= _COL_KEYWORDS:
skipped += 1
continue
category = row[_COL_CATEGORY].strip().lower()
clause_name = row[_COL_CLAUSE_NAME].strip()
keywords = row[_COL_KEYWORDS].strip()
label = _CATEGORY_MAP.get(category)
if not keywords or label is None:
skipped += 1
continue
text = f"{clause_name}: {keywords}" if clause_name else keywords
rows.append((text, label))
if skipped:
print(f" (skipped {skipped} rows — unknown category or empty keywords)")
return rows
def main() -> None:
OUT_CSV.parent.mkdir(parents=True, exist_ok=True)
# Load existing texts to avoid duplicates
existing: set[str] = set()
if OUT_CSV.exists() and OUT_CSV.stat().st_size > 0:
with open(OUT_CSV, newline="", encoding="utf-8") as f:
for row in csv.DictReader(f):
existing.add(row.get("text", "").strip())
new_rows: list[tuple[str, str]] = []
for csv_file in sorted(DATASETS_DIR.glob("*.csv")):
if csv_file.name in _SKIP_FILES:
continue
file_rows = _rows_from_file(csv_file)
added = [(t, l) for t, l in file_rows if t not in existing]
label_counts: dict[str, int] = {}
for _, lbl in added:
label_counts[lbl] = label_counts.get(lbl, 0) + 1
print(f" {csv_file.name}: {len(file_rows)} rows read, {len(added)} new {dict(sorted(label_counts.items()))}")
new_rows.extend(added)
existing.update(t for t, _ in added)
if not new_rows:
print("Nothing new to add.")
return
write_header = not OUT_CSV.exists() or OUT_CSV.stat().st_size == 0
with open(OUT_CSV, "a", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
if write_header:
writer.writerow(["text", "label"])
writer.writerows(new_rows)
total_by_label: dict[str, int] = {}
for _, lbl in new_rows:
total_by_label[lbl] = total_by_label.get(lbl, 0) + 1
print(f"\nAdded {len(new_rows)} rows → {OUT_CSV}")
for lbl, count in sorted(total_by_label.items()):
print(f" {lbl}: {count}")
print("\nRun 'python3 scripts/train_mlp.py' to retrain.")
if __name__ == "__main__":
main()