feat(health): implement dynamic model fleet expansion for wildcard endpoints
This commit is contained in:
1 parent
b84cf34e88
commit
e8988b9c4e
1 file changed
+41
-20
+41
-20
@@ -2,10 +2,10 @@
|
|||||||
title: LiteLLM Dashboard
|
title: LiteLLM Dashboard
|
||||||
author: Kagamine Rin & VAI
|
author: Kagamine Rin & VAI
|
||||||
author_url: https://rin.captcouch.xyz
|
author_url: https://rin.captcouch.xyz
|
||||||
description: Professional LiteLLM observability — Grouped health, wildcard resolution, and Billion-scale token tracking.
|
description: Professional LiteLLM observability — Fleet expansion, proactive budget monitoring, and Billion-scale token tracking.
|
||||||
required_open_webui_version: 0.4.0
|
required_open_webui_version: 0.4.0
|
||||||
requirements: requests
|
requirements: requests
|
||||||
version: 1.6.2
|
version: 1.6.4
|
||||||
licence: MIT
|
licence: MIT
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ class Tools:
|
|||||||
return date_str
|
return date_str
|
||||||
|
|
||||||
def litellm_health(self) -> str:
|
def litellm_health(self) -> str:
|
||||||
"""Check LiteLLM proxy health, proactive budget, and grouped model readiness."""
|
"""Check LiteLLM proxy health, proactive budget, and grouped model fleet expansion."""
|
||||||
self._fetch_live_data()
|
self._fetch_live_data()
|
||||||
lines = [f"LiteLLM Health & Budget — {self._base_url()}"]
|
lines = [f"LiteLLM Health & Budget — {self._base_url()}"]
|
||||||
lines.append("=" * 70)
|
lines.append("=" * 70)
|
||||||
@@ -167,7 +167,7 @@ class Tools:
|
|||||||
lines.append(f"✅ Proxy: {d.get('status')} | DB: {d.get('db')} | v{d.get('litellm_version')}")
|
lines.append(f"✅ Proxy: {d.get('status')} | DB: {d.get('db')} | v{d.get('litellm_version')}")
|
||||||
except Exception: pass
|
except Exception: pass
|
||||||
|
|
||||||
# 3. Model Fleet (Grouped by Provider + Wildcard Linkage)
|
# 3. Model Fleet (Grouped by Provider + Wildcard Expansion)
|
||||||
try:
|
try:
|
||||||
url = f"{self._base_url()}/health"
|
url = f"{self._base_url()}/health"
|
||||||
resp = requests.get(url, headers=self._headers(), timeout=15)
|
resp = requests.get(url, headers=self._headers(), timeout=15)
|
||||||
@@ -179,35 +179,56 @@ class Tools:
|
|||||||
groups = {}
|
groups = {}
|
||||||
for ep in healthy + unhealthy:
|
for ep in healthy + unhealthy:
|
||||||
m_raw = ep.get("model", "unknown")
|
m_raw = ep.get("model", "unknown")
|
||||||
m_display = self._compact_name(m_raw, 32)
|
api_base = ep.get("api_base", "")
|
||||||
|
|
||||||
# Wildcard Linkage
|
# Wildcard & Fleet Discovery
|
||||||
found_alias = False
|
m_display = self._compact_name(m_raw, 32)
|
||||||
|
fleet_members = []
|
||||||
|
|
||||||
|
# Search for wildcard/alias labels
|
||||||
|
target_id = None
|
||||||
for info in self._model_info_cache:
|
for info in self._model_info_cache:
|
||||||
if info.get("model_info", {}).get("health_check_model") == m_raw:
|
m_info = info.get("model_info", {})
|
||||||
alias = info.get("model_name", "unknown")
|
if m_info.get("health_check_model") == m_raw:
|
||||||
m_display = f"{self._compact_name(alias, 28)} (via {m_display})"
|
m_display = info.get("model_name", m_raw)
|
||||||
found_alias = True
|
target_id = m_info.get("id")
|
||||||
break
|
break
|
||||||
|
|
||||||
if not found_alias and "*" in m_raw:
|
if not target_id: # Direct match fallback
|
||||||
meta = ep.get("litellm_metadata", {}) or {}
|
for info in self._model_info_cache:
|
||||||
probe = meta.get("health_check_model", "generic")
|
if info.get("model_name") == m_raw:
|
||||||
m_display = f"{m_display} (via {probe.split('/')[-1]})"
|
target_id = info.get("model_info", {}).get("id")
|
||||||
|
break
|
||||||
|
|
||||||
|
# Populate members sharing this ID (The Fleet)
|
||||||
|
if target_id:
|
||||||
|
for info in self._model_info_cache:
|
||||||
|
if info.get("model_info", {}).get("id") == target_id and info.get("model_name") != m_display:
|
||||||
|
name_part = info.get("model_name", "").split("/")[-1]
|
||||||
|
if name_part and name_part != "*":
|
||||||
|
fleet_members.append(name_part)
|
||||||
|
|
||||||
|
icon = "✅" if ep in healthy else "❌"
|
||||||
|
|
||||||
# Provider Determination
|
# Provider Determination
|
||||||
provider = "other"
|
provider = "other"
|
||||||
if "ollama" in ep.get("api_base", "").lower() or "ollama" in m_raw.lower():
|
if "ollama" in api_base.lower() or "ollama" in m_raw.lower():
|
||||||
provider = "ollama"
|
provider = "ollama"
|
||||||
elif "/" in m_raw:
|
elif "/" in m_raw:
|
||||||
provider = m_raw.split("/")[0]
|
provider = m_raw.split("/")[0]
|
||||||
|
|
||||||
if provider not in groups: groups[provider] = {"ok": [], "fail": []}
|
if provider not in groups: groups[provider] = {"ok": [], "fail": []}
|
||||||
|
|
||||||
icon = "✅" if ep in healthy else "❌"
|
if fleet_members:
|
||||||
info_line = f" {icon} {m_display:40s} | rpm: {ep.get('rpm','?'):>3}"
|
m_display = f"{m_display} ({len(fleet_members)} members)"
|
||||||
if ep in healthy: groups[provider]["ok"].append(info_line)
|
fleet_lines = [f" {icon} {m_display:45s} | rpm: {ep.get('rpm','?'):>3}"]
|
||||||
else: groups[provider]["fail"].append(info_line)
|
fleet_lines.extend([f" └─ • {m}" for m in sorted(list(set(fleet_members)))])
|
||||||
|
info_block = "\n".join(fleet_lines)
|
||||||
|
else:
|
||||||
|
info_block = f" {icon} {m_display:45s} | rpm: {ep.get('rpm','?'):>3}"
|
||||||
|
|
||||||
|
if ep in healthy: groups[provider]["ok"].append(info_block)
|
||||||
|
else: groups[provider]["fail"].append(info_block)
|
||||||
|
|
||||||
lines.append(f"\nFleet Status: {len(healthy)} healthy, {len(unhealthy)} unhealthy")
|
lines.append(f"\nFleet Status: {len(healthy)} healthy, {len(unhealthy)} unhealthy")
|
||||||
for prov in sorted(groups.keys()):
|
for prov in sorted(groups.keys()):
|
||||||
|
|||||||
Reference in new issue
Block a user