Files
YG_FT_Platform/web/pages/model-eval-create.html
2026-01-19 11:33:22 +08:00

437 lines
23 KiB
HTML
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.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>新建评测 / 远光软件微调平台</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#1890ff',
sidebarBg: '#001529',
sidebarText: '#bfcbd9',
headerBg: '#fff',
danger: '#f5222d',
success: '#52c41a',
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
},
}
}
}
</script>
<style type="text/tailwindcss">
@layer utilities {
.sidebar-item-active {
@apply bg-primary/10 text-primary border-l-4 border-primary;
}
.sidebar-section-title {
@apply px-4 py-2 text-xs text-sidebarText/70 font-medium uppercase tracking-wider;
}
.form-select {
@apply w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:border-primary focus:outline-none transition-colors appearance-none bg-white;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
background-position: right 0.5rem center;
background-repeat: no-repeat;
background-size: 1.5em 1.5em;
padding-right: 2.5rem;
}
}
</style>
</head>
<body class="antialiased bg-gray-50 flex h-screen overflow-hidden">
<!-- 侧边导航 -->
<aside class="w-64 bg-sidebarBg text-sidebarText flex-shrink-0 hidden md:block flex flex-col h-full">
<!-- 平台LOGO区域 -->
<div class="p-4 border-b border-sidebarBg/30 flex items-center">
<img src="../assets/logo/logo.png" alt="Logo" class="w-6 h-6 object-contain mr-2">
<span class="text-white font-medium">远光软件微调平台</span>
</div>
<!-- 导航主区域 -->
<nav class="flex-1 overflow-y-auto py-2">
<!-- 第一分区:模型服务 -->
<div class="sidebar-section-title">模型服务</div>
<a href="main.html" data-page="fine-tune" class="nav-link flex items-center px-4 py-2.5 hover:bg-sidebarBg/20 transition-colors">
<i class="fa fa-cogs w-5 text-center"></i>
<span class="ml-2">模型调优</span>
</a>
<a href="main.html?page=my-models" data-page="my-models" class="nav-link flex items-center px-4 py-2.5 hover:bg-sidebarBg/20 transition-colors">
<i class="fa fa-database w-5 text-center"></i>
<span class="ml-2">我的模型</span>
</a>
<a href="main.html?page=model-eval" data-page="model-eval" class="nav-link flex items-center px-4 py-2.5 hover:bg-sidebarBg/20 transition-colors">
<i class="fa fa-line-chart w-5 text-center"></i>
<span class="ml-2">模型评测</span>
</a>
<a href="main.html?page=model-deploy" data-page="model-deploy" class="nav-link flex items-center px-4 py-2.5 hover:bg-sidebarBg/20 transition-colors">
<i class="fa fa-server w-5 text-center"></i>
<span class="ml-2">模型部署</span>
</a>
<!-- 第二分区:资源管理 -->
<div class="sidebar-section-title mt-6">资源管理</div>
<a href="main.html?page=model-manage" data-page="model-manage" class="nav-link flex items-center px-4 py-2.5 hover:bg-sidebarBg/20 transition-colors">
<i class="fa fa-cube w-5 text-center"></i>
<span class="ml-2">模型管理</span>
</a>
<a href="main.html?page=dataset-manage" data-page="dataset-manage" class="nav-link flex items-center px-4 py-2.5 hover:bg-sidebarBg/20 transition-colors">
<i class="fa fa-file-text w-5 text-center"></i>
<span class="ml-2">数据集管理</span>
</a>
<a href="main.html?page=data-generate" data-page="data-generate" class="nav-link flex items-center px-4 py-2.5 hover:bg-sidebarBg/20 transition-colors">
<i class="fa fa-database w-5 text-center"></i>
<span class="ml-2">其他工具</span>
</a>
<!-- 第三分区:系统设置 -->
<div class="sidebar-section-title mt-6">系统设置</div>
<a href="main.html?page=config" data-page="config" class="nav-link flex items-center px-4 py-2.5 hover:bg-sidebarBg/20 transition-colors">
<i class="fa fa-bar-chart w-5 text-center"></i>
<span class="ml-2">平台性能</span>
</a>
</nav>
<!-- 底部信息区域 -->
<div class="p-4 border-t border-sidebarBg/30 text-xs mt-auto">
<div class="mb-2 text-sidebarText/80">默认业务空间</div>
<div class="flex items-center justify-between">
<span class="text-sidebarText">版本 v1.0.0</span>
<i class="fa fa-question-circle-o text-sidebarText/70"></i>
</div>
</div>
</aside>
<!-- 主内容区 -->
<div class="flex-1 flex flex-col overflow-hidden">
<!-- 顶部导航 -->
<header class="bg-headerBg border-b border-gray-200 shadow-sm">
<div class="flex items-center justify-between px-6 h-14">
<div class="flex items-center space-x-4">
<a href="main.html?page=model-eval" class="text-gray-500 hover:text-gray-700 flex items-center">
<i class="fa fa-arrow-left"></i>
<span class="ml-1">上一步</span>
</a>
</div>
<div class="flex items-center space-x-4">
<div class="relative group">
<img src="https://picsum.photos/id/1005/32/32" class="w-8 h-8 rounded-full cursor-pointer" alt="用户头像">
<div class="absolute right-0 top-full mt-2 bg-white rounded shadow-lg py-1 hidden group-hover:block border border-gray-100 min-w-[140px]">
<a href="login.html" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 whitespace-nowrap">
<i class="fa fa-sign-out mr-1"></i>退出登录
</a>
</div>
</div>
</div>
</div>
</header>
<!-- 内容区域 -->
<main class="flex-1 overflow-y-auto p-6 bg-gray-50">
<!-- 页面标题 -->
<div class="bg-white rounded-lg shadow-sm p-4 border-b border-gray-100 mb-4">
<div class="flex items-center text-sm">
<span class="text-primary cursor-pointer hover:underline" onclick="window.location.href='main.html?page=model-eval'">模型评测</span>
<span class="mx-2 text-gray-300">/</span>
<span class="text-gray-800 font-medium">新建评测</span>
</div>
</div>
<!-- 表单内容 -->
<div class="bg-white rounded-lg shadow-sm">
<div class="p-6">
<form id="evalForm">
<!-- 任务名称 -->
<div class="mb-6">
<label class="form-label">
<span class="text-red-500 mr-1">*</span>任务名称
</label>
<div class="flex items-center">
<input type="text" name="name" id="taskName" class="flex-1 px-3 py-2 border border-gray-300 rounded-lg text-sm focus:border-primary focus:outline-none" placeholder="请输入任务名称" maxlength="50">
<span class="text-xs text-gray-400 ml-2"><span id="nameCount">0</span> / 50</span>
</div>
</div>
<!-- 评测方式 -->
<div class="mb-6">
<label class="form-label">
<span class="text-red-500 mr-1">*</span>评测方式
</label>
<div class="grid grid-cols-2 gap-4">
<label class="border-2 border-primary bg-blue-50 rounded-lg p-4 cursor-pointer" id="customEvalLabel">
<input type="radio" name="eval_type" value="custom" checked class="text-primary focus:ring-primary sr-only" onchange="toggleEvalType('custom')">
<div class="font-medium text-gray-800">自定义评测</div>
<p class="text-xs text-gray-500 mt-1">支持基于AI评测、自动化指标计算、人工评测方式<br>自定义评测维度,可自由组合上述各类维度进行评测。</p>
</label>
<label class="border border-gray-200 rounded-lg p-4 cursor-pointer hover:border-primary/50" id="baselineEvalLabel">
<input type="radio" name="eval_type" value="baseline" class="text-primary focus:ring-primary sr-only" onchange="toggleEvalType('baseline')">
<div class="font-medium text-gray-800">基线评测</div>
<p class="text-xs text-gray-500 mt-1">通过预置基线评测集,评测模型基本能力,自动生成评测报告</p>
</label>
</div>
</div>
<!-- 评测对象 -->
<div class="mb-6">
<h3 class="text-sm font-semibold text-gray-700 mb-4 pb-2 border-b border-gray-100">评测对象</h3>
<div class="max-w-md">
<!-- 评测模型 -->
<div class="mb-4">
<label class="block text-sm text-gray-600 mb-1">
<span class="text-red-500 mr-1">*</span>评测模型
</label>
<select name="model_id" id="modelSelect" class="form-select flex-1 max-w-md">
<option value="">请选择</option>
</select>
</div>
<!-- 数据来源 -->
<div class="mb-4">
<label class="block text-sm text-gray-600 mb-2">
<span class="text-red-500 mr-1">*</span>数据来源
</label>
<div class="flex items-center space-x-6">
<label class="flex items-center cursor-pointer">
<input type="radio" name="data_source" value="dataset" class="mr-2" onchange="toggleDataSource('dataset')">
<span class="text-sm text-gray-700">评测数据集</span>
</label>
<label class="flex items-center cursor-pointer">
<input type="radio" name="data_source" value="inference" checked class="mr-2" onchange="toggleDataSource('inference')">
<span class="text-sm text-gray-700">推理结果集</span>
</label>
</div>
</div>
<!-- 推理结果集上传 -->
<div id="inferenceUpload" class="border-2 border-dashed border-gray-200 rounded-lg p-8 text-center hover:border-primary/50 transition-colors cursor-pointer">
<i class="fa fa-cloud-upload text-gray-400 text-xl mb-2"></i>
<p class="text-gray-700 text-sm">点击或拖拽上传推理结果集</p>
<p class="text-xs text-gray-400 mt-1">支持 .xls .xlsx 格式不超过2MB</p>
<a href="#" class="text-primary text-xs mt-2 inline-block hover:underline">下载模板</a>
</div>
</div>
</div>
<!-- 评测数据集选择 -->
<div id="datasetSelect" class="hidden mb-6">
<h3 class="text-sm font-semibold text-gray-700 mb-4 pb-2 border-b border-gray-100">评测数据集</h3>
<div class="flex items-center">
<select name="dataset_id" class="form-select flex-1 max-w-md">
<option value="">请选择评测数据集</option>
</select>
<button type="button" class="ml-2 text-primary text-sm flex items-center hover:text-primary/80">
<i class="fa fa-refresh"></i>
</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" onclick="window.location.href='dataset-create.html'">
+ 新增数据集
</button>
</div>
</div>
<!-- 评测规则 -->
<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>
<div class="flex items-center">
<select name="eval_dimension" class="form-select flex-1 max-w-md">
<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>
<button type="button" class="ml-2 text-primary text-sm flex items-center hover:text-primary/80">
<i class="fa fa-refresh"></i>
</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>
</div>
</div>
<!-- Leaderboard -->
<div class="mb-6">
<h3 class="text-sm font-semibold text-gray-700 mb-4 pb-2 border-b border-gray-100">Leaderboard</h3>
<div class="flex items-center">
<label class="text-gray-700 mr-4">是否参与排行</label>
<div class="relative inline-block w-10 h-5">
<input type="checkbox" name="leaderboard" class="opacity-0 w-0 h-0" onchange="toggleLeaderboard(this)">
<div class="bg-gray-200 rounded-full absolute inset-0 peer-focus:ring-2 peer-focus:ring-primary/30"></div>
<div class="bg-white w-4 h-4 rounded-full absolute left-0.5 top-0.5 transition-transform" id="leaderboardToggle"></div>
</div>
</div>
</div>
<!-- 底部操作 -->
<div class="flex justify-between items-center pt-6 border-t border-gray-100">
<div class="flex items-center space-x-3">
<button type="button" onclick="submitForm()" class="px-4 py-2 bg-primary text-white rounded-lg text-sm hover:bg-primary/90">
开始评测
</button>
<a href="main.html?page=model-eval" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-lg text-sm hover:bg-gray-300">
取消
</a>
</div>
<div class="text-gray-400 text-xs">
费用 以实际发生为准 <a href="#" class="text-primary hover:underline">计算详情</a>
</div>
</div>
</form>
</div>
</div>
</main>
</div>
<script>
// API 基础地址
const getApiBase = () => {
const protocol = window.location.protocol;
const hostname = window.location.hostname;
return `${protocol}//${hostname}:8080/api`;
};
const API_BASE = getApiBase();
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function() {
// 任务名称字数统计
const nameInput = document.getElementById('taskName');
nameInput.addEventListener('input', () => {
document.getElementById('nameCount').textContent = nameInput.value.length;
});
// 初始化评测方式样式
updateEvalTypeStyle('custom');
// 加载模型列表
loadModels();
// 绑定导航点击事件
document.querySelectorAll('.nav-link').forEach(link => {
link.addEventListener('click', function(e) {
if (!this.href.includes('model-eval-create')) {
e.preventDefault();
window.location.href = this.href;
}
});
});
});
// 切换评测方式
function toggleEvalType(type) {
updateEvalTypeStyle(type);
const rulesSection = document.getElementById('evalRulesSection');
if (type === 'baseline') {
rulesSection.classList.add('hidden');
} else {
rulesSection.classList.remove('hidden');
}
}
function updateEvalTypeStyle(type) {
const customLabel = document.getElementById('customEvalLabel');
const baselineLabel = document.getElementById('baselineEvalLabel');
if (type === 'custom') {
customLabel.classList.add('border-primary', 'bg-blue-50');
customLabel.classList.remove('border-gray-200');
baselineLabel.classList.remove('border-primary', 'bg-blue-50');
baselineLabel.classList.add('border-gray-200');
} else {
baselineLabel.classList.add('border-primary', 'bg-blue-50');
baselineLabel.classList.remove('border-gray-200');
customLabel.classList.remove('border-primary', 'bg-blue-50');
customLabel.classList.add('border-gray-200');
}
}
// 切换数据来源
function toggleDataSource(source) {
const inferenceUpload = document.getElementById('inferenceUpload');
const datasetSelect = document.getElementById('datasetSelect');
if (source === 'inference') {
inferenceUpload.classList.remove('hidden');
datasetSelect.classList.add('hidden');
} else {
inferenceUpload.classList.add('hidden');
datasetSelect.classList.remove('hidden');
}
}
// 切换Leaderboard开关样式
function toggleLeaderboard(checkbox) {
const toggle = document.getElementById('leaderboardToggle');
if (checkbox.checked) {
toggle.style.transform = 'translateX(20px)';
toggle.previousElementSibling.classList.remove('bg-gray-200');
toggle.previousElementSibling.classList.add('bg-primary');
} else {
toggle.style.transform = 'translateX(0)';
toggle.previousElementSibling.classList.remove('bg-primary');
toggle.previousElementSibling.classList.add('bg-gray-200');
}
}
// 加载模型列表
async function loadModels() {
try {
const response = await fetch(`${API_BASE}/my-models`);
const result = await response.json();
if (result.code === 0) {
const select = document.getElementById('modelSelect');
select.innerHTML = '<option value="">请选择</option>' +
result.data.map(m => `<option value="${m.id}">${m.name}</option>`).join('');
}
} catch (e) {
console.error('加载模型失败:', e);
}
}
// 提交表单
async function submitForm() {
const form = document.getElementById('evalForm');
const formData = new FormData(form);
const data = {
name: formData.get('name'),
eval_type: formData.get('eval_type'),
model_id: formData.get('model_id'),
data_source: formData.get('data_source'),
leaderboard: formData.get('leader') === 'on'
};
if (!data.name) {
alert('请输入任务名称');
return;
}
if (!data.model_id) {
alert('请选择评测模型');
return;
}
try {
const response = await fetch(`${API_BASE}/model-eval`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
const result = await response.json();
if (result.code === 0) {
alert('创建成功!');
window.location.href = 'main.html?page=model-eval';
} else {
alert(result.message || '创建失败');
}
} catch (error) {
alert('创建失败: ' + error.message);
}
}
</script>
</body>
</html>