Files
param-hub-python/app.py
hubian 420107730c feat: 分类管理和知识库管理
功能:
- 分类管理:可动态添加手机、电脑、汽车等参数大类
- 知识库管理:增删改查知识条目,支持分类筛选
- 概览统计增加分类和知识数量
- 侧边栏导航优化
2026-04-09 02:20:55 +08:00

483 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
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'
CATEGORIES_FILE = DATA_DIR / 'categories.json'
KNOWLEDGE_FILE = DATA_DIR / 'knowledge.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')
@app.route('/admin')
def admin_page():
"""后台管理页面"""
return render_template('admin.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/gpus', methods=['POST'])
def api_create_gpu():
"""创建新GPU"""
data = request.get_json()
gpus = load_data(GPUS_FILE)
import uuid
data['id'] = uuid.uuid4().hex[:12]
data['created_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
gpus.append(data)
save_data(GPUS_FILE, gpus)
return jsonify(data)
@app.route('/api/gpus/<gpu_id>', methods=['PUT'])
def api_update_gpu(gpu_id):
"""更新GPU"""
data = request.get_json()
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
gpu.update(data)
gpu['updated_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
save_data(GPUS_FILE, gpus)
return jsonify(gpu)
@app.route('/api/gpus/<gpu_id>', methods=['DELETE'])
def api_delete_gpu(gpu_id):
"""删除GPU"""
gpus = load_data(GPUS_FILE)
gpus = [g for g in gpus if g['id'] != gpu_id]
save_data(GPUS_FILE, gpus)
return jsonify({'success': True})
@app.route('/api/cpus', methods=['POST'])
def api_create_cpu():
"""创建新CPU"""
data = request.get_json()
cpus = load_data(CPUS_FILE)
import uuid
data['id'] = uuid.uuid4().hex[:12]
data['created_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
cpus.append(data)
save_data(CPUS_FILE, cpus)
return jsonify(data)
@app.route('/api/cpus/<cpu_id>', methods=['PUT'])
def api_update_cpu(cpu_id):
"""更新CPU"""
data = request.get_json()
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
cpu.update(data)
cpu['updated_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
save_data(CPUS_FILE, cpus)
return jsonify(cpu)
@app.route('/api/cpus/<cpu_id>', methods=['DELETE'])
def api_delete_cpu(cpu_id):
"""删除CPU"""
cpus = load_data(CPUS_FILE)
cpus = [c for c in cpus if c['id'] != cpu_id]
save_data(CPUS_FILE, cpus)
return jsonify({'success': True})
@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)
categories = load_data(CATEGORIES_FILE)
knowledge = load_data(KNOWLEDGE_FILE)
return jsonify({
'models_count': len(models),
'gpus_count': len(gpus),
'cpus_count': len(cpus),
'categories_count': len(categories),
'knowledge_count': len(knowledge),
'latest_models': sorted(models, key=lambda x: x.get('created_at', ''), reverse=True)[:5]
})
# ============ 分类管理API ============
@app.route('/api/categories')
def api_categories():
"""获取分类列表"""
categories = load_data(CATEGORIES_FILE)
return jsonify(categories)
@app.route('/api/categories', methods=['POST'])
def api_create_category():
"""创建新分类"""
data = request.get_json()
categories = load_data(CATEGORIES_FILE)
import uuid
data['id'] = uuid.uuid4().hex[:12]
data['created_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
categories.append(data)
save_data(CATEGORIES_FILE, categories)
return jsonify(data)
@app.route('/api/categories/<category_id>', methods=['PUT'])
def api_update_category(category_id):
"""更新分类"""
data = request.get_json()
categories = load_data(CATEGORIES_FILE)
category = next((c for c in categories if c['id'] == category_id), None)
if not category:
return jsonify({'error': 'Category not found'}), 404
category.update(data)
category['updated_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
save_data(CATEGORIES_FILE, categories)
return jsonify(category)
@app.route('/api/categories/<category_id>', methods=['DELETE'])
def api_delete_category(category_id):
"""删除分类"""
categories = load_data(CATEGORIES_FILE)
categories = [c for c in categories if c['id'] != category_id]
save_data(CATEGORIES_FILE, categories)
return jsonify({'success': True})
# ============ 知识库管理API ============
@app.route('/api/knowledge')
def api_knowledge():
"""获取知识列表"""
knowledge = load_data(KNOWLEDGE_FILE)
# 搜索过滤
keyword = request.args.get('q', '').strip().lower()
if keyword:
knowledge = [k for k in knowledge if keyword in k.get('title', '').lower() or
keyword in k.get('content', '').lower()]
# 分类过滤
category = request.args.get('category', '')
if category:
knowledge = [k for k in knowledge if k.get('category') == category]
return jsonify(sorted(knowledge, key=lambda x: x.get('order', 0)))
@app.route('/api/knowledge/<knowledge_id>')
def api_knowledge_detail(knowledge_id):
"""获取单个知识详情"""
knowledge = load_data(KNOWLEDGE_FILE)
item = next((k for k in knowledge if k['id'] == knowledge_id), None)
if not item:
return jsonify({'error': 'Knowledge not found'}), 404
return jsonify(item)
@app.route('/api/knowledge', methods=['POST'])
def api_create_knowledge():
"""创建新知识"""
data = request.get_json()
knowledge = load_data(KNOWLEDGE_FILE)
import uuid
data['id'] = uuid.uuid4().hex[:12]
data['created_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
if 'order' not in data:
data['order'] = len(knowledge)
knowledge.append(data)
save_data(KNOWLEDGE_FILE, knowledge)
return jsonify(data)
@app.route('/api/knowledge/<knowledge_id>', methods=['PUT'])
def api_update_knowledge(knowledge_id):
"""更新知识"""
data = request.get_json()
knowledge = load_data(KNOWLEDGE_FILE)
item = next((k for k in knowledge if k['id'] == knowledge_id), None)
if not item:
return jsonify({'error': 'Knowledge not found'}), 404
item.update(data)
item['updated_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
save_data(KNOWLEDGE_FILE, knowledge)
return jsonify(item)
@app.route('/api/knowledge/<knowledge_id>', methods=['DELETE'])
def api_delete_knowledge(knowledge_id):
"""删除知识"""
knowledge = load_data(KNOWLEDGE_FILE)
knowledge = [k for k in knowledge if k['id'] != knowledge_id]
save_data(KNOWLEDGE_FILE, knowledge)
return jsonify({'success': True})
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)