Spaces:
Sleeping
Sleeping
| """ | |
| قياس زمن كل جزء من 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) | |