v1.8.0: 模块化重构 + 后台登录认证

This commit is contained in:
2026-06-01 18:31:43 +08:00
parent df5404c0fa
commit 05e38f87dd

206
templates/tools.html Normal file
View File

@@ -0,0 +1,206 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ParamHub - 参数百科</title>
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/remixicon@3.5.0/fonts/remixicon.css" rel="stylesheet">
</head>
<body class="bg-gray-50 min-h-screen">
<!-- 导航栏 -->
<nav class="bg-white shadow-sm sticky top-0 z-50">
<div class="max-w-7xl mx-auto px-4 py-3 flex justify-between items-center">
<a href="/" class="flex items-center gap-2">
<i class="ri-dashboard-3-line text-2xl text-indigo-600"></i>
<span class="text-xl font-bold text-gray-800">ParamHub</span>
</a>
<div class="flex gap-4 text-sm" id="topNav">
<!-- 动态加载 -->
</div>
</div>
</nav>
<main class="max-w-7xl mx-auto px-4 py-8">
<div class="mb-6">
<h1 class="text-2xl font-bold text-gray-800 flex items-center gap-2">
<i class="ri-calculator-line text-orange-600"></i>
实用工具
</h1>
<p class="text-gray-500 mt-1">AI开发常用计算工具</p>
</div>
<!-- 显存计算器 -->
<div class="bg-white rounded-xl shadow-sm p-6 mb-6">
<h2 class="text-lg font-semibold text-gray-800 mb-4 flex items-center gap-2">
<i class="ri-cpu-line text-green-600"></i>
显存计算器
</h2>
<p class="text-gray-500 mb-4">计算大模型所需的显存大小并推荐合适的GPU</p>
<div class="grid grid-cols-3 gap-4 mb-6">
<div>
<label class="text-sm text-gray-600 mb-1 block">模型参数量 (B)</label>
<input type="number" id="params" value="7" step="0.1" min="0.1" max="1000"
class="w-full px-4 py-2 border border-gray-200 rounded-lg focus:outline-none focus:border-green-400">
</div>
<div>
<label class="text-sm text-gray-600 mb-1 block">精度</label>
<select id="precision" class="w-full px-4 py-2 border border-gray-200 rounded-lg focus:outline-none focus:border-green-400">
<option value="fp32">FP32 (全精度)</option>
<option value="fp16" selected>FP16 (半精度)</option>
<option value="int8">INT8 (8位量化)</option>
<option value="int4">INT4 (4位量化)</option>
</select>
</div>
<div>
<button onclick="calculateVram()" class="w-full px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition mt-5">
<i class="ri-calculator-line mr-2"></i>计算
</button>
</div>
</div>
<!-- 计算结果 -->
<div id="vramResult" class="hidden">
<div class="grid grid-cols-2 gap-4 mb-4">
<div class="p-4 bg-blue-50 rounded-lg">
<div class="text-sm text-blue-600">模型权重占用</div>
<div class="text-2xl font-bold text-blue-800 mt-1" id="modelVram">-</div>
</div>
<div class="p-4 bg-orange-50 rounded-lg">
<div class="text-sm text-orange-600">总显存需求 (含KV Cache)</div>
<div class="text-2xl font-bold text-orange-800 mt-1" id="totalVram">-</div>
</div>
</div>
<div id="suitableGpus" class="mt-4">
<h3 class="text-sm font-medium text-gray-600 mb-2">推荐的GPU:</h3>
<div id="gpuList" class="grid grid-cols-3 gap-2"></div>
</div>
</div>
</div>
<!-- 精度说明 -->
<div class="bg-white rounded-xl shadow-sm p-6 mb-6">
<h2 class="text-lg font-semibold text-gray-800 mb-4 flex items-center gap-2">
<i class="ri-information-line text-blue-600"></i>
精度与显存关系
</h2>
<div class="grid grid-cols-4 gap-4">
<div class="p-4 bg-gray-50 rounded-lg text-center">
<div class="text-lg font-bold text-gray-800">FP32</div>
<div class="text-2xl font-bold text-blue-600 mt-2">4字节</div>
<div class="text-sm text-gray-500 mt-1">全精度,最高精度</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg text-center">
<div class="text-lg font-bold text-gray-800">FP16</div>
<div class="text-2xl font-bold text-green-600 mt-2">2字节</div>
<div class="text-sm text-gray-500 mt-1">半精度,常用</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg text-center">
<div class="text-lg font-bold text-gray-800">INT8</div>
<div class="text-2xl font-bold text-orange-600 mt-2">1字节</div>
<div class="text-sm text-gray-500 mt-1">8位量化</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg text-center">
<div class="text-lg font-bold text-gray-800">INT4</div>
<div class="text-2xl font-bold text-purple-600 mt-2">0.5字节</div>
<div class="text-sm text-gray-500 mt-1">4位量化最小</div>
</div>
</div>
</div>
<!-- 快速参考表 -->
<div class="bg-white rounded-xl shadow-sm p-6">
<h2 class="text-lg font-semibold text-gray-800 mb-4 flex items-center gap-2">
<i class="ri-table-line text-indigo-600"></i>
常见模型显存需求参考 (FP16)
</h2>
<table class="w-full">
<thead class="bg-gray-50">
<tr>
<th class="px-4 py-2 text-left text-sm font-medium text-gray-600">模型</th>
<th class="px-4 py-2 text-left text-sm font-medium text-gray-600">参数量</th>
<th class="px-4 py-2 text-left text-sm font-medium text-gray-600">模型权重</th>
<th class="px-4 py-2 text-left text-sm font-medium text-gray-600">推荐显存</th>
<th class="px-4 py-2 text-left text-sm font-medium text-gray-600">推荐GPU</th>
</tr>
</thead>
<tbody class="divide-y">
<tr><td class="px-4 py-2 text-gray-800">Mistral 7B</td><td class="px-4 py-2">7B</td><td class="px-4 py-2">14GB</td><td class="px-4 py-2">18GB</td><td class="px-4 py-2 text-gray-600">RTX 3090/4090</td></tr>
<tr><td class="px-4 py-2 text-gray-800">Llama 2 13B</td><td class="px-4 py-2">13B</td><td class="px-4 py-2">26GB</td><td class="px-4 py-2">34GB</td><td class="px-4 py-2 text-gray-600">RTX 4090 + 8GB</td></tr>
<tr><td class="px-4 py-2 text-gray-800">Llama 2 70B</td><td class="px-4 py-2">70B</td><td class="px-4 py-2">140GB</td><td class="px-4 py-2">182GB</td><td class="px-4 py-2 text-gray-600">A100 80GB x2</td></tr>
<tr><td class="px-4 py-2 text-gray-800">Mixtral 8x7B</td><td class="px-4 py-2">47B</td><td class="px-4 py-2">94GB</td><td class="px-4 py-2">122GB</td><td class="px-4 py-2 text-gray-600">A100 80GB x2</td></tr>
<tr><td class="px-4 py-2 text-gray-800">Qwen 72B</td><td class="px-4 py-2">72B</td><td class="px-4 py-2">144GB</td><td class="px-4 py-2">187GB</td><td class="px-4 py-2 text-gray-600">H100 80GB x3</td></tr>
</tbody>
</table>
</div>
</main>
<script>
let categories = [];
// 加载导航栏
async function loadNav() {
const res = await fetch('/api/categories');
categories = await res.json();
const builtinPages = [
{name: '首页', href: '/'},
{name: '工具', href: '/tools'},
{name: '对比', href: '/compare'},
{name: '知识库', href: '/knowledge'}
];
const categoryPages = {
'ai-models': '/models',
'gpus': '/gpus',
'cpus': '/cpus'
};
let navHtml = '';
builtinPages.forEach(p => {
const isActive = window.location.pathname === p.href;
navHtml += `<a href="${p.href}" class="${isActive ? 'text-indigo-600 font-medium' : 'text-gray-600 hover:text-indigo-600'}">${p.name}</a>`;
});
categories.forEach(cat => {
const href = categoryPages[cat.id] || `/category/${cat.id}`;
const isActive = window.location.pathname === href;
navHtml += `<a href="${href}" class="${isActive ? 'text-indigo-600 font-medium' : 'text-gray-600 hover:text-indigo-600'}">${cat.name}</a>`;
});
document.getElementById('topNav').innerHTML = navHtml;
}
async function calculateVram() {
const params = document.getElementById('params').value;
const precision = document.getElementById('precision').value;
const res = await fetch(`/api/calculate/vram?params=${params}&precision=${precision}`);
const data = await res.json();
document.getElementById('modelVram').textContent = data.model_vram + ' GB';
document.getElementById('totalVram').textContent = data.total_vram + ' GB';
// 推荐GPU
const gpuList = document.getElementById('gpuList');
if (data.suitable_gpus && data.suitable_gpus.length > 0) {
gpuList.innerHTML = data.suitable_gpus.map(g => `
<div class="p-3 bg-green-50 rounded-lg border border-green-200">
<div class="font-medium text-green-800">${g.name}</div>
<div class="text-sm text-green-600">${g.memory_gb}GB显存</div>
</div>
`).join('');
} else {
gpuList.innerHTML = `<div class="p-3 bg-red-50 rounded-lg text-red-600 col-span-3">暂无合适的GPU请考虑INT4量化或多卡方案</div>`;
}
document.getElementById('vramResult').classList.remove('hidden');
}
// 初始化
loadNav();
</script>
</body>
</html>