ccpoad / web /model-test.html
anyalerob's picture
Upload folder using huggingface_hub
2986042 verified
Raw
History Blame Contribute Delete
16.4 kB
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="/web/favicon.ico">
<link rel="apple-touch-icon" href="/web/apple-touch-icon.png">
<link rel="manifest" href="/web/manifest.json">
<meta name="theme-color" content="#3b82f6">
<title data-i18n="modelTest.title">模型测试 - Claude Code & Codex Proxy</title>
<link rel="stylesheet" href="/web/assets/css/styles.css?v=__VERSION__">
<link rel="stylesheet" href="/web/assets/css/channels.css?v=__VERSION__">
<script defer src="/web/assets/locales/zh-CN.js?v=__VERSION__"></script>
<script defer src="/web/assets/locales/en.js?v=__VERSION__"></script>
<script defer src="/web/assets/js/i18n.js?v=__VERSION__"></script>
<script defer src="/web/assets/js/template-engine.js?v=__VERSION__"></script>
<script defer src="/web/assets/js/ui.js?v=__VERSION__"></script>
<script defer src="/web/assets/js/model-test.js?v=__VERSION__"></script>
<script defer src="/web/assets/js/logs-channel-editor.js?v=__VERSION__"></script>
</head>
<body>
<div class="app-container">
<main class="main-content">
<div class="content-area">
<section class="glass-card mt-2 mb-2 overflow-visible">
<!-- 模式切换 -->
<div class="model-test-tabs">
<button id="modeTabChannel" type="button" class="mode-tab-btn active" data-action="set-test-mode" data-mode="channel" data-i18n="modelTest.mode.channel">按渠道测试</button>
<button id="modeTabModel" type="button" class="mode-tab-btn" data-action="set-test-mode" data-mode="model" data-i18n="modelTest.mode.model">按模型测试</button>
</div>
<!-- 控制栏 -->
<div class="model-test-toolbar">
<div class="model-test-toolbar-section model-test-toolbar-section--filters">
<label id="channelSelectorLabel" class="model-test-control">
<span class="model-test-control__label" data-i18n="modelTest.channel">渠道</span>
<div id="testChannelSelectContainer"></div>
</label>
<label id="modelTypeLabel" class="model-test-control model-test-control--type hidden">
<span class="model-test-control__label" data-i18n="common.type">类型</span>
<select id="testModelType" class="filter-select model-test-inline-select" aria-label="类型"></select>
</label>
<label id="modelSelectorLabel" class="model-test-control model-test-control--model hidden">
<span class="model-test-control__label" data-i18n="common.model">模型</span>
<div class="filter-combobox-wrapper model-test-model-combobox">
<input
id="testModelSelect"
class="filter-select filter-combobox"
type="text"
autocomplete="off"
spellcheck="false"
data-i18n-placeholder="modelTest.modelInputPlaceholder"
placeholder="输入或选择模型"
>
<div id="testModelSelectDropdown" class="filter-dropdown" role="listbox" aria-label="模型"></div>
</div>
</label>
<div id="protocolTransformContainer" class="model-test-control model-test-control--protocol">
<span class="model-test-control__label" data-i18n="modelTest.protocolTransform">协议转换</span>
<div id="protocolTransformOptions" class="channel-editor-radio-group" role="radiogroup" aria-label="协议转换"></div>
</div>
<div class="model-test-toolbar-toggles">
<label class="model-test-toggle">
<input type="checkbox" id="streamEnabled" class="control-checkbox control-checkbox--sm">
<span data-i18n="modelTest.stream">流式</span>
</label>
<label class="model-test-toggle">
<span data-i18n="modelTest.concurrency">并发</span>
<input type="number" id="concurrency" value="5" min="1" max="20" class="model-test-concurrency-input">
</label>
</div>
<label class="model-test-control model-test-control--content">
<span class="model-test-control__label" data-i18n="modelTest.content">内容</span>
<input type="text" id="modelTestContent" value="" class="model-test-inline-input" data-i18n-placeholder="common.loading" placeholder="加载中...">
</label>
</div>
<div class="model-test-toolbar-section model-test-toolbar-section--meta">
<label class="model-test-control model-test-control--name-filter">
<span class="model-test-control__label" data-i18n="common.search">搜索</span>
<input type="text" id="modelTestMobileNameFilter" value="" class="model-test-inline-input" autocomplete="off" spellcheck="false" placeholder="搜索模型名称...">
</label>
<span id="testProgress" class="model-test-progress"></span>
</div>
</div>
<!-- 模型测试表格 -->
<div class="table-container model-test-table-container mobile-card-table-container">
<table class="modern-table model-test-table mobile-card-table">
<thead class="table-head-sticky">
<tr id="model-test-head-row">
<th class="table-col-select mobile-card-select-header"><input type="checkbox" id="selectAllCheckbox" data-change-action="toggle-all-models"></th>
<th class="table-col-name" data-i18n="common.model" data-sort-key="name">模型</th>
<th class="first-byte-col table-col-duration" data-i18n="modelTest.firstByteDuration" data-sort-key="firstByteDuration">首字</th>
<th class="table-col-duration" data-i18n="modelTest.totalDuration" data-sort-key="duration">总耗时</th>
<th class="table-col-metric" data-i18n="common.input" data-sort-key="inputTokens">输入</th>
<th class="table-col-metric" data-i18n="common.output" data-sort-key="outputTokens">输出</th>
<th class="table-col-speed" data-i18n="modelTest.speed" data-sort-key="speed">速度(tok/s)</th>
<th class="table-col-metric" data-i18n="modelTest.cacheRead" data-sort-key="cacheRead">缓读</th>
<th class="table-col-metric" data-i18n="modelTest.cacheCreate" data-sort-key="cacheCreate">缓建</th>
<th class="table-col-cost" data-i18n="common.cost" data-sort-key="cost">费用</th>
<th class="table-col-response model-test-response-head" data-sort-key="response">
<div class="model-test-response-head-inner">
<div class="model-test-response-head-line">
<span class="model-test-response-head-label" data-i18n="modelTest.responseContent">响应内容</span>
</div>
<div class="model-test-toolbar-section model-test-toolbar-section--actions model-test-head-actions">
<button id="fetchModelsBtn" type="button" data-action="fetch-and-add-models" class="btn btn-secondary model-test-toolbar-btn" data-i18n="modelTest.fetchModels">获取模型</button>
<button id="addModelsBtn" type="button" data-action="open-add-models-modal" class="btn btn-secondary model-test-toolbar-btn hidden" data-i18n="modelTest.addModels">添加模型</button>
<button id="deleteModelsBtn" type="button" data-action="delete-selected-models" class="btn btn-secondary model-test-toolbar-btn model-test-toolbar-btn--danger" data-i18n="modelTest.deleteModels">删除模型</button>
<button id="runTestBtn" type="button" data-action="run-model-tests" class="btn btn-primary model-test-toolbar-btn" data-i18n="modelTest.startTest">开始测试</button>
</div>
</div>
</th>
</tr>
</thead>
<tbody id="model-test-tbody">
<tr class="model-test-empty-row"><td colspan="11" data-i18n="modelTest.selectChannelFirst">请先选择渠道</td></tr>
</tbody>
</table>
</div>
</section>
</div>
</main>
</div>
<!-- 模型行模板 -->
<template id="tpl-model-row">
<tr class="mobile-card-row model-test-row" data-model="{{model}}" data-channel-id="{{channelId}}" data-cost-multiplier="{{costMultiplier}}">
<td class="model-test-col-select mobile-card-no-label" data-mobile-label="{{mobileLabelSelect}}"><input type="checkbox" class="row-checkbox model-checkbox" checked></td>
<td class="model-test-col-name truncate-cell" title="{{model}}" data-mobile-label="{{mobileLabelName}}">
<button type="button" class="channel-link" data-channel-id="{{channelId}}" title="{{model}}">{{displayName}}</button>
</td>
<td class="model-test-col-first-byte first-byte-duration" data-mobile-label="{{mobileLabelFirstByte}}">-</td>
<td class="model-test-col-duration duration" data-mobile-label="{{mobileLabelDuration}}">-</td>
<td class="model-test-col-input input-tokens" data-mobile-label="{{mobileLabelInput}}">-</td>
<td class="model-test-col-output output-tokens" data-mobile-label="{{mobileLabelOutput}}">-</td>
<td class="model-test-col-speed speed" data-mobile-label="{{mobileLabelSpeed}}">-</td>
<td class="model-test-col-cache-read cache-read" data-mobile-label="{{mobileLabelCacheRead}}">-</td>
<td class="model-test-col-cache-create cache-create" data-mobile-label="{{mobileLabelCacheCreate}}">-</td>
<td class="model-test-col-cost cost" data-mobile-label="{{mobileLabelCost}}">-</td>
<td class="model-test-col-response response" title="" data-mobile-label="{{mobileLabelResponse}}">-</td>
</tr>
</template>
<!-- 按模型测试时的渠道行模板 -->
<template id="tpl-channel-row-by-model">
<tr class="mobile-card-row model-test-row" data-channel-id="{{channelId}}" data-model="{{model}}" data-cost-multiplier="{{costMultiplier}}">
<td class="model-test-col-select mobile-card-no-label" data-mobile-label="{{mobileLabelSelect}}"><input type="checkbox" class="row-checkbox channel-checkbox" checked></td>
<td class="model-test-col-name truncate-cell" data-mobile-label="{{mobileLabelName}}">
<button type="button" class="channel-link" data-channel-id="{{channelId}}" title="{{channelName}}">{{channelName}}</button>
</td>
<td class="model-test-col-priority channel-priority" data-mobile-label="{{mobileLabelPriority}}">{{channelPriority}}</td>
<td class="model-test-col-first-byte first-byte-duration" data-mobile-label="{{mobileLabelFirstByte}}">-</td>
<td class="model-test-col-duration duration" data-mobile-label="{{mobileLabelDuration}}">-</td>
<td class="model-test-col-input input-tokens" data-mobile-label="{{mobileLabelInput}}">-</td>
<td class="model-test-col-output output-tokens" data-mobile-label="{{mobileLabelOutput}}">-</td>
<td class="model-test-col-speed speed" data-mobile-label="{{mobileLabelSpeed}}">-</td>
<td class="model-test-col-cache-read cache-read" data-mobile-label="{{mobileLabelCacheRead}}">-</td>
<td class="model-test-col-cache-create cache-create" data-mobile-label="{{mobileLabelCacheCreate}}">-</td>
<td class="model-test-col-cost cost" data-mobile-label="{{mobileLabelCost}}">-</td>
<td class="model-test-col-response response" title="" data-mobile-label="{{mobileLabelResponse}}">-</td>
</tr>
</template>
<!-- 空状态模板 -->
<template id="tpl-empty-row">
<tr class="model-test-empty-row"><td colspan="{{colspan}}">{{message}}</td></tr>
</template>
<!-- 上游请求/响应详情弹窗 -->
<div id="upstreamDetailModal" class="modal">
<div class="modal-content upstream-detail-modal-content">
<div class="modal-header">
<h2 class="modal-title" data-i18n="channels.test.upstreamDetail">上游请求/响应详情</h2>
<button type="button" class="close-btn" onclick="closeUpstreamDetailModal()">&times;</button>
</div>
<div class="upstream-detail-tabs">
<button type="button" class="upstream-tab active" data-tab="request" data-i18n="channels.test.tabRequest">Request</button>
<button type="button" class="upstream-tab" data-tab="response" data-i18n="channels.test.tabResponse">Response</button>
<button type="button" class="upstream-copy-btn upstream-copy-btn--tabs" data-copy-target="upstreamReqRaw" data-i18n="common.copy">复制</button>
</div>
<div id="upstreamTabRequest" class="upstream-tab-panel active">
<div class="upstream-field upstream-field--full">
<pre id="upstreamReqRaw" class="upstream-pre upstream-pre--full"></pre>
</div>
</div>
<div id="upstreamTabResponse" class="upstream-tab-panel">
<div class="upstream-field upstream-field--full">
<pre id="upstreamRespRaw" class="upstream-pre upstream-pre--full"></pre>
</div>
</div>
</div>
</div>
<!-- 批量添加模型弹窗 -->
<div id="addModelsModal" class="modal">
<div class="modal-content modal-content--lg">
<div class="modal-header modal-header--compact">
<h2 class="modal-title" data-i18n="modelTest.addModelsTitle">批量添加模型</h2>
<button id="addModelsCloseBtn" class="close-btn" aria-label="Close">&times;</button>
</div>
<label class="model-test-add-field">
<span class="model-test-add-label" data-i18n="modelTest.addModelsInputLabel">输入模型名称(支持逗号或换行分隔)</span>
<textarea
id="addModelsTextarea"
class="model-test-batch-textarea"
spellcheck="false"
data-i18n-placeholder="modelTest.addModelsPlaceholder"
placeholder="gpt-4o,gpt-4o-mini&#10;claude-3-5-sonnet-20241022&#10;claude-3-5-haiku-latest"
></textarea>
</label>
<div class="model-test-add-help">
<div class="model-test-add-help-title">
<span class="model-test-add-help-icon" aria-hidden="true">!</span>
<strong data-i18n="modelTest.addModelsHelpTitle">使用说明:</strong>
</div>
<ul>
<li><span data-i18n="modelTest.addModelsHelpComma">支持逗号分隔:</span> <code>model1,model2,model3</code></li>
<li data-i18n="modelTest.addModelsHelpLine">支持换行分隔:每行一个模型</li>
<li data-i18n="modelTest.addModelsHelpDedupe">自动去除空格、空行和重复模型</li>
</ul>
</div>
<div class="confirm-actions confirm-actions--end">
<button id="addModelsCancelBtn" class="btn btn-secondary" data-i18n="common.cancel">取消</button>
<button id="addModelsConfirmBtn" class="btn btn-primary" data-i18n="modelTest.addModelsConfirm">确认添加</button>
</div>
</div>
</div>
<!-- 删除预览确认弹窗 -->
<div id="deletePreviewModal" class="modal">
<div class="modal-content modal-content--lg">
<div class="modal-header modal-header--compact">
<h2 class="modal-title" data-i18n="modelTest.deletePreviewTitle">确认删除模型</h2>
<button id="deletePreviewCloseBtn" class="close-btn" aria-label="Close">&times;</button>
</div>
<p class="modal-description" data-i18n="modelTest.deletePreviewDesc">将按以下分组删除,请确认:</p>
<pre id="deletePreviewContent" class="delete-preview-text">-</pre>
<p id="deletePreviewProgress" class="model-test-delete-preview-progress hidden">-</p>
<pre id="deletePreviewRuntimeLog" class="delete-preview-text model-test-delete-preview-log hidden">-</pre>
<div class="confirm-actions confirm-actions--end">
<button id="deletePreviewCancelBtn" class="btn btn-secondary" data-i18n="common.cancel">取消</button>
<button id="deletePreviewConfirmBtn" class="btn btn-danger" data-i18n="modelTest.deletePreviewConfirm">确认删除</button>
</div>
</div>
</div>
</body>
</html>