1. 新增了日志系统
2. 新增了添加新训练选择对应的GPU
This commit is contained in:
@@ -225,6 +225,18 @@
|
||||
<div class="mb-6">
|
||||
<h3 class="text-sm font-semibold text-gray-700 mb-4 pb-2 border-b border-gray-100">训练配置</h3>
|
||||
|
||||
<!-- GPU硬件选择 -->
|
||||
<div class="mb-6">
|
||||
<label class="block text-sm text-gray-600 mb-3">
|
||||
<span class="text-red-500 mr-1">*</span>GPU硬件选择
|
||||
</label>
|
||||
<div id="gpuSelectionArea" class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||
<!-- GPU列表将通过JS动态加载 -->
|
||||
<div class="text-sm text-gray-400 col-span-full">正在加载GPU设备...</div>
|
||||
</div>
|
||||
<p class="text-xs text-gray-400 mt-2">支持选择多个GPU进行训练(多卡训练)</p>
|
||||
</div>
|
||||
|
||||
<!-- 训练方式 -->
|
||||
<div class="mb-6">
|
||||
<label class="block text-sm text-gray-600 mb-3">训练方式</label>
|
||||
@@ -627,6 +639,9 @@
|
||||
// 初始化训练方法参数显示
|
||||
toggleTrainMethod();
|
||||
|
||||
// 加载GPU列表
|
||||
loadGPUList();
|
||||
|
||||
// 设置侧边栏当前页高亮
|
||||
const currentPage = 'fine-tune';
|
||||
document.querySelectorAll('.nav-link').forEach(link => {
|
||||
@@ -790,17 +805,113 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 加载GPU列表
|
||||
async function loadGPUList() {
|
||||
const container = document.getElementById('gpuSelectionArea');
|
||||
if (!container) return;
|
||||
|
||||
try {
|
||||
// 模拟GPU数据 - 实际项目中可以从API获取
|
||||
const gpuData = await fetchGPUs();
|
||||
renderGPUList(gpuData);
|
||||
} catch (error) {
|
||||
console.error('加载GPU列表失败:', error);
|
||||
container.innerHTML = '<div class="text-sm text-red-500 col-span-full">加载GPU设备失败,请刷新重试</div>';
|
||||
}
|
||||
}
|
||||
|
||||
// 获取GPU数据(模拟数据,实际可从API获取)
|
||||
async function fetchGPUs() {
|
||||
// 实际项目中可以调用后端API获取GPU信息
|
||||
// const response = await fetch(`${API_BASE}/gpus`);
|
||||
// return await response.json();
|
||||
|
||||
// 模拟GPU数据
|
||||
return [
|
||||
{ id: 'gpu0', name: 'NVIDIA A100 80GB', memory: '80GB', cuda_cores: 6912, available: true },
|
||||
{ id: 'gpu1', name: 'NVIDIA A100 80GB', memory: '80GB', cuda_cores: 6912, available: true },
|
||||
{ id: 'gpu2', name: 'NVIDIA A100 40GB', memory: '40GB', cuda_cores: 6912, available: true },
|
||||
{ id: 'gpu3', name: 'NVIDIA A100 40GB', memory: '40GB', cuda_cores: 6912, available: false },
|
||||
{ id: 'gpu4', name: 'NVIDIA V100 32GB', memory: '32GB', cuda_cores: 5120, available: true },
|
||||
{ id: 'gpu5', name: 'NVIDIA V100 16GB', memory: '16GB', cuda_cores: 5120, available: false },
|
||||
{ id: 'gpu6', name: 'NVIDIA RTX 3090', memory: '24GB', cuda_cores: 10496, available: true },
|
||||
{ id: 'gpu7', name: 'NVIDIA RTX 4090', memory: '24GB', cuda_cores: 16384, available: true }
|
||||
];
|
||||
}
|
||||
|
||||
// 渲染GPU列表(点击卡片选中,无需复选框)
|
||||
function renderGPUList(gpus) {
|
||||
const container = document.getElementById('gpuSelectionArea');
|
||||
if (!container) return;
|
||||
|
||||
container.innerHTML = gpus.map(gpu => `
|
||||
<div id="gpu_card_${gpu.id}"
|
||||
class="gpu-card ${!gpu.available ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer hover:border-primary'} border rounded-lg p-3 transition-all"
|
||||
onclick="toggleGPUSelection('${gpu.id}')"
|
||||
${!gpu.available ? 'title="该GPU不可用"' : ''}
|
||||
data-gpu-id="${gpu.id}">
|
||||
<div class="flex items-center">
|
||||
<i class="fa fa-microchip text-primary mr-2"></i>
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm font-medium text-gray-700">${gpu.name}</span>
|
||||
${gpu.available
|
||||
? '<i class="fa fa-check-circle text-green-600 text-xs"></i>'
|
||||
: '<i class="fa fa-times-circle text-red-500 text-xs"></i>'}
|
||||
</div>
|
||||
<div class="text-xs text-gray-500 mt-1">
|
||||
<span class="mr-2"><i class="fa fa-floppy-o mr-1"></i>${gpu.memory}</span>
|
||||
<span><i class="fa fa-cog mr-1"></i>${gpu.cuda_cores} CUDA</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
// 切换GPU选择状态
|
||||
function toggleGPUSelection(gpuId) {
|
||||
const card = document.getElementById(`gpu_card_${gpuId}`);
|
||||
if (!card || card.classList.contains('opacity-50')) return;
|
||||
|
||||
// 切换选中状态
|
||||
if (card.classList.contains('border-primary')) {
|
||||
// 取消选中
|
||||
card.classList.remove('border-primary', 'bg-blue-50');
|
||||
card.querySelector('.fa-check-circle').classList.replace('text-primary', 'text-green-600');
|
||||
} else {
|
||||
// 选中
|
||||
card.classList.add('border-primary', 'bg-blue-50');
|
||||
// 移除检查图标,添加选中标记
|
||||
const icon = card.querySelector('.fa-check-circle');
|
||||
if (icon) {
|
||||
icon.classList.remove('fa-check-circle', 'text-green-600');
|
||||
icon.classList.add('fa-check', 'text-primary');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取选中的GPU列表
|
||||
function getSelectedGPUs() {
|
||||
const cards = document.querySelectorAll('.gpu-card.border-primary');
|
||||
return Array.from(cards).map(card => card.dataset.gpuId);
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
async function submitForm() {
|
||||
const form = document.getElementById('createForm');
|
||||
const formData = new FormData(form);
|
||||
const validSplit = formData.get('valid_split');
|
||||
|
||||
// 获取选中的GPU
|
||||
const selectedGPUs = getSelectedGPUs();
|
||||
|
||||
const data = {
|
||||
name: formData.get('name'),
|
||||
base_model: formData.get('base_model'),
|
||||
train_type: formData.get('train_type'),
|
||||
train_method: formData.get('train_method'),
|
||||
gpus: selectedGPUs, // 添加GPU选择
|
||||
train_dataset_id: formData.get('train_dataset_id'),
|
||||
valid_split: validSplit,
|
||||
valid_ratio: parseInt(formData.get('valid_ratio')) || 10,
|
||||
@@ -814,6 +925,10 @@
|
||||
showMessage('提示', '请输入任务名称', 'warning');
|
||||
return;
|
||||
}
|
||||
if (selectedGPUs.length === 0) {
|
||||
showMessage('提示', '请选择至少一个GPU硬件', 'warning');
|
||||
return;
|
||||
}
|
||||
if (!data.base_model) {
|
||||
showMessage('提示', '请选择基础模型', 'warning');
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user