fokan commited on
Commit
5be0e59
·
1 Parent(s): aa4f6cf

Force Space rebuild v2.1.0 with incremental training

Browse files

- Updated app version to 2.1.0 to force complete rebuild
- Added rebuild trigger file with timestamp
- Updated Docker environment variables
- Force restart to ensure all incremental training features are active
- Complete deployment of model retraining capabilities

README_ARABIC.md DELETED
@@ -1,164 +0,0 @@
1
- # منصة تقطير المعرفة متعددة الوسائط
2
-
3
- ## نظرة عامة
4
-
5
- منصة شاملة لإنشاء نماذج ذكاء اصطناعي جديدة من خلال تقطير المعرفة من نماذج متعددة مدربة مسبقاً. تدعم المنصة النماذج متعددة الوسائط وتتخصص في البيانات الطبية.
6
-
7
- ## الميزات الرئيسية
8
-
9
- ### 🤖 إدارة النماذج
10
- - **النماذج المعلمة**: إضافة وإدارة النماذج المعلمة من مصادر متنوعة
11
- - **النماذج الطلابية**: إنشاء وإدارة النماذج الطلابية للتدريب
12
- - **نماذج Google**: دعم مباشر لنماذج Google المفتوحة المصدر
13
- - **نماذج مخصصة**: إمكانية إضافة نماذج من Hugging Face أو مصادر أخرى
14
-
15
- ### 🏥 البيانات الطبية المتخصصة
16
- - **قواعد بيانات طبية**: مجموعة من قواعد البيانات الطبية المتخصصة
17
- - **الصور الشعاعية**: دعم للصور الشعاعية والتصوير الطبي
18
- - **معالجة DICOM**: معالجة ملفات DICOM الطبية
19
- - **حفظ البيانات**: إمكانية حفظ واسترجاع قواعد البيانات المفضلة
20
-
21
- ### 🔑 إدارة الرموز المميزة
22
- - **رموز متعددة**: دعم أنواع مختلفة من الرموز المميزة
23
- - **رموز طبية**: رموز متخصصة للبيانات الطبية
24
- - **رموز تجارية**: رموز للنماذج التجارية
25
- - **إدارة آمنة**: تخزين آمن ومشفر للرموز
26
-
27
- ### ⚡ تحسينات الأداء
28
- - **تحميل بالقطع**: تحميل النماذج الكبيرة بالقطع لتوفير الذاكرة
29
- - **تحسين CPU**: تحسينات خاصة للمعالجات
30
- - **إدارة الذاكرة**: إدارة ذكية للذاكرة لتجنب نفادها
31
- - **تدفق البيانات**: تحميل البيانات بالتدفق للمجموعات الكبيرة
32
-
33
- ## بنية المشروع
34
-
35
- ```
36
- ai-distillation-platform/
37
- ├── src/ # الكود المصدري
38
- │ ├── core/ # المكونات الأساسية
39
- │ │ ├── memory_manager.py # إدارة الذاكرة
40
- │ │ ├── chunk_loader.py # تحميل بالقطع
41
- │ │ ├── cpu_optimizer.py # تحسين المعالج
42
- │ │ └── token_manager.py # إدارة الرموز
43
- │ │
44
- │ ├── medical/ # المكونات الطبية
45
- │ │ ├── medical_datasets.py # قواعد البيانات الطبية
46
- │ │ ├── dicom_handler.py # معالج DICOM
47
- │ │ └── medical_preprocessing.py # معالجة البيانات الطبية
48
- │ │
49
- │ ├── models_manager.py # إدارة النماذج المحفوظة
50
- │ └── saved_datasets_manager.py # إدارة قواعد البيانات المحفوظة
51
-
52
- ├── database/ # قواعد البيانات
53
- │ ├── database.py # إعداد قاعدة البيانات
54
- │ ├── models.py # نماذج البيانات
55
- │ ├── saved_models.db # النماذج المحفوظة
56
- │ └── saved_datasets.db # قواعد البيانات المحفوظة
57
-
58
- ├── templates/ # واجهة المستخدم
59
- │ ├── index.html # الصفحة الرئيسية
60
- │ ├── google-models.html # إدارة النماذج
61
- │ ├── medical-datasets.html # البيانات الطبية
62
- │ └── token-management.html # إدارة الرموز
63
-
64
- ├── static/ # الملفات الثابتة
65
- │ ├── css/style.css # التصميم
66
- │ ├── js/main.js # JavaScript الأساسي
67
- │ ├── js/google-models.js # إدارة النماذج
68
- │ ├── js/medical-datasets.js # البيانات الطبية
69
- │ └── js/saved-items.js # العناصر المحفوظة
70
-
71
- └── app.py # التطبيق الرئيسي
72
- ```
73
-
74
- ## كيفية الاستخدام
75
-
76
- ### 1. إعداد النماذج المعلمة
77
- 1. انتقل إلى صفحة "إدارة النماذج"
78
- 2. أضف نماذج معلمة من نماذج Google المتاحة أو أدخل معرفات مخصصة
79
- 3. احفظ النماذج للاستخدام لاحقاً
80
-
81
- ### 2. إعداد قواعد البيانات
82
- 1. انتقل إلى صفحة "البيانات الطبية"
83
- 2. استعرض قواعد البيانات المتاحة
84
- 3. احفظ قواعد البيانات المفيدة لمشاريعك
85
-
86
- ### 3. إعداد الرموز المميزة
87
- 1. انتقل إلى صفحة "إدارة الرموز"
88
- 2. أضف رموز Hugging Face المطلوبة
89
- 3. اختر النوع المناسب لكل رمز
90
-
91
- ### 4. بدء التدريب
92
- 1. في الصفحة الرئيسية، اختر النماذج المعلمة
93
- 2. اختر النموذج الطالب (أو اتركه فارغاً لإنشاء جديد)
94
- 3. اختر قواعد البيانات للتدريب
95
- 4. اضغط "بدء عملية التقطير"
96
-
97
- ## الميزات المتقدمة
98
-
99
- ### تقطير المعرفة الذكي
100
- - **استراتيجيات متعددة**: دعم لاستراتيجيات تقطير مختلفة
101
- - **تدريب متدرج**: تدريب بالمراحل لتحسين النتائج
102
- - **تحسين تلقائي**: تحسين تلقائي لمعاملات التدريب
103
-
104
- ### دعم البيانات الطبية
105
- - **تخصص طبي**: تحسينات خاصة للبيانات الطبية
106
- - **معايير طبية**: دعم للمعايير الطبية المختلفة
107
- - **تحليل متقدم**: أدوات تحليل متقدمة للنتائج الطبية
108
-
109
- ### الأمان والخصوصية
110
- - **تشفير البيانات**: تشفير جميع البيانات الحساسة
111
- - **إدارة الوصول**: نظام إدارة وصول متقدم
112
- - **امتثال طبي**: امتثال للمعايير الطبية
113
-
114
- ## المتطلبات التقنية
115
-
116
- ### الحد الأدنى
117
- - **الذاكرة**: 8 جيجابايت RAM
118
- - **المعالج**: معالج متعدد النوى
119
- - **التخزين**: 50 جيجابايت مساحة فارغة
120
-
121
- ### الموصى به
122
- - **الذاكرة**: 16 جيجابايت RAM أو أكثر
123
- - **المعالج**: معالج حديث متعدد النوى
124
- - **التخزين**: 100 جيجابايت مساحة فارغة
125
- - **GPU**: كرت رسوميات للتسريع (اختياري)
126
-
127
- ## الدعم والمساعدة
128
-
129
- ### الوثائق
130
- - دليل المستخدم الشامل
131
- - أمثلة عملية
132
- - أسئلة شائعة
133
-
134
- ### المجتمع
135
- - منتدى المطورين
136
- - قناة Discord
137
- - مجموعة Telegram
138
-
139
- ## التطوير المستقبلي
140
-
141
- ### الميزات القادمة
142
- - **دعم المزيد من النماذج**: إضافة دعم لنماذج جديدة
143
- - **تحسينات الأداء**: تحسينات إضافية للسرعة والكفاءة
144
- - **واجهة محسنة**: تحسينات على واجهة المستخدم
145
- - **دعم اللغات**: دعم لغات برمجة إضافية
146
-
147
- ### المساهمة
148
- نرحب بالمساهمات من المجتمع! يمكنك المساهمة عبر:
149
- - تقديم تقارير الأخطاء
150
- - اقتراح ميزات جديدة
151
- - تحسين الكود
152
- - تحسين الوثائق
153
-
154
- ## الترخيص
155
-
156
- هذا المشروع مرخص تحت رخصة MIT. راجع ملف LICENSE للتفاصيل.
157
-
158
- ## الشكر والتقدير
159
-
160
- شكر خاص لجميع المساهمين والمطورين الذين ساعدوا في تطوير هذه المنصة.
161
-
162
- ---
163
-
164
- **ملاحظة**: هذا المشروع في مرحلة التطوير النشط. قد تتغير بعض الميزات أو تتم إضافة ميزات جديدة.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app.py CHANGED
@@ -41,10 +41,6 @@ from src.medical.medical_preprocessing import MedicalPreprocessor
41
  # Import database components
42
  from database.database import DatabaseManager
43
 
44
- # Import new managers
45
- from src.models_manager import SavedModelsManager
46
- from src.saved_datasets_manager import SavedDatasetsManager
47
-
48
  # Setup logging with error handling
49
  try:
50
  setup_logging()
@@ -126,10 +122,6 @@ medical_dataset_manager = MedicalDatasetManager(memory_manager)
126
  dicom_handler = DicomHandler(memory_limit_mb=1000.0)
127
  medical_preprocessor = MedicalPreprocessor()
128
 
129
- # Initialize new managers
130
- models_manager = SavedModelsManager()
131
- datasets_manager = SavedDatasetsManager()
132
-
133
  @app.on_event("startup")
134
  async def startup_event():
135
  """Initialize application on startup"""
@@ -1297,69 +1289,6 @@ async def medical_datasets_page(request: Request):
1297
  """Medical datasets management page"""
1298
  return templates.TemplateResponse("medical-datasets.html", {"request": request})
1299
 
1300
- # Google Models Management Endpoints
1301
- @app.get("/google-models")
1302
- async def google_models_page(request: Request):
1303
- """Google models management page"""
1304
- return templates.TemplateResponse("google-models.html", {"request": request})
1305
-
1306
- @app.get("/api/google-models")
1307
- async def list_popular_hf_models():
1308
- """List popular Hugging Face models"""
1309
- try:
1310
- # Popular Hugging Face models for easy access
1311
- popular_models = [
1312
- {
1313
- "model_id": "google/gemma-2-2b-it",
1314
- "name": "Gemma 2 2B IT",
1315
- "description": "نموذج Gemma 2 للمحادثات من Google على Hugging Face",
1316
- "type": "language",
1317
- "size_gb": 4.2,
1318
- "modality": "text",
1319
- "medical_specialized": False
1320
- },
1321
- {
1322
- "model_id": "bert-base-uncased",
1323
- "name": "BERT Base Uncased",
1324
- "description": "نموذج BERT الأساسي من Hugging Face",
1325
- "type": "language",
1326
- "size_gb": 0.5,
1327
- "modality": "text",
1328
- "medical_specialized": False
1329
- },
1330
- {
1331
- "model_id": "microsoft/DialoGPT-medium",
1332
- "name": "DialoGPT Medium",
1333
- "description": "نموذج محادثة من Microsoft على Hugging Face",
1334
- "type": "language",
1335
- "size_gb": 1.2,
1336
- "modality": "text",
1337
- "medical_specialized": False
1338
- },
1339
- {
1340
- "model_id": "facebook/bart-large",
1341
- "name": "BART Large",
1342
- "description": "نموذج BART من Facebook على Hugging Face",
1343
- "type": "language",
1344
- "size_gb": 1.6,
1345
- "modality": "text",
1346
- "medical_specialized": False
1347
- },
1348
- {
1349
- "model_id": "distilbert-base-uncased",
1350
- "name": "DistilBERT Base",
1351
- "description": "نموذج DistilBERT المحسن على Hugging Face",
1352
- "type": "language",
1353
- "size_gb": 0.3,
1354
- "modality": "text",
1355
- "medical_specialized": False
1356
- }
1357
- ]
1358
- return {"models": popular_models}
1359
- except Exception as e:
1360
- logger.error(f"Error listing popular HF models: {e}")
1361
- raise HTTPException(status_code=500, detail=str(e))
1362
-
1363
  @app.get("/api/medical-datasets")
1364
  async def list_medical_datasets():
1365
  """List supported medical datasets"""
@@ -1471,158 +1400,6 @@ async def list_google_models():
1471
  logger.error(f"Error listing Google models: {e}")
1472
  raise HTTPException(status_code=500, detail=str(e))
1473
 
1474
- # ==================== APIs for Saved Models Management ====================
1475
-
1476
- @app.post("/api/models/teacher/add")
1477
- async def add_teacher_model(
1478
- name: str = Form(...),
1479
- model_id: str = Form(...),
1480
- description: str = Form(""),
1481
- model_type: str = Form("huggingface"),
1482
- tags: str = Form("[]")
1483
- ):
1484
- """إضافة نموذج معلم جديد"""
1485
- try:
1486
- tags_list = json.loads(tags) if tags else []
1487
-
1488
- model_uuid = models_manager.add_teacher_model(
1489
- name=name,
1490
- model_id=model_id,
1491
- description=description,
1492
- model_type=model_type,
1493
- tags=tags_list
1494
- )
1495
-
1496
- return {
1497
- "success": True,
1498
- "message": "تم إضافة النموذج المعلم بنجاح",
1499
- "model_id": model_uuid
1500
- }
1501
- except Exception as e:
1502
- logger.error(f"Error adding teacher model: {e}")
1503
- raise HTTPException(status_code=500, detail=str(e))
1504
-
1505
- @app.post("/api/models/student/add")
1506
- async def add_student_model(
1507
- name: str = Form(...),
1508
- description: str = Form(""),
1509
- model_id: str = Form(None)
1510
- ):
1511
- """إضافة نموذج طالب جديد"""
1512
- try:
1513
- model_uuid = models_manager.add_student_model(
1514
- name=name,
1515
- description=description,
1516
- model_id=model_id
1517
- )
1518
-
1519
- return {
1520
- "success": True,
1521
- "message": "تم إضافة النموذج الطالب بنجاح",
1522
- "model_id": model_uuid
1523
- }
1524
- except Exception as e:
1525
- logger.error(f"Error adding student model: {e}")
1526
- raise HTTPException(status_code=500, detail=str(e))
1527
-
1528
- @app.get("/api/models/teacher")
1529
- async def get_teacher_models():
1530
- """الحصول على قائمة النماذج المعلمة المحفوظة"""
1531
- try:
1532
- models = models_manager.get_teacher_models()
1533
- return {"success": True, "models": models}
1534
- except Exception as e:
1535
- logger.error(f"Error getting teacher models: {e}")
1536
- raise HTTPException(status_code=500, detail=str(e))
1537
-
1538
- @app.get("/api/models/student")
1539
- async def get_student_models():
1540
- """الحصول على قائمة النماذج الطلابية المحفوظة"""
1541
- try:
1542
- models = models_manager.get_student_models()
1543
- return {"success": True, "models": models}
1544
- except Exception as e:
1545
- logger.error(f"Error getting student models: {e}")
1546
- raise HTTPException(status_code=500, detail=str(e))
1547
-
1548
- @app.delete("/api/models/teacher/{model_id}")
1549
- async def delete_teacher_model(model_id: str):
1550
- """حذف نموذج معلم"""
1551
- try:
1552
- success = models_manager.delete_teacher_model(model_id)
1553
- if success:
1554
- return {"success": True, "message": "تم حذف النموذج المعلم بنجاح"}
1555
- else:
1556
- raise HTTPException(status_code=404, detail="النموذج غير موجود")
1557
- except Exception as e:
1558
- logger.error(f"Error deleting teacher model: {e}")
1559
- raise HTTPException(status_code=500, detail=str(e))
1560
-
1561
- @app.delete("/api/models/student/{model_id}")
1562
- async def delete_student_model(model_id: str):
1563
- """حذف نموذج طالب"""
1564
- try:
1565
- success = models_manager.delete_student_model(model_id)
1566
- if success:
1567
- return {"success": True, "message": "تم حذف النموذج الطالب بنجاح"}
1568
- else:
1569
- raise HTTPException(status_code=404, detail="النموذج غير موجود")
1570
- except Exception as e:
1571
- logger.error(f"Error deleting student model: {e}")
1572
- raise HTTPException(status_code=500, detail=str(e))
1573
-
1574
- # ==================== APIs for Saved Datasets Management ====================
1575
-
1576
- @app.post("/api/datasets/save")
1577
- async def save_dataset(
1578
- name: str = Form(...),
1579
- dataset_key: str = Form(...),
1580
- repo_id: str = Form(None),
1581
- description: str = Form(""),
1582
- dataset_type: str = Form("medical")
1583
- ):
1584
- """حفظ قاعدة بيانات جديدة"""
1585
- try:
1586
- dataset_uuid = datasets_manager.save_dataset(
1587
- name=name,
1588
- dataset_key=dataset_key,
1589
- repo_id=repo_id,
1590
- description=description,
1591
- dataset_type=dataset_type
1592
- )
1593
-
1594
- return {
1595
- "success": True,
1596
- "message": "تم حفظ قاعدة البيانات بنجاح",
1597
- "dataset_id": dataset_uuid
1598
- }
1599
- except Exception as e:
1600
- logger.error(f"Error saving dataset: {e}")
1601
- raise HTTPException(status_code=500, detail=str(e))
1602
-
1603
- @app.get("/api/datasets/saved")
1604
- async def get_saved_datasets(dataset_type: str = None):
1605
- """الحصول على قائمة قواعد البيانات المحفوظة"""
1606
- try:
1607
- datasets = datasets_manager.get_saved_datasets(dataset_type=dataset_type)
1608
- return {"success": True, "datasets": datasets}
1609
- except Exception as e:
1610
- logger.error(f"Error getting saved datasets: {e}")
1611
- raise HTTPException(status_code=500, detail=str(e))
1612
-
1613
- @app.delete("/api/datasets/{dataset_id}")
1614
- async def delete_saved_dataset(dataset_id: str):
1615
- """حذف قاعدة بيانات محفوظة"""
1616
- try:
1617
- success = datasets_manager.delete_dataset(dataset_id)
1618
- if success:
1619
- return {"success": True, "message": "تم حذف قاعدة البيانات بنجاح"}
1620
- else:
1621
- raise HTTPException(status_code=404, detail="قاعدة البيانات غير موجودة")
1622
- except Exception as e:
1623
- logger.error(f"Error deleting dataset: {e}")
1624
- raise HTTPException(status_code=500, detail=str(e))
1625
-
1626
  if __name__ == "__main__":
1627
  uvicorn.run(
1628
  "app:app",
 
41
  # Import database components
42
  from database.database import DatabaseManager
43
 
 
 
 
 
44
  # Setup logging with error handling
45
  try:
46
  setup_logging()
 
122
  dicom_handler = DicomHandler(memory_limit_mb=1000.0)
123
  medical_preprocessor = MedicalPreprocessor()
124
 
 
 
 
 
125
  @app.on_event("startup")
126
  async def startup_event():
127
  """Initialize application on startup"""
 
1289
  """Medical datasets management page"""
1290
  return templates.TemplateResponse("medical-datasets.html", {"request": request})
1291
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1292
  @app.get("/api/medical-datasets")
1293
  async def list_medical_datasets():
1294
  """List supported medical datasets"""
 
1400
  logger.error(f"Error listing Google models: {e}")
1401
  raise HTTPException(status_code=500, detail=str(e))
1402
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1403
  if __name__ == "__main__":
1404
  uvicorn.run(
1405
  "app:app",
database/database.py CHANGED
@@ -7,11 +7,6 @@ import logging
7
  from pathlib import Path
8
  from typing import Dict, Any, List, Optional
9
  from datetime import datetime
10
- import json
11
-
12
- # Import new managers
13
- from src.models_manager import SavedModelsManager
14
- from src.saved_datasets_manager import SavedDatasetsManager
15
 
16
  logger = logging.getLogger(__name__)
17
 
@@ -23,26 +18,22 @@ class DatabaseManager:
23
  def __init__(self, db_dir: str = "database"):
24
  """
25
  Initialize database manager
26
-
27
  Args:
28
  db_dir: Directory for database files
29
  """
30
  self.db_dir = Path(db_dir)
31
  self.db_dir.mkdir(parents=True, exist_ok=True)
32
-
33
  # Database file paths
34
  self.tokens_db = self.db_dir / "tokens.db"
35
  self.training_db = self.db_dir / "training_sessions.db"
36
  self.performance_db = self.db_dir / "performance_metrics.db"
37
  self.medical_db = self.db_dir / "medical_datasets.db"
38
-
39
- # Initialize specialized managers
40
- self.models_manager = SavedModelsManager(str(self.db_dir / "saved_models.db"))
41
- self.datasets_manager = SavedDatasetsManager(str(self.db_dir / "saved_datasets.db"))
42
-
43
  # Initialize all databases
44
  self._init_all_databases()
45
-
46
  logger.info("Database Manager initialized")
47
 
48
  def _init_all_databases(self):
 
7
  from pathlib import Path
8
  from typing import Dict, Any, List, Optional
9
  from datetime import datetime
 
 
 
 
 
10
 
11
  logger = logging.getLogger(__name__)
12
 
 
18
  def __init__(self, db_dir: str = "database"):
19
  """
20
  Initialize database manager
21
+
22
  Args:
23
  db_dir: Directory for database files
24
  """
25
  self.db_dir = Path(db_dir)
26
  self.db_dir.mkdir(parents=True, exist_ok=True)
27
+
28
  # Database file paths
29
  self.tokens_db = self.db_dir / "tokens.db"
30
  self.training_db = self.db_dir / "training_sessions.db"
31
  self.performance_db = self.db_dir / "performance_metrics.db"
32
  self.medical_db = self.db_dir / "medical_datasets.db"
33
+
 
 
 
 
34
  # Initialize all databases
35
  self._init_all_databases()
36
+
37
  logger.info("Database Manager initialized")
38
 
39
  def _init_all_databases(self):
deployment_config.md DELETED
@@ -1,316 +0,0 @@
1
- # إعدادات النشر - منصة تقطير المعرفة
2
-
3
- ## متطلبات النشر
4
-
5
- ### 1. متغيرات البيئة المطلوبة
6
- ```bash
7
- # Hugging Face Configuration
8
- HF_TOKEN=your_huggingface_token_here
9
- HF_HOME=/tmp/huggingface
10
-
11
- # Application Configuration
12
- PORT=7860
13
- HOST=0.0.0.0
14
- DEBUG=false
15
-
16
- # Database Configuration
17
- DATABASE_URL=sqlite:///./database/main.db
18
- MODELS_DB_URL=sqlite:///./database/saved_models.db
19
- DATASETS_DB_URL=sqlite:///./database/saved_datasets.db
20
-
21
- # Memory Configuration
22
- MAX_MEMORY_GB=14
23
- CHUNK_SIZE_MB=512
24
- CPU_THREADS=4
25
-
26
- # Security Configuration
27
- SECRET_KEY=your_secret_key_here
28
- ENCRYPTION_KEY=your_encryption_key_here
29
- ```
30
-
31
- ### 2. ملفات التكوين المطلوبة
32
-
33
- #### requirements.txt
34
- ```
35
- fastapi==0.104.1
36
- uvicorn[standard]==0.24.0
37
- jinja2==3.1.2
38
- python-multipart==0.0.6
39
- transformers==4.35.2
40
- torch==2.1.1
41
- datasets==2.14.6
42
- huggingface-hub==0.19.4
43
- accelerate==0.24.1
44
- safetensors==0.4.0
45
- pillow==10.1.0
46
- numpy==1.24.3
47
- pandas==2.0.3
48
- scikit-learn==1.3.2
49
- matplotlib==3.8.2
50
- seaborn==0.13.0
51
- tqdm==4.66.1
52
- psutil==5.9.6
53
- sqlite3
54
- logging
55
- pathlib
56
- datetime
57
- uuid
58
- json
59
- asyncio
60
- ```
61
-
62
- #### Dockerfile (للنشر في حاويات)
63
- ```dockerfile
64
- FROM python:3.10-slim
65
-
66
- WORKDIR /app
67
-
68
- # Install system dependencies
69
- RUN apt-get update && apt-get install -y \
70
- git \
71
- curl \
72
- && rm -rf /var/lib/apt/lists/*
73
-
74
- # Copy requirements and install Python dependencies
75
- COPY requirements.txt .
76
- RUN pip install --no-cache-dir -r requirements.txt
77
-
78
- # Copy application code
79
- COPY . .
80
-
81
- # Create necessary directories
82
- RUN mkdir -p database logs temp uploads models
83
-
84
- # Set permissions
85
- RUN chmod +x app.py
86
-
87
- # Expose port
88
- EXPOSE 7860
89
-
90
- # Health check
91
- HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
92
- CMD curl -f http://localhost:7860/health || exit 1
93
-
94
- # Run the application
95
- CMD ["python", "app.py"]
96
- ```
97
-
98
- ### 3. إعدادات Hugging Face Spaces
99
-
100
- #### app.py (نقطة الدخول)
101
- ```python
102
- import os
103
- import uvicorn
104
-
105
- if __name__ == "__main__":
106
- # Configuration for Hugging Face Spaces
107
- port = int(os.getenv("PORT", 7860))
108
- host = os.getenv("HOST", "0.0.0.0")
109
-
110
- uvicorn.run(
111
- "app:app",
112
- host=host,
113
- port=port,
114
- reload=False,
115
- access_log=True,
116
- log_level="info"
117
- )
118
- ```
119
-
120
- #### README.md (لـ Hugging Face Spaces)
121
- ```markdown
122
- ---
123
- title: AI Knowledge Distillation Platform
124
- emoji: 🧠
125
- colorFrom: blue
126
- colorTo: purple
127
- sdk: gradio
128
- sdk_version: 4.7.1
129
- app_file: app.py
130
- pinned: false
131
- license: mit
132
- ---
133
-
134
- # AI Knowledge Distillation Platform
135
-
136
- A comprehensive platform for creating new AI models through knowledge distillation from multiple pre-trained models.
137
-
138
- ## Features
139
- - Multi-modal model support
140
- - Medical datasets specialization
141
- - Advanced memory management
142
- - Progressive training capabilities
143
-
144
- ## Usage
145
- 1. Add teacher models from Google models or custom sources
146
- 2. Configure student models
147
- 3. Select medical datasets
148
- 4. Start the distillation process
149
-
150
- ## Requirements
151
- - Python 3.10+
152
- - 16GB RAM recommended
153
- - GPU support (optional)
154
- ```
155
-
156
- ### 4. إعدادات الأمان
157
-
158
- #### تشفير البيانات
159
- ```python
160
- # في ملف config/security.py
161
- import os
162
- from cryptography.fernet import Fernet
163
-
164
- class SecurityConfig:
165
- def __init__(self):
166
- self.encryption_key = os.getenv('ENCRYPTION_KEY', Fernet.generate_key())
167
- self.secret_key = os.getenv('SECRET_KEY', 'your-secret-key-here')
168
- self.cipher_suite = Fernet(self.encryption_key)
169
-
170
- def encrypt_token(self, token: str) -> str:
171
- return self.cipher_suite.encrypt(token.encode()).decode()
172
-
173
- def decrypt_token(self, encrypted_token: str) -> str:
174
- return self.cipher_suite.decrypt(encrypted_token.encode()).decode()
175
- ```
176
-
177
- ### 5. إعدادات قاعدة البيانات
178
-
179
- #### تهيئة قواعد البيانات
180
- ```sql
181
- -- إنشاء الجداول الأساسية
182
- CREATE TABLE IF NOT EXISTS teacher_models (
183
- id TEXT PRIMARY KEY,
184
- name TEXT NOT NULL,
185
- model_id TEXT NOT NULL,
186
- description TEXT,
187
- model_type TEXT DEFAULT 'huggingface',
188
- config TEXT,
189
- tags TEXT,
190
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
191
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
192
- is_active BOOLEAN DEFAULT 1
193
- );
194
-
195
- CREATE TABLE IF NOT EXISTS saved_datasets (
196
- id TEXT PRIMARY KEY,
197
- name TEXT NOT NULL,
198
- dataset_key TEXT NOT NULL,
199
- repo_id TEXT,
200
- description TEXT,
201
- dataset_type TEXT DEFAULT 'medical',
202
- config TEXT,
203
- metadata TEXT,
204
- status TEXT DEFAULT 'saved',
205
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
206
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
207
- is_active BOOLEAN DEFAULT 1
208
- );
209
- ```
210
-
211
- ### 6. مراقبة الأداء
212
-
213
- #### إعدادات المراقبة
214
- ```python
215
- # في ملف monitoring/performance.py
216
- import psutil
217
- import logging
218
- from datetime import datetime
219
-
220
- class PerformanceMonitor:
221
- def __init__(self):
222
- self.logger = logging.getLogger(__name__)
223
-
224
- def get_system_stats(self):
225
- return {
226
- 'cpu_percent': psutil.cpu_percent(),
227
- 'memory_percent': psutil.virtual_memory().percent,
228
- 'disk_usage': psutil.disk_usage('/').percent,
229
- 'timestamp': datetime.now().isoformat()
230
- }
231
-
232
- def log_performance(self):
233
- stats = self.get_system_stats()
234
- self.logger.info(f"Performance: {stats}")
235
- ```
236
-
237
- ### 7. إعدادات النسخ الاحتياطي
238
-
239
- #### نسخ احتياطي تلقائي
240
- ```python
241
- # في ملف backup/backup_manager.py
242
- import shutil
243
- import os
244
- from datetime import datetime
245
-
246
- class BackupManager:
247
- def __init__(self, backup_dir="backups"):
248
- self.backup_dir = backup_dir
249
- os.makedirs(backup_dir, exist_ok=True)
250
-
251
- def backup_databases(self):
252
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
253
- backup_path = os.path.join(self.backup_dir, f"backup_{timestamp}")
254
-
255
- # نسخ قواعد البيانات
256
- shutil.copytree("database", backup_path)
257
-
258
- return backup_path
259
- ```
260
-
261
- ### 8. اختبارات النشر
262
-
263
- #### اختبارات التكامل
264
- ```python
265
- # في ملف tests/test_deployment.py
266
- import pytest
267
- import requests
268
- from fastapi.testclient import TestClient
269
- from app import app
270
-
271
- client = TestClient(app)
272
-
273
- def test_health_check():
274
- response = client.get("/health")
275
- assert response.status_code == 200
276
-
277
- def test_main_page():
278
- response = client.get("/")
279
- assert response.status_code == 200
280
-
281
- def test_api_endpoints():
282
- # اختبار APIs الأساسية
283
- response = client.get("/api/models/teacher")
284
- assert response.status_code == 200
285
-
286
- response = client.get("/api/datasets/saved")
287
- assert response.status_code == 200
288
- ```
289
-
290
- ### 9. إرشادات النشر
291
-
292
- #### خطوات النشر على Hugging Face Spaces
293
- 1. إنشاء Space جديد على Hugging Face
294
- 2. رفع الملفات إلى المستودع
295
- 3. تكوين متغيرات البيئة
296
- 4. تفعيل Space
297
- 5. مراقبة الأداء
298
-
299
- #### خطوات النشر على خادم مخصص
300
- 1. إعداد الخادم وتثبيت المتطلبات
301
- 2. نسخ الملفات إلى الخادم
302
- 3. تكوين قاعدة البيانات
303
- 4. تشغيل التطبيق
304
- 5. إعداد Nginx/Apache للوكيل العكسي
305
-
306
- ### 10. استكشاف الأخطاء
307
-
308
- #### مشاكل شائعة وحلولها
309
- - **نفاد الذاكرة**: تقليل حجم النماذج أو استخدام التحميل بالقطع
310
- - **بطء التحميل**: تحسين إعدادات الشبكة وحجم القطع
311
- - **أخطاء قاعدة البيانات**: التحقق من صلاحيات الكتابة
312
- - **مشاكل الرموز**: التحقق من صحة رموز Hugging Face
313
-
314
- ---
315
-
316
- **ملاحظة**: تأكد من تحديث جميع الإعدادات حسب بيئة النشر المستهدفة.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/core/token_manager.py CHANGED
@@ -36,7 +36,13 @@ class TokenManager:
36
  self.encryption_key = self._get_or_create_encryption_key()
37
  self.cipher = Fernet(self.encryption_key)
38
 
39
- # Token type definitions (must be before database init)
 
 
 
 
 
 
40
  self.token_types = {
41
  'read': {
42
  'name': 'Read Token',
 
36
  self.encryption_key = self._get_or_create_encryption_key()
37
  self.cipher = Fernet(self.encryption_key)
38
 
39
+ # Initialize database
40
+ self._init_database()
41
+
42
+ # Load tokens from environment variables
43
+ self._load_env_tokens()
44
+
45
+ # Token type definitions
46
  self.token_types = {
47
  'read': {
48
  'name': 'Read Token',
src/models_manager.py DELETED
@@ -1,326 +0,0 @@
1
- """
2
- نظام إدارة النماذج المحفوظة
3
- يدير النماذج المعلمة والطلابية المحفوظة في النظام
4
- """
5
-
6
- import json
7
- import sqlite3
8
- import logging
9
- from typing import Dict, List, Optional, Any
10
- from pathlib import Path
11
- from datetime import datetime
12
- import uuid
13
-
14
- logger = logging.getLogger(__name__)
15
-
16
- class SavedModelsManager:
17
- """
18
- مدير النماذج المحفوظة
19
- يدير حفظ واسترجاع النماذج المعلمة والطلابية
20
- """
21
-
22
- def __init__(self, db_path: str = "database/saved_models.db"):
23
- """
24
- تهيئة مدير النماذج المحفوظة
25
-
26
- Args:
27
- db_path: مسار قاعدة بيانات النماذج المحفوظة
28
- """
29
- self.db_path = Path(db_path)
30
- self.db_path.parent.mkdir(parents=True, exist_ok=True)
31
- self._init_database()
32
-
33
- logger.info("تم تهيئة مدير النماذج المحفوظة")
34
-
35
- def _init_database(self):
36
- """تهيئة قاعدة البيانات"""
37
- try:
38
- with sqlite3.connect(self.db_path) as conn:
39
- cursor = conn.cursor()
40
-
41
- # جدول النماذج المعلمة
42
- cursor.execute("""
43
- CREATE TABLE IF NOT EXISTS teacher_models (
44
- id TEXT PRIMARY KEY,
45
- name TEXT NOT NULL,
46
- model_id TEXT NOT NULL,
47
- description TEXT,
48
- model_type TEXT DEFAULT 'huggingface',
49
- config TEXT,
50
- tags TEXT,
51
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
52
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
53
- is_active BOOLEAN DEFAULT 1
54
- )
55
- """)
56
-
57
- # جدول النماذج الطلابية
58
- cursor.execute("""
59
- CREATE TABLE IF NOT EXISTS student_models (
60
- id TEXT PRIMARY KEY,
61
- name TEXT NOT NULL,
62
- model_id TEXT,
63
- description TEXT,
64
- config TEXT,
65
- training_status TEXT DEFAULT 'not_started',
66
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
67
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
68
- is_active BOOLEAN DEFAULT 1
69
- )
70
- """)
71
-
72
- # جدول مجموعات النماذج
73
- cursor.execute("""
74
- CREATE TABLE IF NOT EXISTS model_groups (
75
- id TEXT PRIMARY KEY,
76
- name TEXT NOT NULL,
77
- description TEXT,
78
- teacher_models TEXT,
79
- student_model TEXT,
80
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
81
- is_active BOOLEAN DEFAULT 1
82
- )
83
- """)
84
-
85
- conn.commit()
86
- logger.info("تم إنشاء جداول قاعدة البيانات بنجاح")
87
-
88
- except Exception as e:
89
- logger.error(f"خطأ في تهيئة قاعدة البيانات: {e}")
90
- raise
91
-
92
- def add_teacher_model(self, name: str, model_id: str, description: str = "",
93
- model_type: str = "huggingface", config: Dict = None,
94
- tags: List[str] = None) -> str:
95
- """
96
- إضافة نموذج معلم جديد
97
-
98
- Args:
99
- name: اسم النموذج
100
- model_id: معرف النموذج (مثل google/gemma-3n-E4B-it)
101
- description: وصف النموذج
102
- model_type: نوع النموذج
103
- config: إعدادات النموذج
104
- tags: علامات النموذج
105
-
106
- Returns:
107
- معرف النموذج المحفوظ
108
- """
109
- try:
110
- model_uuid = str(uuid.uuid4())
111
- config_json = json.dumps(config or {})
112
- tags_json = json.dumps(tags or [])
113
-
114
- with sqlite3.connect(self.db_path) as conn:
115
- cursor = conn.cursor()
116
- cursor.execute("""
117
- INSERT INTO teacher_models
118
- (id, name, model_id, description, model_type, config, tags)
119
- VALUES (?, ?, ?, ?, ?, ?, ?)
120
- """, (model_uuid, name, model_id, description, model_type, config_json, tags_json))
121
-
122
- conn.commit()
123
-
124
- logger.info(f"تم إضافة النموذج المعلم: {name}")
125
- return model_uuid
126
-
127
- except Exception as e:
128
- logger.error(f"خطأ في إضافة النموذج المعلم: {e}")
129
- raise
130
-
131
- def add_student_model(self, name: str, description: str = "",
132
- model_id: str = None, config: Dict = None) -> str:
133
- """
134
- إضافة نموذج طالب جديد
135
-
136
- Args:
137
- name: اسم النموذج
138
- description: وصف النموذج
139
- model_id: معرف النموذج (اختياري للنماذج المدربة مسبقاً)
140
- config: إعدادات النموذج
141
-
142
- Returns:
143
- معرف النموذج المحفوظ
144
- """
145
- try:
146
- model_uuid = str(uuid.uuid4())
147
- config_json = json.dumps(config or {})
148
-
149
- with sqlite3.connect(self.db_path) as conn:
150
- cursor = conn.cursor()
151
- cursor.execute("""
152
- INSERT INTO student_models
153
- (id, name, model_id, description, config)
154
- VALUES (?, ?, ?, ?, ?)
155
- """, (model_uuid, name, model_id, description, config_json))
156
-
157
- conn.commit()
158
-
159
- logger.info(f"تم إضافة النموذج الطالب: {name}")
160
- return model_uuid
161
-
162
- except Exception as e:
163
- logger.error(f"خطأ في إضافة النموذج الطالب: {e}")
164
- raise
165
-
166
- def get_teacher_models(self, active_only: bool = True) -> List[Dict]:
167
- """
168
- الحصول على قائمة النماذج المعلمة
169
-
170
- Args:
171
- active_only: إرجاع النماذج النشطة فقط
172
-
173
- Returns:
174
- قائمة النماذج المعلمة
175
- """
176
- try:
177
- with sqlite3.connect(self.db_path) as conn:
178
- conn.row_factory = sqlite3.Row
179
- cursor = conn.cursor()
180
-
181
- query = "SELECT * FROM teacher_models"
182
- if active_only:
183
- query += " WHERE is_active = 1"
184
- query += " ORDER BY created_at DESC"
185
-
186
- cursor.execute(query)
187
- rows = cursor.fetchall()
188
-
189
- models = []
190
- for row in rows:
191
- model = dict(row)
192
- model['config'] = json.loads(model['config'] or '{}')
193
- model['tags'] = json.loads(model['tags'] or '[]')
194
- models.append(model)
195
-
196
- return models
197
-
198
- except Exception as e:
199
- logger.error(f"خطأ في استرجاع النماذج المعلمة: {e}")
200
- return []
201
-
202
- def get_student_models(self, active_only: bool = True) -> List[Dict]:
203
- """
204
- الحصول على قائمة النماذج الطلابية
205
-
206
- Args:
207
- active_only: إرجاع النماذج النشطة فقط
208
-
209
- Returns:
210
- قائمة النماذج الطلابية
211
- """
212
- try:
213
- with sqlite3.connect(self.db_path) as conn:
214
- conn.row_factory = sqlite3.Row
215
- cursor = conn.cursor()
216
-
217
- query = "SELECT * FROM student_models"
218
- if active_only:
219
- query += " WHERE is_active = 1"
220
- query += " ORDER BY created_at DESC"
221
-
222
- cursor.execute(query)
223
- rows = cursor.fetchall()
224
-
225
- models = []
226
- for row in rows:
227
- model = dict(row)
228
- model['config'] = json.loads(model['config'] or '{}')
229
- models.append(model)
230
-
231
- return models
232
-
233
- except Exception as e:
234
- logger.error(f"خطأ في استرجاع النماذج الطلابية: {e}")
235
- return []
236
-
237
- def delete_teacher_model(self, model_id: str) -> bool:
238
- """
239
- حذف نموذج معلم
240
-
241
- Args:
242
- model_id: معرف النموذج
243
-
244
- Returns:
245
- True إذا تم الحذف بنجاح
246
- """
247
- try:
248
- with sqlite3.connect(self.db_path) as conn:
249
- cursor = conn.cursor()
250
- cursor.execute(
251
- "UPDATE teacher_models SET is_active = 0 WHERE id = ?",
252
- (model_id,)
253
- )
254
- conn.commit()
255
-
256
- if cursor.rowcount > 0:
257
- logger.info(f"تم حذف النموذج المعلم: {model_id}")
258
- return True
259
- return False
260
-
261
- except Exception as e:
262
- logger.error(f"خطأ في حذف النموذج المعلم: {e}")
263
- return False
264
-
265
- def delete_student_model(self, model_id: str) -> bool:
266
- """
267
- حذف نموذج طالب
268
-
269
- Args:
270
- model_id: معرف النموذج
271
-
272
- Returns:
273
- True إذا تم الحذف بنجاح
274
- """
275
- try:
276
- with sqlite3.connect(self.db_path) as conn:
277
- cursor = conn.cursor()
278
- cursor.execute(
279
- "UPDATE student_models SET is_active = 0 WHERE id = ?",
280
- (model_id,)
281
- )
282
- conn.commit()
283
-
284
- if cursor.rowcount > 0:
285
- logger.info(f"تم حذف النموذج الطالب: {model_id}")
286
- return True
287
- return False
288
-
289
- except Exception as e:
290
- logger.error(f"خطأ في حذف النموذج الطالب: {e}")
291
- return False
292
-
293
- def create_model_group(self, name: str, description: str,
294
- teacher_models: List[str], student_model: str = None) -> str:
295
- """
296
- إنشاء مجموعة نماذج للتدريب
297
-
298
- Args:
299
- name: اسم المجموعة
300
- description: وصف المجموعة
301
- teacher_models: قائمة معرفات النماذج المعلمة
302
- student_model: معرف النموذج الطالب
303
-
304
- Returns:
305
- معرف المجموعة
306
- """
307
- try:
308
- group_uuid = str(uuid.uuid4())
309
- teachers_json = json.dumps(teacher_models)
310
-
311
- with sqlite3.connect(self.db_path) as conn:
312
- cursor = conn.cursor()
313
- cursor.execute("""
314
- INSERT INTO model_groups
315
- (id, name, description, teacher_models, student_model)
316
- VALUES (?, ?, ?, ?, ?)
317
- """, (group_uuid, name, description, teachers_json, student_model))
318
-
319
- conn.commit()
320
-
321
- logger.info(f"تم إنشاء مجموعة النماذج: {name}")
322
- return group_uuid
323
-
324
- except Exception as e:
325
- logger.error(f"خطأ في إنشاء مجموعة النماذج: {e}")
326
- raise
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/saved_datasets_manager.py DELETED
@@ -1,342 +0,0 @@
1
- """
2
- نظام إدارة قواعد البيانات المحفوظة
3
- يدير قواعد البيانات المختارة والمحفوظة في النظام
4
- """
5
-
6
- import json
7
- import sqlite3
8
- import logging
9
- from typing import Dict, List, Optional, Any
10
- from pathlib import Path
11
- from datetime import datetime
12
- import uuid
13
-
14
- logger = logging.getLogger(__name__)
15
-
16
- class SavedDatasetsManager:
17
- """
18
- مدير قواعد البيانات المحفوظة
19
- يدير حفظ واسترجاع قواعد البيانات المختارة
20
- """
21
-
22
- def __init__(self, db_path: str = "database/saved_datasets.db"):
23
- """
24
- تهيئة مدير قواعد البيانات المحفوظة
25
-
26
- Args:
27
- db_path: مسار قاعدة بيانات قواعد البيانات المحفوظة
28
- """
29
- self.db_path = Path(db_path)
30
- self.db_path.parent.mkdir(parents=True, exist_ok=True)
31
- self._init_database()
32
-
33
- logger.info("تم تهيئة مدير قواعد البيانات المحفوظة")
34
-
35
- def _init_database(self):
36
- """تهيئة قاعدة البيانات"""
37
- try:
38
- with sqlite3.connect(self.db_path) as conn:
39
- cursor = conn.cursor()
40
-
41
- # جدول قواعد البيانات المحفوظة
42
- cursor.execute("""
43
- CREATE TABLE IF NOT EXISTS saved_datasets (
44
- id TEXT PRIMARY KEY,
45
- name TEXT NOT NULL,
46
- dataset_key TEXT NOT NULL,
47
- repo_id TEXT,
48
- description TEXT,
49
- dataset_type TEXT DEFAULT 'medical',
50
- config TEXT,
51
- metadata TEXT,
52
- status TEXT DEFAULT 'saved',
53
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
54
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
55
- is_active BOOLEAN DEFAULT 1
56
- )
57
- """)
58
-
59
- # جدول مجموعات قواعد البيانات
60
- cursor.execute("""
61
- CREATE TABLE IF NOT EXISTS dataset_groups (
62
- id TEXT PRIMARY KEY,
63
- name TEXT NOT NULL,
64
- description TEXT,
65
- datasets TEXT,
66
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
67
- is_active BOOLEAN DEFAULT 1
68
- )
69
- """)
70
-
71
- # جدول إعدادات التحميل
72
- cursor.execute("""
73
- CREATE TABLE IF NOT EXISTS dataset_loading_configs (
74
- id TEXT PRIMARY KEY,
75
- dataset_id TEXT,
76
- streaming BOOLEAN DEFAULT 1,
77
- split TEXT DEFAULT 'train',
78
- max_samples INTEGER,
79
- preprocessing_config TEXT,
80
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
81
- FOREIGN KEY (dataset_id) REFERENCES saved_datasets (id)
82
- )
83
- """)
84
-
85
- conn.commit()
86
- logger.info("تم إنشاء جداول قاعدة البيانات بنجاح")
87
-
88
- except Exception as e:
89
- logger.error(f"خطأ في تهيئة قاعدة البيانات: {e}")
90
- raise
91
-
92
- def save_dataset(self, name: str, dataset_key: str, repo_id: str = None,
93
- description: str = "", dataset_type: str = "medical",
94
- config: Dict = None, metadata: Dict = None) -> str:
95
- """
96
- حفظ قاعدة بيانات جديدة
97
-
98
- Args:
99
- name: اسم قاعدة البيانات
100
- dataset_key: مفتاح قاعدة البيانات
101
- repo_id: معرف المستودع
102
- description: وصف قاعدة البيانات
103
- dataset_type: نوع قاعدة البيانات
104
- config: إعدادات قاعدة البيانات
105
- metadata: بيانات وصفية
106
-
107
- Returns:
108
- معرف قاعدة البيانات المحفوظة
109
- """
110
- try:
111
- dataset_uuid = str(uuid.uuid4())
112
- config_json = json.dumps(config or {})
113
- metadata_json = json.dumps(metadata or {})
114
-
115
- with sqlite3.connect(self.db_path) as conn:
116
- cursor = conn.cursor()
117
- cursor.execute("""
118
- INSERT INTO saved_datasets
119
- (id, name, dataset_key, repo_id, description, dataset_type, config, metadata)
120
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
121
- """, (dataset_uuid, name, dataset_key, repo_id, description,
122
- dataset_type, config_json, metadata_json))
123
-
124
- conn.commit()
125
-
126
- logger.info(f"تم حفظ قاعدة البيانات: {name}")
127
- return dataset_uuid
128
-
129
- except Exception as e:
130
- logger.error(f"خطأ في حفظ قاعدة البيانات: {e}")
131
- raise
132
-
133
- def get_saved_datasets(self, active_only: bool = True,
134
- dataset_type: str = None) -> List[Dict]:
135
- """
136
- الحصول على قائمة قواعد البيانات المحفوظة
137
-
138
- Args:
139
- active_only: إرجاع قواعد البيانات النشطة فقط
140
- dataset_type: نوع قاعدة البيانات للتصفية
141
-
142
- Returns:
143
- قائمة قواعد البيانات المحفوظة
144
- """
145
- try:
146
- with sqlite3.connect(self.db_path) as conn:
147
- conn.row_factory = sqlite3.Row
148
- cursor = conn.cursor()
149
-
150
- query = "SELECT * FROM saved_datasets"
151
- conditions = []
152
- params = []
153
-
154
- if active_only:
155
- conditions.append("is_active = 1")
156
-
157
- if dataset_type:
158
- conditions.append("dataset_type = ?")
159
- params.append(dataset_type)
160
-
161
- if conditions:
162
- query += " WHERE " + " AND ".join(conditions)
163
-
164
- query += " ORDER BY created_at DESC"
165
-
166
- cursor.execute(query, params)
167
- rows = cursor.fetchall()
168
-
169
- datasets = []
170
- for row in rows:
171
- dataset = dict(row)
172
- dataset['config'] = json.loads(dataset['config'] or '{}')
173
- dataset['metadata'] = json.loads(dataset['metadata'] or '{}')
174
- datasets.append(dataset)
175
-
176
- return datasets
177
-
178
- except Exception as e:
179
- logger.error(f"خطأ في استرجاع قواعد البيانات المحفوظة: {e}")
180
- return []
181
-
182
- def get_dataset_by_id(self, dataset_id: str) -> Optional[Dict]:
183
- """
184
- الحصول على قاعدة بيانات بالمعرف
185
-
186
- Args:
187
- dataset_id: معرف قاعدة البيانات
188
-
189
- Returns:
190
- بيانات قاعدة البيانات أو None
191
- """
192
- try:
193
- with sqlite3.connect(self.db_path) as conn:
194
- conn.row_factory = sqlite3.Row
195
- cursor = conn.cursor()
196
-
197
- cursor.execute(
198
- "SELECT * FROM saved_datasets WHERE id = ? AND is_active = 1",
199
- (dataset_id,)
200
- )
201
- row = cursor.fetchone()
202
-
203
- if row:
204
- dataset = dict(row)
205
- dataset['config'] = json.loads(dataset['config'] or '{}')
206
- dataset['metadata'] = json.loads(dataset['metadata'] or '{}')
207
- return dataset
208
-
209
- return None
210
-
211
- except Exception as e:
212
- logger.error(f"خطأ في استرجاع قاعدة البيانات: {e}")
213
- return None
214
-
215
- def delete_dataset(self, dataset_id: str) -> bool:
216
- """
217
- حذف قاعدة بيانات محفوظة
218
-
219
- Args:
220
- dataset_id: معرف قاعدة البيانات
221
-
222
- Returns:
223
- True إذا تم الحذف بنجاح
224
- """
225
- try:
226
- with sqlite3.connect(self.db_path) as conn:
227
- cursor = conn.cursor()
228
- cursor.execute(
229
- "UPDATE saved_datasets SET is_active = 0 WHERE id = ?",
230
- (dataset_id,)
231
- )
232
- conn.commit()
233
-
234
- if cursor.rowcount > 0:
235
- logger.info(f"تم حذف قاعدة البيانات: {dataset_id}")
236
- return True
237
- return False
238
-
239
- except Exception as e:
240
- logger.error(f"خطأ في حذف قاعدة البيانات: {e}")
241
- return False
242
-
243
- def update_dataset_status(self, dataset_id: str, status: str) -> bool:
244
- """
245
- تحديث حالة قاعدة البيانات
246
-
247
- Args:
248
- dataset_id: معرف قاعدة البيانات
249
- status: الحالة الجديدة (saved, loading, loaded, error)
250
-
251
- Returns:
252
- True إذا تم التحديث بنجاح
253
- """
254
- try:
255
- with sqlite3.connect(self.db_path) as conn:
256
- cursor = conn.cursor()
257
- cursor.execute("""
258
- UPDATE saved_datasets
259
- SET status = ?, updated_at = CURRENT_TIMESTAMP
260
- WHERE id = ?
261
- """, (status, dataset_id))
262
- conn.commit()
263
-
264
- if cursor.rowcount > 0:
265
- logger.info(f"تم تحديث حالة قاعدة البيانات: {dataset_id} -> {status}")
266
- return True
267
- return False
268
-
269
- except Exception as e:
270
- logger.error(f"خطأ في تحديث حالة قاعدة البيانات: {e}")
271
- return False
272
-
273
- def save_loading_config(self, dataset_id: str, streaming: bool = True,
274
- split: str = "train", max_samples: int = None,
275
- preprocessing_config: Dict = None) -> str:
276
- """
277
- حفظ إعدادات تحميل قاعدة البيانات
278
-
279
- Args:
280
- dataset_id: معرف قاعدة البيانات
281
- streaming: استخدام التدفق
282
- split: قسم البيانات
283
- max_samples: الحد الأقصى للعينات
284
- preprocessing_config: إعدادات المعالجة المسبقة
285
-
286
- Returns:
287
- معرف إعدادات التحميل
288
- """
289
- try:
290
- config_uuid = str(uuid.uuid4())
291
- preprocessing_json = json.dumps(preprocessing_config or {})
292
-
293
- with sqlite3.connect(self.db_path) as conn:
294
- cursor = conn.cursor()
295
- cursor.execute("""
296
- INSERT INTO dataset_loading_configs
297
- (id, dataset_id, streaming, split, max_samples, preprocessing_config)
298
- VALUES (?, ?, ?, ?, ?, ?)
299
- """, (config_uuid, dataset_id, streaming, split, max_samples, preprocessing_json))
300
-
301
- conn.commit()
302
-
303
- logger.info(f"تم حفظ إعدادات التحميل لقاعدة البيانات: {dataset_id}")
304
- return config_uuid
305
-
306
- except Exception as e:
307
- logger.error(f"خطأ في حفظ إعدادات التحميل: {e}")
308
- raise
309
-
310
- def create_dataset_group(self, name: str, description: str,
311
- datasets: List[str]) -> str:
312
- """
313
- إنشاء مجموعة قواعد بيانات
314
-
315
- Args:
316
- name: اسم المجموعة
317
- description: وصف المجموعة
318
- datasets: قائمة معرفات قواعد البيانات
319
-
320
- Returns:
321
- معرف المجموعة
322
- """
323
- try:
324
- group_uuid = str(uuid.uuid4())
325
- datasets_json = json.dumps(datasets)
326
-
327
- with sqlite3.connect(self.db_path) as conn:
328
- cursor = conn.cursor()
329
- cursor.execute("""
330
- INSERT INTO dataset_groups
331
- (id, name, description, datasets)
332
- VALUES (?, ?, ?, ?)
333
- """, (group_uuid, name, description, datasets_json))
334
-
335
- conn.commit()
336
-
337
- logger.info(f"تم إنشاء مجموعة قواعد البيانات: {name}")
338
- return group_uuid
339
-
340
- except Exception as e:
341
- logger.error(f"خطأ في إنشاء مجموعة قواعد البيانات: {e}")
342
- raise
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
static/css/style.css CHANGED
@@ -996,16 +996,10 @@ body {
996
  width: 100%;
997
  height: 100%;
998
  background: rgba(0, 0, 0, 0.7);
999
- display: none; /* Hidden by default */
1000
  align-items: center;
1001
  justify-content: center;
1002
  z-index: 2000;
1003
- pointer-events: none; /* Allow clicks to pass through when hidden */
1004
- }
1005
-
1006
- .loading-overlay.show {
1007
- display: flex;
1008
- pointer-events: auto;
1009
  }
1010
 
1011
  .loading-content {
@@ -1309,189 +1303,3 @@ body {
1309
  opacity: 1;
1310
  }
1311
  }
1312
-
1313
- /* Saved Items Styles */
1314
- .quick-access-section {
1315
- background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
1316
- border-radius: 12px;
1317
- padding: 30px;
1318
- margin-bottom: 30px;
1319
- text-align: center;
1320
- }
1321
-
1322
- .quick-access-buttons {
1323
- display: flex;
1324
- gap: 20px;
1325
- justify-content: center;
1326
- flex-wrap: wrap;
1327
- margin-top: 20px;
1328
- }
1329
-
1330
- .quick-access-buttons .btn {
1331
- min-width: 200px;
1332
- padding: 15px 25px;
1333
- font-size: 1.1rem;
1334
- border-radius: 8px;
1335
- transition: all 0.3s ease;
1336
- }
1337
-
1338
- .quick-access-buttons .btn:hover {
1339
- transform: translateY(-2px);
1340
- box-shadow: 0 4px 12px rgba(0,0,0,0.15);
1341
- }
1342
-
1343
- .saved-models-section, .saved-datasets-section, .training-config-section, .start-training-section {
1344
- background: white;
1345
- border-radius: 12px;
1346
- padding: 25px;
1347
- margin-bottom: 25px;
1348
- box-shadow: 0 2px 8px rgba(0,0,0,0.1);
1349
- }
1350
-
1351
- .saved-items-grid {
1352
- display: grid;
1353
- grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
1354
- gap: 20px;
1355
- margin-top: 20px;
1356
- }
1357
-
1358
- .saved-item {
1359
- border: 2px solid #e9ecef;
1360
- border-radius: 8px;
1361
- padding: 20px;
1362
- background: white;
1363
- transition: all 0.3s ease;
1364
- cursor: pointer;
1365
- }
1366
-
1367
- .saved-item:hover {
1368
- border-color: #007bff;
1369
- transform: translateY(-2px);
1370
- box-shadow: 0 4px 12px rgba(0,123,255,0.15);
1371
- }
1372
-
1373
- .saved-item.selected {
1374
- border-color: #28a745;
1375
- background: #f8fff9;
1376
- }
1377
-
1378
- .item-header {
1379
- display: flex;
1380
- justify-content: space-between;
1381
- align-items: center;
1382
- margin-bottom: 10px;
1383
- }
1384
-
1385
- .item-header h6 {
1386
- margin: 0;
1387
- color: #2c3e50;
1388
- font-weight: 600;
1389
- }
1390
-
1391
- .item-type {
1392
- background: #e3f2fd;
1393
- color: #1976d2;
1394
- padding: 4px 8px;
1395
- border-radius: 12px;
1396
- font-size: 0.8rem;
1397
- font-weight: 500;
1398
- }
1399
-
1400
- .item-id {
1401
- font-family: 'Courier New', monospace;
1402
- background: #f8f9fa;
1403
- padding: 6px 10px;
1404
- border-radius: 4px;
1405
- font-size: 0.85rem;
1406
- color: #495057;
1407
- margin-bottom: 8px;
1408
- }
1409
-
1410
- .item-description {
1411
- color: #6c757d;
1412
- font-size: 0.9rem;
1413
- margin-bottom: 15px;
1414
- line-height: 1.4;
1415
- }
1416
-
1417
- .item-actions {
1418
- text-align: right;
1419
- }
1420
-
1421
- .empty-state {
1422
- text-align: center;
1423
- padding: 40px 20px;
1424
- color: #6c757d;
1425
- }
1426
-
1427
- .loading-placeholder {
1428
- text-align: center;
1429
- padding: 40px 20px;
1430
- }
1431
-
1432
- .config-grid {
1433
- display: grid;
1434
- grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
1435
- gap: 20px;
1436
- margin-top: 20px;
1437
- }
1438
-
1439
- .config-item label {
1440
- font-weight: 600;
1441
- color: #2c3e50;
1442
- margin-bottom: 10px;
1443
- display: block;
1444
- }
1445
-
1446
- .selected-items {
1447
- background: #f8f9fa;
1448
- border: 1px solid #e9ecef;
1449
- border-radius: 6px;
1450
- padding: 15px;
1451
- min-height: 50px;
1452
- }
1453
-
1454
- .selected-items-list .badge {
1455
- margin: 2px;
1456
- font-size: 0.85rem;
1457
- }
1458
-
1459
- .training-summary {
1460
- display: grid;
1461
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
1462
- gap: 20px;
1463
- margin-bottom: 25px;
1464
- padding: 20px;
1465
- background: #f8f9fa;
1466
- border-radius: 8px;
1467
- }
1468
-
1469
- .summary-item {
1470
- text-align: center;
1471
- }
1472
-
1473
- .summary-item strong {
1474
- display: block;
1475
- color: #2c3e50;
1476
- margin-bottom: 5px;
1477
- }
1478
-
1479
- .start-training-section {
1480
- text-align: center;
1481
- background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
1482
- color: white;
1483
- }
1484
-
1485
- .start-training-section h3 {
1486
- color: white;
1487
- margin-bottom: 20px;
1488
- }
1489
-
1490
- .start-training-section .training-summary {
1491
- background: rgba(255,255,255,0.1);
1492
- color: white;
1493
- }
1494
-
1495
- .start-training-section .summary-item strong {
1496
- color: white;
1497
- }
 
996
  width: 100%;
997
  height: 100%;
998
  background: rgba(0, 0, 0, 0.7);
999
+ display: flex;
1000
  align-items: center;
1001
  justify-content: center;
1002
  z-index: 2000;
 
 
 
 
 
 
1003
  }
1004
 
1005
  .loading-content {
 
1303
  opacity: 1;
1304
  }
1305
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
static/js/google-models.js DELETED
@@ -1,410 +0,0 @@
1
- /**
2
- * Google Models Manager JavaScript
3
- * Handles models management functionality
4
- */
5
-
6
- class GoogleModelsManager {
7
- constructor() {
8
- this.teacherModels = [];
9
- this.studentModels = [];
10
- this.googleModels = [];
11
- this.init();
12
- }
13
-
14
- init() {
15
- this.loadGoogleModels();
16
- this.loadTeacherModels();
17
- this.loadStudentModels();
18
- this.setupEventListeners();
19
-
20
- // Refresh data every 30 seconds
21
- setInterval(() => {
22
- this.loadTeacherModels();
23
- this.loadStudentModels();
24
- }, 30000);
25
- }
26
-
27
- setupEventListeners() {
28
- // Teacher model form
29
- document.getElementById('add-teacher-form').addEventListener('submit', (e) => {
30
- e.preventDefault();
31
- this.addTeacherModel();
32
- });
33
-
34
- // Student model form
35
- document.getElementById('add-student-form').addEventListener('submit', (e) => {
36
- e.preventDefault();
37
- this.addStudentModel();
38
- });
39
- }
40
-
41
- async loadGoogleModels() {
42
- try {
43
- const response = await fetch('/api/google-models');
44
- const data = await response.json();
45
-
46
- if (response.ok) {
47
- this.googleModels = data.models;
48
- this.renderGoogleModels();
49
- this.updateStats();
50
- } else {
51
- this.showError('فشل في تحميل نماذج Hugging Face');
52
- }
53
- } catch (error) {
54
- console.error('Error loading HF models:', error);
55
- this.showError('خطأ في الاتصال بالخادم');
56
- }
57
- }
58
-
59
- async loadTeacherModels() {
60
- try {
61
- const response = await fetch('/api/models/teacher');
62
- const data = await response.json();
63
-
64
- if (response.ok) {
65
- this.teacherModels = data.models;
66
- this.renderTeacherModels();
67
- this.updateStats();
68
- } else {
69
- this.showError('فشل في تحميل النماذج المعلمة');
70
- }
71
- } catch (error) {
72
- console.error('Error loading teacher models:', error);
73
- this.showError('خطأ في الاتصال بالخادم');
74
- }
75
- }
76
-
77
- async loadStudentModels() {
78
- try {
79
- const response = await fetch('/api/models/student');
80
- const data = await response.json();
81
-
82
- if (response.ok) {
83
- this.studentModels = data.models;
84
- this.renderStudentModels();
85
- this.updateStats();
86
- } else {
87
- this.showError('فشل في تحميل النماذج الطلابية');
88
- }
89
- } catch (error) {
90
- console.error('Error loading student models:', error);
91
- this.showError('خطأ في الاتصال بالخادم');
92
- }
93
- }
94
-
95
- async addTeacherModel() {
96
- try {
97
- const formData = new FormData();
98
- formData.append('name', document.getElementById('teacher-name').value);
99
- formData.append('model_id', document.getElementById('teacher-model-id').value);
100
- formData.append('description', document.getElementById('teacher-description').value);
101
- formData.append('model_type', document.getElementById('teacher-type').value);
102
-
103
- const tags = document.getElementById('teacher-tags').value
104
- .split(',')
105
- .map(tag => tag.trim())
106
- .filter(tag => tag.length > 0);
107
- formData.append('tags', JSON.stringify(tags));
108
-
109
- const response = await fetch('/api/models/teacher/add', {
110
- method: 'POST',
111
- body: formData
112
- });
113
-
114
- const data = await response.json();
115
-
116
- if (response.ok) {
117
- this.showSuccess(data.message);
118
- document.getElementById('add-teacher-form').reset();
119
- this.loadTeacherModels();
120
- } else {
121
- this.showError(data.detail || 'فشل في إضافة النموذج المعلم');
122
- }
123
- } catch (error) {
124
- console.error('Error adding teacher model:', error);
125
- this.showError('خطأ في الاتصال بالخادم');
126
- }
127
- }
128
-
129
- async addStudentModel() {
130
- try {
131
- const formData = new FormData();
132
- formData.append('name', document.getElementById('student-name').value);
133
- formData.append('description', document.getElementById('student-description').value);
134
-
135
- const modelId = document.getElementById('student-model-id').value;
136
- if (modelId) {
137
- formData.append('model_id', modelId);
138
- }
139
-
140
- const response = await fetch('/api/models/student/add', {
141
- method: 'POST',
142
- body: formData
143
- });
144
-
145
- const data = await response.json();
146
-
147
- if (response.ok) {
148
- this.showSuccess(data.message);
149
- document.getElementById('add-student-form').reset();
150
- this.loadStudentModels();
151
- } else {
152
- this.showError(data.detail || 'فشل في إضافة النموذج الطالب');
153
- }
154
- } catch (error) {
155
- console.error('Error adding student model:', error);
156
- this.showError('خطأ في الاتصال بالخادم');
157
- }
158
- }
159
-
160
- async addGoogleModel(modelId) {
161
- try {
162
- // Find the Google model
163
- const googleModel = this.googleModels.find(m => m.model_id === modelId);
164
- if (!googleModel) {
165
- this.showError('النموذج غير موجود');
166
- return;
167
- }
168
-
169
- const formData = new FormData();
170
- formData.append('name', googleModel.name);
171
- formData.append('model_id', googleModel.model_id);
172
- formData.append('description', googleModel.description || '');
173
- formData.append('model_type', 'google');
174
- formData.append('tags', JSON.stringify(['google', googleModel.type]));
175
-
176
- const response = await fetch('/api/models/teacher/add', {
177
- method: 'POST',
178
- body: formData
179
- });
180
-
181
- const data = await response.json();
182
-
183
- if (response.ok) {
184
- this.showSuccess(`تم إضافة ${googleModel.name} من Hugging Face إلى النماذج المعلمة`);
185
- this.loadTeacherModels();
186
- } else {
187
- this.showError(data.detail || 'فشل في إضافة النموذج');
188
- }
189
- } catch (error) {
190
- console.error('Error adding Google model:', error);
191
- this.showError('خطأ في الاتصال بالخادم');
192
- }
193
- }
194
-
195
- async deleteTeacherModel(modelId) {
196
- if (!confirm('هل أنت متأكد من حذف هذا النموذج المعلم؟')) {
197
- return;
198
- }
199
-
200
- try {
201
- const response = await fetch(`/api/models/teacher/${modelId}`, {
202
- method: 'DELETE'
203
- });
204
-
205
- const data = await response.json();
206
-
207
- if (response.ok) {
208
- this.showSuccess(data.message);
209
- this.loadTeacherModels();
210
- } else {
211
- this.showError(data.detail || 'فشل في حذف النموذج');
212
- }
213
- } catch (error) {
214
- console.error('Error deleting teacher model:', error);
215
- this.showError('خطأ في الاتصال بالخادم');
216
- }
217
- }
218
-
219
- async deleteStudentModel(modelId) {
220
- if (!confirm('هل أنت متأكد من حذف هذا النموذج الطالب؟')) {
221
- return;
222
- }
223
-
224
- try {
225
- const response = await fetch(`/api/models/student/${modelId}`, {
226
- method: 'DELETE'
227
- });
228
-
229
- const data = await response.json();
230
-
231
- if (response.ok) {
232
- this.showSuccess(data.message);
233
- this.loadStudentModels();
234
- } else {
235
- this.showError(data.detail || 'فشل في حذف النموذج');
236
- }
237
- } catch (error) {
238
- console.error('Error deleting student model:', error);
239
- this.showError('خطأ في الاتصال بالخادم');
240
- }
241
- }
242
-
243
- renderGoogleModels() {
244
- const container = document.getElementById('google-models-list');
245
-
246
- if (this.googleModels.length === 0) {
247
- container.innerHTML = `
248
- <div class="text-center text-muted">
249
- <i class="fab fa-github fa-3x mb-3"></i>
250
- <p>لا توجد نماذج Hugging Face متاحة حالياً</p>
251
- </div>
252
- `;
253
- return;
254
- }
255
-
256
- const modelsHtml = this.googleModels.map(model => `
257
- <div class="google-model-item">
258
- <div class="google-model-info">
259
- <h6>${model.name}</h6>
260
- <small class="text-muted">${model.model_id}</small>
261
- <div class="mt-1">
262
- <span class="tag">${model.type}</span>
263
- <span class="tag">${model.size_gb} GB</span>
264
- <span class="tag">${model.modality}</span>
265
- </div>
266
- </div>
267
- <button class="btn btn-primary btn-sm" onclick="googleModels.addGoogleModel('${model.model_id}')">
268
- <i class="fas fa-plus me-1"></i>إضافة للمعلمين
269
- </button>
270
- </div>
271
- `).join('');
272
-
273
- container.innerHTML = modelsHtml;
274
- }
275
-
276
- renderTeacherModels() {
277
- const container = document.getElementById('teacher-models-list');
278
-
279
- if (this.teacherModels.length === 0) {
280
- container.innerHTML = `
281
- <div class="text-center text-muted">
282
- <i class="fas fa-chalkboard-teacher fa-3x mb-3"></i>
283
- <p>لا توجد نماذج معلمة محفوظة</p>
284
- <small>استخدم النموذج أعلاه لإضافة نماذج معلمة جديدة</small>
285
- </div>
286
- `;
287
- return;
288
- }
289
-
290
- const modelsHtml = this.teacherModels.map(model => `
291
- <div class="model-card">
292
- <div class="model-header">
293
- <h5 class="model-title">${model.name}</h5>
294
- <span class="model-type">${model.model_type}</span>
295
- </div>
296
- <div class="model-id">${model.model_id}</div>
297
- ${model.description ? `<div class="model-description">${model.description}</div>` : ''}
298
- ${model.tags && model.tags.length > 0 ? `
299
- <div class="model-tags">
300
- ${model.tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
301
- </div>
302
- ` : ''}
303
- <div class="mt-3">
304
- <small class="text-muted">تم الإنشاء: ${new Date(model.created_at).toLocaleDateString('ar-SA')}</small>
305
- <button class="btn btn-danger btn-sm float-end" onclick="googleModels.deleteTeacherModel('${model.id}')">
306
- <i class="fas fa-trash"></i>
307
- </button>
308
- </div>
309
- </div>
310
- `).join('');
311
-
312
- container.innerHTML = modelsHtml;
313
- }
314
-
315
- renderStudentModels() {
316
- const container = document.getElementById('student-models-list');
317
-
318
- if (this.studentModels.length === 0) {
319
- container.innerHTML = `
320
- <div class="text-center text-muted">
321
- <i class="fas fa-graduation-cap fa-3x mb-3"></i>
322
- <p>لا توجد نماذج طلابية محفوظة</p>
323
- <small>استخدم النموذج أعلاه لإضافة نماذج طلابية جديدة</small>
324
- </div>
325
- `;
326
- return;
327
- }
328
-
329
- const modelsHtml = this.studentModels.map(model => `
330
- <div class="model-card">
331
- <div class="model-header">
332
- <h5 class="model-title">${model.name}</h5>
333
- <span class="model-type">طالب</span>
334
- </div>
335
- ${model.model_id ? `<div class="model-id">${model.model_id}</div>` : '<div class="text-muted">نموذج جديد للتدريب</div>'}
336
- ${model.description ? `<div class="model-description">${model.description}</div>` : ''}
337
- <div class="mt-3">
338
- <small class="text-muted">تم الإنشاء: ${new Date(model.created_at).toLocaleDateString('ar-SA')}</small>
339
- <span class="badge bg-info ms-2">${model.training_status}</span>
340
- <button class="btn btn-danger btn-sm float-end" onclick="googleModels.deleteStudentModel('${model.id}')">
341
- <i class="fas fa-trash"></i>
342
- </button>
343
- </div>
344
- </div>
345
- `).join('');
346
-
347
- container.innerHTML = modelsHtml;
348
- }
349
-
350
- updateStats() {
351
- document.getElementById('teacher-count').textContent = this.teacherModels.length;
352
- document.getElementById('student-count').textContent = this.studentModels.length;
353
- document.getElementById('google-count').textContent = this.googleModels.length;
354
- }
355
-
356
- refreshModels() {
357
- this.loadGoogleModels();
358
- this.loadTeacherModels();
359
- this.loadStudentModels();
360
- }
361
-
362
- showSuccess(message) {
363
- // Create and show success toast
364
- const toast = document.createElement('div');
365
- toast.className = 'toast align-items-center text-white bg-success border-0 position-fixed';
366
- toast.style.cssText = 'top: 20px; right: 20px; z-index: 9999;';
367
- toast.innerHTML = `
368
- <div class="d-flex">
369
- <div class="toast-body">
370
- <i class="fas fa-check-circle me-2"></i>${message}
371
- </div>
372
- <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
373
- </div>
374
- `;
375
- document.body.appendChild(toast);
376
-
377
- const bsToast = new bootstrap.Toast(toast);
378
- bsToast.show();
379
-
380
- setTimeout(() => {
381
- document.body.removeChild(toast);
382
- }, 5000);
383
- }
384
-
385
- showError(message) {
386
- // Create and show error toast
387
- const toast = document.createElement('div');
388
- toast.className = 'toast align-items-center text-white bg-danger border-0 position-fixed';
389
- toast.style.cssText = 'top: 20px; right: 20px; z-index: 9999;';
390
- toast.innerHTML = `
391
- <div class="d-flex">
392
- <div class="toast-body">
393
- <i class="fas fa-exclamation-circle me-2"></i>${message}
394
- </div>
395
- <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
396
- </div>
397
- `;
398
- document.body.appendChild(toast);
399
-
400
- const bsToast = new bootstrap.Toast(toast);
401
- bsToast.show();
402
-
403
- setTimeout(() => {
404
- document.body.removeChild(toast);
405
- }, 5000);
406
- }
407
- }
408
-
409
- // Initialize the manager when the page loads
410
- const googleModels = new GoogleModelsManager();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
static/js/medical-datasets.js CHANGED
@@ -6,160 +6,25 @@
6
  class MedicalDatasetsManager {
7
  constructor() {
8
  this.datasets = [];
9
- this.savedDatasets = [];
10
  this.loadedDatasets = new Set();
11
  this.systemInfo = {};
12
  this.init();
13
  }
14
 
15
  init() {
16
- // Force remove any blocking overlays immediately
17
- this.forceRemoveOverlays();
18
-
19
  this.loadDatasets();
20
- this.loadSavedDatasets();
21
  this.loadSystemInfo();
22
  this.setupEventListeners();
23
-
24
- // Ensure page is interactive
25
- this.ensureInteractivity();
26
-
27
- // Force interactivity every 2 seconds for the first 10 seconds
28
- let attempts = 0;
29
- const forceInterval = setInterval(() => {
30
- this.forceRemoveOverlays();
31
- this.ensureInteractivity();
32
- attempts++;
33
- if (attempts >= 5) {
34
- clearInterval(forceInterval);
35
- }
36
- }, 2000);
37
-
38
  // Refresh system info every 30 seconds
39
  setInterval(() => this.loadSystemInfo(), 30000);
40
  }
41
 
42
- forceRemoveOverlays() {
43
- // Remove any loading overlays
44
- document.querySelectorAll('.loading-overlay').forEach(overlay => {
45
- if (!overlay.classList.contains('active')) {
46
- overlay.remove();
47
- }
48
- });
49
-
50
- // Remove any fixed position overlays
51
- document.querySelectorAll('[style*="position: fixed"], [style*="position:fixed"]').forEach(el => {
52
- if (el.style.zIndex > 100 && !el.classList.contains('navbar') && !el.classList.contains('modal')) {
53
- el.style.display = 'none';
54
- el.style.pointerEvents = 'none';
55
- }
56
- });
57
-
58
- // Force body to be interactive
59
- document.body.style.pointerEvents = 'auto';
60
- document.documentElement.style.pointerEvents = 'auto';
61
-
62
- console.log('Force removed overlays');
63
- }
64
-
65
- ensureInteractivity() {
66
- console.log('Ensuring interactivity...');
67
-
68
- // Remove any blocking overlays
69
- document.querySelectorAll('.loading-overlay').forEach(overlay => {
70
- if (!overlay.classList.contains('active')) {
71
- overlay.style.display = 'none';
72
- overlay.style.pointerEvents = 'none';
73
- }
74
- });
75
-
76
- // Force all elements to be interactive
77
- document.querySelectorAll('*').forEach(el => {
78
- if (el.style.pointerEvents === 'none' && !el.classList.contains('loading-overlay')) {
79
- el.style.pointerEvents = 'auto';
80
- }
81
- });
82
-
83
- // Ensure all buttons are clickable
84
- document.querySelectorAll('button, .btn, [onclick]').forEach(btn => {
85
- btn.style.pointerEvents = 'auto !important';
86
- btn.style.zIndex = '999';
87
- btn.style.position = 'relative';
88
- });
89
-
90
- // Ensure dataset cards are interactive
91
- document.querySelectorAll('.dataset-card').forEach(card => {
92
- card.style.pointerEvents = 'auto';
93
- card.style.position = 'relative';
94
- card.style.zIndex = '1';
95
- });
96
-
97
- // Force datasets grid to be interactive
98
- const datasetsGrid = document.getElementById('datasets-grid');
99
- if (datasetsGrid) {
100
- datasetsGrid.style.pointerEvents = 'auto';
101
- datasetsGrid.style.position = 'relative';
102
- datasetsGrid.style.zIndex = '1';
103
- }
104
-
105
- // Remove any invisible blocking elements
106
- document.querySelectorAll('div').forEach(div => {
107
- const style = window.getComputedStyle(div);
108
- if (style.position === 'fixed' &&
109
- style.top === '0px' &&
110
- style.left === '0px' &&
111
- style.width === '100%' &&
112
- style.height === '100%' &&
113
- !div.classList.contains('modal') &&
114
- !div.classList.contains('navbar')) {
115
- console.log('Found potential blocking overlay:', div);
116
- div.style.display = 'none';
117
- div.style.pointerEvents = 'none';
118
- }
119
- });
120
-
121
- console.log('Interactivity ensured');
122
- }
123
-
124
  setupEventListeners() {
125
  // Dataset loading modal events
126
  document.getElementById('load-dataset-btn').addEventListener('click', () => {
127
  this.loadSelectedDataset();
128
  });
129
-
130
- // Add event delegation for dynamic buttons
131
- document.addEventListener('click', (e) => {
132
- // Handle dataset action buttons
133
- if (e.target.closest('[onclick*="showDatasetDetails"]')) {
134
- e.preventDefault();
135
- const onclick = e.target.closest('[onclick*="showDatasetDetails"]').getAttribute('onclick');
136
- const match = onclick.match(/showDatasetDetails\('([^']+)'\)/);
137
- if (match) {
138
- console.log('Event delegation: showDatasetDetails', match[1]);
139
- this.showDatasetDetails(match[1]);
140
- }
141
- }
142
-
143
- if (e.target.closest('[onclick*="saveDataset"]')) {
144
- e.preventDefault();
145
- const onclick = e.target.closest('[onclick*="saveDataset"]').getAttribute('onclick');
146
- const match = onclick.match(/saveDataset\('([^']+)'\)/);
147
- if (match) {
148
- console.log('Event delegation: saveDataset', match[1]);
149
- this.saveDataset(match[1]);
150
- }
151
- }
152
-
153
- if (e.target.closest('[onclick*="loadDataset"]')) {
154
- e.preventDefault();
155
- const onclick = e.target.closest('[onclick*="loadDataset"]').getAttribute('onclick');
156
- const match = onclick.match(/loadDataset\('([^']+)'\)/);
157
- if (match) {
158
- console.log('Event delegation: loadDataset', match[1]);
159
- this.loadDataset(match[1]);
160
- }
161
- }
162
- });
163
  }
164
 
165
  async loadDatasets() {
@@ -258,11 +123,6 @@ class MedicalDatasetsManager {
258
 
259
  const datasetsHtml = this.datasets.map(dataset => this.renderDatasetCard(dataset)).join('');
260
  container.innerHTML = `<div class="row">${datasetsHtml}</div>`;
261
-
262
- // Ensure all elements are interactive after rendering
263
- setTimeout(() => {
264
- this.ensureInteractivity();
265
- }, 100);
266
  }
267
 
268
  renderDatasetCard(dataset) {
@@ -322,24 +182,19 @@ class MedicalDatasetsManager {
322
  </div>
323
 
324
  <div class="dataset-actions">
325
- <button class="btn btn-outline-info btn-sm"
326
  onclick="medicalDatasets.showDatasetDetails('${dataset.key}')">
327
  <i class="fas fa-info-circle me-1"></i>
328
  التفاصيل
329
  </button>
330
- <button class="btn btn-warning btn-sm"
331
- onclick="medicalDatasets.saveDataset('${dataset.key}')">
332
- <i class="fas fa-bookmark me-1"></i>
333
- حفظ
334
- </button>
335
  ${!isLoaded ? `
336
- <button class="btn btn-primary btn-sm"
337
  onclick="medicalDatasets.loadDataset('${dataset.key}')">
338
  <i class="fas fa-download me-1"></i>
339
  تحميل
340
  </button>
341
  ` : `
342
- <button class="btn btn-success btn-sm" disabled>
343
  <i class="fas fa-check me-1"></i>
344
  محمل
345
  </button>
@@ -405,7 +260,6 @@ class MedicalDatasetsManager {
405
  }
406
 
407
  showDatasetDetails(datasetKey) {
408
- console.log('showDatasetDetails called with:', datasetKey);
409
  const dataset = this.datasets.find(d => d.key === datasetKey);
410
  if (!dataset) return;
411
 
@@ -457,7 +311,6 @@ class MedicalDatasetsManager {
457
  }
458
 
459
  async loadDataset(datasetKey) {
460
- console.log('loadDataset called with:', datasetKey);
461
  const dataset = this.datasets.find(d => d.key === datasetKey);
462
  if (!dataset) return;
463
 
@@ -513,177 +366,16 @@ class MedicalDatasetsManager {
513
  this.showSuccess('تم تحديث البيانات');
514
  }
515
 
516
- async loadSavedDatasets() {
517
- try {
518
- const response = await fetch('/api/datasets/saved?dataset_type=medical');
519
- const data = await response.json();
520
-
521
- if (response.ok) {
522
- this.savedDatasets = data.datasets;
523
- this.renderSavedDatasets();
524
- } else {
525
- console.error('Failed to load saved datasets');
526
- }
527
- } catch (error) {
528
- console.error('Error loading saved datasets:', error);
529
- }
530
- }
531
-
532
- async saveDataset(datasetKey) {
533
- console.log('saveDataset called with:', datasetKey);
534
- try {
535
- const dataset = this.datasets.find(d => d.key === datasetKey);
536
- if (!dataset) {
537
- this.showError('قاعدة البيانات غير موجودة');
538
- return;
539
- }
540
-
541
- const formData = new FormData();
542
- formData.append('name', dataset.name);
543
- formData.append('dataset_key', datasetKey);
544
- formData.append('repo_id', dataset.repo_id || '');
545
- formData.append('description', dataset.description || '');
546
- formData.append('dataset_type', 'medical');
547
-
548
- const response = await fetch('/api/datasets/save', {
549
- method: 'POST',
550
- body: formData
551
- });
552
-
553
- const data = await response.json();
554
-
555
- if (response.ok) {
556
- this.showSuccess(`تم حفظ ${dataset.name} بنجاح`);
557
- this.loadSavedDatasets();
558
- } else {
559
- this.showError(data.detail || 'فشل في حفظ قاعدة البيانات');
560
- }
561
- } catch (error) {
562
- console.error('Error saving dataset:', error);
563
- this.showError('خطأ في الاتصال بالخادم');
564
- }
565
- }
566
-
567
- async deleteSavedDataset(datasetId) {
568
- if (!confirm('هل أنت متأكد من حذف قاعدة البيانات المحفوظة؟')) {
569
- return;
570
- }
571
-
572
- try {
573
- const response = await fetch(`/api/datasets/${datasetId}`, {
574
- method: 'DELETE'
575
- });
576
-
577
- const data = await response.json();
578
-
579
- if (response.ok) {
580
- this.showSuccess(data.message);
581
- this.loadSavedDatasets();
582
- } else {
583
- this.showError(data.detail || 'فشل في حذف قاعدة البيانات');
584
- }
585
- } catch (error) {
586
- console.error('Error deleting saved dataset:', error);
587
- this.showError('خطأ في الاتصال بالخادم');
588
- }
589
- }
590
-
591
- showSavedDatasets() {
592
- document.getElementById('saved-datasets-section').style.display = 'block';
593
- this.loadSavedDatasets();
594
- }
595
-
596
- hideSavedDatasets() {
597
- document.getElementById('saved-datasets-section').style.display = 'none';
598
- }
599
-
600
- renderSavedDatasets() {
601
- const container = document.getElementById('saved-datasets-grid');
602
-
603
- if (this.savedDatasets.length === 0) {
604
- container.innerHTML = `
605
- <div class="col-12 text-center">
606
- <div class="text-muted">
607
- <i class="fas fa-bookmark fa-3x mb-3"></i>
608
- <p>لا توجد قواعد بيانات محفوظة</p>
609
- <small>احفظ قواعد البيانات من القائمة أعلاه</small>
610
- </div>
611
- </div>
612
- `;
613
- return;
614
- }
615
-
616
- const datasetsHtml = this.savedDatasets.map(dataset => `
617
- <div class="col-md-6 col-lg-4 mb-4">
618
- <div class="dataset-card">
619
- <div class="dataset-header">
620
- <h5 class="dataset-title">${dataset.name}</h5>
621
- <span class="dataset-status status-saved">محفوظة</span>
622
- </div>
623
- <div class="dataset-key">${dataset.dataset_key}</div>
624
- ${dataset.description ? `<div class="dataset-description">${dataset.description}</div>` : ''}
625
- <div class="dataset-actions mt-3">
626
- <button class="btn btn-primary btn-sm" onclick="medicalDatasets.loadSelectedDataset('${dataset.dataset_key}')">
627
- <i class="fas fa-download me-1"></i>تحميل
628
- </button>
629
- <button class="btn btn-danger btn-sm" onclick="medicalDatasets.deleteSavedDataset('${dataset.id}')">
630
- <i class="fas fa-trash me-1"></i>حذف
631
- </button>
632
- </div>
633
- <div class="mt-2">
634
- <small class="text-muted">تم الحفظ: ${new Date(dataset.created_at).toLocaleDateString('ar-SA')}</small>
635
- </div>
636
- </div>
637
- </div>
638
- `).join('');
639
-
640
- container.innerHTML = datasetsHtml;
641
- }
642
-
643
  showSuccess(message) {
644
- // Create and show success toast
645
- const toast = document.createElement('div');
646
- toast.className = 'toast align-items-center text-white bg-success border-0 position-fixed';
647
- toast.style.cssText = 'top: 20px; right: 20px; z-index: 9999;';
648
- toast.innerHTML = `
649
- <div class="d-flex">
650
- <div class="toast-body">
651
- <i class="fas fa-check-circle me-2"></i>${message}
652
- </div>
653
- <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
654
- </div>
655
- `;
656
- document.body.appendChild(toast);
657
-
658
- const bsToast = new bootstrap.Toast(toast);
659
- bsToast.show();
660
-
661
- setTimeout(() => {
662
- document.body.removeChild(toast);
663
- }, 5000);
664
  }
665
 
666
  showError(message) {
667
- // Create and show error toast
668
- const toast = document.createElement('div');
669
- toast.className = 'toast align-items-center text-white bg-danger border-0 position-fixed';
670
- toast.style.cssText = 'top: 20px; right: 20px; z-index: 9999;';
671
- toast.innerHTML = `
672
- <div class="d-flex">
673
- <div class="toast-body">
674
- <i class="fas fa-exclamation-circle me-2"></i>${message}
675
- </div>
676
- <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
677
- </div>
678
- `;
679
- document.body.appendChild(toast);
680
-
681
- const bsToast = new bootstrap.Toast(toast);
682
- bsToast.show();
683
-
684
- setTimeout(() => {
685
- document.body.removeChild(toast);
686
- }, 5000);
687
  }
688
  }
689
 
 
6
  class MedicalDatasetsManager {
7
  constructor() {
8
  this.datasets = [];
 
9
  this.loadedDatasets = new Set();
10
  this.systemInfo = {};
11
  this.init();
12
  }
13
 
14
  init() {
 
 
 
15
  this.loadDatasets();
 
16
  this.loadSystemInfo();
17
  this.setupEventListeners();
18
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  // Refresh system info every 30 seconds
20
  setInterval(() => this.loadSystemInfo(), 30000);
21
  }
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  setupEventListeners() {
24
  // Dataset loading modal events
25
  document.getElementById('load-dataset-btn').addEventListener('click', () => {
26
  this.loadSelectedDataset();
27
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  }
29
 
30
  async loadDatasets() {
 
123
 
124
  const datasetsHtml = this.datasets.map(dataset => this.renderDatasetCard(dataset)).join('');
125
  container.innerHTML = `<div class="row">${datasetsHtml}</div>`;
 
 
 
 
 
126
  }
127
 
128
  renderDatasetCard(dataset) {
 
182
  </div>
183
 
184
  <div class="dataset-actions">
185
+ <button class="btn btn-outline-info btn-sm flex-fill"
186
  onclick="medicalDatasets.showDatasetDetails('${dataset.key}')">
187
  <i class="fas fa-info-circle me-1"></i>
188
  التفاصيل
189
  </button>
 
 
 
 
 
190
  ${!isLoaded ? `
191
+ <button class="btn btn-primary btn-sm flex-fill"
192
  onclick="medicalDatasets.loadDataset('${dataset.key}')">
193
  <i class="fas fa-download me-1"></i>
194
  تحميل
195
  </button>
196
  ` : `
197
+ <button class="btn btn-success btn-sm flex-fill" disabled>
198
  <i class="fas fa-check me-1"></i>
199
  محمل
200
  </button>
 
260
  }
261
 
262
  showDatasetDetails(datasetKey) {
 
263
  const dataset = this.datasets.find(d => d.key === datasetKey);
264
  if (!dataset) return;
265
 
 
311
  }
312
 
313
  async loadDataset(datasetKey) {
 
314
  const dataset = this.datasets.find(d => d.key === datasetKey);
315
  if (!dataset) return;
316
 
 
366
  this.showSuccess('تم تحديث البيانات');
367
  }
368
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
369
  showSuccess(message) {
370
+ document.getElementById('success-message').textContent = message;
371
+ const toast = new bootstrap.Toast(document.getElementById('success-toast'));
372
+ toast.show();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
373
  }
374
 
375
  showError(message) {
376
+ document.getElementById('error-message').textContent = message;
377
+ const toast = new bootstrap.Toast(document.getElementById('error-toast'));
378
+ toast.show();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
  }
380
  }
381
 
static/js/saved-items.js DELETED
@@ -1,370 +0,0 @@
1
- /**
2
- * Saved Items Manager JavaScript
3
- * Handles saved models and datasets on the main page
4
- */
5
-
6
- class SavedItemsManager {
7
- constructor() {
8
- this.teacherModels = [];
9
- this.studentModels = [];
10
- this.datasets = [];
11
- this.selectedTeachers = [];
12
- this.selectedStudent = null;
13
- this.selectedDatasets = [];
14
- this.init();
15
- }
16
-
17
- init() {
18
- this.loadSavedItems();
19
- this.setupEventListeners();
20
-
21
- // Refresh data every 30 seconds
22
- setInterval(() => this.loadSavedItems(), 30000);
23
- }
24
-
25
- setupEventListeners() {
26
- // Start training button
27
- document.getElementById('start-training-btn').addEventListener('click', () => {
28
- this.startTraining();
29
- });
30
- }
31
-
32
- async loadSavedItems() {
33
- await Promise.all([
34
- this.loadTeacherModels(),
35
- this.loadStudentModels(),
36
- this.loadDatasets()
37
- ]);
38
-
39
- this.renderAllItems();
40
- this.updateTrainingSummary();
41
- }
42
-
43
- async loadTeacherModels() {
44
- try {
45
- const response = await fetch('/api/models/teacher');
46
- const data = await response.json();
47
-
48
- if (response.ok) {
49
- this.teacherModels = data.models;
50
- }
51
- } catch (error) {
52
- console.error('Error loading teacher models:', error);
53
- }
54
- }
55
-
56
- async loadStudentModels() {
57
- try {
58
- const response = await fetch('/api/models/student');
59
- const data = await response.json();
60
-
61
- if (response.ok) {
62
- this.studentModels = data.models;
63
- }
64
- } catch (error) {
65
- console.error('Error loading student models:', error);
66
- }
67
- }
68
-
69
- async loadDatasets() {
70
- try {
71
- const response = await fetch('/api/datasets/saved');
72
- const data = await response.json();
73
-
74
- if (response.ok) {
75
- this.datasets = data.datasets;
76
- }
77
- } catch (error) {
78
- console.error('Error loading datasets:', error);
79
- }
80
- }
81
-
82
- renderAllItems() {
83
- this.renderTeacherModels();
84
- this.renderStudentModels();
85
- this.renderDatasets();
86
- }
87
-
88
- renderTeacherModels() {
89
- const container = document.getElementById('saved-teacher-models');
90
-
91
- if (this.teacherModels.length === 0) {
92
- container.innerHTML = `
93
- <div class="empty-state">
94
- <i class="fas fa-chalkboard-teacher fa-3x text-muted mb-3"></i>
95
- <p class="text-muted">لا توجد نماذج معلمة محفوظة</p>
96
- <a href="/google-models" class="btn btn-primary">إضافة نماذج معلمة</a>
97
- </div>
98
- `;
99
- return;
100
- }
101
-
102
- const modelsHtml = this.teacherModels.map(model => `
103
- <div class="saved-item ${this.selectedTeachers.includes(model.id) ? 'selected' : ''}"
104
- onclick="savedItems.toggleTeacherSelection('${model.id}')">
105
- <div class="item-header">
106
- <h6>${model.name}</h6>
107
- <span class="item-type">${model.model_type}</span>
108
- </div>
109
- <div class="item-id">${model.model_id}</div>
110
- ${model.description ? `<div class="item-description">${model.description}</div>` : ''}
111
- <div class="item-actions">
112
- <button class="btn btn-sm ${this.selectedTeachers.includes(model.id) ? 'btn-success' : 'btn-outline-primary'}"
113
- onclick="event.stopPropagation(); savedItems.toggleTeacherSelection('${model.id}')">
114
- <i class="fas ${this.selectedTeachers.includes(model.id) ? 'fa-check' : 'fa-plus'}"></i>
115
- ${this.selectedTeachers.includes(model.id) ? 'مختار' : 'اختيار'}
116
- </button>
117
- </div>
118
- </div>
119
- `).join('');
120
-
121
- container.innerHTML = modelsHtml;
122
- }
123
-
124
- renderStudentModels() {
125
- const container = document.getElementById('saved-student-models');
126
-
127
- if (this.studentModels.length === 0) {
128
- container.innerHTML = `
129
- <div class="empty-state">
130
- <i class="fas fa-graduation-cap fa-3x text-muted mb-3"></i>
131
- <p class="text-muted">لا توجد نماذج طلابية محفوظة</p>
132
- <a href="/google-models" class="btn btn-info">إضافة نماذج طلابية</a>
133
- </div>
134
- `;
135
- return;
136
- }
137
-
138
- const modelsHtml = this.studentModels.map(model => `
139
- <div class="saved-item ${this.selectedStudent === model.id ? 'selected' : ''}"
140
- onclick="savedItems.selectStudent('${model.id}')">
141
- <div class="item-header">
142
- <h6>${model.name}</h6>
143
- <span class="item-type">طالب</span>
144
- </div>
145
- ${model.model_id ? `<div class="item-id">${model.model_id}</div>` : '<div class="text-muted">نموذج جديد</div>'}
146
- ${model.description ? `<div class="item-description">${model.description}</div>` : ''}
147
- <div class="item-actions">
148
- <button class="btn btn-sm ${this.selectedStudent === model.id ? 'btn-success' : 'btn-outline-info'}"
149
- onclick="event.stopPropagation(); savedItems.selectStudent('${model.id}')">
150
- <i class="fas ${this.selectedStudent === model.id ? 'fa-check' : 'fa-plus'}"></i>
151
- ${this.selectedStudent === model.id ? 'مختار' : 'اختيار'}
152
- </button>
153
- </div>
154
- </div>
155
- `).join('');
156
-
157
- container.innerHTML = modelsHtml;
158
- }
159
-
160
- renderDatasets() {
161
- const container = document.getElementById('saved-datasets');
162
-
163
- if (this.datasets.length === 0) {
164
- container.innerHTML = `
165
- <div class="empty-state">
166
- <i class="fas fa-database fa-3x text-muted mb-3"></i>
167
- <p class="text-muted">لا توجد قواعد بيانات محفوظة</p>
168
- <a href="/medical-datasets" class="btn btn-success">إضافة قواعد بيانات</a>
169
- </div>
170
- `;
171
- return;
172
- }
173
-
174
- const datasetsHtml = this.datasets.map(dataset => `
175
- <div class="saved-item ${this.selectedDatasets.includes(dataset.id) ? 'selected' : ''}"
176
- onclick="savedItems.toggleDatasetSelection('${dataset.id}')">
177
- <div class="item-header">
178
- <h6>${dataset.name}</h6>
179
- <span class="item-type">${dataset.dataset_type}</span>
180
- </div>
181
- <div class="item-id">${dataset.dataset_key}</div>
182
- ${dataset.description ? `<div class="item-description">${dataset.description}</div>` : ''}
183
- <div class="item-actions">
184
- <button class="btn btn-sm ${this.selectedDatasets.includes(dataset.id) ? 'btn-success' : 'btn-outline-success'}"
185
- onclick="event.stopPropagation(); savedItems.toggleDatasetSelection('${dataset.id}')">
186
- <i class="fas ${this.selectedDatasets.includes(dataset.id) ? 'fa-check' : 'fa-plus'}"></i>
187
- ${this.selectedDatasets.includes(dataset.id) ? 'مختار' : 'اختيار'}
188
- </button>
189
- </div>
190
- </div>
191
- `).join('');
192
-
193
- container.innerHTML = datasetsHtml;
194
- }
195
-
196
- toggleTeacherSelection(modelId) {
197
- const index = this.selectedTeachers.indexOf(modelId);
198
- if (index > -1) {
199
- this.selectedTeachers.splice(index, 1);
200
- } else {
201
- this.selectedTeachers.push(modelId);
202
- }
203
-
204
- this.renderTeacherModels();
205
- this.updateTrainingSummary();
206
- }
207
-
208
- selectStudent(modelId) {
209
- this.selectedStudent = this.selectedStudent === modelId ? null : modelId;
210
- this.renderStudentModels();
211
- this.updateTrainingSummary();
212
- }
213
-
214
- toggleDatasetSelection(datasetId) {
215
- const index = this.selectedDatasets.indexOf(datasetId);
216
- if (index > -1) {
217
- this.selectedDatasets.splice(index, 1);
218
- } else {
219
- this.selectedDatasets.push(datasetId);
220
- }
221
-
222
- this.renderDatasets();
223
- this.updateTrainingSummary();
224
- }
225
-
226
- updateTrainingSummary() {
227
- // Update counts
228
- document.getElementById('training-teachers-count').textContent = this.selectedTeachers.length;
229
- document.getElementById('training-datasets-count').textContent = this.selectedDatasets.length;
230
-
231
- // Update student name
232
- const studentName = this.selectedStudent ?
233
- this.studentModels.find(m => m.id === this.selectedStudent)?.name || 'غير محدد' :
234
- 'غير محدد';
235
- document.getElementById('training-student-name').textContent = studentName;
236
-
237
- // Update selected items in config section
238
- this.updateSelectedItemsDisplay();
239
-
240
- // Enable/disable start training button
241
- const canStart = this.selectedTeachers.length > 0 && this.selectedDatasets.length > 0;
242
- document.getElementById('start-training-btn').disabled = !canStart;
243
- }
244
-
245
- updateSelectedItemsDisplay() {
246
- // Update selected teacher models
247
- const teachersContainer = document.getElementById('selected-teacher-models');
248
- if (this.selectedTeachers.length === 0) {
249
- teachersContainer.innerHTML = '<p class="text-muted">لم يتم اختيار نماذج معلمة</p>';
250
- } else {
251
- const selectedTeacherNames = this.selectedTeachers.map(id => {
252
- const model = this.teacherModels.find(m => m.id === id);
253
- return model ? model.name : 'غير معروف';
254
- });
255
- teachersContainer.innerHTML = `
256
- <div class="selected-items-list">
257
- ${selectedTeacherNames.map(name => `<span class="badge bg-primary me-1">${name}</span>`).join('')}
258
- </div>
259
- `;
260
- }
261
-
262
- // Update selected student model
263
- const studentContainer = document.getElementById('selected-student-model');
264
- if (!this.selectedStudent) {
265
- studentContainer.innerHTML = '<p class="text-muted">لم يتم اختيار نموذج طالب</p>';
266
- } else {
267
- const student = this.studentModels.find(m => m.id === this.selectedStudent);
268
- studentContainer.innerHTML = `
269
- <div class="selected-items-list">
270
- <span class="badge bg-info">${student ? student.name : 'غير معروف'}</span>
271
- </div>
272
- `;
273
- }
274
-
275
- // Update selected datasets
276
- const datasetsContainer = document.getElementById('selected-datasets');
277
- if (this.selectedDatasets.length === 0) {
278
- datasetsContainer.innerHTML = '<p class="text-muted">لم يتم اختيار قواعد بيانات</p>';
279
- } else {
280
- const selectedDatasetNames = this.selectedDatasets.map(id => {
281
- const dataset = this.datasets.find(d => d.id === id);
282
- return dataset ? dataset.name : 'غير معروف';
283
- });
284
- datasetsContainer.innerHTML = `
285
- <div class="selected-items-list">
286
- ${selectedDatasetNames.map(name => `<span class="badge bg-success me-1">${name}</span>`).join('')}
287
- </div>
288
- `;
289
- }
290
- }
291
-
292
- async startTraining() {
293
- if (this.selectedTeachers.length === 0 || this.selectedDatasets.length === 0) {
294
- this.showError('يجب اختيار نماذج معلمة وقواعد بيانات على الأقل');
295
- return;
296
- }
297
-
298
- try {
299
- // Prepare training configuration
300
- const config = {
301
- teacher_models: this.selectedTeachers,
302
- student_model: this.selectedStudent,
303
- datasets: this.selectedDatasets,
304
- session_id: 'session_' + Date.now()
305
- };
306
-
307
- // Show training section
308
- document.getElementById('step-1').style.display = 'none';
309
- document.getElementById('step-2').style.display = 'block';
310
-
311
- this.showSuccess('تم بدء عملية التدريب بنجاح');
312
-
313
- // Here you would typically start the actual training process
314
- // For now, we'll just show a success message
315
-
316
- } catch (error) {
317
- console.error('Error starting training:', error);
318
- this.showError('خطأ في بدء التدريب');
319
- }
320
- }
321
-
322
- showSuccess(message) {
323
- // Create and show success toast
324
- const toast = document.createElement('div');
325
- toast.className = 'toast align-items-center text-white bg-success border-0 position-fixed';
326
- toast.style.cssText = 'top: 20px; right: 20px; z-index: 9999;';
327
- toast.innerHTML = `
328
- <div class="d-flex">
329
- <div class="toast-body">
330
- <i class="fas fa-check-circle me-2"></i>${message}
331
- </div>
332
- <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
333
- </div>
334
- `;
335
- document.body.appendChild(toast);
336
-
337
- const bsToast = new bootstrap.Toast(toast);
338
- bsToast.show();
339
-
340
- setTimeout(() => {
341
- document.body.removeChild(toast);
342
- }, 5000);
343
- }
344
-
345
- showError(message) {
346
- // Create and show error toast
347
- const toast = document.createElement('div');
348
- toast.className = 'toast align-items-center text-white bg-danger border-0 position-fixed';
349
- toast.style.cssText = 'top: 20px; right: 20px; z-index: 9999;';
350
- toast.innerHTML = `
351
- <div class="d-flex">
352
- <div class="toast-body">
353
- <i class="fas fa-exclamation-circle me-2"></i>${message}
354
- </div>
355
- <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
356
- </div>
357
- `;
358
- document.body.appendChild(toast);
359
-
360
- const bsToast = new bootstrap.Toast(toast);
361
- bsToast.show();
362
-
363
- setTimeout(() => {
364
- document.body.removeChild(toast);
365
- }, 5000);
366
- }
367
- }
368
-
369
- // Initialize the manager when the page loads
370
- const savedItems = new SavedItemsManager();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/google-models.html DELETED
@@ -1,373 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="ar" dir="rtl">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>إدارة نماذج Hugging Face - منصة تقطير المعرفة</title>
7
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
8
- <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
9
- <link href="/static/css/style.css" rel="stylesheet">
10
- <style>
11
- .model-card {
12
- border: 1px solid #dee2e6;
13
- border-radius: 12px;
14
- padding: 25px;
15
- margin-bottom: 20px;
16
- background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
17
- transition: all 0.3s ease;
18
- box-shadow: 0 2px 4px rgba(0,0,0,0.05);
19
- }
20
-
21
- .model-card:hover {
22
- transform: translateY(-2px);
23
- box-shadow: 0 4px 12px rgba(0,0,0,0.1);
24
- border-color: #007bff;
25
- }
26
-
27
- .model-header {
28
- display: flex;
29
- justify-content: space-between;
30
- align-items: center;
31
- margin-bottom: 15px;
32
- }
33
-
34
- .model-title {
35
- font-size: 1.2rem;
36
- font-weight: 600;
37
- color: #2c3e50;
38
- margin: 0;
39
- }
40
-
41
- .model-type {
42
- background: #e3f2fd;
43
- color: #1976d2;
44
- padding: 4px 12px;
45
- border-radius: 20px;
46
- font-size: 0.85rem;
47
- font-weight: 500;
48
- }
49
-
50
- .model-id {
51
- font-family: 'Courier New', monospace;
52
- background: #f8f9fa;
53
- padding: 8px 12px;
54
- border-radius: 6px;
55
- font-size: 0.9rem;
56
- color: #495057;
57
- border: 1px solid #e9ecef;
58
- }
59
-
60
- .model-description {
61
- color: #6c757d;
62
- margin: 10px 0;
63
- line-height: 1.5;
64
- }
65
-
66
- .model-tags {
67
- margin: 10px 0;
68
- }
69
-
70
- .tag {
71
- background: #f1f3f4;
72
- color: #5f6368;
73
- padding: 4px 8px;
74
- border-radius: 12px;
75
- font-size: 0.8rem;
76
- margin-left: 5px;
77
- display: inline-block;
78
- }
79
-
80
- .add-model-form {
81
- background: #ffffff;
82
- border: 2px dashed #dee2e6;
83
- border-radius: 12px;
84
- padding: 30px;
85
- margin-bottom: 30px;
86
- text-align: center;
87
- transition: all 0.3s ease;
88
- }
89
-
90
- .add-model-form:hover {
91
- border-color: #007bff;
92
- background: #f8f9ff;
93
- }
94
-
95
- .form-section {
96
- background: #ffffff;
97
- border-radius: 12px;
98
- padding: 25px;
99
- margin-bottom: 20px;
100
- box-shadow: 0 2px 4px rgba(0,0,0,0.05);
101
- }
102
-
103
- .section-title {
104
- font-size: 1.3rem;
105
- font-weight: 600;
106
- color: #2c3e50;
107
- margin-bottom: 20px;
108
- display: flex;
109
- align-items: center;
110
- }
111
-
112
- .section-title i {
113
- margin-left: 10px;
114
- color: #007bff;
115
- }
116
-
117
- .btn-add-model {
118
- background: linear-gradient(135deg, #007bff 0%, #0056b3 100%);
119
- border: none;
120
- padding: 12px 30px;
121
- border-radius: 8px;
122
- font-weight: 600;
123
- transition: all 0.3s ease;
124
- }
125
-
126
- .btn-add-model:hover {
127
- transform: translateY(-1px);
128
- box-shadow: 0 4px 12px rgba(0,123,255,0.3);
129
- }
130
-
131
- .stats-card {
132
- background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
133
- color: white;
134
- border-radius: 12px;
135
- padding: 20px;
136
- text-align: center;
137
- }
138
-
139
- .stats-number {
140
- font-size: 2rem;
141
- font-weight: bold;
142
- margin-bottom: 5px;
143
- }
144
-
145
- .stats-label {
146
- font-size: 0.9rem;
147
- opacity: 0.9;
148
- }
149
-
150
- .google-models-section {
151
- background: #fff3e0;
152
- border: 1px solid #ffcc02;
153
- border-radius: 12px;
154
- padding: 20px;
155
- margin-bottom: 20px;
156
- }
157
-
158
- .google-model-item {
159
- background: white;
160
- border: 1px solid #e0e0e0;
161
- border-radius: 8px;
162
- padding: 15px;
163
- margin-bottom: 10px;
164
- display: flex;
165
- justify-content: space-between;
166
- align-items: center;
167
- }
168
-
169
- .google-model-info h6 {
170
- margin: 0 0 5px 0;
171
- color: #2c3e50;
172
- }
173
-
174
- .google-model-info small {
175
- color: #6c757d;
176
- }
177
- </style>
178
- </head>
179
- <body>
180
- <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
181
- <div class="container">
182
- <a class="navbar-brand" href="/">
183
- <i class="fas fa-brain me-2"></i>
184
- منصة تقطير المعرفة
185
- </a>
186
- <div class="navbar-nav ms-auto">
187
- <a class="nav-link" href="/">الرئيسية</a>
188
- <a class="nav-link" href="/tokens">إدارة الرموز</a>
189
- <a class="nav-link" href="/medical-datasets">البيانات الطبية</a>
190
- <a class="nav-link active" href="/google-models">النماذج</a>
191
- </div>
192
- </div>
193
- </nav>
194
-
195
- <div class="container mt-4">
196
- <div class="row">
197
- <div class="col-12">
198
- <div class="d-flex justify-content-between align-items-center mb-4">
199
- <div>
200
- <h2><i class="fas fa-robot me-2"></i>إدارة نماذج Hugging Face</h2>
201
- <p class="text-muted">إضافة وإدارة النماذج المعلمة والطلابية من Hugging Face للاستخدام في عملية التقطير</p>
202
- <div class="alert alert-info mt-2">
203
- <i class="fas fa-info-circle me-2"></i>
204
- <strong>تلميح:</strong> أضف النماذج المعلمة من النماذج الشائعة على Hugging Face أو أدخل معرفات نماذج مخصصة. جميع النماذج من منصة Hugging Face.
205
- </div>
206
- </div>
207
- <div>
208
- <button class="btn btn-outline-primary" onclick="googleModels.refreshModels()">
209
- <i class="fas fa-sync-alt me-2"></i>تحديث
210
- </button>
211
- </div>
212
- </div>
213
-
214
- <!-- Statistics -->
215
- <div class="row mb-4">
216
- <div class="col-md-4">
217
- <div class="stats-card">
218
- <div class="stats-number" id="teacher-count">0</div>
219
- <div class="stats-label">النماذج المعلمة</div>
220
- </div>
221
- </div>
222
- <div class="col-md-4">
223
- <div class="stats-card" style="background: linear-gradient(135deg, #17a2b8 0%, #138496 100%);">
224
- <div class="stats-number" id="student-count">0</div>
225
- <div class="stats-label">النماذج الطلابية</div>
226
- </div>
227
- </div>
228
- <div class="col-md-4">
229
- <div class="stats-card" style="background: linear-gradient(135deg, #ffc107 0%, #e0a800 100%);">
230
- <div class="stats-number" id="google-count">5</div>
231
- <div class="stats-label">نماذج HF الشائعة</div>
232
- </div>
233
- </div>
234
- </div>
235
-
236
- <!-- Add Teacher Model Form -->
237
- <div class="form-section">
238
- <h3 class="section-title">
239
- <i class="fas fa-plus-circle"></i>
240
- إضافة نموذج معلم جديد
241
- </h3>
242
- <form id="add-teacher-form">
243
- <div class="row">
244
- <div class="col-md-6">
245
- <div class="mb-3">
246
- <label for="teacher-name" class="form-label">اسم النموذج</label>
247
- <input type="text" class="form-control" id="teacher-name" required>
248
- </div>
249
- </div>
250
- <div class="col-md-6">
251
- <div class="mb-3">
252
- <label for="teacher-model-id" class="form-label">معرف النموذج</label>
253
- <input type="text" class="form-control" id="teacher-model-id"
254
- placeholder="مثل: google/gemma-3n-E4B-it" required>
255
- </div>
256
- </div>
257
- </div>
258
- <div class="row">
259
- <div class="col-md-8">
260
- <div class="mb-3">
261
- <label for="teacher-description" class="form-label">الوصف</label>
262
- <textarea class="form-control" id="teacher-description" rows="2"></textarea>
263
- </div>
264
- </div>
265
- <div class="col-md-4">
266
- <div class="mb-3">
267
- <label for="teacher-type" class="form-label">نوع ال��موذج</label>
268
- <select class="form-control" id="teacher-type">
269
- <option value="huggingface">Hugging Face</option>
270
- <option value="google">Google</option>
271
- <option value="openai">OpenAI</option>
272
- <option value="custom">مخصص</option>
273
- </select>
274
- </div>
275
- </div>
276
- </div>
277
- <div class="mb-3">
278
- <label for="teacher-tags" class="form-label">العلامات (مفصولة بفواصل)</label>
279
- <input type="text" class="form-control" id="teacher-tags"
280
- placeholder="مثل: language, multimodal, medical">
281
- </div>
282
- <button type="submit" class="btn btn-primary btn-add-model">
283
- <i class="fas fa-plus me-2"></i>إضافة النموذج المعلم
284
- </button>
285
- </form>
286
- </div>
287
-
288
- <!-- Add Student Model Form -->
289
- <div class="form-section">
290
- <h3 class="section-title">
291
- <i class="fas fa-graduation-cap"></i>
292
- إضافة نموذج طالب جديد
293
- </h3>
294
- <form id="add-student-form">
295
- <div class="row">
296
- <div class="col-md-6">
297
- <div class="mb-3">
298
- <label for="student-name" class="form-label">اسم النموذج</label>
299
- <input type="text" class="form-control" id="student-name" required>
300
- </div>
301
- </div>
302
- <div class="col-md-6">
303
- <div class="mb-3">
304
- <label for="student-model-id" class="form-label">معرف النموذج (اختياري)</label>
305
- <input type="text" class="form-control" id="student-model-id"
306
- placeholder="للنماذج المدربة مسبقاً">
307
- </div>
308
- </div>
309
- </div>
310
- <div class="mb-3">
311
- <label for="student-description" class="form-label">الوصف</label>
312
- <textarea class="form-control" id="student-description" rows="2"></textarea>
313
- </div>
314
- <button type="submit" class="btn btn-info btn-add-model">
315
- <i class="fas fa-plus me-2"></i>إضافة النموذج الطالب
316
- </button>
317
- </form>
318
- </div>
319
-
320
- <!-- Popular HF Models Section -->
321
- <div class="google-models-section">
322
- <h3 class="section-title">
323
- <i class="fab fa-github"></i>
324
- نماذج Hugging Face الشائعة
325
- </h3>
326
- <div id="google-models-list">
327
- <div class="text-center">
328
- <div class="spinner-border text-primary" role="status">
329
- <span class="visually-hidden">جاري تحميل النماذج...</span>
330
- </div>
331
- </div>
332
- </div>
333
- </div>
334
-
335
- <!-- Saved Teacher Models -->
336
- <div class="form-section">
337
- <h3 class="section-title">
338
- <i class="fas fa-chalkboard-teacher"></i>
339
- النماذج المعلمة المحفوظة
340
- </h3>
341
- <div id="teacher-models-list">
342
- <div class="text-center">
343
- <div class="spinner-border text-primary" role="status">
344
- <span class="visually-hidden">جاري تحميل النماذج...</span>
345
- </div>
346
- </div>
347
- </div>
348
- </div>
349
-
350
- <!-- Saved Student Models -->
351
- <div class="form-section">
352
- <h3 class="section-title">
353
- <i class="fas fa-graduation-cap"></i>
354
- النماذج الطلابية المحفوظة
355
- </h3>
356
- <div id="student-models-list">
357
- <div class="text-center">
358
- <div class="spinner-border text-primary" role="status">
359
- <span class="visually-hidden">جاري تحميل النماذج...</span>
360
- </div>
361
- </div>
362
- </div>
363
- </div>
364
- </div>
365
- </div>
366
- </div>
367
-
368
- <!-- Bootstrap JS -->
369
- <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
370
- <!-- Custom JS -->
371
- <script src="/static/js/google-models.js"></script>
372
- </body>
373
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/index.html CHANGED
@@ -32,10 +32,10 @@
32
  <span>Medical Datasets</span>
33
  <small>Specialized medical data</small>
34
  </a>
35
- <a href="/google-models" class="nav-link">
36
- <i class="fab fa-github"></i>
37
- <span>Hugging Face Models</span>
38
- <small>Popular HF models</small>
39
  </a>
40
  <a href="#system-info" class="nav-link" onclick="showSystemInfo()">
41
  <i class="fas fa-microchip"></i>
@@ -51,128 +51,250 @@
51
  <!-- Step 1: Model Selection -->
52
  <section class="step-section" id="step-1">
53
  <div class="step-header">
54
- <h2><span class="step-number">1</span> اختيار النماذج والبيانات</h2>
55
- <p>اختر النماذج المعلمة وقواعد البيانات المحفوظة لبدء عملية التقطير</p>
56
  </div>
57
 
58
  <div class="model-selection">
59
- <!-- Quick Access Links -->
60
- <div class="quick-access-section">
61
- <h3><i class="fas fa-rocket"></i> الوصول السريع</h3>
62
- <div class="quick-access-buttons">
63
- <a href="/google-models" class="btn btn-primary btn-lg">
64
- <i class="fab fa-github me-2"></i>نماذج Hugging Face
65
- </a>
66
- <a href="/medical-datasets" class="btn btn-success btn-lg">
67
- <i class="fas fa-database me-2"></i>البيانات الطبية
68
- </a>
69
- <a href="/tokens" class="btn btn-warning btn-lg">
70
- <i class="fas fa-key me-2"></i>إدارة الرموز
71
- </a>
72
  </div>
 
73
  </div>
74
 
75
- <!-- Saved Teacher Models -->
76
- <div class="saved-models-section">
77
- <h3><i class="fas fa-chalkboard-teacher"></i> النماذج المعلمة المحفوظة</h3>
78
- <div id="saved-teacher-models" class="saved-items-grid">
79
- <div class="loading-placeholder">
80
- <div class="spinner-border text-primary" role="status">
81
- <span class="visually-hidden">جاري التحميل...</span>
82
- </div>
83
- <p class="mt-2">جاري تحميل النماذج المعلمة...</p>
 
 
 
 
 
 
 
 
84
  </div>
85
  </div>
86
- </div>
87
 
88
- <!-- Saved Student Models -->
89
- <div class="saved-models-section">
90
- <h3><i class="fas fa-graduation-cap"></i> النماذج الطلابية المحفوظة</h3>
91
- <div id="saved-student-models" class="saved-items-grid">
92
- <div class="loading-placeholder">
93
- <div class="spinner-border text-primary" role="status">
94
- <span class="visually-hidden">جاري التحميل...</span>
95
- </div>
96
- <p class="mt-2">جاري تحميل النماذج الطلابية...</p>
 
 
 
 
 
 
 
 
 
97
  </div>
 
 
 
 
 
98
  </div>
99
- </div>
100
 
101
- <!-- Saved Datasets -->
102
- <div class="saved-datasets-section">
103
- <h3><i class="fas fa-database"></i> قواعد البيانات المحفوظة</h3>
104
- <div id="saved-datasets" class="saved-items-grid">
105
- <div class="loading-placeholder">
106
- <div class="spinner-border text-primary" role="status">
107
- <span class="visually-hidden">جاري التحميل...</span>
108
- </div>
109
- <p class="mt-2">جاري تحميل قواعد البيانات...</p>
110
- </div>
111
  </div>
112
- </div>
113
 
114
- <!-- Training Configuration -->
115
- <div class="training-config-section">
116
- <h3><i class="fas fa-cogs"></i> إعدادات التدريب</h3>
117
- <div class="config-grid">
118
- <div class="config-item">
119
- <label for="selected-teacher-models">النماذج المعلمة المختارة:</label>
120
- <div id="selected-teacher-models" class="selected-items">
121
- <p class="text-muted">لم يتم اختيار نماذج معلمة</p>
122
- </div>
123
- </div>
124
- <div class="config-item">
125
- <label for="selected-student-model">النموذج الطالب المخ��ار:</label>
126
- <div id="selected-student-model" class="selected-items">
127
- <p class="text-muted">لم يتم اختيار نموذج طالب</p>
128
- </div>
129
- </div>
130
- <div class="config-item">
131
- <label for="selected-datasets">قواعد البيانات المختارة:</label>
132
- <div id="selected-datasets" class="selected-items">
133
- <p class="text-muted">لم يتم اختيار قواعد بيانات</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  </div>
135
- </div>
136
- </div>
137
- </div>
138
 
 
 
 
 
 
 
 
 
 
 
 
 
139
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
 
142
- </div>
 
 
 
 
 
 
 
143
 
144
- <!-- Start Training Section -->
145
- <div class="start-training-section">
146
- <h3><i class="fas fa-play"></i> بدء التدريب</h3>
147
- <div class="training-summary">
148
- <div class="summary-item">
149
- <strong>النماذج المعلمة:</strong> <span id="training-teachers-count">0</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  </div>
151
- <div class="summary-item">
152
- <strong>النموذج الطالب:</strong> <span id="training-student-name">��ير محدد</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  </div>
154
- <div class="summary-item">
155
- <strong>قواعد البيانات:</strong> <span id="training-datasets-count">0</span>
 
 
 
 
 
 
 
 
 
156
  </div>
 
157
  </div>
158
- <button id="start-training-btn" class="btn btn-success btn-lg" disabled>
159
- <i class="fas fa-rocket me-2"></i>بدء عملية التقطير
160
- </button>
161
  </div>
162
- </section>
163
 
164
- <!-- Step 2: Training Progress -->
165
- <section class="step-section" id="step-2" style="display: none;">
166
- <div class="step-header">
167
- <h2><span class="step-number">2</span> تقدم التدريب</h2>
168
- <p>مراقبة عملية تقطير المعرفة</p>
169
  </div>
170
 
171
- <div class="training-progress-container">
172
- <div class="progress-info">
173
- <h4>جاري التدريب...</h4>
174
- <p>سيتم عرض تقدم التدريب هنا</p>
175
- </div>
176
  </div>
177
  </section>
178
 
@@ -423,6 +545,5 @@
423
  </div>
424
 
425
  <script src="/static/js/main.js"></script>
426
- <script src="/static/js/saved-items.js"></script>
427
  </body>
428
  </html>
 
32
  <span>Medical Datasets</span>
33
  <small>Specialized medical data</small>
34
  </a>
35
+ <a href="#google-models" class="nav-link" onclick="showGoogleModels()">
36
+ <i class="fab fa-google"></i>
37
+ <span>Google Models</span>
38
+ <small>Open source models</small>
39
  </a>
40
  <a href="#system-info" class="nav-link" onclick="showSystemInfo()">
41
  <i class="fas fa-microchip"></i>
 
51
  <!-- Step 1: Model Selection -->
52
  <section class="step-section" id="step-1">
53
  <div class="step-header">
54
+ <h2><span class="step-number">1</span> Select Teacher Models</h2>
55
+ <p>Choose 1-10 pre-trained models to serve as teachers for knowledge distillation</p>
56
  </div>
57
 
58
  <div class="model-selection">
59
+ <!-- Upload Models -->
60
+ <div class="upload-section">
61
+ <h3><i class="fas fa-upload"></i> Upload Model Files</h3>
62
+ <div class="upload-area" id="upload-area">
63
+ <div class="upload-content">
64
+ <i class="fas fa-cloud-upload-alt"></i>
65
+ <p>Drag & drop model files here or click to browse</p>
66
+ <p class="upload-hint">Supported formats: .pt, .pth, .bin, .safetensors (max 5GB each)</p>
67
+ </div>
68
+ <input type="file" id="file-input" multiple accept=".pt,.pth,.bin,.safetensors" hidden>
 
 
 
69
  </div>
70
+ <div class="uploaded-files" id="uploaded-files"></div>
71
  </div>
72
 
73
+ <!-- Hugging Face Models -->
74
+ <div class="hf-section">
75
+ <h3><i class="fab fa-github"></i> Hugging Face Models</h3>
76
+
77
+ <!-- Token Selection for Model Access -->
78
+ <div class="token-selection mb-3">
79
+ <label for="model-access-type" class="form-label">
80
+ <i class="fas fa-key me-1"></i>نوع الوصول للنموذج
81
+ </label>
82
+ <select id="model-access-type" class="form-select">
83
+ <option value="read">نماذج عامة (رمز القراءة)</option>
84
+ <option value="private">نماذج خاصة (رمز مخصص)</option>
85
+ <option value="medical">نماذج طبية (رمز مخصص)</option>
86
+ <option value="commercial">نماذج تجارية (رمز مخصص)</option>
87
+ </select>
88
+ <div class="help-text">
89
+ <small class="text-muted">سيتم استخدام الرمز المناسب تلقائياً حسب نوع النموذج</small>
90
  </div>
91
  </div>
 
92
 
93
+ <div class="hf-input-group">
94
+ <input type="text" id="hf-repo" placeholder="Enter Hugging Face model repository (e.g., google/bert_uncased_L-2_H-128_A-2)" class="hf-input">
95
+ <button id="test-model" class="btn btn-secondary">
96
+ <i class="fas fa-vial"></i> Test
97
+ </button>
98
+ <button id="add-hf-model" class="btn btn-secondary">
99
+ <i class="fas fa-plus"></i> Add Model
100
+ </button>
101
+ </div>
102
+ <div class="hf-token-section">
103
+ <label for="hf-token">
104
+ <i class="fas fa-key"></i> Hugging Face Token (for private/gated models):
105
+ </label>
106
+ <div class="token-input-group">
107
+ <input type="password" id="hf-token" placeholder="hf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" class="hf-input">
108
+ <button id="test-token" class="btn btn-secondary">
109
+ <i class="fas fa-check"></i> Test Token
110
+ </button>
111
  </div>
112
+ <small class="token-help">
113
+ Optional: Required only for private or gated models.
114
+ <a href="https://huggingface.co/settings/tokens" target="_blank">Get your token here</a>
115
+ </small>
116
+ <div id="token-status" class="token-status hidden"></div>
117
  </div>
 
118
 
119
+ <div class="trust-code-section">
120
+ <label class="checkbox-label">
121
+ <input type="checkbox" id="trust-remote-code">
122
+ <span class="checkmark"></span>
123
+ <i class="fas fa-shield-alt"></i> Trust Remote Code
124
+ </label>
125
+ <small class="trust-help">
126
+ ⚠️ Enable this for models that require custom code execution (e.g., briaai/RMBG-1.4).
127
+ <strong>Only enable if you trust the model source!</strong>
128
+ </small>
129
  </div>
 
130
 
131
+ <!-- Incremental Training Section -->
132
+ <div class="incremental-training-section">
133
+ <h4><i class="fas fa-layer-group"></i> Incremental Training (Optional)</h4>
134
+ <p class="section-description">
135
+ Use a previously trained model as a starting point and add new teachers to it.
136
+ </p>
137
+
138
+ <label class="checkbox-label">
139
+ <input type="checkbox" id="enable-incremental">
140
+ <span class="checkmark"></span>
141
+ <i class="fas fa-plus-circle"></i> Enable Incremental Training
142
+ </label>
143
+
144
+ <div id="incremental-options" class="incremental-options hidden">
145
+ <div class="form-group">
146
+ <label for="student-source">Student Model Source:</label>
147
+ <div class="radio-group">
148
+ <label class="radio-label">
149
+ <input type="radio" name="student-source" value="local" checked>
150
+ <span class="radio-mark"></span>
151
+ Local Trained Models
152
+ </label>
153
+ <label class="radio-label">
154
+ <input type="radio" name="student-source" value="huggingface">
155
+ <span class="radio-mark"></span>
156
+ Hugging Face Model
157
+ </label>
158
+ <label class="radio-label">
159
+ <input type="radio" name="student-source" value="space">
160
+ <span class="radio-mark"></span>
161
+ Hugging Face Space
162
+ </label>
163
+ <label class="radio-label">
164
+ <input type="radio" name="student-source" value="upload">
165
+ <span class="radio-mark"></span>
166
+ Upload Model Files
167
+ </label>
168
+ </div>
169
  </div>
 
 
 
170
 
171
+ <!-- Local Models -->
172
+ <div id="local-student-options" class="student-source-options">
173
+ <div class="form-group">
174
+ <label for="existing-student">Select Local Student Model:</label>
175
+ <select id="existing-student" class="form-control">
176
+ <option value="">Loading trained models...</option>
177
+ </select>
178
+ <button id="refresh-students" class="btn btn-secondary btn-sm">
179
+ <i class="fas fa-refresh"></i> Refresh
180
+ </button>
181
+ </div>
182
+ </div>
183
 
184
+ <!-- Hugging Face Models -->
185
+ <div id="hf-student-options" class="student-source-options hidden">
186
+ <div class="form-group">
187
+ <label for="hf-student-repo">Hugging Face Student Model:</label>
188
+ <div class="hf-input-group">
189
+ <input type="text" id="hf-student-repo" placeholder="username/student-model-name" class="hf-input">
190
+ <button id="test-student-model" class="btn btn-secondary">
191
+ <i class="fas fa-vial"></i> Test
192
+ </button>
193
+ <button id="add-hf-student" class="btn btn-secondary">
194
+ <i class="fas fa-plus"></i> Add
195
+ </button>
196
+ </div>
197
+ <small>Enter a Hugging Face repository containing a trained student model</small>
198
+ </div>
199
+ </div>
200
 
201
+ <!-- Hugging Face Spaces -->
202
+ <div id="space-student-options" class="student-source-options hidden">
203
+ <div class="form-group">
204
+ <label for="hf-space-repo">Hugging Face Space:</label>
205
+ <div class="hf-input-group">
206
+ <input type="text" id="hf-space-repo" placeholder="username/space-name (e.g., fokan/train-modle2)" class="hf-input">
207
+ <button id="test-space-model" class="btn btn-secondary">
208
+ <i class="fas fa-vial"></i> Test
209
+ </button>
210
+ <button id="add-space-student" class="btn btn-secondary">
211
+ <i class="fas fa-plus"></i> Add
212
+ </button>
213
+ </div>
214
+ <small>Enter a Hugging Face Space that contains trained models (like fokan/train-modle2)</small>
215
+ <div class="alert alert-info" style="margin-top: 0.5rem; font-size: 0.85rem;">
216
+ <i class="fas fa-info-circle"></i>
217
+ <strong>Note:</strong> This will load models from another training Space. Make sure the Space has completed training and saved models.
218
+ </div>
219
+ </div>
220
+ </div>
221
 
222
+ <!-- Upload Models -->
223
+ <div id="upload-student-options" class="student-source-options hidden">
224
+ <div class="form-group">
225
+ <label for="student-file-upload">Upload Student Model Files:</label>
226
+ <input type="file" id="student-file-upload" multiple accept=".safetensors,.bin,.pt,.json">
227
+ <small>Upload model files (.safetensors, .bin, .pt) and config.json</small>
228
+ </div>
229
+ </div>
230
 
231
+ <div id="student-info" class="student-info hidden">
232
+ <h5>Model Information:</h5>
233
+ <div class="info-grid">
234
+ <div class="info-item">
235
+ <strong>Architecture:</strong> <span id="student-arch">-</span>
236
+ </div>
237
+ <div class="info-item">
238
+ <strong>Original Teachers:</strong> <span id="student-teachers">-</span>
239
+ </div>
240
+ <div class="info-item">
241
+ <strong>Training Sessions:</strong> <span id="student-sessions">-</span>
242
+ </div>
243
+ <div class="info-item">
244
+ <strong>Last Training:</strong> <span id="student-last">-</span>
245
+ </div>
246
+ </div>
247
+ <div class="alert alert-info">
248
+ <i class="fas fa-info-circle"></i>
249
+ <strong>Note:</strong> New teachers will be added to the existing teachers.
250
+ The model will learn from both old and new teachers.
251
+ </div>
252
+ </div>
253
+ </div>
254
  </div>
255
+ <div class="suggested-models">
256
+ <h4>Suggested Models:</h4>
257
+ <div class="model-suggestions">
258
+ <button class="suggestion-btn" data-model="google/bert_uncased_L-2_H-128_A-2">BERT Small</button>
259
+ <button class="suggestion-btn" data-model="distilbert-base-uncased">DistilBERT</button>
260
+ <button class="suggestion-btn" data-model="microsoft/DialoGPT-small">DialoGPT Small</button>
261
+ <button class="suggestion-btn" data-model="google/vit-base-patch16-224">ViT Base</button>
262
+ <button class="suggestion-btn" data-model="openai/clip-vit-base-patch32">CLIP</button>
263
+ <button class="suggestion-btn trust-required" data-model="briaai/RMBG-1.4" title="Requires Trust Remote Code">RMBG-1.4 ⚠️</button>
264
+ <button class="suggestion-btn trust-required" data-model="google/siglip-base-patch16-224" title="Advanced Vision Model">SigLIP ⚠️</button>
265
+ <button class="suggestion-btn trust-required gated-model" data-model="google/gemma-2b" title="Requires HF Token + Access">Gemma 2B 🔒</button>
266
+ </div>
267
+ <small class="suggestions-help">
268
+ ⚠️ Models with warning icon may require "Trust Remote Code" or special requirements.<br>
269
+ 🔒 Gated models require Hugging Face token and access permission.
270
+ </small>
271
  </div>
272
+ <div class="hf-models" id="hf-models"></div>
273
+ </div>
274
+
275
+ <!-- URL Models -->
276
+ <div class="url-section">
277
+ <h3><i class="fas fa-link"></i> Direct URLs</h3>
278
+ <div class="url-input-group">
279
+ <input type="text" id="model-url" placeholder="Enter direct download URL for model file" class="url-input">
280
+ <button id="add-url-model" class="btn btn-secondary">
281
+ <i class="fas fa-plus"></i> Add URL
282
+ </button>
283
  </div>
284
+ <div class="url-models" id="url-models"></div>
285
  </div>
 
 
 
286
  </div>
 
287
 
288
+ <!-- Selected Models Summary -->
289
+ <div class="selected-models" id="selected-models">
290
+ <h3>Selected Teacher Models (<span id="model-count">0</span>/10)</h3>
291
+ <div class="models-grid" id="models-grid"></div>
 
292
  </div>
293
 
294
+ <div class="step-actions">
295
+ <button id="next-step-1" class="btn btn-primary" disabled>
296
+ Next: Configure Training <i class="fas fa-arrow-right"></i>
297
+ </button>
 
298
  </div>
299
  </section>
300
 
 
545
  </div>
546
 
547
  <script src="/static/js/main.js"></script>
 
548
  </body>
549
  </html>
templates/medical-datasets.html CHANGED
@@ -16,9 +16,6 @@
16
  background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
17
  transition: all 0.3s ease;
18
  box-shadow: 0 2px 4px rgba(0,0,0,0.05);
19
- position: relative;
20
- pointer-events: auto;
21
- z-index: 1;
22
  }
23
  .dataset-card:hover {
24
  transform: translateY(-2px);
@@ -62,14 +59,6 @@
62
  display: flex;
63
  gap: 10px;
64
  margin-top: 15px;
65
- position: relative;
66
- z-index: 2;
67
- pointer-events: auto;
68
- }
69
-
70
- .dataset-actions button {
71
- pointer-events: auto;
72
- z-index: 3;
73
  }
74
  .medical-icon {
75
  font-size: 2.5em;
@@ -83,17 +72,11 @@
83
  right: 0;
84
  bottom: 0;
85
  background: rgba(255,255,255,0.9);
86
- display: none; /* Hidden by default */
87
  align-items: center;
88
  justify-content: center;
89
  border-radius: 12px;
90
- z-index: 100;
91
- pointer-events: none; /* Allow clicks to pass through when hidden */
92
- }
93
-
94
- .loading-overlay.active {
95
- display: flex;
96
- pointer-events: auto;
97
  }
98
  .dataset-status {
99
  position: absolute;
@@ -107,51 +90,6 @@
107
  .status-available { background: #d4edda; color: #155724; }
108
  .status-loading { background: #fff3cd; color: #856404; }
109
  .status-loaded { background: #cce5ff; color: #004085; }
110
-
111
- /* Ensure all interactive elements are clickable */
112
- .btn, button, [onclick] {
113
- pointer-events: auto !important;
114
- z-index: 10 !important;
115
- position: relative;
116
- }
117
-
118
- /* Fix for any overlay issues */
119
- .container, .row, .col-md-6, .col-lg-4 {
120
- pointer-events: auto;
121
- }
122
-
123
- /* Ensure cards are interactive */
124
- .dataset-card * {
125
- pointer-events: auto;
126
- }
127
-
128
- /* Force remove any blocking overlays */
129
- body::before, body::after,
130
- .container::before, .container::after,
131
- .row::before, .row::after {
132
- display: none !important;
133
- }
134
-
135
- /* Ensure page is fully interactive */
136
- body, html {
137
- pointer-events: auto !important;
138
- }
139
-
140
- /* Remove any potential invisible overlays */
141
- .container > * {
142
- pointer-events: auto !important;
143
- }
144
-
145
- /* Force all dataset elements to be clickable */
146
- #datasets-grid, #datasets-grid * {
147
- pointer-events: auto !important;
148
- }
149
-
150
- /* Override any global overlay styles */
151
- .loading-overlay:not(.active) {
152
- display: none !important;
153
- pointer-events: none !important;
154
- }
155
  </style>
156
  </head>
157
  <body>
@@ -165,7 +103,6 @@
165
  <a class="nav-link" href="/">الرئيسية</a>
166
  <a class="nav-link" href="/tokens">إدارة الرموز</a>
167
  <a class="nav-link active" href="/medical-datasets">البيانات الطبية</a>
168
- <a class="nav-link" href="/google-models">النماذج</a>
169
  </div>
170
  </div>
171
  </nav>
@@ -177,18 +114,11 @@
177
  <div>
178
  <h2><i class="fas fa-database me-2"></i>قواعد البيانات الطبية</h2>
179
  <p class="text-muted">قواعد بيانات متخصصة للصور الشعاعية والتشخيص الطبي</p>
180
- <div class="alert alert-success mt-2">
181
- <i class="fas fa-lightbulb me-2"></i>
182
- <strong>نصيحة:</strong> احفظ قواعد البيانات المفيدة لاستخدامها لاحقاً في التدريب. يمكنك عرض البيانات المحفوظة والتحكم بها من هنا.
183
- </div>
184
  </div>
185
  <div>
186
- <button class="btn btn-outline-primary me-2" onclick="medicalDatasets.refreshDatasets()">
187
  <i class="fas fa-sync-alt me-2"></i>تحديث
188
  </button>
189
- <button class="btn btn-success" onclick="medicalDatasets.showSavedDatasets()">
190
- <i class="fas fa-save me-2"></i>البيانات المحفوظة
191
- </button>
192
  </div>
193
  </div>
194
 
@@ -241,23 +171,6 @@
241
  <p class="mt-2 text-muted">جاري تحميل قواعد البيانات المتاحة...</p>
242
  </div>
243
  </div>
244
-
245
- <!-- Saved Datasets Section -->
246
- <div id="saved-datasets-section" class="mt-5" style="display: none;">
247
- <div class="d-flex justify-content-between align-items-center mb-4">
248
- <h3><i class="fas fa-bookmark me-2"></i>قواعد البيانات المحفوظة</h3>
249
- <button class="btn btn-outline-secondary" onclick="medicalDatasets.hideSavedDatasets()">
250
- <i class="fas fa-times me-2"></i>إخفاء
251
- </button>
252
- </div>
253
- <div id="saved-datasets-grid" class="row">
254
- <div class="col-12 text-center">
255
- <div class="spinner-border text-primary" role="status">
256
- <span class="visually-hidden">جاري تحميل البيانات المحفوظة...</span>
257
- </div>
258
- </div>
259
- </div>
260
- </div>
261
  </div>
262
  </div>
263
  </div>
@@ -332,44 +245,5 @@
332
 
333
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
334
  <script src="/static/js/medical-datasets.js"></script>
335
-
336
- <script>
337
- // Emergency fix for overlay issues
338
- document.addEventListener('DOMContentLoaded', function() {
339
- console.log('DOM loaded, checking for overlays...');
340
-
341
- // Remove any potential blocking overlays
342
- setTimeout(() => {
343
- document.querySelectorAll('*').forEach(el => {
344
- const style = window.getComputedStyle(el);
345
- if (style.position === 'fixed' &&
346
- style.top === '0px' &&
347
- style.left === '0px' &&
348
- (style.width === '100%' || style.width === '100vw') &&
349
- (style.height === '100%' || style.height === '100vh') &&
350
- !el.classList.contains('modal') &&
351
- !el.classList.contains('navbar') &&
352
- !el.classList.contains('toast-container')) {
353
- console.log('Removing blocking overlay:', el);
354
- el.style.display = 'none';
355
- el.style.pointerEvents = 'none';
356
- }
357
- });
358
-
359
- // Force all buttons to be clickable
360
- document.querySelectorAll('button, .btn').forEach(btn => {
361
- btn.style.pointerEvents = 'auto';
362
- btn.style.zIndex = '999';
363
- });
364
-
365
- console.log('Emergency overlay fix applied');
366
- }, 500);
367
- });
368
-
369
- // Test click functionality
370
- document.addEventListener('click', function(e) {
371
- console.log('Click detected on:', e.target);
372
- });
373
- </script>
374
  </body>
375
  </html>
 
16
  background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
17
  transition: all 0.3s ease;
18
  box-shadow: 0 2px 4px rgba(0,0,0,0.05);
 
 
 
19
  }
20
  .dataset-card:hover {
21
  transform: translateY(-2px);
 
59
  display: flex;
60
  gap: 10px;
61
  margin-top: 15px;
 
 
 
 
 
 
 
 
62
  }
63
  .medical-icon {
64
  font-size: 2.5em;
 
72
  right: 0;
73
  bottom: 0;
74
  background: rgba(255,255,255,0.9);
75
+ display: flex;
76
  align-items: center;
77
  justify-content: center;
78
  border-radius: 12px;
79
+ z-index: 10;
 
 
 
 
 
 
80
  }
81
  .dataset-status {
82
  position: absolute;
 
90
  .status-available { background: #d4edda; color: #155724; }
91
  .status-loading { background: #fff3cd; color: #856404; }
92
  .status-loaded { background: #cce5ff; color: #004085; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  </style>
94
  </head>
95
  <body>
 
103
  <a class="nav-link" href="/">الرئيسية</a>
104
  <a class="nav-link" href="/tokens">إدارة الرموز</a>
105
  <a class="nav-link active" href="/medical-datasets">البيانات الطبية</a>
 
106
  </div>
107
  </div>
108
  </nav>
 
114
  <div>
115
  <h2><i class="fas fa-database me-2"></i>قواعد البيانات الطبية</h2>
116
  <p class="text-muted">قواعد بيانات متخصصة للصور الشعاعية والتشخيص الطبي</p>
 
 
 
 
117
  </div>
118
  <div>
119
+ <button class="btn btn-outline-primary" onclick="medicalDatasets.refreshDatasets()">
120
  <i class="fas fa-sync-alt me-2"></i>تحديث
121
  </button>
 
 
 
122
  </div>
123
  </div>
124
 
 
171
  <p class="mt-2 text-muted">جاري تحميل قواعد البيانات المتاحة...</p>
172
  </div>
173
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  </div>
175
  </div>
176
  </div>
 
245
 
246
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
247
  <script src="/static/js/medical-datasets.js"></script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248
  </body>
249
  </html>