offload / app.py
osamabyc86's picture
Update app.py
7ca8135 verified
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ู†ุธุงู… ุชูˆุฒูŠุน ุงู„ู…ู‡ุงู… ุงู„ุฐูƒูŠ - ุงู„ุฎุงุฏู… ุงู„ู…ุฑูƒุฒูŠ ุนู„ู‰ Hugging Face
ูŠุฌู…ุน ุจูŠู† ูˆุงุฌู‡ุฉ Gradio ูˆุฎุงุฏู… ุงู„ุชูˆุฒูŠุน ุงู„ู…ุฑูƒุฒูŠ
"""
import os
import sys
import time
import json
import logging
import threading
import random
import queue
from datetime import datetime
from typing import Dict, List, Optional, Any
from dataclasses import dataclass, field, asdict
import gradio as gr
from flask import Flask, request, jsonify
from flask_cors import CORS
import requests
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ ุฅุนุฏุงุฏ ุงู„ุณุฌู„ุงุช โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger("CentralServerHF")
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ ู‡ูŠุงูƒู„ ุงู„ุจูŠุงู†ุงุช โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
@dataclass
class NodeInfo:
"""ู…ุนู„ูˆู…ุงุช ุงู„ุนู‚ุฏุฉ ุงู„ู…ุชุตู„ุฉ"""
node_id: str
ip: str
port: int
url: str
capabilities: List[str]
cpu_usage: float = 0.0
memory_usage: float = 0.0
status: str = "online"
last_seen: datetime = field(default_factory=datetime.now)
success_rate: float = 1.0
response_time: float = 0.0
tasks_completed: int = 0
tasks_failed: int = 0
current_tasks: int = 0
weight: float = 1.0 # ู„ู„ุฃูˆุฒุงู† ุงู„ุฐูƒูŠุฉ
@property
def score(self) -> float:
"""ุญุณุงุจ ุฏุฑุฌุฉ ุงู„ุนู‚ุฏุฉ"""
health = 0.4 * (100 - (self.cpu_usage + self.memory_usage) / 2) / 100
performance = 0.3 * self.success_rate
availability = 0.2 * (1.0 - self.current_tasks / 5)
speed = 0.1 * max(0, 1 - self.response_time / 10)
return (health + performance + availability + speed) * self.weight
@dataclass
class TaskInfo:
"""ู…ุนู„ูˆู…ุงุช ุงู„ู…ู‡ู…ุฉ"""
task_id: str
task_type: str
params: Dict[str, Any]
sender: str
status: str = "pending" # pending, processing, completed, failed
assigned_to: Optional[str] = None
result: Optional[Any] = None
error: Optional[str] = None
created_at: datetime = field(default_factory=datetime.now)
started_at: Optional[datetime] = None
completed_at: Optional[datetime] = None
priority: int = 2 # 1=high, 2=medium, 3=low
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ ูุฆุฉ ุงู„ุฎุงุฏู… ุงู„ู…ุฑูƒุฒูŠ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
class CentralServer:
"""ุงู„ุฎุงุฏู… ุงู„ู…ุฑูƒุฒูŠ ุงู„ุฐูƒูŠ ู„ุชูˆุฒูŠุน ุงู„ู…ู‡ุงู…"""
def __init__(self):
self.nodes: Dict[str, NodeInfo] = {}
self.tasks: Dict[str, TaskInfo] = {}
self.task_queue = queue.PriorityQueue()
self.lock = threading.RLock()
self.is_running = True
# ุฅุญุตุงุฆูŠุงุช ุงู„ู†ุธุงู…
self.metrics = {
"total_nodes": 0,
"online_nodes": 0,
"total_tasks": 0,
"completed_tasks": 0,
"failed_tasks": 0,
"avg_response_time": 0.0,
"system_uptime": time.time()
}
# ุจุฏุก ุงู„ุฎุฏู…ุงุช ุงู„ุฎู„ููŠุฉ
self._start_background_services()
logger.info("๐Ÿš€ ุจุฏุก ุชุดุบูŠู„ ุงู„ุฎุงุฏู… ุงู„ู…ุฑูƒุฒูŠ ุนู„ู‰ Hugging Face")
def _start_background_services(self):
"""ุจุฏุก ุงู„ุฎุฏู…ุงุช ุงู„ุฎู„ููŠุฉ"""
# ุฎูŠุท ุชูˆุฒูŠุน ุงู„ู…ู‡ุงู…
self.dispatcher = threading.Thread(target=self._dispatch_loop, daemon=True)
self.dispatcher.start()
# ุฎูŠุท ูุญุต ุตุญุฉ ุงู„ุนู‚ุฏ
self.health_checker = threading.Thread(target=self._health_check_loop, daemon=True)
self.health_checker.start()
# ุฎูŠุท ู…ุญุงูƒุงุฉ ุงู„ุนู‚ุฏ (ู„ู„ุชุฌุฑุจุฉ)
self.simulator = threading.Thread(target=self._simulate_nodes, daemon=True)
self.simulator.start()
def register_node(self, node_data: Dict) -> Dict:
"""ุชุณุฌูŠู„ ุนู‚ุฏุฉ ุฌุฏูŠุฏุฉ"""
with self.lock:
node_id = node_data.get('node_id', f"node_{len(self.nodes)+1}")
node = NodeInfo(
node_id=node_id,
ip=node_data.get('ip', '127.0.0.1'),
port=node_data.get('port', 0),
url=node_data.get('url', ''),
capabilities=node_data.get('capabilities', ['general']),
cpu_usage=node_data.get('cpu_usage', 0.0),
memory_usage=node_data.get('memory_usage', 0.0),
status='online'
)
self.nodes[node_id] = node
self.metrics["total_nodes"] = len(self.nodes)
self.metrics["online_nodes"] = len([n for n in self.nodes.values() if n.status == 'online'])
logger.info(f"โœ… ุนู‚ุฏุฉ ู…ุณุฌู„ุฉ: {node_id}")
return {
"status": "success",
"node_id": node_id,
"message": "ุชู… ุงู„ุชุณุฌูŠู„ ุจู†ุฌุงุญ",
"server_time": datetime.now().isoformat()
}
def update_node_status(self, node_id: str, metrics: Dict):
"""ุชุญุฏูŠุซ ุญุงู„ุฉ ุงู„ุนู‚ุฏุฉ"""
with self.lock:
if node_id in self.nodes:
node = self.nodes[node_id]
if 'cpu_usage' in metrics:
node.cpu_usage = metrics['cpu_usage']
if 'memory_usage' in metrics:
node.memory_usage = metrics['memory_usage']
if 'current_tasks' in metrics:
node.current_tasks = metrics['current_tasks']
if 'status' in metrics:
node.status = metrics['status']
node.last_seen = datetime.now()
# ุชุญุฏูŠุซ ู…ุนุฏู„ ุงู„ู†ุฌุงุญ
total = node.tasks_completed + node.tasks_failed
if total > 0:
node.success_rate = node.tasks_completed / total
return {"status": "updated"}
return {"error": "ุงู„ุนู‚ุฏุฉ ุบูŠุฑ ู…ูˆุฌูˆุฏุฉ"}
def submit_task(self, task_data: Dict) -> Dict:
"""ุฅุฑุณุงู„ ู…ู‡ู…ุฉ ุฌุฏูŠุฏุฉ"""
task_id = task_data.get('task_id', f"task_{int(time.time())}_{random.randint(1000,9999)}")
task = TaskInfo(
task_id=task_id,
task_type=task_data.get('task_type', 'general'),
params=task_data.get('params', {}),
sender=task_data.get('sender', 'unknown'),
priority=task_data.get('priority', 2)
)
with self.lock:
self.tasks[task_id] = task
self.metrics["total_tasks"] = len(self.tasks)
# ุฅุถุงูุฉ ุฅู„ู‰ ู‚ุงุฆู…ุฉ ุงู„ุงู†ุชุธุงุฑ
self.task_queue.put((task.priority, task_id))
logger.info(f"๐Ÿ“จ ู…ู‡ู…ุฉ ู…ุณุชู„ู…ุฉ: {task_id} ({task.task_type})")
return {
"status": "accepted",
"task_id": task_id,
"queue_position": self.task_queue.qsize(),
"estimated_wait": self.task_queue.qsize() * 2 # ุซุงู†ูŠุชูŠู† ู„ูƒู„ ู…ู‡ู…ุฉ
}
def _dispatch_loop(self):
"""ุญู„ู‚ุฉ ุชูˆุฒูŠุน ุงู„ู…ู‡ุงู…"""
while self.is_running:
try:
# ุงู†ุชุธุงุฑ ู…ู‡ู…ุฉ
priority, task_id = self.task_queue.get(timeout=1.0)
with self.lock:
task = self.tasks.get(task_id)
if not task or task.status != "pending":
continue
# ุฅูŠุฌุงุฏ ุฃูุถู„ ุนู‚ุฏุฉ
best_node = self._select_best_node(task.task_type)
if best_node:
# ุชุนูŠูŠู† ุงู„ู…ู‡ู…ุฉ
self._assign_task(task, best_node)
else:
# ุฅุนุงุฏุฉ ุงู„ู…ุญุงูˆู„ุฉ
time.sleep(3)
self.task_queue.put((priority, task_id))
except queue.Empty:
continue
except Exception as e:
logger.error(f"โŒ ุฎุทุฃ ููŠ ุงู„ุชูˆุฒูŠุน: {e}")
time.sleep(5)
def _select_best_node(self, task_type: str) -> Optional[NodeInfo]:
"""ุงุฎุชูŠุงุฑ ุฃูุถู„ ุนู‚ุฏุฉ ู„ู„ู…ู‡ู…ุฉ"""
with self.lock:
# ูู„ุชุฑุฉ ุงู„ุนู‚ุฏ ุงู„ู…ุชุงุญุฉ
available = []
for node in self.nodes.values():
if node.status != 'online':
continue
if node.cpu_usage > 85 or node.memory_usage > 85:
continue
if node.current_tasks >= 3:
continue
# ุงู„ุชุญู‚ู‚ ู…ู† ุงู„ู‚ุฏุฑุงุช
capabilities_needed = []
if task_type in ['matrix', 'fibonacci']:
capabilities_needed = ['cpu_intensive']
elif task_type in ['data', 'processing']:
capabilities_needed = ['memory']
if capabilities_needed:
if not any(cap in node.capabilities for cap in capabilities_needed):
continue
available.append(node)
if not available:
return None
# ุงุฎุชูŠุงุฑ ุงู„ุฃุนู„ู‰ ุฏุฑุฌุฉ
return max(available, key=lambda n: n.score)
def _assign_task(self, task: TaskInfo, node: NodeInfo):
"""ุชุนูŠูŠู† ู…ู‡ู…ุฉ ู„ุนู‚ุฏุฉ"""
try:
# ุชุญุฏูŠุซ ุญุงู„ุฉ ุงู„ู…ู‡ู…ุฉ
with self.lock:
task.status = "processing"
task.assigned_to = node.node_id
task.started_at = datetime.now()
node.current_tasks += 1
logger.info(f"๐ŸŽฏ ุชุนูŠูŠู† {task.task_id} โ†’ {node.node_id}")
# ู…ุญุงูƒุงุฉ ุงู„ุชู†ููŠุฐ
execution_time = self._simulate_task_execution(task, node)
# ุชุญุฏูŠุซ ุงู„ู†ุชูŠุฌุฉ
with self.lock:
task.status = "completed"
task.completed_at = datetime.now()
task.result = {
"executed_on": node.node_id,
"execution_time": execution_time,
"task_type": task.task_type,
"result": f"ู†ุชูŠุฌุฉ ู…ุญุงูƒุงุฉ ู„ู€ {task.task_type}"
}
node.current_tasks -= 1
node.tasks_completed += 1
node.response_time = execution_time
self.metrics["completed_tasks"] += 1
logger.info(f"โœ… ู…ูƒุชู…ู„ุฉ: {task.task_id} ููŠ {execution_time:.2f}s")
except Exception as e:
logger.error(f"โŒ ูุดู„ุช ุงู„ู…ู‡ู…ุฉ {task.task_id}: {e}")
with self.lock:
task.status = "failed"
task.error = str(e)
self.metrics["failed_tasks"] += 1
if node.node_id in self.nodes:
self.nodes[node.node_id].tasks_failed += 1
self.nodes[node.node_id].current_tasks -= 1
def _simulate_task_execution(self, task: TaskInfo, node: NodeInfo) -> float:
"""ู…ุญุงูƒุงุฉ ุชู†ููŠุฐ ุงู„ู…ู‡ู…ุฉ"""
# ุฃูˆู‚ุงุช ุชู†ููŠุฐ ู…ุฎุชู„ูุฉ ุญุณุจ ู†ูˆุน ุงู„ู…ู‡ู…ุฉ
base_times = {
'matrix': 1.5,
'fibonacci': 0.8,
'primes': 1.2,
'data': 0.5,
'image': 2.0,
'general': 0.3
}
base_time = base_times.get(task.task_type, 0.5)
# ุชุฃุซูŠุฑ ุญู…ู„ ุงู„ุนู‚ุฏุฉ
load_factor = 1 + (node.cpu_usage + node.memory_usage) / 200
# ุชุฃุซูŠุฑ ุญุฌู… ุงู„ู…ู‡ู…ุฉ
size = task.params.get('size', 10) if isinstance(task.params, dict) else 10
size_factor = 1 + (size / 1000)
# ูˆู‚ุช ุชู†ููŠุฐ ู…ุญุงูƒูŠ
execution_time = base_time * load_factor * size_factor
# ู…ุญุงูƒุงุฉ ุงู„ุงู†ุชุธุงุฑ
time.sleep(min(execution_time, 3.0))
return execution_time
def _health_check_loop(self):
"""ูุญุต ุตุญุฉ ุงู„ุนู‚ุฏ"""
while self.is_running:
try:
with self.lock:
now = datetime.now()
for node in self.nodes.values():
# ุฅุฐุง ู…ุฑ ุฃูƒุซุฑ ู…ู† 2 ุฏู‚ูŠู‚ุฉ ุฏูˆู† ุชุญุฏูŠุซ
if (now - node.last_seen).total_seconds() > 120:
node.status = "offline"
# ุชุญุฏูŠุซ ุงู„ุฅุญุตุงุฆูŠุงุช
self.metrics["online_nodes"] = len(
[n for n in self.nodes.values() if n.status == 'online']
)
time.sleep(30)
except Exception as e:
logger.error(f"โŒ ุฎุทุฃ ููŠ ูุญุต ุงู„ุตุญุฉ: {e}")
time.sleep(60)
def _simulate_nodes(self):
"""ู…ุญุงูƒุงุฉ ุนู‚ุฏ ุงูุชุฑุงุถูŠุฉ (ู„ู„ุชุฌุฑุจุฉ)"""
# ุฅู†ุดุงุก ุนู‚ุฏ ุงูุชุฑุงุถูŠุฉ
virtual_nodes = [
{"id": "node_cpu1", "capabilities": ["cpu_intensive"], "cpu": 20, "memory": 40},
{"id": "node_mem1", "capabilities": ["memory"], "cpu": 30, "memory": 25},
{"id": "node_gpu1", "capabilities": ["gpu", "image"], "cpu": 25, "memory": 50},
{"id": "node_gen1", "capabilities": ["general"], "cpu": 15, "memory": 35}
]
for vnode in virtual_nodes:
self.register_node({
"node_id": vnode["id"],
"ip": "192.168.1." + str(random.randint(100, 200)),
"port": random.randint(5000, 6000),
"url": f"http://192.168.1.{random.randint(100,200)}:{random.randint(5000,6000)}",
"capabilities": vnode["capabilities"],
"cpu_usage": vnode["cpu"],
"memory_usage": vnode["memory"]
})
# ู…ุญุงูƒุงุฉ ุชุญุฏูŠุซุงุช ุฏูˆุฑูŠุฉ
while self.is_running:
try:
with self.lock:
for node_id in list(self.nodes.keys())[:4]: # ุฃูˆู„ 4 ุนู‚ุฏ (ุงู„ุงูุชุฑุงุถูŠุฉ)
if node_id in self.nodes:
node = self.nodes[node_id]
node.cpu_usage = max(5, min(80, node.cpu_usage + random.uniform(-5, 5)))
node.memory_usage = max(10, min(70, node.memory_usage + random.uniform(-3, 3)))
node.current_tasks = random.randint(0, 2)
node.last_seen = datetime.now()
time.sleep(10)
except Exception as e:
logger.error(f"โŒ ุฎุทุฃ ููŠ ู…ุญุงูƒุงุฉ ุงู„ุนู‚ุฏ: {e}")
time.sleep(30)
def get_system_overview(self) -> Dict:
"""ู†ุธุฑุฉ ุนุงู…ุฉ ุนู„ู‰ ุงู„ู†ุธุงู…"""
with self.lock:
now = datetime.now()
# ุญุณุงุจ ู…ุชูˆุณุท ูˆู‚ุช ุงู„ุงุณุชุฌุงุจุฉ
response_times = [n.response_time for n in self.nodes.values() if n.response_time > 0]
avg_response = sum(response_times) / len(response_times) if response_times else 0
# ุงู„ู…ู‡ุงู… ุงู„ุฃุฎูŠุฑุฉ
recent_tasks = list(self.tasks.values())[-10:] # ุขุฎุฑ 10 ู…ู‡ุงู…
return {
"metrics": {
**self.metrics,
"uptime": time.time() - self.metrics["system_uptime"],
"avg_response_time": avg_response,
"queue_size": self.task_queue.qsize(),
"timestamp": now.isoformat()
},
"nodes": [
{
"id": n.node_id,
"status": n.status,
"score": round(n.score, 3),
"cpu": n.cpu_usage,
"memory": n.memory_usage,
"tasks": n.current_tasks,
"success_rate": round(n.success_rate, 2),
"last_seen": (now - n.last_seen).total_seconds()
}
for n in self.nodes.values()
],
"recent_tasks": [
{
"id": t.task_id,
"type": t.task_type,
"status": t.status,
"assigned_to": t.assigned_to,
"created": t.created_at.strftime("%H:%M:%S")
}
for t in recent_tasks
]
}
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ ุฅู†ุดุงุก ุงู„ุฎุงุฏู… ุงู„ู…ุฑูƒุฒูŠ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
central_server = CentralServer()
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ ุฏูˆุงู„ Gradio โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
def get_system_status():
"""ุงู„ุญุตูˆู„ ุนู„ู‰ ุญุงู„ุฉ ุงู„ู†ุธุงู…"""
overview = central_server.get_system_overview()
metrics = overview["metrics"]
nodes = overview["nodes"]
tasks = overview["recent_tasks"]
# ุชู†ุณูŠู‚ ุงู„ู†ุต
status_text = f"""
# ๐ŸŒ ุงู„ุฎุงุฏู… ุงู„ู…ุฑูƒุฒูŠ ู„ุชูˆุฒูŠุน ุงู„ู…ู‡ุงู…
## ๐Ÿ“Š ุฅุญุตุงุฆูŠุงุช ุงู„ู†ุธุงู…
- **ุงู„ูˆู‚ุช:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
- **ู…ุฏุฉ ุงู„ุชุดุบูŠู„:** {metrics['uptime']/3600:.1f} ุณุงุนุฉ
- **ุงู„ุนู‚ุฏ ุงู„ุฅุฌู…ุงู„ูŠุฉ:** {metrics['total_nodes']}
- **ุงู„ุนู‚ุฏ ุงู„ู†ุดุทุฉ:** {metrics['online_nodes']}
- **ุงู„ู…ู‡ุงู… ุงู„ุฅุฌู…ุงู„ูŠุฉ:** {metrics['total_tasks']}
- **ุงู„ู…ู‡ุงู… ุงู„ู…ูƒุชู…ู„ุฉ:** {metrics['completed_tasks']}
- **ุงู„ู…ู‡ุงู… ุงู„ูุงุดู„ุฉ:** {metrics['failed_tasks']}
- **ู…ุชูˆุณุท ูˆู‚ุช ุงู„ุงุณุชุฌุงุจุฉ:** {metrics['avg_response_time']:.2f} ุซุงู†ูŠุฉ
- **ุงู„ู…ู‡ุงู… ููŠ ุงู„ุงู†ุชุธุงุฑ:** {metrics['queue_size']}
## ๐Ÿ‘ฅ ุงู„ุนู‚ุฏ ุงู„ู…ุชุตู„ุฉ ({len(nodes)})
"""
for node in nodes:
status_emoji = "๐ŸŸข" if node['status'] == 'online' else "๐Ÿ”ด" if node['status'] == 'offline' else "๐ŸŸก"
status_text += f"\n**{status_emoji} {node['id']}**"
status_text += f"\n - ุงู„ู†ู‚ุงุท: {node['score']:.3f}"
status_text += f"\n - CPU: {node['cpu']:.1f}% | ุฐุงูƒุฑุฉ: {node['memory']:.1f}%"
status_text += f"\n - ุงู„ู…ู‡ุงู… ุงู„ู†ุดุทุฉ: {node['tasks']}"
status_text += f"\n - ู…ุนุฏู„ ุงู„ู†ุฌุงุญ: {node['success_rate']*100:.1f}%"
status_text += f"\n - ุขุฎุฑ ุธู‡ูˆุฑ: {node['last_seen']:.0f} ุซุงู†ูŠุฉ ู…ุถุช"
if tasks:
status_text += f"\n\n## ๐Ÿ“‹ ุขุฎุฑ ุงู„ู…ู‡ุงู… ({len(tasks)})"
for task in tasks[-5:]: # ุขุฎุฑ 5 ู…ู‡ุงู…
status_emoji = "๐ŸŸข" if task['status'] == 'completed' else "๐ŸŸก" if task['status'] == 'processing' else "๐Ÿ”ด"
status_text += f"\n{status_emoji} **{task['id']}** ({task['type']}) โ†’ {task['assigned_to'] or 'ููŠ ุงู„ุงู†ุชุธุงุฑ'}"
return status_text
def submit_task_ui(task_type, params_json):
"""ุฅุฑุณุงู„ ู…ู‡ู…ุฉ ุฌุฏูŠุฏุฉ"""
try:
params = json.loads(params_json) if params_json else {}
except:
params = {"size": 10}
task_data = {
"task_type": task_type,
"params": params,
"sender": "gradio_ui",
"priority": 2
}
result = central_server.submit_task(task_data)
if "error" in result:
return f"## โŒ ุฎุทุฃ\n{result['error']}"
return f"""
## โœ… ุชู… ู‚ุจูˆู„ ุงู„ู…ู‡ู…ุฉ
### ๐Ÿ“ ู…ุนู„ูˆู…ุงุช ุงู„ู…ู‡ู…ุฉ
- **ู…ุนุฑู ุงู„ู…ู‡ู…ุฉ:** {result['task_id']}
- **ู†ูˆุน ุงู„ู…ู‡ู…ุฉ:** {task_type}
- **ุงู„ุญุงู„ุฉ:** ููŠ ู‚ุงุฆู…ุฉ ุงู„ุงู†ุชุธุงุฑ
- **ุงู„ู…ูˆู‚ุน ููŠ ุงู„ุทุงุจูˆุฑ:** {result['queue_position']}
- **ุงู„ูˆู‚ุช ุงู„ู…ุชูˆู‚ุน:** {result['estimated_wait']} ุซุงู†ูŠุฉ
- **ุงู„ูˆู‚ุช:** {datetime.now().strftime('%H:%M:%S')}
### ๐Ÿ“Š ุชุชุจุน ุงู„ู…ู‡ู…ุฉ
ุณูŠุชู… ุชุนูŠูŠู† ุงู„ู…ู‡ู…ุฉ ู„ุฃูุถู„ ุนู‚ุฏุฉ ู…ุชุงุญุฉ ุชู„ู‚ุงุฆูŠุงู‹.
"""
def get_node_details():
"""ุงู„ุญุตูˆู„ ุนู„ู‰ ุชูุงุตูŠู„ ุงู„ุนู‚ุฏ"""
overview = central_server.get_system_overview()
nodes = overview["nodes"]
headers = ["ุงู„ุนู‚ุฏุฉ", "ุงู„ุญุงู„ุฉ", "ุงู„ู†ู‚ุงุท", "CPU%", "ุงู„ุฐุงูƒุฑุฉ%", "ุงู„ู…ู‡ุงู…", "ู…ุนุฏู„ ุงู„ู†ุฌุงุญ", "ุขุฎุฑ ุธู‡ูˆุฑ"]
data = []
for node in nodes:
status_emoji = "๐ŸŸข" if node['status'] == 'online' else "๐Ÿ”ด"
data.append([
node['id'],
f"{status_emoji} {node['status']}",
f"{node['score']:.3f}",
f"{node['cpu']:.1f}",
f"{node['memory']:.1f}",
str(node['tasks']),
f"{node['success_rate']*100:.1f}%",
f"{node['last_seen']:.0f}s"
])
return data
def simulate_new_node():
"""ู…ุญุงูƒุงุฉ ุนู‚ุฏุฉ ุฌุฏูŠุฏุฉ"""
node_id = f"node_{int(time.time())}"
caps = random.choice([['cpu_intensive'], ['memory'], ['general'], ['gpu', 'image']])
result = central_server.register_node({
"node_id": node_id,
"ip": f"10.0.0.{random.randint(1, 255)}",
"port": random.randint(5000, 6000),
"url": f"http://10.0.0.{random.randint(1,255)}:{random.randint(5000,6000)}",
"capabilities": caps,
"cpu_usage": random.uniform(10, 40),
"memory_usage": random.uniform(20, 60)
})
return f"## ๐Ÿ†• ุนู‚ุฏุฉ ู…ุญุงูƒุงุฉ\n**{node_id}** - {', '.join(caps)}\n\nุชู… ุงู„ุชุณุฌูŠู„ ุจู†ุฌุงุญ!"
def simulate_task_load(count: int):
"""ู…ุญุงูƒุงุฉ ุญู…ู„ ู…ู‡ุงู…"""
task_types = ['matrix', 'fibonacci', 'primes', 'data', 'image', 'general']
for i in range(min(count, 10)): # ุญุฏ ุฃู‚ุตู‰ 10 ู…ู‡ุงู…
task_type = random.choice(task_types)
central_server.submit_task({
"task_type": task_type,
"params": {"size": random.randint(10, 1000)},
"sender": "simulation",
"priority": random.randint(1, 3)
})
time.sleep(0.1)
return f"## ๐Ÿ“จ ู…ุญุงูƒุงุฉ ุญู…ู„\nุชู… ุฅุฑุณุงู„ {min(count, 10)} ู…ู‡ุงู… ุนุดูˆุงุฆูŠุฉ!"
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ ูˆุงุฌู‡ุฉ Gradio โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
def create_interface():
"""ุฅู†ุดุงุก ูˆุงุฌู‡ุฉ Gradio"""
with gr.Blocks(
title="ุงู„ุฎุงุฏู… ุงู„ู…ุฑูƒุฒูŠ ู„ุชูˆุฒูŠุน ุงู„ู…ู‡ุงู…",
theme=gr.themes.Soft(primary_hue="blue", secondary_hue="teal")
) as demo:
gr.Markdown("# ๐ŸŒ ุงู„ุฎุงุฏู… ุงู„ู…ุฑูƒุฒูŠ ุงู„ุฐูƒูŠ ู„ุชูˆุฒูŠุน ุงู„ู…ู‡ุงู…")
gr.Markdown("### ู†ุณุฎุฉ Hugging Face Spaces - ุฎุงุฏู… ุญู‚ูŠู‚ูŠ")
with gr.Tabs():
# ุชุจูˆูŠุจ ุญุงู„ุฉ ุงู„ู†ุธุงู…
with gr.TabItem("๐Ÿ“Š ู„ูˆุญุฉ ุงู„ุชุญูƒู…"):
status_output = gr.Markdown()
refresh_btn = gr.Button("๐Ÿ”„ ุชุญุฏูŠุซ ุงู„ุญุงู„ุฉ", variant="primary")
refresh_btn.click(get_system_status, outputs=status_output)
demo.load(get_system_status, outputs=status_output)
# ุชุจูˆูŠุจ ุฅุฑุณุงู„ ุงู„ู…ู‡ุงู…
with gr.TabItem("๐Ÿš€ ุฅุฑุณุงู„ ุงู„ู…ู‡ุงู…"):
with gr.Row():
with gr.Column():
gr.Markdown("### ุฅุฑุณุงู„ ู…ู‡ู…ุฉ ุฌุฏูŠุฏุฉ")
task_type = gr.Dropdown(
choices=[
("ุถุฑุจ ุงู„ู…ุตููˆูุงุช (CPU)", "matrix"),
("ู…ุชุณู„ุณู„ุฉ ููŠุจูˆู†ุงุชุดูŠ", "fibonacci"),
("ุงู„ุฃุนุฏุงุฏ ุงู„ุฃูˆู„ูŠุฉ", "primes"),
("ู…ุนุงู„ุฌุฉ ุงู„ุจูŠุงู†ุงุช", "data"),
("ู…ุญุงูƒุงุฉ ู…ุนุงู„ุฌุฉ ุงู„ุตูˆุฑ", "image"),
("ู…ู‡ู…ุฉ ุนุงู…ุฉ", "general")
],
label="ู†ูˆุน ุงู„ู…ู‡ู…ุฉ",
value="matrix"
)
params_input = gr.Textbox(
label="ู…ุนุงู…ู„ุงุช ุงู„ู…ู‡ู…ุฉ (JSON)",
value='{"size": 100}',
placeholder='{"size": 100} ุฃูˆ {"limit": 1000}'
)
submit_btn = gr.Button("๐Ÿ“จ ุฅุฑุณุงู„ ุงู„ู…ู‡ู…ุฉ", variant="primary")
with gr.Column():
gr.Markdown("### ู†ุชูŠุฌุฉ ุงู„ุฅุฑุณุงู„")
task_result = gr.Markdown()
submit_btn.click(submit_task_ui, [task_type, params_input], task_result)
# ุชุจูˆูŠุจ ุงู„ุนู‚ุฏ
with gr.TabItem("๐Ÿ‘ฅ ุฅุฏุงุฑุฉ ุงู„ุนู‚ุฏ"):
gr.Markdown("### ุงู„ุนู‚ุฏ ุงู„ู…ุชุตู„ุฉ")
nodes_table = gr.Dataframe(
headers=["ุงู„ุนู‚ุฏุฉ", "ุงู„ุญุงู„ุฉ", "ุงู„ู†ู‚ุงุท", "CPU%", "ุงู„ุฐุงูƒุฑุฉ%", "ุงู„ู…ู‡ุงู…", "ู…ุนุฏู„ ุงู„ู†ุฌุงุญ", "ุขุฎุฑ ุธู‡ูˆุฑ"],
interactive=False,
datatype=["str", "str", "str", "str", "str", "str", "str", "str"]
)
with gr.Row():
refresh_nodes = gr.Button("๐Ÿ”„ ุชุญุฏูŠุซ ู‚ุงุฆู…ุฉ ุงู„ุนู‚ุฏ")
sim_node = gr.Button("โž• ู…ุญุงูƒุงุฉ ุนู‚ุฏุฉ ุฌุฏูŠุฏุฉ")
sim_tasks = gr.Button("๐Ÿ“จ ู…ุญุงูƒุงุฉ ุญู…ู„ ู…ู‡ุงู…")
task_count = gr.Slider(1, 10, value=3, label="ุนุฏุฏ ุงู„ู…ู‡ุงู…")
sim_result = gr.Markdown()
refresh_nodes.click(get_node_details, outputs=nodes_table)
sim_node.click(simulate_new_node, outputs=sim_result)
sim_tasks.click(simulate_task_load, task_count, sim_result)
demo.load(get_node_details, outputs=nodes_table)
# ุชุจูˆูŠุจ ุงู„ู…ุนู„ูˆู…ุงุช
with gr.TabItem("โ„น๏ธ ู…ุนู„ูˆู…ุงุช ุงู„ู†ุธุงู…"):
gr.Markdown("""
## ๐Ÿ“– ุนู† ุงู„ุฎุงุฏู… ุงู„ู…ุฑูƒุฒูŠ
ู‡ุฐุง ุชุทุจูŠู‚ **ุฎุงุฏู… ู…ุฑูƒุฒูŠ ุญู‚ูŠู‚ูŠ** ูŠุนู…ู„ ุนู„ู‰ Hugging Face Spaces.
### โœจ ุงู„ู…ู…ูŠุฒุงุช:
- **ุชูˆุฒูŠุน ุฐูƒูŠ ู„ู„ู…ู‡ุงู…** ุนู„ู‰ ุฃูุถู„ ุนู‚ุฏุฉ ู…ุชุงุญุฉ
- **ู…ุฑุงู‚ุจุฉ ููŠ ุงู„ูˆู‚ุช ุงู„ูุนู„ูŠ** ู„ุฌู…ูŠุน ุงู„ุนู‚ุฏ
- **ู…ุญุงูƒุงุฉ ู…ุชู‚ุฏู…ุฉ** ู„ู„ุนู‚ุฏ ูˆุงู„ู…ู‡ุงู…
- **ุฅุญุตุงุฆูŠุงุช ู…ูุตู„ุฉ** ุนู† ุฃุฏุงุก ุงู„ู†ุธุงู…
- **ูˆุงุฌู‡ุฉ ุชุญูƒู… ูƒุงู…ู„ุฉ** ุนุจุฑ Gradio
### ๐Ÿ—๏ธ ูƒูŠููŠุฉ ุงู„ุนู…ู„:
1. **ุงู„ุนู‚ุฏ ุชุชุตู„** ุจุงู„ุฎุงุฏู… ูˆุชุณุฌู„ ู†ูุณู‡ุง
2. **ุงู„ู…ู‡ุงู… ุชุฑุณู„** ู„ู„ุฎุงุฏู… ุงู„ู…ุฑูƒุฒูŠ
3. **ุงู„ุฎุงุฏู… ูŠุฎุชุงุฑ** ุฃูุถู„ ุนู‚ุฏุฉ ุจู†ุงุกู‹ ุนู„ู‰:
- ุงุณุชุฎุฏุงู… CPU ูˆุงู„ุฐุงูƒุฑุฉ
- ู…ุนุฏู„ ุงู„ู†ุฌุงุญ ุงู„ุณุงุจู‚
- ุนุฏุฏ ุงู„ู…ู‡ุงู… ุงู„ู†ุดุทุฉ
- ูˆู‚ุช ุงู„ุงุณุชุฌุงุจุฉ
4. **ุงู„ู…ู‡ุงู… ุชู†ูุฐ** ุนู„ู‰ ุงู„ุนู‚ุฏ ุงู„ู…ุฎุชุงุฑุฉ
5. **ุงู„ู†ุชุงุฆุฌ ุชุฑุฌุน** ู„ู„ุฎุงุฏู…
### ๐ŸŒ API ุงู„ู…ุชุงุญ:
ูŠู…ูƒู† ู„ู„ุนู‚ุฏ ุงู„ุญู‚ูŠู‚ูŠุฉ ุงู„ุงุชุตุงู„ ุนุจุฑ:
- `POST /register` - ุชุณุฌูŠู„ ุนู‚ุฏุฉ
- `POST /task/submit` - ุฅุฑุณุงู„ ู…ู‡ู…ุฉ
- `POST /status/update` - ุชุญุฏูŠุซ ุญุงู„ุฉ
- `GET /nodes` - ู‚ุงุฆู…ุฉ ุงู„ุนู‚ุฏ
- `GET /tasks` - ู‚ุงุฆู…ุฉ ุงู„ู…ู‡ุงู…
### ๐Ÿ”ง ุงู„ุชู‚ู†ูŠุงุช:
- Python 3 ู…ุน ู…ุนุงู„ุฌุฉ ู…ุชุนุฏุฏุฉ ุงู„ุฎูŠูˆุท
- Gradio ู„ู„ูˆุงุฌู‡ุฉ ุงู„ุฃู…ุงู…ูŠุฉ
- ุฎูˆุงุฑุฒู…ูŠุงุช ุชูˆุฒูŠุน ุฐูƒูŠุฉ
- ู†ุธุงู… ู…ุญุงูƒุงุฉ ู…ุชูƒุงู…ู„
""")
gr.Markdown("---\n*ุงู„ุฎุงุฏู… ุงู„ู…ุฑูƒุฒูŠ ู„ุชูˆุฒูŠุน ุงู„ู…ู‡ุงู… ุงู„ุฐูƒูŠ - ุงู„ุฅุตุฏุงุฑ 3.0.0*")
return demo
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ API Flask (ู„ู„ุนู‚ุฏ ุงู„ุญู‚ูŠู‚ูŠุฉ) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
flask_app = Flask(__name__)
CORS(flask_app)
@flask_app.route('/')
def api_home():
return jsonify({
"message": "ุงู„ุฎุงุฏู… ุงู„ู…ุฑูƒุฒูŠ ู„ุชูˆุฒูŠุน ุงู„ู…ู‡ุงู…",
"version": "3.0.0",
"status": "running",
"gradio_url": "https://huggingface.co/spaces/your-username/your-space"
})
@flask_app.route('/register', methods=['POST'])
def api_register():
try:
data = request.get_json()
result = central_server.register_node(data)
return jsonify(result)
except Exception as e:
return jsonify({"error": str(e)}), 500
@flask_app.route('/task/submit', methods=['POST'])
def api_submit_task():
try:
data = request.get_json()
result = central_server.submit_task(data)
return jsonify(result)
except Exception as e:
return jsonify({"error": str(e)}), 500
@flask_app.route('/status/update', methods=['POST'])
def api_update_status():
try:
data = request.get_json()
node_id = data.get('node_id')
if not node_id:
return jsonify({"error": "ู…ุนุฑู ุงู„ุนู‚ุฏุฉ ู…ุทู„ูˆุจ"}), 400
result = central_server.update_node_status(node_id, data)
return jsonify(result)
except Exception as e:
return jsonify({"error": str(e)}), 500
@flask_app.route('/nodes', methods=['GET'])
def api_get_nodes():
try:
overview = central_server.get_system_overview()
return jsonify({
"status": "success",
"count": len(overview["nodes"]),
"nodes": overview["nodes"]
})
except Exception as e:
return jsonify({"error": str(e)}), 500
@flask_app.route('/tasks', methods=['GET'])
def api_get_tasks():
try:
with central_server.lock:
tasks = list(central_server.tasks.values())[-50:]
tasks_data = []
for task in tasks:
task_dict = asdict(task)
for field in ["created_at", "started_at", "completed_at"]:
if task_dict[field]:
task_dict[field] = task_dict[field].isoformat()
tasks_data.append(task_dict)
return jsonify({
"status": "success",
"count": len(tasks_data),
"tasks": tasks_data
})
except Exception as e:
return jsonify({"error": str(e)}), 500
@flask_app.route('/stats', methods=['GET'])
def api_get_stats():
try:
overview = central_server.get_system_overview()
return jsonify({
"status": "success",
"stats": overview["metrics"]
})
except Exception as e:
return jsonify({"error": str(e)}), 500
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ ุจุฏุก Flask ููŠ ุฎูŠุท ู…ู†ูุตู„ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
def start_flask_server():
"""ุจุฏุก ุฎุงุฏู… Flask ู„ู„ุนู‚ุฏ ุงู„ุญู‚ูŠู‚ูŠุฉ"""
port = 7861 # ู…ู†ูุฐ ู…ุฎุชู„ู ุนู† Gradio
flask_app.run(
host="0.0.0.0",
port=port,
debug=False,
threaded=True,
use_reloader=False
)
# โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ ุงู„ุฏุงู„ุฉ ุงู„ุฑุฆูŠุณูŠุฉ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
def main():
"""ุงู„ุฏุงู„ุฉ ุงู„ุฑุฆูŠุณูŠุฉ"""
logger.info("๐Ÿš€ ุจุฏุก ุชุดุบูŠู„ ุชุทุจูŠู‚ Hugging Face ูƒุฎุงุฏู… ู…ุฑูƒุฒูŠ")
# ุจุฏุก ุฎุงุฏู… Flask ู„ู„API ููŠ ุฎูŠุท ู…ู†ูุตู„
flask_thread = threading.Thread(target=start_flask_server, daemon=True)
flask_thread.start()
logger.info("โœ… ุจุฏุก ุฎุงุฏู… Flask API ุนู„ู‰ ุงู„ู…ู†ูุฐ 7861")
# ุฅู†ุดุงุก ูˆุงุฌู‡ุฉ Gradio
demo = create_interface()
# ุชุดุบูŠู„ Gradio
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
debug=False
)
if __name__ == "__main__":
main()