shahdAI's picture
ربط المشروع الفعلي بالـSpace (استبدال قالب Streamlit الافتراضي)
4a920c4 verified
Raw
History Blame Contribute Delete
4.45 kB
"""
قياس زمن كل جزء من 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)