更新了模型评估页面的新建
This commit is contained in:
15002
datasets/1769073525693_13_json
Normal file
15002
datasets/1769073525693_13_json
Normal file
File diff suppressed because one or more lines are too long
99
src/main.py
99
src/main.py
@@ -84,6 +84,7 @@ def init_database():
|
|||||||
# 模型评测表
|
# 模型评测表
|
||||||
"""CREATE TABLE IF NOT EXISTS model_eval (
|
"""CREATE TABLE IF NOT EXISTS model_eval (
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
model_name VARCHAR(255) NOT NULL,
|
model_name VARCHAR(255) NOT NULL,
|
||||||
dataset VARCHAR(255),
|
dataset VARCHAR(255),
|
||||||
metric VARCHAR(100),
|
metric VARCHAR(100),
|
||||||
@@ -215,12 +216,14 @@ def init_database():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" 表 {i+1} 创建失败: {e}")
|
print(f" 表 {i+1} 创建失败: {e}")
|
||||||
|
|
||||||
# 为已存在的 model_manage 表添加 purpose 列
|
# 为已存在的表添加缺失的列(静默处理,不显示重复列的提示)
|
||||||
try:
|
for table_col in [("model_manage", "purpose"), ("model_eval", "name")]:
|
||||||
cursor.execute("ALTER TABLE model_manage ADD COLUMN purpose VARCHAR(50) DEFAULT 'inference'")
|
try:
|
||||||
print(" model_manage 表添加 purpose 列成功")
|
table_name, col_name = table_col
|
||||||
except Exception as e:
|
cursor.execute(f"ALTER TABLE {table_name} ADD COLUMN {col_name} VARCHAR(255) DEFAULT ''")
|
||||||
print(f" model_manage 表 purpose 列处理: {e}")
|
print(f" {table_name} 表添加 {col_name} 列成功")
|
||||||
|
except Exception as e:
|
||||||
|
pass # 列已存在时不输出任何信息
|
||||||
|
|
||||||
# 插入默认管理员用户
|
# 插入默认管理员用户
|
||||||
cursor.execute("SELECT * FROM users WHERE username = 'admin'")
|
cursor.execute("SELECT * FROM users WHERE username = 'admin'")
|
||||||
@@ -240,13 +243,8 @@ def init_database():
|
|||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.config['SECRET_KEY'] = CONFIG['secret_key']
|
app.config['SECRET_KEY'] = CONFIG['secret_key']
|
||||||
app.config['CORS_HEADERS'] = 'Content-Type'
|
app.config['CORS_HEADERS'] = 'Content-Type'
|
||||||
CORS(app, resources={
|
# 使用字符串形式的 origins
|
||||||
r"/api/*": {
|
CORS(app, origins="*", methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"], allow_headers=["Content-Type", "Authorization"], supports_credentials=False)
|
||||||
"origins": "*",
|
|
||||||
"methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
|
||||||
"allow_headers": ["Content-Type", "Authorization"]
|
|
||||||
}
|
|
||||||
}, supports_credentials=False)
|
|
||||||
|
|
||||||
# 注册蓝图
|
# 注册蓝图
|
||||||
register_blueprints(app)
|
register_blueprints(app)
|
||||||
@@ -434,14 +432,85 @@ def get_model_eval():
|
|||||||
@app.route('/api/model-eval', methods=['POST'])
|
@app.route('/api/model-eval', methods=['POST'])
|
||||||
def create_model_eval():
|
def create_model_eval():
|
||||||
data = request.json
|
data = request.json
|
||||||
new_id = generic_create('model_eval', data)
|
|
||||||
|
# 获取模型名称和数据集名称
|
||||||
|
model_id = data.get('model_id')
|
||||||
|
dataset_id = data.get('dataset_id')
|
||||||
|
eval_dimension = data.get('eval_dimension', '')
|
||||||
|
|
||||||
|
# 获取模型名称
|
||||||
|
model_name = ''
|
||||||
|
if model_id:
|
||||||
|
conn = get_db_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("SELECT name FROM model_manage WHERE id = %s", (model_id,))
|
||||||
|
model_result = cursor.fetchone()
|
||||||
|
cursor.close()
|
||||||
|
conn.close()
|
||||||
|
if model_result:
|
||||||
|
model_name = model_result['name']
|
||||||
|
|
||||||
|
# 获取数据集名称
|
||||||
|
dataset_name = ''
|
||||||
|
if dataset_id:
|
||||||
|
conn = get_db_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("SELECT name FROM dataset_manage WHERE id = %s", (dataset_id,))
|
||||||
|
dataset_result = cursor.fetchone()
|
||||||
|
cursor.close()
|
||||||
|
conn.close()
|
||||||
|
if dataset_result:
|
||||||
|
dataset_name = dataset_result['name']
|
||||||
|
|
||||||
|
# 构建插入数据,映射到数据库字段
|
||||||
|
insert_data = {
|
||||||
|
'name': data.get('name', ''),
|
||||||
|
'model_name': model_name,
|
||||||
|
'dataset': dataset_name,
|
||||||
|
'metric': eval_dimension,
|
||||||
|
'status': 'pending'
|
||||||
|
}
|
||||||
|
|
||||||
|
new_id = generic_create('model_eval', insert_data)
|
||||||
return jsonify({'code': 0, 'message': '创建成功', 'id': new_id})
|
return jsonify({'code': 0, 'message': '创建成功', 'id': new_id})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/model-eval/<int:id>', methods=['PUT'])
|
@app.route('/api/model-eval/<int:id>', methods=['PUT'])
|
||||||
def update_model_eval(id):
|
def update_model_eval(id):
|
||||||
data = request.json
|
data = request.json
|
||||||
generic_update('model_eval', id, data)
|
|
||||||
|
# 构建更新数据,映射到数据库字段
|
||||||
|
update_data = {}
|
||||||
|
|
||||||
|
if 'name' in data:
|
||||||
|
update_data['name'] = data['name']
|
||||||
|
|
||||||
|
if 'model_id' in data:
|
||||||
|
model_id = data['model_id']
|
||||||
|
conn = get_db_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("SELECT name FROM model_manage WHERE id = %s", (model_id,))
|
||||||
|
model_result = cursor.fetchone()
|
||||||
|
cursor.close()
|
||||||
|
conn.close()
|
||||||
|
update_data['model_name'] = model_result['name'] if model_result else ''
|
||||||
|
|
||||||
|
if 'dataset_id' in data:
|
||||||
|
dataset_id = data['dataset_id']
|
||||||
|
conn = get_db_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("SELECT name FROM dataset_manage WHERE id = %s", (dataset_id,))
|
||||||
|
dataset_result = cursor.fetchone()
|
||||||
|
cursor.close()
|
||||||
|
conn.close()
|
||||||
|
update_data['dataset'] = dataset_result['name'] if dataset_result else ''
|
||||||
|
|
||||||
|
if 'eval_dimension' in data:
|
||||||
|
update_data['metric'] = data['eval_dimension']
|
||||||
|
|
||||||
|
if update_data:
|
||||||
|
generic_update('model_eval', id, update_data)
|
||||||
|
|
||||||
return jsonify({'code': 0, 'message': '更新成功'})
|
return jsonify({'code': 0, 'message': '更新成功'})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -959,6 +959,41 @@
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 获取 URL 参数
|
||||||
|
function getUrlParam(name) {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
return urlParams.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载维度数据(编辑模式)
|
||||||
|
async function loadDimensionData(id) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${API_BASE}/dimension/${id}`);
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
if (result.code === 0 && result.data) {
|
||||||
|
const dim = result.data;
|
||||||
|
|
||||||
|
// 填充基本信息
|
||||||
|
document.querySelector('input[name="name"]').value = dim.name || '';
|
||||||
|
document.querySelector('textarea[name="description"]').value = dim.description || '';
|
||||||
|
|
||||||
|
// 更新字数统计
|
||||||
|
document.getElementById('nameCount').textContent = (dim.name || '').length;
|
||||||
|
document.getElementById('descCount').textContent = (dim.description || '').length;
|
||||||
|
|
||||||
|
// 填充指标类型
|
||||||
|
const dimensionType = document.getElementById('dimensionType');
|
||||||
|
if (dimensionType && dim.type) {
|
||||||
|
dimensionType.value = dim.type;
|
||||||
|
toggleEvalConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载维度数据失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化函数
|
// 初始化函数
|
||||||
async function initPage() {
|
async function initPage() {
|
||||||
// 绑定指标类型下拉框事件
|
// 绑定指标类型下拉框事件
|
||||||
@@ -970,6 +1005,12 @@
|
|||||||
// 加载评测模型列表
|
// 加载评测模型列表
|
||||||
await loadEvalModels();
|
await loadEvalModels();
|
||||||
|
|
||||||
|
// 检查是否是编辑模式
|
||||||
|
const editId = getUrlParam('id');
|
||||||
|
if (editId) {
|
||||||
|
await loadDimensionData(editId);
|
||||||
|
}
|
||||||
|
|
||||||
// 绑定 Markdown 编辑器事件
|
// 绑定 Markdown 编辑器事件
|
||||||
const evalPromptEditor = document.getElementById('evalPromptEditor');
|
const evalPromptEditor = document.getElementById('evalPromptEditor');
|
||||||
if (evalPromptEditor) {
|
if (evalPromptEditor) {
|
||||||
@@ -1175,22 +1216,36 @@
|
|||||||
data.pass_threshold = parseFloat(formData.get('pass_threshold')) || 3;
|
data.pass_threshold = parseFloat(formData.get('pass_threshold')) || 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 判断是新建还是编辑
|
||||||
|
const editId = getUrlParam('id');
|
||||||
|
const isEdit = !!editId;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE}/dimension`, {
|
let url = `${API_BASE}/dimension`;
|
||||||
method: 'POST',
|
let method = 'POST';
|
||||||
|
let successMsg = '评测维度创建成功!';
|
||||||
|
|
||||||
|
if (isEdit) {
|
||||||
|
url = `${API_BASE}/dimension/${editId}`;
|
||||||
|
method = 'PUT';
|
||||||
|
successMsg = '评测维度更新成功!';
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: method,
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify(data)
|
body: JSON.stringify(data)
|
||||||
});
|
});
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
if (result.code === 0) {
|
if (result.code === 0) {
|
||||||
showMessage('成功', '评测维度创建成功!', 'success', () => {
|
showMessage('成功', successMsg, 'success', () => {
|
||||||
goBack();
|
goBack();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
showMessage('错误', result.message || '创建失败', 'error');
|
showMessage('错误', result.message || '操作失败', 'error');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showMessage('错误', '创建失败: ' + error.message, 'error');
|
showMessage('错误', '操作失败: ' + error.message, 'error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -305,18 +305,13 @@
|
|||||||
<div class="mb-6" id="evalRulesSection">
|
<div class="mb-6" id="evalRulesSection">
|
||||||
<h3 class="text-sm font-semibold text-gray-700 mb-4 pb-2 border-b border-gray-100">评测规则</h3>
|
<h3 class="text-sm font-semibold text-gray-700 mb-4 pb-2 border-b border-gray-100">评测规则</h3>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<select name="eval_dimension" class="form-select flex-1 max-w-md">
|
<select name="eval_dimension" id="dimensionSelect" class="form-select flex-1 max-w-md">
|
||||||
<option value="">请选择评测维度</option>
|
<option value="">请选择评测维度</option>
|
||||||
<option value="accuracy">准确率</option>
|
|
||||||
<option value="recall">召回率</option>
|
|
||||||
<option value="f1">F1值</option>
|
|
||||||
<option value="bleu">BLEU</option>
|
|
||||||
<option value="rouge">ROUGE</option>
|
|
||||||
</select>
|
</select>
|
||||||
<button type="button" class="ml-2 text-primary text-sm flex items-center hover:text-primary/80">
|
<button type="button" class="ml-2 text-primary text-sm flex items-center hover:text-primary/80" onclick="loadDimensions()">
|
||||||
<i class="fa fa-refresh"></i>
|
<i class="fa fa-refresh"></i>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="ml-3 bg-white border border-primary text-primary rounded px-3 py-1.5 text-sm hover:bg-primary/5">
|
<button type="button" class="ml-3 bg-white border border-primary text-primary rounded px-3 py-1.5 text-sm hover:bg-primary/5" onclick="window.location.href='model-dimension-create.html'">
|
||||||
+ 创建评测维度
|
+ 创建评测维度
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -384,6 +379,9 @@
|
|||||||
// 加载评测数据集
|
// 加载评测数据集
|
||||||
loadTestDatasets();
|
loadTestDatasets();
|
||||||
|
|
||||||
|
// 加载评测维度
|
||||||
|
loadDimensions();
|
||||||
|
|
||||||
// 设置侧边栏当前页高亮
|
// 设置侧边栏当前页高亮
|
||||||
const currentPage = 'model-eval';
|
const currentPage = 'model-eval';
|
||||||
document.querySelectorAll('.nav-link').forEach(link => {
|
document.querySelectorAll('.nav-link').forEach(link => {
|
||||||
@@ -510,6 +508,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加载评测维度列表
|
||||||
|
async function loadDimensions() {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${API_BASE}/dimension`);
|
||||||
|
const result = await response.json();
|
||||||
|
if (result.code === 0 && result.data) {
|
||||||
|
const select = document.getElementById('dimensionSelect');
|
||||||
|
select.innerHTML = '<option value="">请选择评测维度</option>' +
|
||||||
|
result.data.map(d => `<option value="${d.id}">${d.name} (${getDimensionTypeName(d.type)})</option>`).join('');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('加载评测维度失败:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取评测维度类型名称
|
||||||
|
function getDimensionTypeName(type) {
|
||||||
|
const typeMap = {
|
||||||
|
'classification': '分类',
|
||||||
|
'metric': '指标',
|
||||||
|
'text_similarity': '文本相似度'
|
||||||
|
};
|
||||||
|
return typeMap[type] || type || '未知';
|
||||||
|
}
|
||||||
|
|
||||||
// 提交表单
|
// 提交表单
|
||||||
async function submitForm() {
|
async function submitForm() {
|
||||||
const form = document.getElementById('evalForm');
|
const form = document.getElementById('evalForm');
|
||||||
@@ -518,6 +541,8 @@
|
|||||||
name: formData.get('name'),
|
name: formData.get('name'),
|
||||||
eval_type: formData.get('eval_type'),
|
eval_type: formData.get('eval_type'),
|
||||||
model_id: formData.get('model_id'),
|
model_id: formData.get('model_id'),
|
||||||
|
dataset_id: formData.get('dataset_id'),
|
||||||
|
eval_dimension: formData.get('eval_dimension'),
|
||||||
data_source: formData.get('data_source'),
|
data_source: formData.get('data_source'),
|
||||||
leaderboard: formData.get('leader') === 'on'
|
leaderboard: formData.get('leader') === 'on'
|
||||||
};
|
};
|
||||||
@@ -530,6 +555,14 @@
|
|||||||
showMessage('提示', '请选择评测模型', 'warning');
|
showMessage('提示', '请选择评测模型', 'warning');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!data.dataset_id) {
|
||||||
|
showMessage('提示', '请选择评测数据集', 'warning');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!data.eval_dimension) {
|
||||||
|
showMessage('提示', '请选择评测维度', 'warning');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE}/model-eval`, {
|
const response = await fetch(`${API_BASE}/model-eval`, {
|
||||||
|
|||||||
@@ -200,7 +200,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 加载评测维度数据
|
// 加载评测维度数据
|
||||||
async function loadDimensions() {
|
window.loadDimensions = async function() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE}/dimension`);
|
const response = await fetch(`${API_BASE}/dimension`);
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
@@ -263,30 +263,30 @@
|
|||||||
return 'bg-gray-50 text-gray-500';
|
return 'bg-gray-50 text-gray-500';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 操作函数
|
// 操作函数(挂载到 window 以便 onclick 调用)
|
||||||
function viewReport(id) {
|
window.viewReport = function(id) {
|
||||||
alert('查看报告功能开发中');
|
alert('查看报告功能开发中');
|
||||||
}
|
};
|
||||||
|
|
||||||
function deleteTask(id) {
|
window.deleteTask = function(id) {
|
||||||
if (confirm('确定要删除此评测任务吗?')) {
|
if (confirm('确定要删除此评测任务吗?')) {
|
||||||
alert('删除功能开发中');
|
alert('删除功能开发中');
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
function addDimension() {
|
window.addDimension = function() {
|
||||||
window.location.href = 'model-dimension-create.html';
|
window.location.href = 'model-dimension-create.html';
|
||||||
}
|
};
|
||||||
|
|
||||||
function editDimension(id) {
|
window.editDimension = function(id) {
|
||||||
alert('编辑维度功能开发中');
|
window.location.href = `model-dimension-create.html?id=${id}`;
|
||||||
}
|
};
|
||||||
|
|
||||||
async function deleteDimension(id) {
|
window.deleteDimension = function(id) {
|
||||||
showConfirm('确认删除', '确定要删除此评测维度吗?', () => {
|
showConfirm('确认删除', '确定要删除此评测维度吗?', () => {
|
||||||
executeDelete(id);
|
executeDelete(id);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
async function executeDelete(id) {
|
async function executeDelete(id) {
|
||||||
try {
|
try {
|
||||||
@@ -308,12 +308,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 切换到评测维度tab
|
// 切换到评测维度tab
|
||||||
function switchToDimensionsTab() {
|
window.switchToDimensionsTab = function() {
|
||||||
const dimBtn = document.querySelector('[data-tab="dimensions"]');
|
const dimBtn = document.querySelector('[data-tab="dimensions"]');
|
||||||
if (dimBtn) {
|
if (dimBtn) {
|
||||||
dimBtn.click();
|
dimBtn.click();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// 页面加载时初始化
|
// 页面加载时初始化
|
||||||
async function initPage() {
|
async function initPage() {
|
||||||
|
|||||||
Reference in New Issue
Block a user