| # گزارش بهروزرسانی 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) | |