|
|
|
|
|
""" |
|
|
AI Models Monitor API |
|
|
API برای نظارت و مدیریت مدلهای AI |
|
|
""" |
|
|
|
|
|
from fastapi import APIRouter, HTTPException, BackgroundTasks |
|
|
from typing import Dict, List, Any, Optional |
|
|
from pydantic import BaseModel |
|
|
from datetime import datetime |
|
|
|
|
|
from backend.services.ai_models_monitor import db, monitor, agent |
|
|
|
|
|
router = APIRouter(prefix="/api/ai-models", tags=["AI Models Monitor"]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ScanResponse(BaseModel): |
|
|
total: int |
|
|
available: int |
|
|
loading: int |
|
|
failed: int |
|
|
auth_required: int |
|
|
not_found: int = 0 |
|
|
models: List[Dict[str, Any]] |
|
|
|
|
|
|
|
|
class ModelInfo(BaseModel): |
|
|
model_id: str |
|
|
model_key: Optional[str] |
|
|
task: str |
|
|
category: str |
|
|
provider: str = "huggingface" |
|
|
total_checks: Optional[int] |
|
|
successful_checks: Optional[int] |
|
|
success_rate: Optional[float] |
|
|
avg_response_time_ms: Optional[float] |
|
|
|
|
|
|
|
|
class AgentStatus(BaseModel): |
|
|
running: bool |
|
|
interval_minutes: int |
|
|
last_scan: Optional[str] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/scan", response_model=ScanResponse) |
|
|
async def trigger_scan(background_tasks: BackgroundTasks): |
|
|
""" |
|
|
شروع اسکن فوری همه مدلها |
|
|
|
|
|
این endpoint یک اسکن کامل از همه مدلها انجام میدهد و نتایج را در دیتابیس ذخیره میکند. |
|
|
""" |
|
|
try: |
|
|
result = await monitor.scan_all_models() |
|
|
return result |
|
|
except Exception as e: |
|
|
raise HTTPException(status_code=500, detail=f"Scan failed: {str(e)}") |
|
|
|
|
|
|
|
|
@router.get("/models", response_model=List[ModelInfo]) |
|
|
async def get_all_models(status: Optional[str] = None): |
|
|
""" |
|
|
دریافت لیست همه مدلها |
|
|
|
|
|
Args: |
|
|
status: فیلتر بر اساس وضعیت (available, loading, failed, etc.) |
|
|
""" |
|
|
try: |
|
|
if status: |
|
|
models = monitor.get_models_by_status(status) |
|
|
else: |
|
|
models = db.get_all_models() |
|
|
|
|
|
return models |
|
|
except Exception as e: |
|
|
raise HTTPException(status_code=500, detail=f"Failed to get models: {str(e)}") |
|
|
|
|
|
|
|
|
@router.get("/models/{model_id}/history") |
|
|
async def get_model_history(model_id: str, limit: int = 100): |
|
|
""" |
|
|
دریافت تاریخچه یک مدل |
|
|
|
|
|
Args: |
|
|
model_id: شناسه مدل (مثلاً kk08/CryptoBERT) |
|
|
limit: تعداد رکوردها (پیشفرض: 100) |
|
|
""" |
|
|
try: |
|
|
history = db.get_model_history(model_id, limit) |
|
|
return { |
|
|
"model_id": model_id, |
|
|
"total_records": len(history), |
|
|
"history": history |
|
|
} |
|
|
except Exception as e: |
|
|
raise HTTPException(status_code=500, detail=f"Failed to get history: {str(e)}") |
|
|
|
|
|
|
|
|
@router.get("/models/{model_id}/stats") |
|
|
async def get_model_stats(model_id: str): |
|
|
""" |
|
|
دریافت آمار یک مدل خاص |
|
|
""" |
|
|
try: |
|
|
models = db.get_all_models() |
|
|
model = next((m for m in models if m['model_id'] == model_id), None) |
|
|
|
|
|
if not model: |
|
|
raise HTTPException(status_code=404, detail=f"Model not found: {model_id}") |
|
|
|
|
|
history = db.get_model_history(model_id, limit=10) |
|
|
|
|
|
return { |
|
|
"model_info": model, |
|
|
"recent_checks": history |
|
|
} |
|
|
except HTTPException: |
|
|
raise |
|
|
except Exception as e: |
|
|
raise HTTPException(status_code=500, detail=f"Failed to get stats: {str(e)}") |
|
|
|
|
|
|
|
|
@router.get("/stats/summary") |
|
|
async def get_summary_stats(): |
|
|
""" |
|
|
دریافت آمار خلاصه از همه مدلها |
|
|
""" |
|
|
try: |
|
|
models = db.get_all_models() |
|
|
|
|
|
total = len(models) |
|
|
with_checks = sum(1 for m in models if m.get('total_checks', 0) > 0) |
|
|
avg_success_rate = sum(m.get('success_rate', 0) for m in models if m.get('success_rate')) / with_checks if with_checks > 0 else 0 |
|
|
|
|
|
|
|
|
by_category = {} |
|
|
for model in models: |
|
|
cat = model.get('category', 'unknown') |
|
|
if cat not in by_category: |
|
|
by_category[cat] = { |
|
|
'total': 0, |
|
|
'avg_success_rate': 0, |
|
|
'models': [] |
|
|
} |
|
|
by_category[cat]['total'] += 1 |
|
|
by_category[cat]['models'].append(model['model_id']) |
|
|
if model.get('success_rate'): |
|
|
by_category[cat]['avg_success_rate'] += model['success_rate'] |
|
|
|
|
|
|
|
|
for cat in by_category: |
|
|
if by_category[cat]['total'] > 0: |
|
|
by_category[cat]['avg_success_rate'] /= by_category[cat]['total'] |
|
|
|
|
|
return { |
|
|
"total_models": total, |
|
|
"models_with_checks": with_checks, |
|
|
"overall_success_rate": avg_success_rate, |
|
|
"by_category": by_category, |
|
|
"timestamp": datetime.now().isoformat() |
|
|
} |
|
|
except Exception as e: |
|
|
raise HTTPException(status_code=500, detail=f"Failed to get summary: {str(e)}") |
|
|
|
|
|
|
|
|
@router.get("/agent/status", response_model=AgentStatus) |
|
|
async def get_agent_status(): |
|
|
""" |
|
|
دریافت وضعیت Agent |
|
|
""" |
|
|
return { |
|
|
"running": agent.running, |
|
|
"interval_minutes": agent.interval / 60, |
|
|
"last_scan": None |
|
|
} |
|
|
|
|
|
|
|
|
@router.post("/agent/start") |
|
|
async def start_agent(background_tasks: BackgroundTasks): |
|
|
""" |
|
|
شروع Agent خودکار |
|
|
|
|
|
Agent به صورت خودکار هر 5 دقیقه مدلها را بررسی میکند |
|
|
""" |
|
|
if agent.running: |
|
|
return { |
|
|
"status": "already_running", |
|
|
"message": "Agent is already running", |
|
|
"interval_minutes": agent.interval / 60 |
|
|
} |
|
|
|
|
|
try: |
|
|
background_tasks.add_task(agent.start) |
|
|
return { |
|
|
"status": "started", |
|
|
"message": "Agent started successfully", |
|
|
"interval_minutes": agent.interval / 60 |
|
|
} |
|
|
except Exception as e: |
|
|
raise HTTPException(status_code=500, detail=f"Failed to start agent: {str(e)}") |
|
|
|
|
|
|
|
|
@router.post("/agent/stop") |
|
|
async def stop_agent(): |
|
|
""" |
|
|
توقف Agent |
|
|
""" |
|
|
if not agent.running: |
|
|
return { |
|
|
"status": "not_running", |
|
|
"message": "Agent is not running" |
|
|
} |
|
|
|
|
|
try: |
|
|
await agent.stop() |
|
|
return { |
|
|
"status": "stopped", |
|
|
"message": "Agent stopped successfully" |
|
|
} |
|
|
except Exception as e: |
|
|
raise HTTPException(status_code=500, detail=f"Failed to stop agent: {str(e)}") |
|
|
|
|
|
|
|
|
@router.get("/dashboard") |
|
|
async def get_dashboard_data(): |
|
|
""" |
|
|
دریافت دادههای کامل برای داشبورد |
|
|
""" |
|
|
try: |
|
|
models = db.get_all_models() |
|
|
summary = await get_summary_stats() |
|
|
|
|
|
|
|
|
top_models = sorted( |
|
|
[m for m in models if m.get('success_rate', 0) > 0], |
|
|
key=lambda x: x.get('success_rate', 0), |
|
|
reverse=True |
|
|
)[:10] |
|
|
|
|
|
|
|
|
failed_models = sorted( |
|
|
[m for m in models if m.get('success_rate', 0) < 50], |
|
|
key=lambda x: x.get('success_rate', 0) |
|
|
)[:10] |
|
|
|
|
|
return { |
|
|
"summary": summary, |
|
|
"top_models": top_models, |
|
|
"failed_models": failed_models, |
|
|
"agent_running": agent.running, |
|
|
"total_models": len(models), |
|
|
"timestamp": datetime.now().isoformat() |
|
|
} |
|
|
except Exception as e: |
|
|
raise HTTPException(status_code=500, detail=f"Failed to get dashboard data: {str(e)}") |
|
|
|
|
|
|
|
|
@router.get("/models/available") |
|
|
async def get_available_models(): |
|
|
""" |
|
|
فقط مدلهایی که در حال حاضر کار میکنند |
|
|
""" |
|
|
try: |
|
|
models = monitor.get_models_by_status('available') |
|
|
return { |
|
|
"total": len(models), |
|
|
"models": models |
|
|
} |
|
|
except Exception as e: |
|
|
raise HTTPException(status_code=500, detail=f"Failed to get available models: {str(e)}") |
|
|
|
|
|
|
|
|
@router.get("/health") |
|
|
async def health_check(): |
|
|
""" |
|
|
بررسی سلامت سیستم |
|
|
""" |
|
|
return { |
|
|
"status": "healthy", |
|
|
"database": "connected", |
|
|
"agent_running": agent.running, |
|
|
"timestamp": datetime.now().isoformat() |
|
|
} |
|
|
|
|
|
|