feat: ParamHub参数百科Python版
功能: - 模型数据库 (12个模型) - GPU数据库 (10个GPU) - CPU数据库 (8个CPU) - 显存计算器 - 对比工具 - 知识库
This commit is contained in:
270
app.py
Normal file
270
app.py
Normal 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)
|
||||
Reference in New Issue
Block a user