Files
ewoooc/templates/admin/agent_orchestration.html
ogt f02723b7f4
Some checks failed
CD Pipeline / deploy (push) Has been cancelled
style(obs): compact agent orchestration workbench copy
2026-07-02 19:39:17 +08:00

31 lines
11 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "ewoooc_base.html" %}
{% block title %}AI 分工指揮台{% endblock %}
{% block ewooo_content %}
<style>
.agent-hero,.agent-panel,.agent-table-shell{border:1px solid var(--obs-line);border-radius:26px;background:var(--obs-card);box-shadow:0 16px 38px rgba(70,46,28,.08)}
.agent-hero{padding:clamp(1.2rem,2.4vw,2rem);background:radial-gradient(circle at 12% 14%,rgba(201,100,66,.18),transparent 24rem),radial-gradient(circle at 88% 8%,rgba(79,111,143,.14),transparent 22rem),linear-gradient(135deg,rgba(255,248,239,.98),rgba(255,255,255,.74))}.agent-kicker{color:var(--obs-accent);font-size:.76rem;letter-spacing:.13em;text-transform:uppercase;font-weight:850}.agent-title{margin:.45rem 0 .25rem;font-family: var(--momo-font-display, "Inter", "Noto Sans TC", system-ui, sans-serif);font-size:var(--obs-title-size);letter-spacing: 0;line-height:.98}.agent-subtitle{color:var(--obs-muted);max-width:870px;line-height:1.7}.agent-mode-row{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:.75rem}.agent-mode{display:inline-flex;align-items:center;min-height:28px;padding:.32rem .65rem;border:1px solid var(--obs-line);border-radius:10px;background:rgba(255,255,255,.62);color:var(--obs-muted);font-size:.74rem;font-weight:850;white-space:nowrap}.agent-subtitle,.agent-signal-note,.agent-row-desc,.agent-card-desc,.agent-footer-copy{display:none}.agent-filter{display:flex;gap:.55rem;flex-wrap:wrap;margin-top:1rem;padding:.8rem;border:1px solid var(--obs-line);border-radius:20px;background:rgba(255,255,255,.58)}.agent-command{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:.75rem;margin-top:1rem}.agent-signal{padding:.95rem;border:1px solid var(--obs-line);border-radius:20px;background:rgba(255,255,255,.62)}.agent-label{color:var(--obs-muted);font-size:.72rem;letter-spacing:.1em;text-transform:uppercase}.agent-value{display:block;margin-top:.28rem;font-size:var(--obs-value-size);font-weight:880;letter-spacing: 0}.agent-grid{display:grid;grid-template-columns:minmax(0,1.2fr) minmax(330px,.8fr);gap:1rem;margin-top:1rem}.agent-stack{display:grid;gap:1rem}.agent-panel-head,.agent-table-title{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem;padding:1.05rem 1.1rem .25rem}.agent-panel-title,.agent-table-title h3{margin:.15rem 0 0;font-size:1.1rem;font-weight:850;letter-spacing: 0}.agent-panel-body{padding:1rem 1.1rem 1.1rem}.agent-table-shell{overflow:hidden;margin-top:1rem}.agent-card{padding:.9rem;border:1px solid var(--obs-line);border-radius:20px;background:rgba(255,255,255,.58);margin-bottom:.75rem}.agent-card-top{display:flex;justify-content:space-between;gap:.8rem;align-items:start}.agent-meter{height:7px;border-radius:999px;background:rgba(86,64,48,.1);overflow:hidden;margin-top:.65rem}.agent-meter span{display:block;height:100%;background:var(--obs-accent)}.rec-card{padding:.85rem;border:1px solid var(--obs-line);border-radius:18px;background:rgba(255,255,255,.58);margin-bottom:.7rem}.status-good{color:var(--obs-green)}.status-warn{color:var(--obs-amber)}.status-bad{color:var(--obs-red)}.status-blue{color:var(--obs-blue)}@media(max-width:1100px){.agent-command{grid-template-columns:repeat(2,minmax(0,1fr))}.agent-grid{grid-template-columns:1fr}}@media(max-width:720px){.agent-command{grid-template-columns:1fr}}
</style>
{% import "admin/_observability_labels.html" as obs_label %}
<div class="container-fluid mt-3">
<section class="agent-hero" data-density-guardrail="compact-agent-workbench"><div class="agent-kicker"><i class="fas fa-network-wired me-1"></i> AI 分工指揮台 · {{ hours }} 小時視窗</div><h1 class="agent-title">AI 分工指揮台</h1><div class="agent-mode-row" aria-label="AI 分工狀態模式"><span class="agent-mode">AI 分工</span><span class="agent-mode">成本守門</span><span class="agent-mode">知識命中</span></div><p class="agent-subtitle">確認 AI 分工、建議路徑、知識命中與工具編排是否支撐業績決策。</p><form method="get" class="agent-filter"><select name="hours" class="form-select form-select-sm" onchange="this.form.submit()">{% for h in [1,6,24,72,168] %}<option value="{{ h }}" {% if hours == h %}selected{% endif %}>{% if h < 24 %}過去 {{ h }} 小時{% else %}過去 {{ h//24 }} {% endif %}</option>{% endfor %}</select></form>{% if overall %}<div class="agent-command"><div class="agent-signal"><div class="agent-label">呼叫總量</div><span class="agent-value">{{ "{:,}".format(overall.total_calls) }}</span><small class="text-muted agent-signal-note">{{ "{:,}".format(overall.total_tokens) }} 用量</small></div><div class="agent-signal"><div class="agent-label">主力路徑占比</div><span class="agent-value status-good">{{ "%.0f"|format(overall.local_pct) }}%</span><small class="text-muted agent-signal-note">{{ "{:,}".format(overall.local_calls) }} 次主力呼叫</small></div><div class="agent-signal"><div class="agent-label">付費成本</div><span class="agent-value {% if overall.total_cost > 0 %}status-warn{% else %}status-good{% endif %}">${{ "%.2f"|format(overall.total_cost) }}</span><small class="text-muted agent-signal-note">{{ "{:,}".format(overall.paid_calls) }} 次付費呼叫</small></div><div class="agent-signal"><div class="agent-label">知識命中率</div><span class="agent-value status-blue">{{ "%.0f"|format(overall.rag_rate) }}%</span><small class="text-muted agent-signal-note">{{ "{:,}".format(overall.rag_hits) }} 次命中</small></div></div>{% endif %}</section>
{% if error %}<div class="alert alert-warning mt-3"><strong><i class="fas fa-triangle-exclamation me-1"></i></strong>{{ error }}</div>{% endif %}
<section class="agent-grid">
<div class="agent-stack">
<article class="agent-table-shell"><div class="agent-table-title"><div><div class="agent-label">AI 分工矩陣</div><h3>建議路徑、工具與知識命中矩陣</h3></div></div><div class="table-responsive"><table class="table mb-0"><thead class="table-light"><tr><th>分工</th><th class="text-end">呼叫</th><th class="text-end">成本</th><th class="text-end">主力路徑</th><th class="text-end">付費</th><th class="text-end">工具</th><th class="text-end">知識</th><th class="text-end">錯誤</th><th class="text-end">耗時</th></tr></thead><tbody>{% for ag in agent_matrix %}<tr><td><strong>{{ ag.label }}</strong><small class="d-block text-muted agent-row-desc">{{ ag.desc }}</small></td><td class="text-end">{% if ag.calls > 0 %}<strong>{{ "{:,}".format(ag.calls) }}</strong><small class="d-block text-muted agent-signal-note">{{ "{:,}".format(ag.tokens) }} 用量</small>{% else %}<small class="text-muted"></small>{% endif %}</td><td class="text-end">{% if ag.calls > 0 %}${{ "%.2f"|format(ag.cost) }}{% else %}<small class="text-muted"></small>{% endif %}</td><td class="text-end">{% if ag.calls > 0 %}<strong class="status-good">{{ "%.0f"|format(ag.ollama_pct) }}%</strong><small class="d-block text-muted agent-signal-note">主力 {{ ag.ollama_gcp_a }} · 備援 {{ ag.ollama_gcp_b }} · 第三 {{ ag.ollama_111 }}</small>{% else %}<small class="text-muted"></small>{% endif %}</td><td class="text-end">{% if ag.calls > 0 %}<strong class="{% if ag.paid_pct > 50 %}status-bad{% elif ag.paid_pct > 20 %}status-warn{% endif %}">{{ "%.0f"|format(ag.paid_pct) }}%</strong><small class="d-block text-muted agent-signal-note">雲端備援 {{ ag.gemini }}{% if ag.other_paid %} · 其他 {{ ag.other_paid }}{% endif %}</small>{% else %}<small class="text-muted"></small>{% endif %}</td><td class="text-end">{% if ag.calls > 0 %}<strong class="{% if ag.mcp_rate >= 30 %}status-blue{% elif ag.mcp_rate >= 10 %}status-warn{% else %}text-muted{% endif %}">{{ "%.1f"|format(ag.mcp_rate) }}%</strong><small class="d-block text-muted agent-signal-note">{{ ag.mcp_calls }}</small>{% else %}<small class="text-muted"></small>{% endif %}</td><td class="text-end">{% if ag.calls > 0 %}<strong class="status-blue">{{ "%.1f"|format(ag.rag_rate) }}%</strong><small class="d-block text-muted agent-signal-note">{{ ag.rag_hits }}</small>{% else %}<small class="text-muted"></small>{% endif %}</td><td class="text-end">{% if ag.calls > 0 %}<strong class="{% if ag.error_rate >= 15 %}status-bad{% elif ag.error_rate >= 5 %}status-warn{% else %}status-good{% endif %}">{{ "%.1f"|format(ag.error_rate) }}%</strong><small class="d-block text-muted agent-signal-note">{{ ag.errors }}</small>{% else %}<small class="text-muted"></small>{% endif %}</td><td class="text-end">{% if ag.calls > 0 %}{{ ag.avg_ms }} ms{% else %}<small class="text-muted"></small>{% endif %}</td></tr>{% endfor %}</tbody></table></div></article>
</div>
<aside class="agent-stack">
<article class="agent-panel"><div class="agent-panel-head"><div><div class="agent-label">分工卡片</div><h2 class="agent-panel-title">分工健康速覽</h2></div></div><div class="agent-panel-body">{% for ag in agent_matrix %}<div class="agent-card"><div class="agent-card-top"><div><strong>{{ ag.label }}</strong><small class="d-block text-muted agent-card-desc">{{ ag.desc }}</small></div><span class="badge {% if ag.error_rate >= 15 %}bg-danger{% elif ag.calls == 0 %}bg-secondary{% else %}bg-success{% endif %}">{{ ag.calls }} 次呼叫</span></div><div class="agent-meter"><span style="width:{{ ag.ollama_pct|round|int if ag.calls > 0 else 0 }}%"></span></div><small class="text-muted">主力路徑 {{ "%.0f"|format(ag.ollama_pct) if ag.calls > 0 else 0 }}% · 知識 {{ "%.0f"|format(ag.rag_rate) if ag.calls > 0 else 0 }}% · 工具 {{ "%.0f"|format(ag.mcp_rate) if ag.calls > 0 else 0 }}%</small></div>{% endfor %}</div></article>
</aside>
</section>
{% if recommendations %}<section class="agent-panel mt-3"><div class="agent-panel-head"><div><div class="agent-label">策略規則</div><h2 class="agent-panel-title">編排策略自動建議</h2></div></div><div class="agent-panel-body">{% for r in recommendations %}<div class="rec-card"><span class="badge {% if r.severity == 'high' %}bg-danger{% elif r.severity == 'med' %}bg-warning{% else %}bg-info{% endif %} me-1">{{ r.severity|upper }}</span><strong>{{ r.agent }}</strong><div class="small mt-1"><i class="fas fa-search me-1"></i><strong>發現:</strong>{{ r.finding }}</div><div class="small text-muted"><i class="fas fa-arrow-right me-1"></i><strong>建議:</strong>{{ r.suggestion }}</div></div>{% endfor %}</div></section>{% endif %}
{% if mcp_matrix %}<section class="agent-table-shell"><div class="agent-table-title"><div><div class="agent-label">工具協作明細</div><h3>工具協作 × 使用情境</h3></div></div><div class="table-responsive"><table class="table table-sm mb-0"><thead class="table-light"><tr><th>工具服務</th><th>使用情境</th><th class="text-end">工具協作</th><th class="text-end">快取</th><th class="text-end">快取率</th><th class="text-end">成本</th></tr></thead><tbody>{% for m in mcp_matrix %}<tr><td><span>服務元件</span></td><td><span>{{ obs_label.caller(m.caller) }}</span></td><td class="text-end">{{ "{:,}".format(m.calls) }}</td><td class="text-end">{{ m.cache_hits }}</td><td class="text-end"><span class="{% if m.cache_rate >= 50 %}status-good{% elif m.cache_rate >= 20 %}status-warn{% endif %}">{{ "%.0f"|format(m.cache_rate) }}%</span></td><td class="text-end">${{ "%.4f"|format(m.cost) }}</td></tr>{% endfor %}</tbody></table></div></section>{% endif %}
<p class="text-muted mt-3 agent-footer-copy"><small><i class="fas fa-robot me-1"></i>AI 分工指揮台</small></p>
</div>
{% endblock %}