All checks were successful
CD Pipeline / deploy (push) Successful in 2m25s
Operation Ollama-First v5.0 / Phase 27 + 28 — 戰役觀測前端化
routes/admin_observability_routes.py (新檔, 200+ 行)
- admin_observability_bp blueprint,url_prefix='/admin'
- /admin/ai_calls — Phase 27 主入口(KPI / by provider / TOP 100)
- /admin/promotion_review — Phase 28 PromotionGate 待審列表 + 通過/拒絕按鈕
- /admin/quality_trend — Phase 25 caller 反饋趨勢視覺化
- /admin/host_health — 三主機 + MCP + cost throttle 即時健康
- 失敗安全:DB 查詢失敗回空清單 + 警告 banner(不 raise)
- promotion_review_approve/reject 走 hash_human_approver SHA1[:8] 不存原 username
templates/admin/ (4 個新檔)
- ai_calls_dashboard.html 篩選 bar + 6 KPI cards + by provider + recent 100
- promotion_review.html 卡片列表 + 通過/拒絕 AJAX 按鈕(即時 UI feedback)
- quality_trend.html avg score 升序排列 + 進度條 bar + 智能建議區
- host_health.html 三主機 HTTP probe + 已載入模型 + MCP + throttle
統帥提問「需要哪些前端讓兩者互補互動」答覆:
6 項最該前端化(已實作 4 項,剩 2 項為後續):
✅ ai_calls 即時查詢 → /admin/ai_calls
✅ PromotionGate 待審核 → /admin/promotion_review (互動最強)
✅ caller 反饋趨勢 → /admin/quality_trend
✅ 三主機 + MCP + throttle → /admin/host_health
⏳ ai_call_budgets 預算管理 → Phase 29 補
⏳ PPT 視覺審核結果列表 → Phase 29 補
互補 Telegram 哲學:
Telegram = push(重要事件主動通知)
Web = pull(統帥隨時可查 / 互動審核 / 找問題)
PromotionGate Stage 4:Telegram 推 awaiting_review + Web 批次審核(兩者皆可)
app.py blueprint 註冊 + CSRF exempt(AJAX POST 走 server-side check)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
123 lines
4.4 KiB
HTML
123 lines
4.4 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}Host Health Dashboard{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="container-fluid mt-3">
|
||
<h2 class="mb-3">🏥 Host Health Dashboard
|
||
<small class="text-muted">三主機 + MCP + Cost Throttle 即時狀態</small>
|
||
</h2>
|
||
|
||
<!-- Ollama 三主機 -->
|
||
<div class="card mb-3">
|
||
<div class="card-header"><strong>🤖 Ollama 三主機(HTTP /api/tags 即時 probe)</strong></div>
|
||
<div class="card-body p-0">
|
||
<table class="table mb-0">
|
||
<thead class="table-light">
|
||
<tr><th>角色</th><th>主機</th><th>HTTP 健康</th><th>unhealthy mark</th><th>已載入模型</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for h in ollama_hosts %}
|
||
<tr>
|
||
<td><strong>{{ h.label }}</strong></td>
|
||
<td><code>{{ h.host }}</code></td>
|
||
<td>
|
||
{% if h.healthy %}
|
||
<span class="badge bg-success">✅ HTTP OK</span>
|
||
{% else %}
|
||
<span class="badge bg-danger">❌ DOWN</span>
|
||
{% endif %}
|
||
</td>
|
||
<td>
|
||
{% if h.unhealthy_mark %}
|
||
<span class="badge bg-warning">⚠️ marked unhealthy (30s)</span>
|
||
{% else %}
|
||
<span class="badge bg-light text-dark">—</span>
|
||
{% endif %}
|
||
</td>
|
||
<td>
|
||
{% for m in h.models %}
|
||
<span class="badge bg-info text-dark me-1">{{ m }}</span>
|
||
{% endfor %}
|
||
{% if not h.models %}<small class="text-muted">無 / 未連線</small>{% endif %}
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- MCP servers -->
|
||
<div class="card mb-3">
|
||
<div class="card-header"><strong>🔌 MCP Servers(Phase 10/10.5)</strong></div>
|
||
<div class="card-body p-0">
|
||
<table class="table mb-0">
|
||
<thead class="table-light">
|
||
<tr><th>Server</th><th>狀態</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for server, healthy in mcp_status.items() %}
|
||
<tr>
|
||
<td><code>{{ server }}</code></td>
|
||
<td>
|
||
{% if healthy %}
|
||
<span class="badge bg-success">✅ healthy</span>
|
||
{% else %}
|
||
<span class="badge bg-secondary">— 未啟用 / DOWN</span>
|
||
{% endif %}
|
||
</td>
|
||
</tr>
|
||
{% else %}
|
||
<tr><td colspan="2" class="text-muted small">MCP_ROUTER_ENABLED=false 或 mcp-stack 未 deploy</td></tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Cost Throttle 狀態(Phase 20) -->
|
||
<div class="card mb-3">
|
||
<div class="card-header"><strong>💰 Cost Throttle 狀態(Phase 20)</strong></div>
|
||
<div class="card-body p-0">
|
||
{% if throttle_state %}
|
||
<table class="table mb-0">
|
||
<thead class="table-light">
|
||
<tr><th>Provider</th><th>Spent</th><th>Budget</th><th>月底推估</th><th>Ratio</th><th>狀態</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for provider, info in throttle_state.items() %}
|
||
<tr {% if info.throttled %}class="table-warning"{% endif %}>
|
||
<td><code>{{ provider }}</code></td>
|
||
<td>${{ "%.2f"|format(info.spent) }}</td>
|
||
<td>${{ "%.2f"|format(info.budget) }}</td>
|
||
<td>${{ "%.2f"|format(info.projected) }}</td>
|
||
<td>{{ "%.0f"|format(info.ratio * 100) }}%</td>
|
||
<td>
|
||
{% if info.throttled %}
|
||
<span class="badge bg-danger">⚠️ THROTTLED</span>
|
||
{% else %}
|
||
<span class="badge bg-success">✅ 正常</span>
|
||
{% endif %}
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
{% else %}
|
||
<p class="text-muted m-3 small">
|
||
COST_THROTTLE_ENABLED=false 或尚未首次 evaluate(每小時 cron 跑)
|
||
</p>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
|
||
<p class="text-muted mt-3"><small>
|
||
🤖 Operation Ollama-First v5.0 / Phase 27 — Host Health Dashboard
|
||
| <a href="/admin/ai_calls">AI Calls</a>
|
||
| <a href="/admin/promotion_review">Promotion Review</a>
|
||
| <a href="/admin/quality_trend">Quality Trend</a>
|
||
</small></p>
|
||
</div>
|
||
{% endblock %}
|