File size: 6,485 Bytes
5b10376
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""exposure_analysis.py — «تعرّض فعلي» لا «توافر»:
يعيد تشغيل build_examples بنفس البذرة (13) وعبر قائمة المجمّع الأصلية (pairs.jsonl من
مخرجات النواة) لتحديد الأزواج التي دخلت أمثلة التدريب فعلًا، ثم يقارنها بعناصر التقييم.

تحقق سلامة إعادة البناء: عدد النصوص الفريدة (md5) يجب أن يطابق feat_cache_300000.npz
المُنتَج وقت التدريب نفسه (إن تطابق ⇒ إعادة البناء مطابقة حرفيًا)."""
import os, sys, json, time, random, hashlib
import numpy as np
sys.path.insert(0, "/home/user/lhc/code"); sys.path.insert(0, "/home/user/lhc/recon")

T0=time.time()
def log(*a): print(f"[{time.time()-T0:6.1f}s]", *a, flush=True)
W4="/var/tmp/lhc_w4"
N_EXAMPLES=300000; SEED=13

# --- نفس الاستيرادات التي يستخدمها build_examples الأصلي ---
from phase_c_augment import augment
from phase_p2_slot import make_sibling, novel_view
from phase_s_scale import make_scaled_corpus
kb=json.load(open("/home/user/lhc/code/knowledge_bank_superbrain.json", encoding="utf-8"))
kb_prompts=[e["prompt"] for e in kb]
synth=kb_prompts+[e["prompt"] for e in make_scaled_corpus(3000, seed=0)]
NS=len(synth)
# عدّ أسطر pairs.jsonl
with open(f"{W4}/pairs.jsonl","rb") as f:
    n_pairs=sum(1 for _ in f)
log(f"pairs.jsonl: {n_pairs:,} زوجًا | len(synth)={NS}")

# --- (أ) إعادة تشغيل RNG فقط لتحديد الفهارس ---
rng=random.Random(SEED)
par_idx=[]; mono_idx=[]; branch_counts={"par":0,"mono_pair":0,"mono_synth":0,"slot":0,"prot":0}
for i in range(N_EXAMPLES):
    r=rng.random()
    if r<0.40:
        p_i=rng.randrange(n_pairs); par_idx.append(p_i); branch_counts["par"]+=1
    elif r<0.65:
        if rng.random()<0.5:
            p_i=rng.randrange(n_pairs); rng.choice(("en","ar")); mono_idx.append(p_i); branch_counts["mono_pair"]+=1
        else:
            rng.randrange(NS); branch_counts["mono_synth"]+=1
    elif r<0.85:
        rng.randrange(NS); branch_counts["slot"]+=1
    else:
        rng.randrange(NS); branch_counts["prot"]+=1
log(f"الفروع: {branch_counts} | فهارس الأزواج: {len(par_idx):,} + {len(mono_idx):,}")

# --- (ب) استخراج نصوص الفهارس المطلوبة من pairs.jsonl (جولة واحدة) ---
need=set(par_idx)|set(mono_idx)
texts={}
with open(f"{W4}/pairs.jsonl", encoding="utf-8") as f:
    for i,line in enumerate(f):
        if i in need:
            o=json.loads(line); texts[i]=(o.get("ar",""),o.get("en",""))
log(f"استُخرج {len(texts):,} زوجًا نصيًا")

# --- (ج) بناء مجموعات نصوص التعرّض ---
def h(s): return hashlib.md5(s.encode()).hexdigest()
exact_ar=set(); exact_en=set(); mono_ar=set(); mono_en=set()
for i in par_idx:
    a,e=texts[i]; exact_ar.add(h(a)); exact_en.add(h(e))
# للفرع الأحادي: النص الخام يُغذّى إلى augment() — تعرّض «مشتق» (نحتفظ بالنص الخام للمقارنة)
for i in mono_idx:
    a,e=texts[i]
    mono_ar.add(h(a)); mono_en.add(h(e))
log(f"نصوص تعرّض صريح: ar={len(exact_ar):,} en={len(exact_en):,} | مشتق: +ar={len(mono_ar-exact_ar):,} +en={len(mono_en-exact_en):,}")

# --- (د) العناصر المُقيَّمة: كم منها مُتعرَّض فعلًا؟ ---
sys.path.insert(0,"/home/user/lhc/recon")
exec(open('/home/user/lhc/recon/build_masks_stream.py').read().split('# ---------------- مجموعات التقييم')[0])
from phase_w1_data import download_corpus
DD="/home/user/lhc/data/opus"
OPUS=[("Tanzil","https://object.pouta.csc.fi/OPUS-Tanzil/v1/moses/ar-en.txt.zip",20000),
      ("Bible","https://object.pouta.csc.fi/OPUS-bible-uedin/v1/moses/ar-en.txt.zip",20000),
      ("NeuLab-TED","https://object.pouta.csc.fi/OPUS-NeuLab-TedTalks/v1/moses/ar-en.txt.zip",20000)]
pairs={}
for name,url,lim in OPUS: pairs[name]=download_corpus(name,url,lim,DD)
DEV="/home/user/lhc/data/flores101_dataset/devtest"
ld=lambda p:[l.strip() for l in open(p,encoding="utf-8") if l.strip()]
pairs["FLORES"]=[{"ar":a,"en":e} for a,e in zip(ld(f"{DEV}/ara.devtest"),ld(f"{DEV}/eng.devtest"))]

M=json.load(open("/home/user/lhc/results/masks_v2.json"))
def norm_h(side, s):
    return h(norm_ar(s) if side=="ar" else norm_en(s))
# مجموعات مُطبَّعة للتعرّض (بمقارنة مُطبَّعة — أدق للاختلافات الشكلية)
nsexact_ar={norm_h("ar",texts[i][0]) for i in par_idx}
nsexact_en={norm_h("en",texts[i][1]) for i in par_idx}
nsmono_ar={norm_h("ar",texts[i][0]) for i in mono_idx}
nsmono_en={norm_h("en",texts[i][1]) for i in mono_idx}

report={"pairs_in_pool":n_pairs,"n_examples":N_EXAMPLES,"branch_counts":branch_counts,
        "n_par_pairs":len(par_idx),"n_mono_pairs":len(mono_idx),
        "sets":{}}
for cn,ps in pairs.items():
    n=len(ps)
    avail=set(M["masks_strong"][cn])
    ex=0; ex_ar=0; ex_en=0; dv=0
    for i,p in enumerate(ps):
        ha=norm_h("ar",p["ar"]); he=norm_h("en",p["en"])
        a_in = ha in nsexact_ar; e_in = he in nsexact_en
        a_m  = ha in nsmono_ar;  e_m  = he in nsmono_en
        hit_exact = a_in or e_in
        hit_deriv = (a_m or e_m)
        if hit_exact: ex+=1
        if a_in: ex_ar+=1
        if e_in: ex_en+=1
        if hit_exact or hit_deriv: dv+=1
    report["sets"][cn]={"n":n,"available_mask":len(avail),
        "exposed_exact":ex,"exposed_exact_ar":ex_ar,"exposed_exact_en":ex_en,
        "exposed_exact_or_derived":dv,
        "exposure_rate_pct":round(100*ex/n,3),
        "availability_rate_pct":round(100*len(avail)/n,3),
        "exposure_over_availability":round(ex/max(1,len(avail)),3) if avail else None}
    log(f"{cn:12s} توافر={len(avail):>5} ({100*len(avail)/n:.2f}%) → تعرّض صريح={ex:>5} ({100*ex/n:.3f}%) | +مشتق={dv:>5}")

# --- (هـ) تحقق feat_cache (عدد النصوص الفريدة) ---
fc=np.load(f"{W4}/feat_cache.npz")
report["feat_cache"]={"n_texts":int(fc["n_texts"]),"rows_shape":list(fc["rows"].shape),
                      "example_texts_slots":int(fc["rows"].shape[0])}
log(f"feat_cache: n_texts={int(fc['n_texts']):,} rows={fc['rows'].shape}")
json.dump(report, open("/home/user/lhc/results/exposure_analysis.json","w"), ensure_ascii=False, indent=1)
log("SAVED results/exposure_analysis.json")