feat: ParamHub参数百科Python版

功能:
- 模型数据库 (12个模型)
- GPU数据库 (10个GPU)
- CPU数据库 (8个CPU)
- 显存计算器
- 对比工具
- 知识库
This commit is contained in:
2026-04-09 01:59:09 +08:00
commit 7d90603b23
15 changed files with 1742 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
__pycache__/
*.pyc
.env
.idea/
+71
View File
@@ -0,0 +1,71 @@
# ParamHub - 参数百科 (Python版)
> AI大模型与硬件参数速查平台
## 功能特点
- **模型数据库**: GPT-4、Llama、Claude等大模型参数规格
- **GPU数据库**: H100、A100、RTX 4090等GPU详细规格
- **CPU数据库**: AMD EPYC、Intel Xeon等服务器CPU参数
- **实用工具**: 显存计算器、GPU推荐
- **对比工具**: 多维度对比模型/GPU/CPU
- **知识库**: 参数解释、选型指南
## 技术栈
- Python 3 + Flask
- Tailwind CSS (CDN)
- RemixIcon
## 快速开始
```bash
# 安装依赖
pip install -r requirements.txt
# 运行服务
python app.py
# 访问地址
http://localhost:19010
```
## 目录结构
```
param-hub-python/
├── app.py # Flask主程序
├── templates/ # HTML页面
│ ├── index.html # 首页
│ ├── models.html # 模型数据库
│ ├── gpus.html # GPU数据库
│ ├── cpus.html # CPU数据库
│ ├── tools.html # 实用工具
│ ├── compare.html # 对比工具
│ └── knowledge.html # 知识库
├── data/ # 数据文件
│ ├── models.json # 模型数据
│ ├── gpus.json # GPU数据
│ └── cpus.json # CPU数据
├── requirements.txt # Python依赖
├── run.sh # 启动脚本
└── README.md # 说明文档
```
## API接口
| 接口 | 方法 | 说明 |
|------|------|------|
| `/api/models` | GET | 获取模型列表 |
| `/api/models/<id>` | GET | 获取模型详情 |
| `/api/gpus` | GET | 获取GPU列表 |
| `/api/gpus/<id>` | GET | 获取GPU详情 |
| `/api/cpus` | GET | 获取CPU列表 |
| `/api/cpus/<id>` | GET | 获取CPU详情 |
| `/api/search` | GET | 全局搜索 |
| `/api/calculate/vram` | GET | 显存计算 |
| `/api/stats` | GET | 统计数据 |
## 版本
- v0.1.0 - 初始版本
+270
View File
@@ -0,0 +1,270 @@
"""
ParamHub - 参数百科
AI大模型与硬件参数速查平台
"""
from flask import Flask, render_template, jsonify, request
from flask_cors import CORS
import json
from pathlib import Path
from datetime import datetime
app = Flask(__name__, static_folder='static', static_url_path='/static')
CORS(app)
# 数据目录
DATA_DIR = Path(__file__).parent / 'data'
DATA_DIR.mkdir(exist_ok=True)
# 数据文件
MODELS_FILE = DATA_DIR / 'models.json'
GPUS_FILE = DATA_DIR / 'gpus.json'
CPUS_FILE = DATA_DIR / 'cpus.json'
def load_data(file_path):
"""加载JSON数据"""
if file_path.exists():
return json.loads(file_path.read_text(encoding='utf-8'))
return []
def save_data(file_path, data):
"""保存JSON数据"""
file_path.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding='utf-8')
# ============ 页面路由 ============
@app.route('/')
def index():
"""首页"""
return render_template('index.html')
@app.route('/models')
def models_page():
"""模型数据库页面"""
return render_template('models.html')
@app.route('/gpus')
def gpus_page():
"""GPU数据库页面"""
return render_template('gpus.html')
@app.route('/cpus')
def cpus_page():
"""CPU数据库页面"""
return render_template('cpus.html')
@app.route('/tools')
def tools_page():
"""工具页面"""
return render_template('tools.html')
@app.route('/compare')
def compare_page():
"""对比页面"""
return render_template('compare.html')
@app.route('/knowledge')
def knowledge_page():
"""知识库页面"""
return render_template('knowledge.html')
# ============ API路由 ============
@app.route('/api/models')
def api_models():
"""获取模型列表"""
models = load_data(MODELS_FILE)
# 搜索过滤
keyword = request.args.get('q', '').strip().lower()
if keyword:
models = [m for m in models if keyword in m.get('name', '').lower() or
keyword in m.get('organization', '').lower()]
# 排序
sort_by = request.args.get('sort', 'name')
reverse = request.args.get('order', 'asc') == 'desc'
if sort_by in ['name', 'parameters', 'context_length', 'mmlu']:
models = sorted(models, key=lambda x: x.get(sort_by, 0) or 0, reverse=reverse)
return jsonify(models)
@app.route('/api/models/<model_id>')
def api_model_detail(model_id):
"""获取单个模型详情"""
models = load_data(MODELS_FILE)
model = next((m for m in models if m['id'] == model_id), None)
if not model:
return jsonify({'error': 'Model not found'}), 404
return jsonify(model)
@app.route('/api/models', methods=['POST'])
def api_create_model():
"""创建新模型"""
data = request.get_json()
models = load_data(MODELS_FILE)
# 生成ID
import uuid
data['id'] = uuid.uuid4().hex[:12]
data['created_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
models.append(data)
save_data(MODELS_FILE, models)
return jsonify(data)
@app.route('/api/models/<model_id>', methods=['PUT'])
def api_update_model(model_id):
"""更新模型"""
data = request.get_json()
models = load_data(MODELS_FILE)
model = next((m for m in models if m['id'] == model_id), None)
if not model:
return jsonify({'error': 'Model not found'}), 404
model.update(data)
model['updated_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
save_data(MODELS_FILE, models)
return jsonify(model)
@app.route('/api/models/<model_id>', methods=['DELETE'])
def api_delete_model(model_id):
"""删除模型"""
models = load_data(MODELS_FILE)
models = [m for m in models if m['id'] != model_id]
save_data(MODELS_FILE, models)
return jsonify({'success': True})
@app.route('/api/gpus')
def api_gpus():
"""获取GPU列表"""
gpus = load_data(GPUS_FILE)
keyword = request.args.get('q', '').strip().lower()
if keyword:
gpus = [g for g in gpus if keyword in g.get('name', '').lower() or
keyword in g.get('manufacturer', '').lower()]
return jsonify(gpus)
@app.route('/api/gpus/<gpu_id>')
def api_gpu_detail(gpu_id):
"""获取单个GPU详情"""
gpus = load_data(GPUS_FILE)
gpu = next((g for g in gpus if g['id'] == gpu_id), None)
if not gpu:
return jsonify({'error': 'GPU not found'}), 404
return jsonify(gpu)
@app.route('/api/cpus')
def api_cpus():
"""获取CPU列表"""
cpus = load_data(CPUS_FILE)
keyword = request.args.get('q', '').strip().lower()
if keyword:
cpus = [c for c in cpus if keyword in c.get('name', '').lower() or
keyword in c.get('manufacturer', '').lower()]
return jsonify(cpus)
@app.route('/api/cpus/<cpu_id>')
def api_cpu_detail(cpu_id):
"""获取单个CPU详情"""
cpus = load_data(CPUS_FILE)
cpu = next((c for c in cpus if c['id'] == cpu_id), None)
if not cpu:
return jsonify({'error': 'CPU not found'}), 404
return jsonify(cpu)
@app.route('/api/search')
def api_search():
"""全局搜索"""
keyword = request.args.get('q', '').strip().lower()
if not keyword:
return jsonify({'models': [], 'gpus': [], 'cpus': []})
models = load_data(MODELS_FILE)
gpus = load_data(GPUS_FILE)
cpus = load_data(CPUS_FILE)
result = {
'models': [m for m in models if keyword in m.get('name', '').lower() or
keyword in m.get('organization', '').lower()],
'gpus': [g for g in gpus if keyword in g.get('name', '').lower() or
keyword in g.get('manufacturer', '').lower()],
'cpus': [c for c in cpus if keyword in c.get('name', '').lower() or
keyword in c.get('manufacturer', '').lower()]
}
return jsonify(result)
@app.route('/api/calculate/vram')
def api_calculate_vram():
"""显存计算"""
params = request.args.get('params', '7', type=float) # 参数量(B)
precision = request.args.get('precision', 'fp16', type=str) # 精度
# 计算公式
# FP32: 参数 * 4字节
# FP16: 参数 * 2字节
# INT8: 参数 * 1字节
# INT4: 参数 * 0.5字节
bytes_per_param = {
'fp32': 4,
'fp16': 2,
'int8': 1,
'int4': 0.5
}
multiplier = bytes_per_param.get(precision, 2)
vram_gb = params * multiplier * 1e9 / (1024**3) # 转换为GB
# 加上KV cache和激活值估算(约30%额外开销)
total_vram = vram_gb * 1.3
# 推荐GPU
gpus = load_data(GPUS_FILE)
suitable_gpus = [g for g in gpus if g.get('memory_gb', 0) >= total_vram]
return jsonify({
'model_vram': round(vram_gb, 2),
'total_vram': round(total_vram, 2),
'suitable_gpus': suitable_gpus
})
@app.route('/api/stats')
def api_stats():
"""统计数据"""
models = load_data(MODELS_FILE)
gpus = load_data(GPUS_FILE)
cpus = load_data(CPUS_FILE)
return jsonify({
'models_count': len(models),
'gpus_count': len(gpus),
'cpus_count': len(cpus),
'latest_models': sorted(models, key=lambda x: x.get('created_at', ''), reverse=True)[:5]
})
if __name__ == '__main__':
print("=" * 50)
print("ParamHub - 参数百科")
print("=" * 50)
print(f"访问地址: http://localhost:19010")
print("=" * 50)
app.run(host='0.0.0.0', port=19010, debug=True)
+10
View File
@@ -0,0 +1,10 @@
[
{"id": "epyc9654", "name": "AMD EPYC 9654", "manufacturer": "AMD", "architecture": "Zen 4", "cores": 96, "threads": 192, "base_clock_ghz": 2.4, "boost_clock_ghz": 3.7, "l3_cache_mb": 384, "tdp_watts": 360, "price_usd": 11000, "release_year": 2022, "description": "AMD顶级服务器CPU96核心"},
{"id": "epyc9554", "name": "AMD EPYC 9554", "manufacturer": "AMD", "architecture": "Zen 4", "cores": 64, "threads": 128, "base_clock_ghz": 3.1, "boost_clock_ghz": 3.8, "l3_cache_mb": 256, "tdp_watts": 360, "price_usd": 6800, "release_year": 2022, "description": "64核心高性能服务器CPU"},
{"id": "epyc9454", "name": "AMD EPYC 9454", "manufacturer": "AMD", "architecture": "Zen 4", "cores": 48, "threads": 96, "base_clock_ghz": 2.75, "boost_clock_ghz": 3.8, "l3_cache_mb": 192, "tdp_watts": 290, "price_usd": 4100, "release_year": 2022, "description": "48核心服务器CPU"},
{"id": "xeonw9359x", "name": "Intel Xeon w9-3595X", "manufacturer": "Intel", "architecture": "Sapphire Rapids", "cores": 56, "threads": 112, "base_clock_ghz": 1.9, "boost_clock_ghz": 4.8, "l3_cache_mb": 105, "tdp_watts": 350, "price_usd": 6200, "release_year": 2023, "description": "Intel顶级工作站CPU"},
{"id": "xeonw5345", "name": "Intel Xeon w5-3435", "manufacturer": "Intel", "architecture": "Sapphire Rapids", "cores": 24, "threads": 48, "base_clock_ghz": 3.1, "boost_clock_ghz": 4.7, "l3_cache_mb": 45, "tdp_watts": 230, "price_usd": 950, "release_year": 2023, "description": "中端工作站CPU"},
{"id": "ryzen97950x", "name": "AMD Ryzen 9 7950X", "manufacturer": "AMD", "architecture": "Zen 4", "cores": 16, "threads": 32, "base_clock_ghz": 4.5, "boost_clock_ghz": 5.7, "l3_cache_mb": 64, "tdp_watts": 170, "price_usd": 550, "release_year": 2022, "description": "顶级消费级CPU,适合AI开发"},
{"id": "ryzen97950x3d", "name": "AMD Ryzen 9 7950X3D", "manufacturer": "AMD", "architecture": "Zen 4", "cores": 16, "threads": 32, "base_clock_ghz": 4.2, "boost_clock_ghz": 5.7, "l3_cache_mb": 144, "tdp_watts": 120, "price_usd": 700, "release_year": 2023, "description": "带3D V-Cache,游戏性能更强"},
{"id": "intel14900k", "name": "Intel Core i9-14900K", "manufacturer": "Intel", "architecture": "Raptor Lake Refresh", "cores": 24, "threads": 32, "base_clock_ghz": 3.2, "boost_clock_ghz": 6.0, "l3_cache_mb": 36, "tdp_watts": 125, "price_usd": 580, "release_year": 2023, "description": "Intel顶级消费级CPU"}
]
+12
View File
@@ -0,0 +1,12 @@
[
{"id": "h100", "name": "NVIDIA H100", "manufacturer": "NVIDIA", "architecture": "Hopper", "cuda_cores": 16896, "tensor_cores": 528, "memory_gb": 80, "memory_bandwidth_gbs": 3352, "fp32_tflops": 67, "fp16_tflops": 1979, "int8_perf_tops": 3958, "price_usd": 30000, "release_year": 2022, "description": "数据中心顶级GPU,专为AI训练设计"},
{"id": "a100", "name": "NVIDIA A100", "manufacturer": "NVIDIA", "architecture": "Ampere", "cuda_cores": 6912, "tensor_cores": 432, "memory_gb": 80, "memory_bandwidth_gbs": 2039, "fp32_tflops": 19.5, "fp16_tflops": 312, "int8_perf_tops": 624, "price_usd": 10000, "release_year": 2020, "description": "数据中心主力GPUAI训练推理通用"},
{"id": "a10040g", "name": "NVIDIA A100 40GB", "manufacturer": "NVIDIA", "architecture": "Ampere", "cuda_cores": 6912, "tensor_cores": 432, "memory_gb": 40, "memory_bandwidth_gbs": 1555, "fp32_tflops": 19.5, "fp16_tflops": 312, "int8_perf_tops": 624, "price_usd": 6000, "release_year": 2020, "description": "A100 40GB版本,性价比更高"},
{"id": "l40s", "name": "NVIDIA L40S", "manufacturer": "NVIDIA", "architecture": "Ada Lovelace", "cuda_cores": 18176, "tensor_cores": 568, "memory_gb": 48, "memory_bandwidth_gbs": 864, "fp32_tflops": 91.6, "fp16_tflops": 362, "int8_perf_tops": 724, "price_usd": 7000, "release_year": 2023, "description": "新一代数据中心GPU,推理优化"},
{"id": "rtx4090", "name": "NVIDIA RTX 4090", "manufacturer": "NVIDIA", "architecture": "Ada Lovelace", "cuda_cores": 16384, "tensor_cores": 512, "memory_gb": 24, "memory_bandwidth_gbs": 1008, "fp32_tflops": 82.6, "fp16_tflops": 330, "int8_perf_tops": 660, "price_usd": 1600, "release_year": 2022, "description": "消费级最强GPU,适合个人AI开发"},
{"id": "rtx4090d", "name": "NVIDIA RTX 4090D", "manufacturer": "NVIDIA", "architecture": "Ada Lovelace", "cuda_cores": 14592, "tensor_cores": 456, "memory_gb": 24, "memory_bandwidth_gbs": 1008, "fp32_tflops": 73.5, "fp16_tflops": 294, "int8_perf_tops": 588, "price_usd": 1400, "release_year": 2024, "description": "4090中国特供版,性能略降"},
{"id": "rtx3090", "name": "NVIDIA RTX 3090", "manufacturer": "NVIDIA", "architecture": "Ampere", "cuda_cores": 10496, "tensor_cores": 328, "memory_gb": 24, "memory_bandwidth_gbs": 936, "fp32_tflops": 35.6, "fp16_tflops": 142, "int8_perf_tops": 284, "price_usd": 1200, "release_year": 2020, "description": "上一代旗舰,性价比高"},
{"id": "rtx3080", "name": "NVIDIA RTX 3080", "manufacturer": "NVIDIA", "architecture": "Ampere", "cuda_cores": 8704, "tensor_cores": 272, "memory_gb": 10, "memory_bandwidth_gbs": 760, "fp32_tflops": 29.8, "fp16_tflops": 119, "int8_perf_tops": 238, "price_usd": 700, "release_year": 2020, "description": "中高端消费级GPU"},
{"id": "v100", "name": "NVIDIA V100", "manufacturer": "NVIDIA", "architecture": "Volta", "cuda_cores": 5120, "tensor_cores": 640, "memory_gb": 32, "memory_bandwidth_gbs": 900, "fp32_tflops": 14.8, "fp16_tflops": 118, "int8_perf_tops": 236, "price_usd": 4000, "release_year": 2017, "description": "上一代数据中心GPU,仍有价值"},
{"id": "mi300x", "name": "AMD MI300X", "manufacturer": "AMD", "architecture": "CDNA 3", "cuda_cores": 0, "tensor_cores": 304, "memory_gb": 192, "memory_bandwidth_gbs": 5300, "fp32_tflops": 81.7, "fp16_tflops": 1307, "int8_perf_tops": 2614, "price_usd": 15000, "release_year": 2023, "description": "AMD最强AI GPU192GB显存"}
]
+14
View File
@@ -0,0 +1,14 @@
[
{"id": "gpt4", "name": "GPT-4", "organization": "OpenAI", "parameters": 1760, "architecture": "Transformer", "context_length": 8192, "input_price": 0.03, "output_price": 0.06, "mmlu": 86.4, "humaneval": 67.0, "is_open_source": false, "license": "Proprietary", "description": "OpenAI最强大的多模态大模型", "created_at": "2024-01-01"},
{"id": "gpt4turbo", "name": "GPT-4 Turbo", "organization": "OpenAI", "parameters": 1760, "architecture": "Transformer", "context_length": 128000, "input_price": 0.01, "output_price": 0.03, "mmlu": 86.4, "humaneval": 67.0, "is_open_source": false, "license": "Proprietary", "description": "GPT-4增强版,128K上下文", "created_at": "2024-01-01"},
{"id": "gpt35", "name": "GPT-3.5 Turbo", "organization": "OpenAI", "parameters": 175, "architecture": "Transformer", "context_length": 16385, "input_price": 0.0005, "output_price": 0.0015, "mmlu": 70.0, "humaneval": 48.1, "is_open_source": false, "license": "Proprietary", "description": "性价比高的通用模型", "created_at": "2024-01-01"},
{"id": "claude3opus", "name": "Claude 3 Opus", "organization": "Anthropic", "parameters": 400, "architecture": "Transformer", "context_length": 200000, "input_price": 0.015, "output_price": 0.075, "mmlu": 86.8, "humaneval": 84.9, "is_open_source": false, "license": "Proprietary", "description": "Anthropic最强模型,200K上下文", "created_at": "2024-01-01"},
{"id": "claude3sonnet", "name": "Claude 3 Sonnet", "organization": "Anthropic", "parameters": 175, "architecture": "Transformer", "context_length": 200000, "input_price": 0.003, "output_price": 0.015, "mmlu": 79.0, "humaneval": 73.0, "is_open_source": false, "license": "Proprietary", "description": "平衡性能与成本", "created_at": "2024-01-01"},
{"id": "llama270b", "name": "Llama 2 70B", "organization": "Meta", "parameters": 70, "architecture": "Transformer", "context_length": 4096, "input_price": 0, "output_price": 0, "mmlu": 69.8, "humaneval": 29.9, "is_open_source": true, "license": "Llama 2 Community", "description": "Meta开源大模型,70B参数", "created_at": "2024-01-01"},
{"id": "llama3", "name": "Llama 3 70B", "organization": "Meta", "parameters": 70, "architecture": "Transformer", "context_length": 8192, "input_price": 0, "output_price": 0, "mmlu": 82.0, "humaneval": 81.7, "is_open_source": true, "license": "Llama 3 Community", "description": "Meta最新开源模型,性能接近GPT-4", "created_at": "2024-01-01"},
{"id": "mistral7b", "name": "Mistral 7B", "organization": "Mistral AI", "parameters": 7, "architecture": "Transformer", "context_length": 32768, "input_price": 0, "output_price": 0, "mmlu": 62.5, "humaneval": 26.8, "is_open_source": true, "license": "Apache 2.0", "description": "小巧高效的开源模型", "created_at": "2024-01-01"},
{"id": "mixtral8x7b", "name": "Mixtral 8x7B", "organization": "Mistral AI", "parameters": 47, "architecture": "MoE", "context_length": 32768, "input_price": 0, "output_price": 0, "mmlu": 70.6, "humaneval": 40.2, "is_open_source": true, "license": "Apache 2.0", "description": "MoE架构,高效推理", "created_at": "2024-01-01"},
{"id": "qwen72b", "name": "Qwen 72B", "organization": "Alibaba", "parameters": 72, "architecture": "Transformer", "context_length": 32768, "input_price": 0, "output_price": 0, "mmlu": 83.1, "humaneval": 65.4, "is_open_source": true, "license": "Apache 2.0", "description": "阿里开源大模型,中文能力强", "created_at": "2024-01-01"},
{"id": "deepseekv3", "name": "DeepSeek V3", "organization": "DeepSeek", "parameters": 685, "architecture": "MoE", "context_length": 128000, "input_price": 0.00014, "output_price": 0.00028, "mmlu": 88.5, "humaneval": 86.2, "is_open_source": true, "license": "MIT", "description": "DeepSeek最新模型,性价比极高", "created_at": "2024-01-01"},
{"id": "glm4", "name": "GLM-4", "organization": "Zhipu AI", "parameters": 130, "architecture": "Transformer", "context_length": 128000, "input_price": 0.014, "output_price": 0.014, "mmlu": 81.0, "humaneval": 70.0, "is_open_source": false, "license": "Proprietary", "description": "智谱AI大模型,中文能力强", "created_at": "2024-01-01"}
]
+2
View File
@@ -0,0 +1,2 @@
flask
flask-cors
+3
View File
@@ -0,0 +1,3 @@
#!/bin/bash
cd "$(dirname "$0")"
python3 app.py
+208
View File
@@ -0,0 +1,208 @@
<!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>
<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-6 text-sm">
<a href="/" class="text-gray-600 hover:text-indigo-600">首页</a>
<a href="/models" class="text-gray-600 hover:text-indigo-600">模型</a>
<a href="/gpus" class="text-gray-600 hover:text-indigo-600">GPU</a>
<a href="/cpus" class="text-gray-600 hover:text-indigo-600">CPU</a>
<a href="/tools" class="text-gray-600 hover:text-indigo-600">工具</a>
<a href="/compare" class="text-indigo-600 font-medium">对比</a>
<a href="/knowledge" class="text-gray-600 hover:text-indigo-600">知识库</a>
</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-git-merge-line text-purple-600"></i>
对比工具
</h1>
<p class="text-gray-500 mt-1">多维度对比模型或硬件参数</p>
</div>
<!-- 对比类型选择 -->
<div class="bg-white rounded-xl shadow-sm p-4 mb-6">
<div class="flex gap-4">
<button onclick="setCompareType('model')" id="btnModel" class="px-4 py-2 bg-indigo-600 text-white rounded-lg">
<i class="ri-robot-line mr-2"></i>模型对比
</button>
<button onclick="setCompareType('gpu')" id="btnGpu" class="px-4 py-2 bg-gray-200 text-gray-600 rounded-lg hover:bg-gray-300">
<i class="ri-cpu-line mr-2"></i>GPU对比
</button>
<button onclick="setCompareType('cpu')" id="btnCpu" class="px-4 py-2 bg-gray-200 text-gray-600 rounded-lg hover:bg-gray-300">
<i class="ri-memory-line mr-2"></i>CPU对比
</button>
</div>
</div>
<!-- 选择列表 -->
<div class="grid grid-cols-2 gap-4 mb-6">
<div class="bg-white rounded-xl shadow-sm p-4">
<label class="text-sm font-medium text-gray-600 mb-2 block">选择第一项</label>
<select id="select1" class="w-full px-4 py-2 border border-gray-200 rounded-lg" onchange="compare()">
<option value="">请选择...</option>
</select>
</div>
<div class="bg-white rounded-xl shadow-sm p-4">
<label class="text-sm font-medium text-gray-600 mb-2 block">选择第二项</label>
<select id="select2" class="w-full px-4 py-2 border border-gray-200 rounded-lg" onchange="compare()">
<option value="">请选择...</option>
</select>
</div>
</div>
<!-- 对比结果 -->
<div id="compareResult" class="bg-white rounded-xl shadow-sm p-6 hidden">
<h2 class="text-lg font-semibold text-gray-800 mb-4">对比结果</h2>
<div id="compareTable"></div>
</div>
</main>
<script>
let compareType = 'model';
let allData = [];
async function setCompareType(type) {
compareType = type;
// 更新按钮样式
document.getElementById('btnModel').className = type === 'model'
? 'px-4 py-2 bg-indigo-600 text-white rounded-lg'
: 'px-4 py-2 bg-gray-200 text-gray-600 rounded-lg hover:bg-gray-300';
document.getElementById('btnGpu').className = type === 'gpu'
? 'px-4 py-2 bg-green-600 text-white rounded-lg'
: 'px-4 py-2 bg-gray-200 text-gray-600 rounded-lg hover:bg-gray-300';
document.getElementById('btnCpu').className = type === 'cpu'
? 'px-4 py-2 bg-purple-600 text-white rounded-lg'
: 'px-4 py-2 bg-gray-200 text-gray-600 rounded-lg hover:bg-gray-300';
// 加载数据
const res = await fetch(`/api/${type}s`);
allData = await res.json();
// 填充下拉框
const select1 = document.getElementById('select1');
const select2 = document.getElementById('select2');
select1.innerHTML = '<option value="">请选择...</option>' +
allData.map(d => `<option value="${d.id}">${d.name}</option>`).join('');
select2.innerHTML = '<option value="">请选择...</option>' +
allData.map(d => `<option value="${d.id}">${d.name}</option>`).join('');
document.getElementById('compareResult').classList.add('hidden');
}
async function compare() {
const id1 = document.getElementById('select1').value;
const id2 = document.getElementById('select2').value;
if (!id1 || !id2) {
document.getElementById('compareResult').classList.add('hidden');
return;
}
const res1 = await fetch(`/api/${compareType}s/${id1}`);
const res2 = await fetch(`/api/${compareType}s/${id2}`);
const item1 = await res1.json();
const item2 = await res2.json();
let fields = [];
if (compareType === 'model') {
fields = [
{ key: 'name', label: '名称' },
{ key: 'organization', label: '厂商' },
{ key: 'parameters', label: '参数量(B)', unit: 'B' },
{ key: 'context_length', label: '上下文长度' },
{ key: 'mmlu', label: 'MMLU分数', unit: '%' },
{ key: 'humaneval', label: 'HumanEval', unit: '%' },
{ key: 'is_open_source', label: '类型', format: v => v ? '开源' : '商业' },
{ key: 'input_price', label: '输入价格', unit: '$/1K' },
{ key: 'output_price', label: '输出价格', unit: '$/1K' },
];
} else if (compareType === 'gpu') {
fields = [
{ key: 'name', label: '名称' },
{ key: 'manufacturer', label: '厂商' },
{ key: 'architecture', label: '架构' },
{ key: 'memory_gb', label: '显存', unit: 'GB' },
{ key: 'cuda_cores', label: 'CUDA核心' },
{ key: 'fp16_tflops', label: 'FP16性能', unit: 'TF' },
{ key: 'price_usd', label: '价格', unit: '$' },
];
} else {
fields = [
{ key: 'name', label: '名称' },
{ key: 'manufacturer', label: '厂商' },
{ key: 'cores', label: '核心数' },
{ key: 'threads', label: '线程数' },
{ key: 'base_clock_ghz', label: '基础频率', unit: 'GHz' },
{ key: 'boost_clock_ghz', label: '加速频率', unit: 'GHz' },
{ key: 'l3_cache_mb', label: 'L3缓存', unit: 'MB' },
{ key: 'tdp_watts', label: 'TDP', unit: 'W' },
{ key: 'price_usd', label: '价格', unit: '$' },
];
}
const html = `
<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-center text-sm font-medium text-gray-600">${item1.name}</th>
<th class="px-4 py-2 text-center text-sm font-medium text-gray-600">${item2.name}</th>
<th class="px-4 py-2 text-center text-sm font-medium text-gray-600">差异</th>
</tr>
</thead>
<tbody class="divide-y">
${fields.map(f => {
const v1 = item1[f.key] || '-';
const v2 = item2[f.key] || '-';
const fv1 = f.format ? f.format(v1) : (v1 + (f.unit && typeof v1 === 'number' ? f.unit : ''));
const fv2 = f.format ? f.format(v2) : (v2 + (f.unit && typeof v2 === 'number' ? f.unit : ''));
let diff = '';
if (typeof v1 === 'number' && typeof v2 === 'number') {
const d = v2 - v1;
diff = d > 0 ? `<span class="text-green-600">+${d}${f.unit || ''}</span>` :
d < 0 ? `<span class="text-red-600">${d}${f.unit || ''}</span>` : '-';
}
return `
<tr>
<td class="px-4 py-2 text-gray-600">${f.label}</td>
<td class="px-4 py-2 text-center font-medium">${fv1}</td>
<td class="px-4 py-2 text-center font-medium">${fv2}</td>
<td class="px-4 py-2 text-center">${diff}</td>
</tr>
`;
}).join('')}
</tbody>
</table>
`;
document.getElementById('compareTable').innerHTML = html;
document.getElementById('compareResult').classList.remove('hidden');
}
// 初始化
setCompareType('model');
</script>
</body>
</html>
+186
View File
@@ -0,0 +1,186 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CPU数据库 - ParamHub</title>
<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-6 text-sm">
<a href="/" class="text-gray-600 hover:text-indigo-600">首页</a>
<a href="/models" class="text-gray-600 hover:text-indigo-600">模型</a>
<a href="/gpus" class="text-gray-600 hover:text-indigo-600">GPU</a>
<a href="/cpus" class="text-indigo-600 font-medium">CPU</a>
<a href="/tools" class="text-gray-600 hover:text-indigo-600">工具</a>
<a href="/compare" class="text-gray-600 hover:text-indigo-600">对比</a>
<a href="/knowledge" class="text-gray-600 hover:text-indigo-600">知识库</a>
</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-memory-line text-purple-600"></i>
CPU数据库
</h1>
<p class="text-gray-500 mt-1">处理器规格参数一览</p>
</div>
<div class="bg-white rounded-xl shadow-sm p-4 mb-6">
<div class="relative">
<i class="ri-search-line absolute left-3 top-1/2 -translate-y-1/2 text-gray-400"></i>
<input type="text" id="searchInput" placeholder="搜索CPU名称或厂商..."
class="w-full pl-10 pr-4 py-2 border border-gray-200 rounded-lg focus:outline-none focus:border-purple-400"
oninput="loadCpus()">
</div>
</div>
<div class="bg-white rounded-xl shadow-sm overflow-hidden">
<table class="w-full">
<thead class="bg-gray-50 border-b">
<tr>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">CPU名称</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">厂商</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">核心/线程</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">主频</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">L3缓存</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">TDP</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">价格</th>
<th class="px-4 py-3 text-center text-sm font-medium text-gray-600">操作</th>
</tr>
</thead>
<tbody id="cpusTable">
<tr><td colspan="8" class="text-center text-gray-400 py-8">加载中...</td></tr>
</tbody>
</table>
</div>
</main>
<div id="detailModal" class="fixed inset-0 bg-black/50 z-50 hidden flex items-center justify-center">
<div class="bg-white rounded-xl max-w-2xl w-full mx-4 max-h-[80vh] overflow-auto">
<div class="p-6 border-b flex justify-between items-center">
<h2 class="text-xl font-bold text-gray-800" id="modalTitle">CPU详情</h2>
<button onclick="closeModal()" class="text-gray-400 hover:text-gray-600">
<i class="ri-close-line text-2xl"></i>
</button>
</div>
<div id="modalContent" class="p-6"></div>
</div>
</div>
<script>
async function loadCpus() {
const keyword = document.getElementById('searchInput').value.trim();
let url = '/api/cpus';
if (keyword) url += `?q=${encodeURIComponent(keyword)}`;
const res = await fetch(url);
const cpus = await res.json();
if (cpus.length === 0) {
document.getElementById('cpusTable').innerHTML = `
<tr><td colspan="8" class="text-center text-gray-400 py-8">暂无数据</td></tr>
`;
return;
}
const html = cpus.map(c => `
<tr class="border-b hover:bg-gray-50 transition">
<td class="px-4 py-3">
<div class="font-medium text-gray-800">${c.name}</div>
<div class="text-xs text-gray-500">${c.release_year || ''}</div>
</td>
<td class="px-4 py-3 text-gray-600">${c.manufacturer}</td>
<td class="px-4 py-3">
<span class="px-2 py-1 bg-purple-100 text-purple-700 rounded text-sm">${c.cores}/${c.threads}</span>
</td>
<td class="px-4 py-3 text-gray-600">${c.base_clock_ghz}-${c.boost_clock_ghz}GHz</td>
<td class="px-4 py-3 text-gray-600">${c.l3_cache_mb}MB</td>
<td class="px-4 py-3 text-gray-600">${c.tdp_watts}W</td>
<td class="px-4 py-3 text-gray-600">$${c.price_usd || '-'}</td>
<td class="px-4 py-3 text-center">
<button onclick="showDetail('${c.id}')" class="text-purple-600 hover:text-purple-800 text-sm">
<i class="ri-eye-line mr-1"></i>详情
</button>
</td>
</tr>
`).join('');
document.getElementById('cpusTable').innerHTML = html;
}
async function showDetail(id) {
const res = await fetch(`/api/cpus/${id}`);
const cpu = await res.json();
document.getElementById('modalTitle').textContent = cpu.name;
document.getElementById('modalContent').innerHTML = `
<div class="grid grid-cols-2 gap-4">
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">厂商</div>
<div class="font-medium text-gray-800 mt-1">${cpu.manufacturer}</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">架构</div>
<div class="font-medium text-gray-800 mt-1">${cpu.architecture}</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">核心数</div>
<div class="font-medium text-gray-800 mt-1">${cpu.cores}</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">线程数</div>
<div class="font-medium text-gray-800 mt-1">${cpu.threads}</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">基础频率</div>
<div class="font-medium text-gray-800 mt-1">${cpu.base_clock_ghz}GHz</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">加速频率</div>
<div class="font-medium text-gray-800 mt-1">${cpu.boost_clock_ghz}GHz</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">L3缓存</div>
<div class="font-medium text-gray-800 mt-1">${cpu.l3_cache_mb}MB</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">TDP功耗</div>
<div class="font-medium text-gray-800 mt-1">${cpu.tdp_watts}W</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg col-span-2">
<div class="text-sm text-gray-500">价格</div>
<div class="font-medium text-gray-800 mt-1">$${cpu.price_usd || '-'}</div>
</div>
</div>
<div class="mt-4 p-4 bg-purple-50 rounded-lg">
<div class="text-sm text-purple-600">简介</div>
<div class="text-gray-800 mt-1">${cpu.description || '暂无描述'}</div>
</div>
`;
document.getElementById('detailModal').classList.remove('hidden');
}
function closeModal() {
document.getElementById('detailModal').classList.add('hidden');
}
document.getElementById('detailModal').addEventListener('click', function(e) {
if (e.target === this) closeModal();
});
loadCpus();
</script>
</body>
</html>
+193
View File
@@ -0,0 +1,193 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GPU数据库 - ParamHub</title>
<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-6 text-sm">
<a href="/" class="text-gray-600 hover:text-indigo-600">首页</a>
<a href="/models" class="text-gray-600 hover:text-indigo-600">模型</a>
<a href="/gpus" class="text-indigo-600 font-medium">GPU</a>
<a href="/cpus" class="text-gray-600 hover:text-indigo-600">CPU</a>
<a href="/tools" class="text-gray-600 hover:text-indigo-600">工具</a>
<a href="/compare" class="text-gray-600 hover:text-indigo-600">对比</a>
<a href="/knowledge" class="text-gray-600 hover:text-indigo-600">知识库</a>
</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-cpu-line text-green-600"></i>
GPU数据库
</h1>
<p class="text-gray-500 mt-1">显卡规格参数一览</p>
</div>
<!-- 搜索 -->
<div class="bg-white rounded-xl shadow-sm p-4 mb-6">
<div class="relative">
<i class="ri-search-line absolute left-3 top-1/2 -translate-y-1/2 text-gray-400"></i>
<input type="text" id="searchInput" placeholder="搜索GPU名称或厂商..."
class="w-full pl-10 pr-4 py-2 border border-gray-200 rounded-lg focus:outline-none focus:border-green-400"
oninput="loadGpus()">
</div>
</div>
<!-- GPU列表 -->
<div class="bg-white rounded-xl shadow-sm overflow-hidden">
<table class="w-full">
<thead class="bg-gray-50 border-b">
<tr>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">GPU名称</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">厂商</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">架构</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">显存</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">CUDA核心</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">FP16性能</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">价格</th>
<th class="px-4 py-3 text-center text-sm font-medium text-gray-600">操作</th>
</tr>
</thead>
<tbody id="gpusTable">
<tr><td colspan="8" class="text-center text-gray-400 py-8">加载中...</td></tr>
</tbody>
</table>
</div>
</main>
<!-- 详情弹窗 -->
<div id="detailModal" class="fixed inset-0 bg-black/50 z-50 hidden flex items-center justify-center">
<div class="bg-white rounded-xl max-w-2xl w-full mx-4 max-h-[80vh] overflow-auto">
<div class="p-6 border-b flex justify-between items-center">
<h2 class="text-xl font-bold text-gray-800" id="modalTitle">GPU详情</h2>
<button onclick="closeModal()" class="text-gray-400 hover:text-gray-600">
<i class="ri-close-line text-2xl"></i>
</button>
</div>
<div id="modalContent" class="p-6"></div>
</div>
</div>
<script>
async function loadGpus() {
const keyword = document.getElementById('searchInput').value.trim();
let url = '/api/gpus';
if (keyword) url += `?q=${encodeURIComponent(keyword)}`;
const res = await fetch(url);
const gpus = await res.json();
if (gpus.length === 0) {
document.getElementById('gpusTable').innerHTML = `
<tr><td colspan="8" class="text-center text-gray-400 py-8">暂无数据</td></tr>
`;
return;
}
const html = gpus.map(g => `
<tr class="border-b hover:bg-gray-50 transition">
<td class="px-4 py-3">
<div class="font-medium text-gray-800">${g.name}</div>
<div class="text-xs text-gray-500">${g.release_year || ''}</div>
</td>
<td class="px-4 py-3 text-gray-600">${g.manufacturer}</td>
<td class="px-4 py-3 text-gray-600">${g.architecture}</td>
<td class="px-4 py-3">
<span class="px-2 py-1 bg-green-100 text-green-700 rounded text-sm">${g.memory_gb}GB</span>
</td>
<td class="px-4 py-3 text-gray-600">${g.cuda_cores || '-'}</td>
<td class="px-4 py-3 text-gray-600">${g.fp16_tflops || '-'} TF</td>
<td class="px-4 py-3 text-gray-600">$${g.price_usd || '-'}</td>
<td class="px-4 py-3 text-center">
<button onclick="showDetail('${g.id}')" class="text-green-600 hover:text-green-800 text-sm">
<i class="ri-eye-line mr-1"></i>详情
</button>
</td>
</tr>
`).join('');
document.getElementById('gpusTable').innerHTML = html;
}
async function showDetail(id) {
const res = await fetch(`/api/gpus/${id}`);
const gpu = await res.json();
document.getElementById('modalTitle').textContent = gpu.name;
document.getElementById('modalContent').innerHTML = `
<div class="grid grid-cols-2 gap-4">
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">厂商</div>
<div class="font-medium text-gray-800 mt-1">${gpu.manufacturer}</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">架构</div>
<div class="font-medium text-gray-800 mt-1">${gpu.architecture}</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">显存</div>
<div class="font-medium text-gray-800 mt-1">${gpu.memory_gb}GB</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">显存带宽</div>
<div class="font-medium text-gray-800 mt-1">${gpu.memory_bandwidth_gbs || '-'} GB/s</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">CUDA核心</div>
<div class="font-medium text-gray-800 mt-1">${gpu.cuda_cores || '-'}</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">Tensor核心</div>
<div class="font-medium text-gray-800 mt-1">${gpu.tensor_cores || '-'}</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">FP32性能</div>
<div class="font-medium text-gray-800 mt-1">${gpu.fp32_tflops || '-'} TFLOPS</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">FP16性能</div>
<div class="font-medium text-gray-800 mt-1">${gpu.fp16_tflops || '-'} TFLOPS</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">INT8性能</div>
<div class="font-medium text-gray-800 mt-1">${gpu.int8_perf_tops || '-'} TOPS</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">价格</div>
<div class="font-medium text-gray-800 mt-1">$${gpu.price_usd || '-'}</div>
</div>
</div>
<div class="mt-4 p-4 bg-green-50 rounded-lg">
<div class="text-sm text-green-600">简介</div>
<div class="text-gray-800 mt-1">${gpu.description || '暂无描述'}</div>
</div>
`;
document.getElementById('detailModal').classList.remove('hidden');
}
function closeModal() {
document.getElementById('detailModal').classList.add('hidden');
}
document.getElementById('detailModal').addEventListener('click', function(e) {
if (e.target === this) closeModal();
});
loadGpus();
</script>
</body>
</html>
+168
View File
@@ -0,0 +1,168 @@
<!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>
<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">
<div 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>
<span class="text-sm text-gray-500">参数百科</span>
</div>
<div class="flex gap-6 text-sm">
<a href="/" class="text-indigo-600 font-medium">首页</a>
<a href="/models" class="text-gray-600 hover:text-indigo-600">模型</a>
<a href="/gpus" class="text-gray-600 hover:text-indigo-600">GPU</a>
<a href="/cpus" class="text-gray-600 hover:text-indigo-600">CPU</a>
<a href="/tools" class="text-gray-600 hover:text-indigo-600">工具</a>
<a href="/compare" class="text-gray-600 hover:text-indigo-600">对比</a>
<a href="/knowledge" class="text-gray-600 hover:text-indigo-600">知识库</a>
</div>
</div>
</nav>
<!-- 主内容 -->
<main class="max-w-7xl mx-auto px-4 py-8">
<!-- 搜索框 -->
<div class="bg-white rounded-xl shadow-sm p-6 mb-8">
<div class="flex gap-4">
<div class="flex-1 relative">
<i class="ri-search-line absolute left-4 top-1/2 -translate-y-1/2 text-gray-400"></i>
<input type="text" id="searchInput" placeholder="搜索模型、GPU、CPU..."
class="w-full pl-12 pr-4 py-3 border border-gray-200 rounded-lg focus:outline-none focus:border-indigo-400 text-lg"
onkeyup="if(event.key==='Enter')search()">
</div>
<button onclick="search()" class="px-6 py-3 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition">
<i class="ri-search-line mr-2"></i>搜索
</button>
</div>
</div>
<!-- 统计卡片 -->
<div class="grid grid-cols-3 gap-6 mb-8" id="statsCards">
<div class="bg-gradient-to-r from-blue-500 to-blue-600 rounded-xl p-6 text-white">
<div class="flex items-center gap-4">
<i class="ri-robot-line text-4xl"></i>
<div>
<div class="text-3xl font-bold" id="modelsCount">-</div>
<div class="text-sm opacity-80">AI模型</div>
</div>
</div>
</div>
<div class="bg-gradient-to-r from-green-500 to-green-600 rounded-xl p-6 text-white">
<div class="flex items-center gap-4">
<i class="ri-cpu-line text-4xl"></i>
<div>
<div class="text-3xl font-bold" id="gpusCount">-</div>
<div class="text-sm opacity-80">GPU显卡</div>
</div>
</div>
</div>
<div class="bg-gradient-to-r from-purple-500 to-purple-600 rounded-xl p-6 text-white">
<div class="flex items-center gap-4">
<i class="ri-memory-line text-4xl"></i>
<div>
<div class="text-3xl font-bold" id="cpusCount">-</div>
<div class="text-sm opacity-80">CPU处理器</div>
</div>
</div>
</div>
</div>
<!-- 快捷入口 -->
<div class="grid grid-cols-4 gap-6 mb-8">
<a href="/models" class="bg-white rounded-xl shadow-sm p-6 hover:shadow-md transition group">
<div class="text-center">
<i class="ri-robot-line text-5xl text-blue-500 group-hover:scale-110 transition"></i>
<div class="mt-4 font-medium text-gray-800">模型数据库</div>
<div class="text-sm text-gray-500 mt-1">GPT、Llama、Claude...</div>
</div>
</a>
<a href="/gpus" class="bg-white rounded-xl shadow-sm p-6 hover:shadow-md transition group">
<div class="text-center">
<i class="ri-cpu-line text-5xl text-green-500 group-hover:scale-110 transition"></i>
<div class="mt-4 font-medium text-gray-800">GPU数据库</div>
<div class="text-sm text-gray-500 mt-1">H100、A100、4090...</div>
</div>
</a>
<a href="/tools" class="bg-white rounded-xl shadow-sm p-6 hover:shadow-md transition group">
<div class="text-center">
<i class="ri-calculator-line text-5xl text-orange-500 group-hover:scale-110 transition"></i>
<div class="mt-4 font-medium text-gray-800">实用工具</div>
<div class="text-sm text-gray-500 mt-1">显存计算器...</div>
</div>
</a>
<a href="/compare" class="bg-white rounded-xl shadow-sm p-6 hover:shadow-md transition group">
<div class="text-center">
<i class="ri-git-merge-line text-5xl text-purple-500 group-hover:scale-110 transition"></i>
<div class="mt-4 font-medium text-gray-800">对比工具</div>
<div class="text-sm text-gray-500 mt-1">多维度对比</div>
</div>
</a>
</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-flashlight-line text-indigo-600"></i>
热门模型
</h2>
<div id="latestModels" class="grid grid-cols-2 gap-4">
<div class="text-center text-gray-400 py-8">加载中...</div>
</div>
</div>
</main>
<!-- 页脚 -->
<footer class="bg-white border-t mt-8 py-6 text-center text-gray-500 text-sm">
ParamHub - 参数百科 | AI模型与硬件参数速查平台
</footer>
<script>
// 加载统计数据
async function loadStats() {
const res = await fetch('/api/stats');
const data = await res.json();
document.getElementById('modelsCount').textContent = data.models_count;
document.getElementById('gpusCount').textContent = data.gpus_count;
document.getElementById('cpusCount').textContent = data.cpus_count;
// 最新模型
if (data.latest_models && data.latest_models.length > 0) {
const html = data.latest_models.map(m => `
<a href="/models" class="flex items-center gap-4 p-4 rounded-lg hover:bg-gray-50 transition">
<div class="w-12 h-12 rounded-full bg-indigo-100 flex items-center justify-center text-indigo-600 font-bold">
${m.name.substring(0, 2)}
</div>
<div class="flex-1">
<div class="font-medium text-gray-800">${m.name}</div>
<div class="text-sm text-gray-500">${m.organization} | ${m.parameters}B参数</div>
</div>
<div class="text-sm text-gray-400">${m.is_open_source ? '开源' : '商业'}</div>
</a>
`).join('');
document.getElementById('latestModels').innerHTML = html;
}
}
// 搜索
async function search() {
const keyword = document.getElementById('searchInput').value.trim();
if (!keyword) return;
window.location.href = `/models?q=${encodeURIComponent(keyword)}`;
}
// 初始化
loadStats();
</script>
</body>
</html>
+187
View File
@@ -0,0 +1,187 @@
<!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>
<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-6 text-sm">
<a href="/" class="text-gray-600 hover:text-indigo-600">首页</a>
<a href="/models" class="text-gray-600 hover:text-indigo-600">模型</a>
<a href="/gpus" class="text-gray-600 hover:text-indigo-600">GPU</a>
<a href="/cpus" class="text-gray-600 hover:text-indigo-600">CPU</a>
<a href="/tools" class="text-gray-600 hover:text-indigo-600">工具</a>
<a href="/compare" class="text-gray-600 hover:text-indigo-600">对比</a>
<a href="/knowledge" class="text-indigo-600 font-medium">知识库</a>
</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-book-open-line text-teal-600"></i>
知识库
</h1>
<p class="text-gray-500 mt-1">AI模型参数与硬件知识</p>
</div>
<div class="grid grid-cols-2 gap-6">
<!-- 参数量 -->
<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-calculator-line text-blue-600"></i>
什么是参数量?
</h2>
<p class="text-gray-600 leading-relaxed">
参数量(Parameters)是衡量大模型规模的指标,表示模型中权重参数的数量。
例如 GPT-3 有 175B 参数,即约1750亿个参数。
</p>
<div class="mt-4 p-4 bg-blue-50 rounded-lg">
<div class="font-medium text-blue-800 mb-2">常见规模分类:</div>
<ul class="text-sm text-blue-600 space-y-1">
<li>• 小模型:&lt;1B (适合边缘设备)</li>
<li>• 中模型:1B-10B (消费级GPU可运行)</li>
<li>• 大模型:10B-100B (需要多GPU)</li>
<li>• 超大模型:&gt;100B (需要数据中心)</li>
</ul>
</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-text-wrap text-green-600"></i>
什么是上下文长度?
</h2>
<p class="text-gray-600 leading-relaxed">
上下文长度(Context Length)是模型能处理的输入文本最大长度。
更长的上下文意味着模型可以理解更长的文档或对话历史。
</p>
<div class="mt-4 p-4 bg-green-50 rounded-lg">
<div class="font-medium text-green-800 mb-2">常见长度:</div>
<ul class="text-sm text-green-600 space-y-1">
<li>• 4K:传统长度,适合简单对话</li>
<li>• 32K:中等长度,适合长文档</li>
<li>• 128K:超长上下文,如GPT-4 Turbo</li>
<li>• 200KClaude 3的极限长度</li>
</ul>
</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-memory-line text-orange-600"></i>
如何计算显存需求?
</h2>
<p class="text-gray-600 leading-relaxed">
模型显存需求 ≈ 参数量 × 每参数字节数 × 1.3(含KV Cache开销)
</p>
<div class="mt-4 p-4 bg-orange-50 rounded-lg">
<div class="font-medium text-orange-800 mb-2">计算公式:</div>
<ul class="text-sm text-orange-600 space-y-1">
<li>• FP32: 参数量 × 4字节 × 1.3</li>
<li>• FP16: 参数量 × 2字节 × 1.3</li>
<li>• INT8: 参数量 × 1字节 × 1.3</li>
<li>• INT4: 参数量 × 0.5字节 × 1.3</li>
</ul>
</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-scales-3-line text-purple-600"></i>
什么是量化?
</h2>
<p class="text-gray-600 leading-relaxed">
量化(Quantization)是将模型参数从高精度转换为低精度,减少显存占用和计算量。
如FP16→INT8→INT4,精度损失可控,资源节省显著。
</p>
<div class="mt-4 p-4 bg-purple-50 rounded-lg">
<div class="font-medium text-purple-800 mb-2">量化效果:</div>
<ul class="text-sm text-purple-600 space-y-1">
<li>• FP32→FP16: 显存减半,精度基本不变</li>
<li>• FP16→INT8: 显存再减半,精度略降</li>
<li>• INT8→INT4: 显存再减半,需特殊技术</li>
</ul>
</div>
</div>
<!-- MMLU -->
<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-bar-chart-box-line text-red-600"></i>
什么是MMLU
</h2>
<p class="text-gray-600 leading-relaxed">
MMLUMassive Multitask Language Understanding)是评估大模型综合能力的标准测试集,
覆盖57个学科领域,分数越高代表模型知识面越广。
</p>
<div class="mt-4 p-4 bg-red-50 rounded-lg">
<div class="font-medium text-red-800 mb-2">分数参考:</div>
<ul class="text-sm text-red-600 space-y-1">
<li>• 60-70%:入门级,如GPT-3</li>
<li>• 70-80%:中等水平,如Llama 2 70B</li>
<li>• 80-90%:优秀水平,如GPT-4、Claude 3</li>
</ul>
</div>
</div>
<!-- HumanEval -->
<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-code-box-line text-teal-600"></i>
什么是HumanEval
</h2>
<p class="text-gray-600 leading-relaxed">
HumanEval是评估模型代码能力的测试集,包含164个编程题目。
分数表示模型能正确完成的题目比例。
</p>
<div class="mt-4 p-4 bg-teal-50 rounded-lg">
<div class="font-medium text-teal-800 mb-2">分数参考:</div>
<ul class="text-sm text-teal-600 space-y-1">
<li>• 20-30%:基础代码能力</li>
<li>• 40-50%:中等代码能力</li>
<li>• 80%+:优秀代码能力,如Claude 3 Opus</li>
</ul>
</div>
</div>
</div>
<!-- 选型指南 -->
<div class="bg-white rounded-xl shadow-sm p-6 mt-6">
<h2 class="text-lg font-semibold text-gray-800 mb-4 flex items-center gap-2">
<i class="ri-lightbulb-line text-yellow-600"></i>
GPU选型指南
</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">推荐GPU</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>
</tr>
</thead>
<tbody class="divide-y">
<tr><td class="px-4 py-2 text-gray-800">个人学习/推理7B</td><td class="px-4 py-2">RTX 3060 12GB</td><td class="px-4 py-2">12-16GB</td><td class="px-4 py-2 text-gray-600">$300</td></tr>
<tr><td class="px-4 py-2 text-gray-800">个人开发/推理13B</td><td class="px-4 py-2">RTX 3090/4090</td><td class="px-4 py-2">24GB</td><td class="px-4 py-2 text-gray-600">$700-$1600</td></tr>
<tr><td class="px-4 py-2 text-gray-800">小团队训练/推理70B</td><td class="px-4 py-2">A100 40GB x2</td><td class="px-4 py-2">80GB</td><td class="px-4 py-2 text-gray-600">$12,000</td></tr>
<tr><td class="px-4 py-2 text-gray-800">企业训练大模型</td><td class="px-4 py-2">H100 80GB集群</td><td class="px-4 py-2">数百GB</td><td class="px-4 py-2 text-gray-600">$30,000+</td></tr>
</tbody>
</table>
</div>
</main>
</body>
</html>
+240
View File
@@ -0,0 +1,240 @@
<!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>
<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-6 text-sm">
<a href="/" class="text-gray-600 hover:text-indigo-600">首页</a>
<a href="/models" class="text-indigo-600 font-medium">模型</a>
<a href="/gpus" class="text-gray-600 hover:text-indigo-600">GPU</a>
<a href="/cpus" class="text-gray-600 hover:text-indigo-600">CPU</a>
<a href="/tools" class="text-gray-600 hover:text-indigo-600">工具</a>
<a href="/compare" class="text-gray-600 hover:text-indigo-600">对比</a>
<a href="/knowledge" class="text-gray-600 hover:text-indigo-600">知识库</a>
</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-robot-line text-indigo-600"></i>
模型数据库
</h1>
<p class="text-gray-500 mt-1">AI大模型参数规格一览</p>
</div>
<!-- 搜索和筛选 -->
<div class="bg-white rounded-xl shadow-sm p-4 mb-6">
<div class="flex gap-4 items-center">
<div class="flex-1 relative">
<i class="ri-search-line absolute left-3 top-1/2 -translate-y-1/2 text-gray-400"></i>
<input type="text" id="searchInput" placeholder="搜索模型名称或厂商..."
class="w-full pl-10 pr-4 py-2 border border-gray-200 rounded-lg focus:outline-none focus:border-indigo-400"
oninput="loadModels()">
</div>
<select id="sortBy" class="px-4 py-2 border border-gray-200 rounded-lg" onchange="loadModels()">
<option value="name">按名称</option>
<option value="parameters">按参数量</option>
<option value="mmlu">按MMLU分数</option>
<option value="context_length">按上下文长度</option>
</select>
<select id="sortOrder" class="px-4 py-2 border border-gray-200 rounded-lg" onchange="loadModels()">
<option value="asc">升序</option>
<option value="desc">降序</option>
</select>
<select id="filterType" class="px-4 py-2 border border-gray-200 rounded-lg" onchange="loadModels()">
<option value="all">全部</option>
<option value="open">开源</option>
<option value="closed">商业</option>
</select>
</div>
</div>
<!-- 模型列表 -->
<div class="bg-white rounded-xl shadow-sm overflow-hidden">
<table class="w-full">
<thead class="bg-gray-50 border-b">
<tr>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">模型名称</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">厂商</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">参数量</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">上下文</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">MMLU</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">类型</th>
<th class="px-4 py-3 text-left text-sm font-medium text-gray-600">价格</th>
<th class="px-4 py-3 text-center text-sm font-medium text-gray-600">操作</th>
</tr>
</thead>
<tbody id="modelsTable">
<tr><td colspan="8" class="text-center text-gray-400 py-8">加载中...</td></tr>
</tbody>
</table>
</div>
</main>
<!-- 详情弹窗 -->
<div id="detailModal" class="fixed inset-0 bg-black/50 z-50 hidden flex items-center justify-center">
<div class="bg-white rounded-xl max-w-2xl w-full mx-4 max-h-[80vh] overflow-auto">
<div class="p-6 border-b flex justify-between items-center">
<h2 class="text-xl font-bold text-gray-800" id="modalTitle">模型详情</h2>
<button onclick="closeModal()" class="text-gray-400 hover:text-gray-600">
<i class="ri-close-line text-2xl"></i>
</button>
</div>
<div id="modalContent" class="p-6"></div>
</div>
</div>
<script>
let allModels = [];
async function loadModels() {
const keyword = document.getElementById('searchInput').value.trim();
const sortBy = document.getElementById('sortBy').value;
const sortOrder = document.getElementById('sortOrder').value;
const filterType = document.getElementById('filterType').value;
let url = `/api/models?sort=${sortBy}&order=${sortOrder}`;
if (keyword) url += `&q=${encodeURIComponent(keyword)}`;
const res = await fetch(url);
let models = await res.json();
allModels = models;
// 本地过滤类型
if (filterType === 'open') {
models = models.filter(m => m.is_open_source);
} else if (filterType === 'closed') {
models = models.filter(m => !m.is_open_source);
}
renderModels(models);
}
function renderModels(models) {
if (models.length === 0) {
document.getElementById('modelsTable').innerHTML = `
<tr><td colspan="8" class="text-center text-gray-400 py-8">暂无数据</td></tr>
`;
return;
}
const html = models.map(m => `
<tr class="border-b hover:bg-gray-50 transition">
<td class="px-4 py-3">
<div class="font-medium text-gray-800">${m.name}</div>
<div class="text-xs text-gray-500">${m.architecture || ''}</div>
</td>
<td class="px-4 py-3 text-gray-600">${m.organization}</td>
<td class="px-4 py-3">
<span class="px-2 py-1 bg-blue-100 text-blue-700 rounded text-sm">${m.parameters}B</span>
</td>
<td class="px-4 py-3 text-gray-600">${formatContext(m.context_length)}</td>
<td class="px-4 py-3">
<span class="px-2 py-1 bg-green-100 text-green-700 rounded text-sm">${m.mmlu || '-'}%</span>
</td>
<td class="px-4 py-3">
${m.is_open_source
? '<span class="px-2 py-1 bg-emerald-100 text-emerald-700 rounded text-sm">开源</span>'
: '<span class="px-2 py-1 bg-gray-100 text-gray-700 rounded text-sm">商业</span>'}
</td>
<td class="px-4 py-3 text-sm text-gray-600">
${m.input_price ? `$${m.input_price}/$${m.output_price}` : '免费'}
</td>
<td class="px-4 py-3 text-center">
<button onclick="showDetail('${m.id}')" class="text-indigo-600 hover:text-indigo-800 text-sm">
<i class="ri-eye-line mr-1"></i>详情
</button>
</td>
</tr>
`).join('');
document.getElementById('modelsTable').innerHTML = html;
}
function formatContext(len) {
if (!len) return '-';
if (len >= 1000000) return (len / 1000) + 'K';
if (len >= 1000) return (len / 1000) + 'K';
return len;
}
async function showDetail(id) {
const res = await fetch(`/api/models/${id}`);
const model = await res.json();
document.getElementById('modalTitle').textContent = model.name;
document.getElementById('modalContent').innerHTML = `
<div class="grid grid-cols-2 gap-4">
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">厂商</div>
<div class="font-medium text-gray-800 mt-1">${model.organization}</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">架构</div>
<div class="font-medium text-gray-800 mt-1">${model.architecture || '-'}</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">参数量</div>
<div class="font-medium text-gray-800 mt-1">${model.parameters}B</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">上下文长度</div>
<div class="font-medium text-gray-800 mt-1">${formatContext(model.context_length)}</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">MMLU分数</div>
<div class="font-medium text-gray-800 mt-1">${model.mmlu || '-'}%</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">HumanEval</div>
<div class="font-medium text-gray-800 mt-1">${model.humaneval || '-'}%</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">许可证</div>
<div class="font-medium text-gray-800 mt-1">${model.license || '-'}</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg">
<div class="text-sm text-gray-500">API价格</div>
<div class="font-medium text-gray-800 mt-1">
${model.input_price ? `输入: $${model.input_price}/1K 输出: $${model.output_price}/1K` : '免费'}
</div>
</div>
</div>
<div class="mt-4 p-4 bg-blue-50 rounded-lg">
<div class="text-sm text-blue-600">简介</div>
<div class="text-gray-800 mt-1">${model.description || '暂无描述'}</div>
</div>
`;
document.getElementById('detailModal').classList.remove('hidden');
}
function closeModal() {
document.getElementById('detailModal').classList.add('hidden');
}
// 点击弹窗外部关闭
document.getElementById('detailModal').addEventListener('click', function(e) {
if (e.target === this) closeModal();
});
// 初始化
loadModels();
</script>
</body>
</html>
+174
View File
@@ -0,0 +1,174 @@
<!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>
<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-6 text-sm">
<a href="/" class="text-gray-600 hover:text-indigo-600">首页</a>
<a href="/models" class="text-gray-600 hover:text-indigo-600">模型</a>
<a href="/gpus" class="text-gray-600 hover:text-indigo-600">GPU</a>
<a href="/cpus" class="text-gray-600 hover:text-indigo-600">CPU</a>
<a href="/tools" class="text-indigo-600 font-medium">工具</a>
<a href="/compare" class="text-gray-600 hover:text-indigo-600">对比</a>
<a href="/knowledge" class="text-gray-600 hover:text-indigo-600">知识库</a>
</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-memory-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>
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');
}
</script>
</body>
</html>