支持gimini格式,优化debug日志
This commit is contained in:
parent
e726f11bad
commit
4de6db13f9
16 changed files with 1783 additions and 55 deletions
|
|
@ -59,6 +59,7 @@ main{padding:28px 0 60px}
|
|||
.tag-anthropic{background:rgba(249,115,22,.15);color:#fb923c}
|
||||
.tag-openai{background:rgba(16,185,129,.15);color:#34d399}
|
||||
.tag-responses{background:rgba(59,130,246,.15);color:#60a5fa}
|
||||
.tag-gemini{background:rgba(66,133,244,.15);color:#4285f4}
|
||||
.tag-auto{background:rgba(139,92,246,.15);color:#a78bfa}
|
||||
.tag-override{background:rgba(59,130,246,.1);color:var(--primary)}
|
||||
.tag-instructions{background:rgba(234,179,8,.15);color:var(--yellow)}
|
||||
|
|
@ -66,6 +67,11 @@ main{padding:28px 0 60px}
|
|||
.mapping-actions{margin-left:auto;display:flex;gap:6px}
|
||||
.empty{text-align:center;padding:40px;color:var(--muted)}
|
||||
|
||||
.stats-table{width:100%;border-collapse:collapse;font-size:13px}
|
||||
.stats-table th{text-align:left;color:var(--muted);font-weight:500;padding:8px 12px;border-bottom:1px solid var(--border)}
|
||||
.stats-table td{padding:8px 12px;border-bottom:1px solid var(--border)}
|
||||
.stats-table tr:hover{background:var(--surface)}
|
||||
|
||||
.modal-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:100;align-items:center;justify-content:center}
|
||||
.modal-overlay.active{display:flex}
|
||||
.modal{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:28px;width:520px;max-width:90vw;max-height:85vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.5)}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,15 @@
|
|||
</div>
|
||||
<div id="mappingList"></div>
|
||||
</div>
|
||||
|
||||
<!-- 用量统计 -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2>用量统计</h2>
|
||||
<button class="btn btn-ghost btn-sm" onclick="loadStats()">刷新</button>
|
||||
</div>
|
||||
<div id="statsContent"><div class="empty">加载中…</div></div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
|
|
@ -95,13 +104,15 @@
|
|||
<option value="anthropic">Anthropic (/v1/messages)</option>
|
||||
<option value="openai">OpenAI (/v1/chat/completions)</option>
|
||||
<option value="responses">OpenAI Responses (/v1/responses)</option>
|
||||
<option value="gemini">Gemini (generateContent)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="hint">
|
||||
<b>anthropic</b>:转换为 Anthropic Messages 格式 — 适用于中转站通过 <code>/v1/messages</code> 提供 Claude 模型<br>
|
||||
<b>openai</b>:保持 OpenAI Chat Completions 格式 — 适用于 GPT、DeepSeek、Codex 或通过 <code>/v1/chat/completions</code> 提供所有模型的中转站<br>
|
||||
<b>responses</b>:保持 OpenAI Responses 格式 — 适用于中转站仅通过 <code>/v1/responses</code> 提供模型能力<br>
|
||||
<b>自动检测</b>:根据上游模型名判断(含 claude → anthropic,其他 → openai)
|
||||
<b>gemini</b>:转换为 Gemini Contents 格式 — 适用于 Google Gemini API 或兼容的中转站<br>
|
||||
<b>自动检测</b>:根据上游模型名判断(含 claude → anthropic,含 gemini → gemini,其他 → openai)
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
|
|
|
|||
|
|
@ -70,11 +70,39 @@ async function loadDashboard() {
|
|||
document.getElementById('envKey').textContent = s.env_api_key ? '环境变量: (已配置)' : '环境变量: (未设置)';
|
||||
await loadMappings();
|
||||
checkHealth();
|
||||
loadStats();
|
||||
} catch (e) {
|
||||
toast('加载设置失败: ' + e.message, false);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadStats() {
|
||||
const el = document.getElementById('statsContent');
|
||||
try {
|
||||
const data = await api('/api/admin/stats');
|
||||
const models = data.models || {};
|
||||
const keys = Object.keys(models);
|
||||
if (!keys.length) {
|
||||
el.innerHTML = '<div class="empty">暂无请求统计数据</div>';
|
||||
return;
|
||||
}
|
||||
const uptime = data.uptime_seconds || 0;
|
||||
const h = Math.floor(uptime / 3600);
|
||||
const m = Math.floor((uptime % 3600) / 60);
|
||||
let html = '<div class="hint" style="margin-bottom:12px">运行时长: ' + h + '小时' + m + '分钟</div>';
|
||||
html += '<table class="stats-table"><thead><tr><th>模型</th><th>请求数</th><th>输入 Tokens</th><th>输出 Tokens</th><th>总 Tokens</th></tr></thead><tbody>';
|
||||
keys.sort((a, b) => models[b].request_count - models[a].request_count);
|
||||
for (const name of keys) {
|
||||
const s = models[name];
|
||||
html += '<tr><td>' + esc(name) + '</td><td>' + s.request_count + '</td><td>' + s.input_tokens.toLocaleString() + '</td><td>' + s.output_tokens.toLocaleString() + '</td><td>' + s.total_tokens.toLocaleString() + '</td></tr>';
|
||||
}
|
||||
html += '</tbody></table>';
|
||||
el.innerHTML = html;
|
||||
} catch (e) {
|
||||
el.innerHTML = '<div class="empty">加载统计失败</div>';
|
||||
}
|
||||
}
|
||||
|
||||
async function checkHealth() {
|
||||
try {
|
||||
const r = await fetch(API + '/health');
|
||||
|
|
@ -130,7 +158,9 @@ async function loadMappings() {
|
|||
? 'tag-responses'
|
||||
: backend === 'openai'
|
||||
? 'tag-openai'
|
||||
: 'tag-auto';
|
||||
: backend === 'gemini'
|
||||
? 'tag-gemini'
|
||||
: 'tag-auto';
|
||||
const tagLabel = backend === 'auto'
|
||||
? '自动'
|
||||
: backend === 'responses'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue