گزارش بهروزرسانی app.py
📋 خلاصه تغییرات
تمام موارد درخواستی در فایل app.py (Gradio Admin Dashboard) پیادهسازی شده است.
تاریخ: 2025-11-17
وضعیت: ✅ تکمیل شده
فایل: /workspace/app.py
✅ موارد پیادهسازی شده
1️⃣ Logs قابل کپی (Copyable) ✅
موقعیت: خط 779-823 (تابع get_logs)
پیادهسازی:
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)
پیادهسازی:
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)
پیادهسازی:
# 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)
پیادهسازی:
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_modelsset برای جلوگیری از تکرار - ✅ هر model فقط یک بار نمایش داده میشود
- ✅ ستون "Source" نشان میدهد model از کجا آمده (config.py یا providers_config)
- ✅ اولویت: loaded models → configured models → registry models
5️⃣ System Status با فرمت Copy-Friendly ✅
موقعیت: خط 92-169 (تابع get_status_tab)
بهبودها:
# 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)
پیادهسازی:
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:
# اجرای app.py
python3 app.py
# رفتن به تب Logs
# کلیک روی Refresh Logs
# تلاش برای کپی کردن لاگها → باید موفق شود ✅
2. تست API Requests Count:
# رفتن به تب Status
# کلیک روی Refresh Status
# مشاهده "API Requests: X" در Quick Stats ✅
3. تست Provider IDs:
# رفتن به تب Providers
# مشاهده ستون "Provider ID"
# کپی کردن یک Provider ID از جدول ✅
4. تست HF Models Deduplication:
# رفتن به تب 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 پیادهسازی شده و تست شده است:
- ✅ Logs: در code block با شماره خط و قابل کپی
- ✅ API Resources: Provider ID در ستون جداگانه و copyable
- ✅ Request Count: نمایش تعداد API Requests در System Status
- ✅ HF Models: deduplication با استفاده از set و نمایش Source
همه چیز آماده استفاده است! 🎉
تاریخ: 2025-11-17
وضعیت: ✅ تکمیل شده
فایل اصلی: /workspace/app.py (Gradio Admin Dashboard)