// 标签切换功能 function openTab(evt, tabName) { var i, tabContent, tabLinks; tabContent = document.getElementsByClassName("tab-content"); for (i = 0; i < tabContent.length; i++) { tabContent[i].classList.add("hidden"); } tabLinks = document.getElementsByClassName("tab"); for (i = 0; i < tabLinks.length; i++) { tabLinks[i].classList.remove("active"); } document.getElementById(tabName).classList.remove("hidden"); evt.currentTarget.classList.add("active"); // 当切换到其他标签页时,清除所有日志自动更新定时器 if (tabName !== 'processes') { for (let processId in logTimers) { clearInterval(logTimers[processId]); delete logTimers[processId]; } } // 如果切换到进程页面,刷新进程列表 if (tabName === 'processes') { loadProcesses(); } else if (tabName === 'logfiles') { loadLogFiles(); } } // 根据训练类型显示/隐藏特定参数 document.getElementById('train_type').addEventListener('change', function() { const trainType = this.value; const pretrainSftFields = document.querySelectorAll('.pretrain-sft'); const loraFields = document.querySelectorAll('.lora'); const dpoFields = document.querySelectorAll('.dpo'); const dpoParamCard = document.querySelector('.parameter-card.dpo'); pretrainSftFields.forEach(field => { field.style.display = (trainType === 'pretrain' || trainType === 'sft') ? 'block' : 'none'; }); loraFields.forEach(field => { field.style.display = trainType === 'lora' ? 'block' : 'none'; }); dpoFields.forEach(field => { field.style.display = trainType === 'dpo' ? 'block' : 'none'; }); if (dpoParamCard) { dpoParamCard.style.display = trainType === 'dpo' ? 'block' : 'none'; } // 设置默认值 if (trainType === 'pretrain') { document.getElementById('save_dir').value = '../out'; document.getElementById('save_weight').value = 'pretrain'; document.getElementById('epochs').value = '1'; document.getElementById('batch_size').value = '32'; document.getElementById('learning_rate').value = '5e-4'; document.getElementById('data_path').value = '../dataset/pretrain_hq.jsonl'; document.getElementById('from_weight').value = 'none'; document.getElementById('log_interval').value = '100'; document.getElementById('save_interval').value = '100'; } else if (trainType === 'sft') { document.getElementById('save_dir').value = '../out'; document.getElementById('save_weight').value = 'full_sft'; document.getElementById('epochs').value = '2'; document.getElementById('batch_size').value = '16'; document.getElementById('learning_rate').value = '5e-7'; document.getElementById('data_path').value = '../dataset/sft_mini_512.jsonl'; document.getElementById('from_weight').value = 'pretrain'; document.getElementById('log_interval').value = '100'; document.getElementById('save_interval').value = '100'; } else if (trainType === 'lora') { document.getElementById('save_dir').value = '../out/lora'; document.getElementById('lora_name').value = 'lora_identity'; document.getElementById('epochs').value = '50'; document.getElementById('batch_size').value = '32'; document.getElementById('learning_rate').value = '1e-4'; document.getElementById('data_path').value = '../dataset/lora_identity.jsonl'; document.getElementById('from_weight').value = 'full_sft'; document.getElementById('log_interval').value = '10'; document.getElementById('save_interval').value = '1'; } else if (trainType === 'dpo') { document.getElementById('save_dir').value = '../out'; document.getElementById('save_weight').value = 'dpo'; document.getElementById('epochs').value = '1'; document.getElementById('batch_size').value = '4'; document.getElementById('learning_rate').value = '4e-8'; document.getElementById('data_path').value = '../dataset/dpo.jsonl'; document.getElementById('from_weight').value = 'full_sft'; document.getElementById('log_interval').value = '100'; document.getElementById('save_interval').value = '100'; document.getElementById('beta').value = '0.1'; } }); // 初始触发一次change事件以设置默认值 document.getElementById('train_type').dispatchEvent(new Event('change')); // 加载进程列表 function loadProcesses() { fetch('/processes') .then(response => response.json()) .then(data => { const processList = document.getElementById('process-list'); processList.innerHTML = ''; if (data.length === 0) { processList.innerHTML = '
暂无训练进程
'; return; } data.forEach(process => { const processItem = document.createElement('div'); processItem.className = 'process-item'; let statusClass = ''; // 根据后端返回的status字段设置状态类 if (process.status === '运行中') { statusClass = 'status-running'; } else if (process.status === '手动停止') { statusClass = 'status-manual-stop'; } else if (process.status === '出错') { statusClass = 'status-error'; } else { statusClass = 'status-completed'; } // 设置进程数据属性,用于后续检查状态 processItem.dataset.processId = process.id; processItem.dataset.processStatus = process.status; processItem.innerHTML = `暂无日志文件
'; return; } // 按日期倒序排序 data.sort((a, b) => new Date(b.modified_time) - new Date(a.modified_time)); data.forEach(logfile => { const fileItem = document.createElement('div'); fileItem.className = 'process-item'; // 从文件名提取训练类型 let trainType = '未知'; if (logfile.filename.includes('train_pretrain_')) { trainType = 'pretrain'; } else if (logfile.filename.includes('train_sft_')) { trainType = 'sft'; } else if (logfile.filename.includes('train_lora_')) { trainType = 'lora'; } else if (logfile.filename.includes('train_dpo_')) { trainType = 'dpo'; } else if (logfile.filename.includes('train_ppo_')) { trainType = 'ppo'; } else if (logfile.filename.includes('train_grpo_')) { trainType = 'grpo'; } else if (logfile.filename.includes('train_spo_')) { trainType = 'spo'; } fileItem.innerHTML = `