File size: 4,452 Bytes
4a920c4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
قياس زمن كل جزء من pipeline البحث + مقارنة كاشف النية (محلي مقابل Groq API).
الاستخدام:
    PYTHONPATH=. .venv/bin/python scripts/benchmark.py
    PYTHONPATH=. .venv/bin/python scripts/benchmark.py "صوت الرعد" "جذر كلمة هزيم"
"""

import os
import sys
import time

QUERIES = sys.argv[1:] or [
    "صوت يصدر عن السحاب",
    "جذر كلمة هزيم",
    "شخص يحب القراءة",
]

SEP = "─" * 52
DSEP = "═" * 52


def ms(seconds: float) -> str:
    return f"{seconds * 1000:.0f} ms"


def benchmark(query: str) -> dict:
    from app.intent_detector import detect_intent, detect_intent_groq

    print(f"\n{SEP}")
    print(f"  الاستعلام: {query}")
    print(SEP)

    # 1. Intent Detection — مقارنة الطريقتين
    t0 = time.perf_counter()
    local_result = detect_intent(query)
    t_local = time.perf_counter() - t0

    t0 = time.perf_counter()
    groq_result = detect_intent_groq(query)
    t_groq = time.perf_counter() - t0

    groq_error = groq_result["intent"] == "ERROR"
    match = (not groq_error) and local_result["intent"] == groq_result["intent"]

    print("  1. Intent Detection")
    print(f"     محلي (Embeddings):    {ms(t_local):>8}{local_result}")
    if groq_error:
        print(f"     Groq API:             تعذّر       → {groq_result['word']}")
    else:
        print(f"     Groq API:             {ms(t_groq):>8}{groq_result}")
    print(f"     متطابقان؟ {'✓' if match else '✗'}")

    # يكمل الـ pipeline بناءً على النتيجة المحلية فقط (سلوك التطبيق لا يتغير)
    intent_result = local_result

    if intent_result["intent"] == "ROOT":
        from app.root_search import search_root
        t0 = time.perf_counter()
        root = search_root(intent_result["word"] or query, db=None)
        t_root = time.perf_counter() - t0
        print(f"  2. Root Search (lexicon)     {ms(t_root):>10}")
        print(f"     → {root.get('type')} | {root.get('stem', '—')}")
        print(f"{SEP}")
        print(f"  الإجمالي (محلي)              {ms(t_local + t_root):>10}")

    else:
        from app.search import get_searcher
        searcher = get_searcher()
        t0 = time.perf_counter()
        candidates = searcher.search(query)
        t_faiss = time.perf_counter() - t0
        print(f"  2. FAISS Search              {ms(t_faiss):>10}  ({len(candidates)} نتيجة)")

        from app.reranker import get_reranker
        reranker = get_reranker()
        t0 = time.perf_counter()
        results = reranker.rerank(query, candidates)
        t_rerank = time.perf_counter() - t0
        print(f"  3. Reranker (BGE)            {ms(t_rerank):>10}  ({len(results)} نتيجة)")

        total = t_local + t_faiss + t_rerank
        print(f"{SEP}")
        print(f"  الإجمالي (محلي)              {ms(total):>10}")
        print(f"  أفضل نتيجة: {results[0].word if results else '—'}")

    print(SEP)

    return {"t_local": t_local, "t_groq": t_groq, "match": match, "groq_error": groq_error}


if __name__ == "__main__":
    print("\n⏳ تحميل النماذج (مرة واحدة فقط)...")
    load_start = time.perf_counter()
    from app.search import get_searcher
    from app.reranker import get_reranker
    get_searcher()
    get_reranker()
    print(f"✅ جاهز ({ms(time.perf_counter() - load_start)})\n")

    if not os.getenv("GROQ_API_KEY", "").strip():
        print("⚠️  تحذير: GROQ_API_KEY غير موجود في .env — نتائج Groq ستظهر كأخطاء أدناه.\n")

    stats = [benchmark(q) for q in QUERIES]

    valid = [s for s in stats if not s["groq_error"]]
    matches = sum(1 for s in valid if s["match"])
    avg_local = sum(s["t_local"] for s in stats) / len(stats)
    avg_groq = sum(s["t_groq"] for s in valid) / len(valid) if valid else 0

    print(f"\n{DSEP}")
    print("  ملخص المقارنة")
    print(DSEP)
    print(f"  عدد الاستعلامات:             {len(stats)}")
    print(f"  تطابق التصنيف:               {matches}/{len(valid)}" + ("  (0 بسبب فشل Groq)" if not valid else ""))
    print(f"  متوسط الزمن — محلي:          {ms(avg_local)}")
    print(f"  متوسط الزمن — Groq:          {ms(avg_groq) if valid else '—'}")
    print(DSEP)