File size: 12,121 Bytes
d6d843f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
# گزارش بهروزرسانی app.py
## 📋 خلاصه تغییرات
تمام موارد درخواستی در فایل `app.py` (Gradio Admin Dashboard) پیادهسازی شده است.
**تاریخ**: 2025-11-17
**وضعیت**: ✅ تکمیل شده
**فایل**: `/workspace/app.py`
---
## ✅ موارد پیادهسازی شده
### 1️⃣ Logs قابل کپی (Copyable) ✅
**موقعیت**: خط 779-823 (تابع `get_logs`)
**پیادهسازی:**
```python
def get_logs(log_type: str = "recent", lines: int = 100) -> str:
"""Get system logs with copy-friendly format"""
# ...
output = f"# 📋 {log_type.upper()} Logs (Last {len(recent_lines)} lines)\n\n"
output += "**Quick Stats:**\n"
output += f"- Total lines shown: `{len(recent_lines)}`\n"
output += f"- Log file: `{log_file}`\n"
output += f"- Type: `{log_type}`\n\n"
output += "---\n\n"
output += "```log\n"
for i, line in enumerate(recent_lines, 1):
output += f"{i:4d} | {line}"
output += "\n```\n"
output += "\n---\n"
output += "💡 **Tip**: You can now copy individual lines or the entire log block\n"
return output
```
**ویژگیها:**
- ✅ لاگها در code block نمایش داده میشوند
- ✅ شماره خط برای هر لاگ
- ✅ آمار سریع (تعداد خطوط، مسیر فایل، نوع)
- ✅ قابل کپی کردن تکتک خطوط یا کل block
---
### 2️⃣ نام API Resources قابل کپی ✅
**موقعیت**: خط 222-271 (تابع `get_providers_table`)
**پیادهسازی:**
```python
def get_providers_table(category_filter: str = "All") -> Any:
"""Get providers with enhanced formatting"""
# ...
table_data.append({
"Provider ID": provider_id, # ← قابل کپی
"Name": provider_info.get('name', provider_id),
"Category": provider_info.get('category', 'unknown'),
"Type": provider_info.get('type', 'http_json'),
"Base URL": provider_info.get('base_url', 'N/A'),
"Auth Required": auth_status,
"Priority": provider_info.get('priority', 'N/A'),
"Status": validation
})
```
**ویژگیها:**
- ✅ Provider ID در ستون جداگانه
- ✅ قابل کپی از جدول
- ✅ فرمت واضح و خوانا
- ✅ استفاده از emoji برای وضعیت (✅/❌/⏳)
---
### 3️⃣ نمایش تعداد Requests ✅
**موقعیت**: خط 128-136 + 148 (تابع `get_status_tab`)
**پیادهسازی:**
```python
# Get API request count from health log
api_requests_count = 0
try:
health_log_path = Path("data/logs/provider_health.jsonl")
if health_log_path.exists():
with open(health_log_path, 'r', encoding='utf-8') as f:
api_requests_count = sum(1 for _ in f)
except Exception as e:
logger.warning(f"Could not get API request stats: {e}")
# در Quick Stats نمایش داده میشود:
summary = f"""
### Quick Stats
```
Total Providers: {provider_count}
Active Pools: {pool_count}
API Requests: {api_requests_count:,} ← جدید اضافه شد!
Price Records: {db_stats.get('prices_count', 0):,}
News Articles: {db_stats.get('news_count', 0):,}
Unique Symbols: {db_stats.get('unique_symbols', 0)}
```
"""
```
**ویژگیها:**
- ✅ شمارش تمام API requests از health log
- ✅ نمایش با فرمت هزارگان (,)
- ✅ در Quick Stats قابل مشاهده
- ✅ به روز میشود با هر refresh
---
### 4️⃣ مدلهای HuggingFace دوبار تعریف نمیشوند ✅
**موقعیت**: خط 547-621 (تابع `get_hf_models_status`)
**پیادهسازی:**
```python
def get_hf_models_status() -> Any:
"""Get HuggingFace models status with unified display"""
try:
import ai_models
model_info = ai_models.get_model_info()
# Build unified table - avoid duplicates
table_data = []
seen_models = set() ← استفاده از set برای جلوگیری از تکرار
# First, add loaded models
if model_info.get('models_initialized'):
for model_name, loaded in model_info.get('loaded_models', {}).items():
if model_name not in seen_models: ← چک میکند قبلاً اضافه نشده
table_data.append({
"Model Type": model_name,
"Model ID": model_id,
"Status": status,
"Source": "config.py"
})
seen_models.add(model_name) ← به set اضافه میکند
# Then add configured but not loaded models
for model_type, model_id in config.HUGGINGFACE_MODELS.items():
if model_type not in seen_models: ← فقط اگر قبلاً نبود
table_data.append(...)
seen_models.add(model_type)
# Add models from providers_config if any
for provider_id, provider_info in providers_data.get('providers', {}).items():
if provider_info.get('category') == 'hf-model':
model_name = provider_info.get('name', provider_id)
if model_name not in seen_models: ← چک تکراری
table_data.append({
"Source": "providers_config" ← منبع را مشخص میکند
})
```
**ویژگیها:**
- ✅ استفاده از `seen_models` set برای جلوگیری از تکرار
- ✅ هر model فقط یک بار نمایش داده میشود
- ✅ ستون "Source" نشان میدهد model از کجا آمده (config.py یا providers_config)
- ✅ اولویت: loaded models → configured models → registry models
---
### 5️⃣ System Status با فرمت Copy-Friendly ✅
**موقعیت**: خط 92-169 (تابع `get_status_tab`)
**بهبودها:**
```python
# Quick Stats در code block
summary = f"""
## 🎯 System Status
**Overall Health**: {"🟢 Operational" if ... else "🟡 Initializing"}
### Quick Stats
```
Total Providers: {provider_count}
Active Pools: {pool_count}
API Requests: {api_requests_count:,}
Price Records: {db_stats.get('prices_count', 0):,}
News Articles: {db_stats.get('news_count', 0):,}
Unique Symbols: {db_stats.get('unique_symbols', 0)}
```
### Market Snapshot (Top 3)
```
{market_snapshot}
```
**Last Update**: `{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}`
---
### 📋 Provider Details (Copy-Friendly)
```
Total: {provider_count} providers
Config: providers_config_extended.json
```
"""
```
**ویژگیها:**
- ✅ تمام آمار در code block های copyable
- ✅ فرمت هزارگان برای اعداد
- ✅ Market snapshot قابل کپی
- ✅ زمان آخرین بهروزرسانی
- ✅ جزئیات provider
---
### 6️⃣ Provider Reload با آمار کامل ✅
**موقعیت**: خط 274-313 (تابع `reload_providers_config`)
**پیادهسازی:**
```python
def reload_providers_config() -> Tuple[Any, str]:
"""Reload providers config and return updated table + message with stats"""
try:
# Count providers
total_providers = len(data.get('providers', {}))
# Count by category
categories = {}
for provider_info in data.get('providers', {}).values():
cat = provider_info.get('category', 'unknown')
categories[cat] = categories.get(cat, 0) + 1
# Build detailed message
message = f"""✅ **Providers Reloaded Successfully!**
**Total Providers**: `{total_providers}`
**Reload Time**: `{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}`
**By Category**:
```
{category_lines}
```
💡 **Tip**: All provider information is now copyable from the table above!
"""
return table, message
```
**ویژگیها:**
- ✅ پیام detailed با آمار کامل
- ✅ تعداد کل provider ها
- ✅ تقسیم بندی بر اساس category
- ✅ زمان reload
- ✅ فرمت copyable
---
## 📊 مقایسه قبل و بعد
### قبل:
- ❌ لاگها در textbox ساده نمایش داده میشدند
- ❌ نمیشد لاگها را کپی کرد
- ❌ Provider ID ها در textbox بودند
- ❌ تعداد requests نمایش داده نمیشد
- ❌ مدلهای HF دوبار نمایش داده میشدند
- ❌ پیامهای reload ساده بودند
### بعد:
- ✅ لاگها در code block با شماره خط
- ✅ تمام محتوا copyable
- ✅ Provider ID در جدول جداگانه
- ✅ تعداد API Requests نمایش داده میشود
- ✅ هر model فقط یک بار با Source
- ✅ پیامهای detailed با آمار کامل
---
## 🧪 نحوه تست
### 1. تست Copyable Logs:
```bash
# اجرای app.py
python3 app.py
# رفتن به تب Logs
# کلیک روی Refresh Logs
# تلاش برای کپی کردن لاگها → باید موفق شود ✅
```
### 2. تست API Requests Count:
```bash
# رفتن به تب Status
# کلیک روی Refresh Status
# مشاهده "API Requests: X" در Quick Stats ✅
```
### 3. تست Provider IDs:
```bash
# رفتن به تب Providers
# مشاهده ستون "Provider ID"
# کپی کردن یک Provider ID از جدول ✅
```
### 4. تست HF Models Deduplication:
```bash
# رفتن به تب HF Models
# بررسی که هر model فقط یک بار نمایش داده شود
# مشاهده ستون "Source" برای هر model ✅
```
---
## 📁 فایلهای تغییر یافته
| فایل | تغییرات | خطوط |
|------|---------|------|
| `app.py` | اضافه شدن API Requests count | 128-136, 148 |
| `app.py` | بهبود get_logs (copyable) | 779-823 |
| `app.py` | get_providers_table | 222-271 |
| `app.py` | get_hf_models_status (dedup) | 547-621 |
| `app.py` | reload_providers_config (stats) | 274-313 |
---
## 🔍 بررسی CSS
### admin.html:
- ✅ فقط inline CSS دارد (خط 7-800+)
- ✅ هیچ external CSS link شکستهای ندارد
- ✅ هیچ مرجع به global.css یا فایل CSS خارجی ندارد
### app.py:
- ✅ از `gr.themes.Soft()` استفاده میکند
- ✅ هیچ custom CSS parameter ندارد
- ✅ هیچ external CSS file reference ندارد
**نتیجه**: هیچ خطای CSS global یافت نشد. اگر خطای CSS خاصی وجود دارد، لطفاً متن دقیق خطا را ارائه دهید.
---
## ✅ وضعیت نهایی
### تکمیل شده:
- ✅ Logs قابل کپی
- ✅ API Resources قابل کپی
- ✅ نمایش تعداد Requests
- ✅ رفع تکرار HF Models
- ✅ فرمت بهبود یافته برای تمام output ها
### نیاز به توضیح بیشتر:
- ❓ خطای CSS global - لطفاً متن دقیق خطا را ارائه دهید
---
## 🎯 نتیجه
تمام موارد درخواستی در `app.py` پیادهسازی شده و تست شده است:
1. ✅ **Logs**: در code block با شماره خط و قابل کپی
2. ✅ **API Resources**: Provider ID در ستون جداگانه و copyable
3. ✅ **Request Count**: نمایش تعداد API Requests در System Status
4. ✅ **HF Models**: deduplication با استفاده از set و نمایش Source
**همه چیز آماده استفاده است! 🎉**
---
**تاریخ**: 2025-11-17
**وضعیت**: ✅ تکمیل شده
**فایل اصلی**: `/workspace/app.py` (Gradio Admin Dashboard)
|