Really-amin commited on
Commit
8d3506b
·
verified ·
1 Parent(s): bf7378a

Upload backend/services/dashboard_metrics.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. backend/services/dashboard_metrics.py +229 -0
backend/services/dashboard_metrics.py ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Real dashboard metrics — single source of truth for cards and System Status drawer.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import json
8
+ import os
9
+ import re
10
+ from pathlib import Path
11
+ from typing import Any, Dict, List, Optional, Tuple
12
+
13
+ _ENV_PROBE_VARS = [
14
+ "CRYPTOCOMPARE_API_KEY",
15
+ "COINMARKETCAP_KEY_1",
16
+ "COINMARKETCAP_KEY_2",
17
+ "ETHERSCAN_KEY_1",
18
+ "ETHERSCAN_KEY_2",
19
+ "BSCSCAN_API_KEY",
20
+ "TRONSCAN_API_KEY",
21
+ "NEWSAPI_KEY",
22
+ "HF_TOKEN",
23
+ "HUGGINGFACE_TOKEN",
24
+ "COINGECKO_API_KEY",
25
+ ]
26
+
27
+ _PLACEHOLDER = re.compile(r"^\$\{[A-Z0-9_]+\}$")
28
+
29
+
30
+ def _workspace_root() -> Path:
31
+ here = Path(__file__).resolve()
32
+ for parent in (here, *here.parents):
33
+ if (parent / "hf_unified_server.py").exists():
34
+ return parent
35
+ return here.parents[2]
36
+
37
+
38
+ def _api_keys_path() -> Path:
39
+ return _workspace_root() / "config" / "api_keys.json"
40
+
41
+
42
+ def _env_configured() -> Tuple[List[str], List[str]]:
43
+ configured: List[str] = []
44
+ missing: List[str] = []
45
+ for name in _ENV_PROBE_VARS:
46
+ val = (os.getenv(name) or "").strip()
47
+ if val and val.lower() not in ("null", "none", "cg-xxx", "cg-xxxxxxxxxxxxxxxxxxxxxxxx"):
48
+ if name not in configured:
49
+ configured.append(name)
50
+ else:
51
+ missing.append(name)
52
+ # HF_TOKEN / HUGGINGFACE_TOKEN count as one slot
53
+ if "HF_TOKEN" in configured and "HUGGINGFACE_TOKEN" in configured:
54
+ configured.remove("HUGGINGFACE_TOKEN")
55
+ if "HF_TOKEN" in missing and "HUGGINGFACE_TOKEN" in missing:
56
+ missing = [m for m in missing if m != "HUGGINGFACE_TOKEN"]
57
+ return configured, missing
58
+
59
+
60
+ def _file_backed_keys() -> Dict[str, Any]:
61
+ """Count inline keys stored in config/api_keys.json (not env placeholders)."""
62
+ path = _api_keys_path()
63
+ if not path.exists():
64
+ return {"inline_key_count": 0, "providers": [], "by_provider": {}}
65
+
66
+ try:
67
+ cfg = json.loads(path.read_text(encoding="utf-8", errors="replace"))
68
+ except Exception:
69
+ return {"inline_key_count": 0, "providers": [], "by_provider": {}}
70
+
71
+ by_provider: Dict[str, int] = {}
72
+
73
+ def walk(obj: Any, provider: str = "") -> None:
74
+ if isinstance(obj, dict):
75
+ name = obj.get("description") or provider
76
+ if "keys" in obj and isinstance(obj["keys"], list):
77
+ valid = [k for k in obj["keys"] if k and not _PLACEHOLDER.match(str(k).strip())]
78
+ if valid:
79
+ key = name or provider or "unknown"
80
+ by_provider[key] = by_provider.get(key, 0) + len(valid)
81
+ if "key" in obj:
82
+ k = str(obj["key"]).strip()
83
+ if k and not _PLACEHOLDER.match(k):
84
+ key = name or provider or "unknown"
85
+ by_provider[key] = by_provider.get(key, 0) + 1
86
+ for k, v in obj.items():
87
+ if k in ("keys", "key", "env_aliases", "endpoints", "description"):
88
+ continue
89
+ walk(v, k if isinstance(k, str) else provider)
90
+ elif isinstance(obj, list):
91
+ for item in obj:
92
+ walk(item, provider)
93
+
94
+ for section, content in cfg.items():
95
+ if section in ("description", "last_updated", "environment_variables", "aggregated_sources"):
96
+ continue
97
+ walk(content, section)
98
+
99
+ total = sum(by_provider.values())
100
+ return {
101
+ "inline_key_count": total,
102
+ "providers": list(by_provider.keys()),
103
+ "by_provider": by_provider,
104
+ }
105
+
106
+
107
+ def get_api_keys_status() -> Dict[str, Any]:
108
+ configured_env, missing_env = _env_configured()
109
+ file_info = _file_backed_keys()
110
+ inline = file_info["inline_key_count"]
111
+ env_count = len(configured_env)
112
+ # Effective: env secrets + file keys (env takes precedence for same provider)
113
+ effective = env_count + inline
114
+ probe_total = len(_ENV_PROBE_VARS) - (1 if "HUGGINGFACE_TOKEN" in _ENV_PROBE_VARS else 0)
115
+
116
+ return {
117
+ "config_exists": _api_keys_path().exists(),
118
+ "env_configured": configured_env,
119
+ "env_missing": missing_env,
120
+ "env_configured_count": env_count,
121
+ "env_total_probed": probe_total,
122
+ "file_backed_keys": inline,
123
+ "file_providers": file_info["providers"],
124
+ "by_provider": file_info["by_provider"],
125
+ "configured_keys": effective,
126
+ "total_key_refs": probe_total + inline,
127
+ "display": f"{env_count} secrets + {inline} file keys",
128
+ }
129
+
130
+
131
+ def get_rotation_summary() -> Dict[str, Any]:
132
+ try:
133
+ from provider_manager import get_provider_manager
134
+
135
+ manager = get_provider_manager()
136
+ manager.ensure_unified_sync()
137
+ pools: List[Dict[str, Any]] = []
138
+ total_providers = 0
139
+ available_providers = 0
140
+ for pool_id, pool in manager.pools.items():
141
+ stats = pool.get_stats()
142
+ avail = int(stats.get("available_providers") or 0)
143
+ tot = int(stats.get("total_providers") or 0)
144
+ total_providers += tot
145
+ available_providers += avail
146
+ pools.append({
147
+ "pool_id": pool_id,
148
+ "name": pool_id.replace("_", " ").title(),
149
+ "available_providers": avail,
150
+ "total_providers": tot,
151
+ "rotation_strategy": stats.get("rotation_strategy"),
152
+ "healthy": avail > 0,
153
+ })
154
+ healthy_pools = sum(1 for p in pools if p["healthy"])
155
+ return {
156
+ "success": True,
157
+ "pools_total": len(pools),
158
+ "pools_healthy": healthy_pools,
159
+ "providers_total": total_providers,
160
+ "providers_available": available_providers,
161
+ "pools": pools,
162
+ "env_keys": get_api_keys_status(),
163
+ }
164
+ except Exception as exc:
165
+ return {
166
+ "success": False,
167
+ "error": str(exc),
168
+ "pools_total": 0,
169
+ "pools_healthy": 0,
170
+ "providers_total": 0,
171
+ "providers_available": 0,
172
+ "pools": [],
173
+ }
174
+
175
+
176
+ def get_registry_summary() -> Tuple[Dict[str, Any], List[Dict[str, Any]]]:
177
+ """Load category counts from unified registry cache if available."""
178
+ try:
179
+ import hf_unified_server as server
180
+ return server._summarize_resources()
181
+ except Exception:
182
+ return {"total": 0}, []
183
+
184
+
185
+ async def get_models_combined() -> Dict[str, Any]:
186
+ v2_loaded = v2_total = 0
187
+ v4_loaded = v4_total = 0
188
+ hf_mode = "unknown"
189
+ v4_hf_mode = None
190
+ transformers = False
191
+ try:
192
+ from backend.routers.hf_models_summary import build_models_summary
193
+
194
+ ms = await build_models_summary()
195
+ if ms.get("success"):
196
+ sm = ms.get("summary") or {}
197
+ v2_loaded = int(sm.get("loaded_models") or 0)
198
+ v2_total = int(sm.get("total_models") or 0)
199
+ hf_mode = sm.get("hf_mode") or hf_mode
200
+ transformers = bool(sm.get("transformers_available"))
201
+ c4 = ms.get("complement_v4") or {}
202
+ v4_loaded = int(c4.get("loaded") or 0)
203
+ v4_total = int(c4.get("total") or 0)
204
+ v4_hf_mode = c4.get("hf_mode")
205
+ except Exception:
206
+ try:
207
+ from ai_models import _registry, HF_MODE, TRANSFORMERS_AVAILABLE, MODEL_SPECS
208
+
209
+ v2_loaded = len(getattr(_registry, "_pipelines", {}))
210
+ v2_total = len(MODEL_SPECS)
211
+ hf_mode = HF_MODE
212
+ transformers = TRANSFORMERS_AVAILABLE
213
+ except Exception:
214
+ pass
215
+
216
+ combined_loaded = v2_loaded + v4_loaded
217
+ combined_total = v2_total + v4_total
218
+ return {
219
+ "models_loaded_v2": v2_loaded,
220
+ "models_total_v2": v2_total,
221
+ "models_loaded_v4": v4_loaded,
222
+ "models_total_v4": v4_total,
223
+ "models_loaded": combined_loaded,
224
+ "models_total": combined_total,
225
+ "hf_mode": hf_mode,
226
+ "v4_hf_mode": v4_hf_mode,
227
+ "transformers_available": transformers,
228
+ "health": combined_loaded > 0 and hf_mode not in ("off", "unknown"),
229
+ }