|
|
|
|
|
"""
|
|
|
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()
|
|
|
}
|
|
|
|
|
|
|