Files

218 lines
10 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.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>LLM 速度测试台</title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<header class="topbar">
<div class="brand">
<span class="logo"></span>
<h1>LLM 速度测试台</h1>
<span class="sub">大模型推理性能基准 · 预填充 / 首字 / 解码</span>
</div>
<div class="status-badge" id="run-status"><span class="dot"></span>空闲</div>
</header>
<main class="layout">
<!-- 左侧:配置 -->
<aside class="config-panel">
<section class="card">
<h2>🔌 大模型接口配置</h2>
<div class="field">
<label>提供商类型</label>
<select id="cfg-provider">
<option value="openai">OpenAI 兼容(OpenAI / DeepSeek / 火山方舟…)</option>
<option value="anthropic">AnthropicClaude</option>
<option value="google">Google Gemini</option>
</select>
</div>
<div class="field">
<label>已保存配置</label>
<div class="row">
<select id="cfg-list"><option value="">— 选择配置加载 —</option></select>
<button class="btn small" id="btn-load-config" title="加载选中配置">载入</button>
<button class="btn small primary" id="btn-save-config" title="保存当前输入">保存</button>
<button class="btn small danger" id="btn-del-config" title="删除选中配置">删除</button>
</div>
</div>
<div class="field">
<label>配置名称</label>
<div class="icon-input"><span class="icon">📛</span><input id="cfg-name" placeholder="例如:DeepSeek-V4"></div>
</div>
<div class="field">
<label>Base URL</label>
<div class="icon-input"><span class="icon">🌐</span><input id="cfg-baseurl" placeholder="留空使用官方默认地址"></div>
<div class="hint" id="cfg-default-url"></div>
</div>
<div class="field">
<label>API Key</label>
<div class="row">
<input id="cfg-apikey" type="password" placeholder="sk-... / key...">
<button class="btn small" id="btn-toggle-key" title="显示/隐藏">👁</button>
</div>
</div>
<div class="field">
<label>模型名称</label>
<div class="icon-input"><span class="icon">🤖</span><input id="cfg-model" placeholder="如 gpt-4o / deepseek-chat / claude-sonnet-4"></div>
</div>
<div class="field">
<label>温度 Temperature <b id="tmp-val">0.7</b></label>
<input id="cfg-temp" type="range" min="0" max="2" step="0.1" value="0.7">
</div>
<button class="btn block" id="btn-test-conn">🔍 测试连接</button>
<div class="conn-result" id="conn-result" hidden></div>
</section>
<section class="card">
<h2>🚀 速度测试配置</h2>
<div class="field">
<label>测试名称(主题)</label>
<input id="gen-name" type="text" placeholder="如:DeepSeek-V4 不同上下文长度速度对比">
</div>
<div class="field">
<label>上下文长度(tokens,点击切换启停)</label>
<div class="chips" id="gen-contexts"></div>
<div class="row" style="margin-top:6px">
<input id="gen-context-add" type="number" min="16" step="16" placeholder="自定义长度(≥16">
<button class="btn small" id="btn-context-add"> 添加</button>
</div>
</div>
<div class="field">
<label>解码输出长度(max tokens</label>
<input id="gen-max-tokens" type="number" min="1" step="1" value="128">
</div>
<div class="field">
<label>每个长度×并发采样次数</label>
<input id="gen-samples" type="number" min="1" max="50" value="2">
</div>
<div class="field">
<label>并发数(同时请求流数,默认单流)</label>
<div class="chips" id="gen-concurrency"></div>
<div class="row" style="margin-top:6px">
<input id="gen-conc-add" type="number" min="1" max="64" placeholder="自定义并发数(≥1">
<button class="btn small" id="btn-conc-add"> 添加</button>
</div>
<div class="hint">选中多个并发数时,同一测试会分别跑各并发档并放在一起对比</div>
</div>
<div class="field switch-field">
<label>测试前预热<span class="hint-inline">空转不计速度,避免冷启动偏差</span></label>
<label class="switch">
<input type="checkbox" id="gen-warmup" checked>
<span class="slider"></span>
</label>
</div>
<div class="field switch-field">
<label>避免缓存<span class="hint-inline">随机前缀,测真实预填充</span></label>
<label class="switch">
<input type="checkbox" id="gen-avoid-cache" checked>
<span class="slider"></span>
</label>
</div>
<div class="btn-group">
<button class="btn primary block" id="btn-start">▶ 开始测试</button>
<button class="btn danger block" id="btn-cancel" disabled>■ 停止</button>
</div>
</section>
<section class="card">
<h2>📤 评测站同步</h2>
<div class="field">
<label>评测站地址</label>
<div class="icon-input"><span class="icon">🌐</span><input id="eval-url" placeholder="http://127.0.0.1:16066"></div>
</div>
<div class="field">
<label>评测站账号(结果挂到该账号下)</label>
<div class="icon-input"><span class="icon">👥</span><input id="eval-account" placeholder="如:性能评测组"></div>
</div>
<div class="field">
<label>硬件 / GPU(自动探测可修改,随结果一并发送)</label>
<div class="row">
<div class="icon-input"><span class="icon">🖥</span><input id="eval-hardware" placeholder="如:NVIDIA A100 80G"></div>
<button class="btn small" id="btn-detect-gpu" title="自动探测本机GPU">🔍 探测</button>
</div>
</div>
<button class="btn block" id="btn-eval-test">🔗 测试连接</button>
<div class="conn-result" id="eval-result" hidden></div>
<div class="hint" style="margin-top:6px">测试完成后,在历史列表或详情里点「📤 发送到评测站」,一键把结果发布到模型评测网站(端口 16066)对应账号下。</div>
</section>
</aside>
<!-- 右侧:指标 + 日志 + 历史 -->
<section class="main">
<div class="metrics">
<div class="metric-card"><div class="m-label">首字延迟</div><div class="m-value" id="m-ttft"></div><div class="m-unit" id="m-ttft-u">ms</div></div>
<div class="metric-card"><div class="m-label">预填充速度</div><div class="m-value" id="m-prefill"></div><div class="m-unit">tok/s</div></div>
<div class="metric-card"><div class="m-label">解码速度</div><div class="m-value" id="m-decode"></div><div class="m-unit">tok/s</div></div>
<div class="metric-card"><div class="m-label">上文 Tokens</div><div class="m-value" id="m-prompts"></div><div class="m-unit">tok</div></div>
<div class="metric-card"><div class="m-label">输出 Tokens</div><div class="m-value" id="m-outputs"></div><div class="m-unit">tok</div></div>
<div class="metric-card"><div class="m-label">总耗时</div><div class="m-value" id="m-total"></div><div class="m-unit">ms</div></div>
</div>
<div class="card log-card">
<div class="card-head">
<h2>📋 测试日志</h2>
<div class="log-actions">
<span class="hint" id="log-count"></span>
<button class="btn small" id="btn-clear-console">清屏</button>
<button class="btn small" id="btn-export-log" title="导出当前测试完整日志">导出日志</button>
</div>
</div>
<div class="console" id="console"></div>
</div>
<div class="card">
<div class="card-head">
<h2>🗂 测试历史</h2>
<div class="log-actions">
<span class="hint" id="hist-selected"></span>
<button class="btn small primary" id="btn-compare">⚖️ 对比所选</button>
<button class="btn small" id="btn-refresh-history">刷新</button>
</div>
</div>
<div class="table-wrap">
<table class="history" id="history">
<thead><tr>
<th class="chk-col"><input type="checkbox" id="hist-check-all" title="全选"></th>
<th>#</th><th>时间</th><th>名称</th><th>提供商</th><th>模型</th><th>并发</th><th>采样</th>
<th>首字 ms</th><th>预填充 tok/s</th><th>解码 tok/s</th><th>状态</th><th>操作</th>
</tr></thead>
<tbody></tbody>
</table>
</div>
</div>
</section>
</main>
<!-- 详情弹窗 -->
<div class="modal-mask" id="detail-mask" hidden>
<div class="modal">
<div class="modal-head">
<h2>测试详情 #<span id="dt-id"></span></h2>
<div>
<button class="btn small primary" id="dt-send-eval">📤 发送到评测站</button>
<button class="btn small primary" id="dt-export-xlsx">⬇ 导出 Excel</button>
<button class="btn small primary" id="dt-export">导出 JSON</button>
<button class="btn small" id="dt-close"></button>
</div>
</div>
<div class="modal-body" id="dt-body"></div>
</div>
</div>
<!-- 多测试对比弹窗 -->
<div class="modal-mask" id="cmp-mask" hidden>
<div class="modal">
<div class="modal-head">
<h2>⚖️ 多测试结果对比</h2>
<button class="btn small" id="cmp-close"></button>
</div>
<div class="modal-body" id="cmp-body"></div>
</div>
</div>
<script src="/js/app.js"></script>
</body>
</html>