File size: 2,977 Bytes
a882958
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#!/usr/bin/env python3
"""Kural tabanlı aday süzgeci (DeBERTa yok): görünür + etkileşimli etiketler + metni dolu yaygın etiketler,
TF-IDF sırasıyla en fazla K aday. pos_idx yeniden hesaplanır. Kullanım:
    python m2w_filter.py --data m2w_full_all --out m2w_v2 --K 128"""
import argparse, gzip, json, os
import numpy as np

INTER = {"a", "button", "input", "select", "textarea", "option", "label", "summary"}
EXTRA = {"li", "img", "svg", "i", "span", "div", "td", "tr", "th", "h1", "h2", "h3", "h4", "p"}


def level(c):
    """0 = görünür + etkileşimli etiket (öncelikli), 1 = görünür + metni dolu yaygın etiket, None = at."""
    b = c.get("bbox")
    if b is None or b[2] <= 0 or b[3] <= 0:
        return None
    if c["tag"] in INTER:
        return 0
    if c["tag"] in EXTRA and "|" in c["text"] and len(c["text"].split("|")[-1].strip()) > 0:
        return 1
    return None


def select(cands, K):
    """Önce seviye 0 (TF-IDF sırasıyla, en çok K), yer kalırsa seviye 1; sonra özgün TF-IDF sırasına döndür."""
    lv = [level(c) for c in cands]
    first = [i for i, l in enumerate(lv) if l == 0][:K]
    rest = [i for i, l in enumerate(lv) if l == 1][: K - len(first)]
    return sorted(first + rest)


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--data", default="m2w_full_all")
    ap.add_argument("--out", default="m2w_v2")
    ap.add_argument("--K", type=int, default=160)
    ap.add_argument("--splits", nargs="+", default=["train", "val", "test_task", "test_website", "test_domain"])
    a = ap.parse_args()
    os.makedirs(a.out, exist_ok=True)
    summ = {}
    for s in a.splits:
        p = os.path.join(a.data, f"{s}.jsonl.gz")
        if not os.path.exists(p):
            continue
        n = hit = 0
        sizes = []
        with gzip.open(p, "rt", encoding="utf-8") as f, gzip.open(os.path.join(a.out, f"{s}.jsonl.gz"), "wt", encoding="utf-8") as g:
            for l in f:
                ex = json.loads(l)
                pos = set(ex["pos_idx"])
                keep = select(ex["cands"], a.K)
                new = dict(ex)
                new["cands"] = [ex["cands"][i] for i in keep]
                new["pos_idx"] = [r for r, i in enumerate(keep) if i in pos]
                new["n_total_before"] = len(ex["cands"])
                new["dropped_pos"] = [ex["cands"][i] for i in sorted(pos) if i not in set(keep)]   # eğitimde "doğruyu ekle" için
                g.write(json.dumps(new, ensure_ascii=False) + "\n")
                n += 1; hit += len(new["pos_idx"]) > 0; sizes.append(len(keep))
        summ[s] = {"n": n, f"recall@K": hit / n, "aday_ortanca": int(np.median(sizes)), "aday_p90": int(np.percentile(sizes, 90))}
        print(f"  {s}: n={n} | doğru kalıyor (tavan)={hit/n:.3f} | aday ortanca={summ[s]['aday_ortanca']} p90={summ[s]['aday_p90']}")
    json.dump(summ, open(os.path.join(a.out, "filtre_ozet.json"), "w"), indent=2)


if __name__ == "__main__":
    main()