Spaces:
Sleeping
Sleeping
| """ | |
| التعامل مع MongoDB Atlas: تسجيل المقيّمين، حفظ التقييمات، وقراءة الإحصائيات. | |
| """ | |
| from __future__ import annotations | |
| import logging | |
| from datetime import datetime, timezone | |
| from functools import lru_cache | |
| import certifi | |
| from pymongo import MongoClient | |
| from pymongo.collection import Collection | |
| from pymongo.database import Database | |
| from app import config | |
| logger = logging.getLogger(__name__) | |
| def get_database() -> Database: | |
| if not config.MONGODB_URI: | |
| raise RuntimeError( | |
| "متغير البيئة MONGODB_URI غير مُعرَّف." | |
| ) | |
| uri = config.MONGODB_URI | |
| use_tls = "mongodb+srv" in uri.lower() | |
| kwargs = {"tlsCAFile": certifi.where()} if use_tls else {} | |
| client = MongoClient(uri, serverSelectionTimeoutMS=5000, **kwargs) | |
| client.admin.command("ping") | |
| return client[config.MONGODB_DB_NAME] | |
| def _evaluators_collection() -> Collection: | |
| return get_database()[config.EVALUATORS_COLLECTION] | |
| def _evaluations_collection() -> Collection: | |
| return get_database()[config.EVALUATIONS_COLLECTION] | |
| # ============================================================ | |
| # المقيّمون | |
| # ============================================================ | |
| def register_evaluator(name: str, email: str) -> None: | |
| """تسجيل/تحديث بيانات المقيّم (upsert حسب البريد الإلكتروني).""" | |
| _evaluators_collection().update_one( | |
| {"email": email}, | |
| { | |
| "$set": {"name": name, "email": email}, | |
| "$setOnInsert": {"created_at": datetime.now(timezone.utc)}, | |
| }, | |
| upsert=True, | |
| ) | |
| # ============================================================ | |
| # التقييمات | |
| # ============================================================ | |
| def save_evaluation( | |
| evaluator_email: str, | |
| query_definition: str, | |
| results: list[dict], | |
| ) -> None: | |
| """ | |
| حفظ نتيجة استعلام واحد مع تقييم المقيّم لكل نتيجة. | |
| شكل `results` المتوقع: | |
| [ | |
| { | |
| "word": "...", | |
| "definition": "...", | |
| "retrieval_score": 0.83, | |
| "rerank_score": 4.12, | |
| "rank": 1, | |
| "is_correct": True, | |
| }, | |
| ... | |
| ] | |
| """ | |
| _evaluations_collection().insert_one( | |
| { | |
| "evaluator_email": evaluator_email, | |
| "query_definition": query_definition, | |
| "results": results, | |
| "created_at": datetime.now(timezone.utc), | |
| } | |
| ) | |
| # ============================================================ | |
| # الإحصائيات | |
| # ============================================================ | |
| def get_stats(evaluator_email: str | None = None) -> dict: | |
| """ | |
| إحصائيات مجمَّعة: عدد الاستعلامات، عدد النتائج الصحيحة، وعدد الخاطئة. | |
| لو تم تمرير `evaluator_email`، تُحسب الإحصائيات لذلك المقيّم فقط. | |
| """ | |
| query: dict = {} | |
| if evaluator_email: | |
| query["evaluator_email"] = evaluator_email | |
| cursor = _evaluations_collection().find(query, {"results": 1}) | |
| total_queries = 0 | |
| correct = 0 | |
| incorrect = 0 | |
| for doc in cursor: | |
| total_queries += 1 | |
| for r in doc.get("results", []): | |
| if r.get("is_correct"): | |
| correct += 1 | |
| else: | |
| incorrect += 1 | |
| return { | |
| "total_queries": total_queries, | |
| "correct": correct, | |
| "incorrect": incorrect, | |
| } | |
| # ============================================================ | |
| # سجلّ الاستعلامات | |
| # ============================================================ | |
| def log_search(query: str, path: str, results: list[dict]) -> None: | |
| """ | |
| يُخزِّن سجل بحث بعد ظهور النتائج للمستخدم مباشرة. | |
| path: "ROOT" أو "DEFINITION" | |
| results: قائمة بالنتائج الظاهرة فعلاً للمستخدم، كل عنصر: | |
| {"rank": int, "word": str, "definition": str} | |
| يعمل بصمت — لو فشل الاتصال بـMongoDB لا يوقف التطبيق. | |
| """ | |
| try: | |
| db = get_database() | |
| db["search_logs"].insert_one({ | |
| "timestamp": datetime.now(timezone.utc), | |
| "query": query, | |
| "path": path, | |
| "results": results, | |
| }) | |
| except Exception as exc: | |
| logger.warning("MongoDB log_search failed: %s", exc) | |