From 826a1fbe1e0cee066225ae884de1afa925db21cc Mon Sep 17 00:00:00 2001 From: wangyuzhan Date: Fri, 21 Nov 2025 17:44:24 +0800 Subject: [PATCH] add process step --- trainer_web/static/js/processes/list.js | 62 ++++++++++++++++-- trainer_web/train_web_ui.py | 84 +++++++++++++++++++------ trainer_web/training_processes.json | 1 + 3 files changed, 122 insertions(+), 25 deletions(-) create mode 100644 trainer_web/training_processes.json diff --git a/trainer_web/static/js/processes/list.js b/trainer_web/static/js/processes/list.js index 5d3ea58..551c1ad 100644 --- a/trainer_web/static/js/processes/list.js +++ b/trainer_web/static/js/processes/list.js @@ -68,7 +68,11 @@ function calculateProgress(process) { remaining: process.progress.remaining_time || '计算中...', loss: process.progress.current_loss || null, epoch: process.progress.current_epoch ? `${process.progress.current_epoch}/${process.progress.total_epochs}` : null, - lr: process.progress.current_lr || null + lr: process.progress.current_lr || null, + step: process.progress.current_step && process.progress.total_steps ? + `${process.progress.current_step}/${process.progress.total_steps}` : null, + currentStep: process.progress.current_step || 0, + totalSteps: process.progress.total_steps || 0 }; } @@ -88,6 +92,9 @@ function calculateProgress(process) { let current = 0; let total = 0; let percentage = 0; + let currentStep = 0; + let totalSteps = 0; + let stepInfo = null; for (const pattern of epochPatterns) { const match = logText.match(pattern); @@ -99,6 +106,28 @@ function calculateProgress(process) { } } + // 提取step信息 - 支持多种格式 + const stepPatterns = [ + /step\s+(\d+)\s*\/\s*(\d+)/i, // step 150/1000 + /Step\s+(\d+)\s*of\s*(\d+)/i, // Step 150 of 1000 + /\[(\d+)\/(\d+)\]/i, // [150/1000] + /step\s*[::]\s*(\d+)\s*\/\s*(\d+)/i, // step: 150/1000 + /第\s*(\d+)\s*步\s*\/\s*共\s*(\d+)\s*步/i, // 第150步/共1000步 + /步数\s*(\d+)\s*\/\s*(\d+)/i, // 步数 150/1000 + /batch\s+(\d+)\s*\/\s*(\d+)/i, // batch 150/1000 + /Batch\s+(\d+)\s*of\s*(\d+)/i // Batch 150 of 1000 + ]; + + for (const pattern of stepPatterns) { + const match = logText.match(pattern); + if (match) { + currentStep = parseInt(match[1]); + totalSteps = parseInt(match[2]); + stepInfo = `${currentStep}/${totalSteps}`; + break; + } + } + // 提取loss信息 - 支持多种格式 const lossPatterns = [ /loss[\s:=]\s*([\d.]+(?:e[+-]?\d+)?)/i, // loss: 4.32 or loss = 4.32 @@ -149,14 +178,29 @@ function calculateProgress(process) { // 如果找到了有效的epoch信息,返回进度 if (total > 0) { + // 重新计算百分比 - 支持epoch和step双重进度 + let finalPercentage = percentage; + if (totalSteps > 0 && currentStep > 0) { + // 基础epoch进度 + const epochPercentage = (current / total) * 100; + // 当前epoch内的step进度 + const stepPercentageInEpoch = (currentStep / totalSteps) * 100; + // 将step进度加到epoch进度上(每个epoch占总进度的1/total) + const stepContribution = stepPercentageInEpoch / total; + finalPercentage = Math.min(100, Math.max(0, Math.round(epochPercentage + stepContribution))); + } + return { - percentage, + percentage: finalPercentage, current, total, remaining: calculateRemainingTime(current, total, logText), loss: currentLoss, epoch: `${current}/${total}`, - lr: currentLr + lr: currentLr, + step: stepInfo, + currentStep, + totalSteps }; } } @@ -321,12 +365,13 @@ export function addProcessItemToGroup(parent, process) {
- 进度: ${progressInfo.current}/${progressInfo.total} + 进度: ${progressInfo.current}/${progressInfo.total}${progressInfo.step ? ` (${progressInfo.step})` : ''} 剩余时间: ${progressInfo.remaining}
${progressInfo.loss ? `
Loss:${progressInfo.loss}
` : ''} ${progressInfo.epoch ? `
Epoch:${progressInfo.epoch}
` : ''} + ${progressInfo.step ? `
Step:${progressInfo.step}
` : ''} ${progressInfo.lr ? `
LR:${progressInfo.lr}
` : ''}
@@ -379,7 +424,8 @@ export function updateProcessProgress(item, process) { } if (progressText) { - progressText.textContent = `进度: ${progressInfo.current}/${progressInfo.total}`; + const stepText = progressInfo.step ? ` (${progressInfo.step})` : ''; + progressText.textContent = `进度: ${progressInfo.current}/${progressInfo.total}${stepText}`; } if (remainingText) { @@ -390,7 +436,8 @@ export function updateProcessProgress(item, process) { // 更新指标 - 只更新有变化的值来减少DOM操作 const lossItem = metricsContainer.querySelector('.metric-item:nth-child(1) .metric-value'); const epochItem = metricsContainer.querySelector('.metric-item:nth-child(2) .metric-value'); - const lrItem = metricsContainer.querySelector('.metric-item:nth-child(3) .metric-value'); + const stepItem = metricsContainer.querySelector('.metric-item:nth-child(3) .metric-value'); + const lrItem = metricsContainer.querySelector('.metric-item:nth-child(4) .metric-value'); if (progressInfo.loss && lossItem) { lossItem.textContent = progressInfo.loss; @@ -398,6 +445,9 @@ export function updateProcessProgress(item, process) { if (progressInfo.epoch && epochItem) { epochItem.textContent = progressInfo.epoch; } + if (progressInfo.step && stepItem) { + stepItem.textContent = progressInfo.step; + } if (progressInfo.lr && lrItem) { lrItem.textContent = progressInfo.lr; } diff --git a/trainer_web/train_web_ui.py b/trainer_web/train_web_ui.py index f1cea06..4589d40 100644 --- a/trainer_web/train_web_ui.py +++ b/trainer_web/train_web_ui.py @@ -40,6 +40,8 @@ def calculate_training_progress(process_id, process_info): 'percentage': 0, 'current_epoch': 0, 'total_epochs': 0, + 'current_step': 0, + 'total_steps': 0, 'remaining_time': '计算中...', 'current_loss': None, 'current_lr': None @@ -110,6 +112,26 @@ def calculate_training_progress(process_id, process_info): total_epochs = int(match.group(2)) break + # 提取step信息 - 支持多种格式 + # 格式: step 150/1000, Step 150 of 1000, [150/1000], step: 150/1000 + step_patterns = [ + r'step\s+(\d+)\s*/\s*(\d+)', + r'Step\s+(\d+)\s*of\s*(\d+)', + r'\[(\d+)/(\d+)\]', + r'step\s*[::]\s*(\d+)\s*/\s*(\d+)', + r'第\s*(\d+)\s*步\s*/\s*共\s*(\d+)\s*步', + r'步数\s*(\d+)\s*/\s*(\d+)', + r'batch\s+(\d+)\s*/\s*(\d+)', # 也支持batch格式 + r'Batch\s+(\d+)\s*of\s*(\d+)' + ] + + for pattern in step_patterns: + match = re.search(pattern, line, re.IGNORECASE) + if match: + progress['current_step'] = int(match.group(1)) + progress['total_steps'] = int(match.group(2)) + break + # 提取loss信息 - 支持多种格式 if not current_loss: # 格式: loss: 4.32, training_loss: 4.32, train_loss: 4.32, Loss: 4.32, 训练损失: 4.32 @@ -157,10 +179,29 @@ def calculate_training_progress(process_id, process_info): if total_epochs and current_loss and current_lr: break - # 计算进度百分比 + # 计算进度百分比 - 支持epoch和step双重进度 percentage = 0 if total_epochs > 0: - percentage = min(100, max(0, int((current_epoch / total_epochs) * 100))) + # 基础epoch进度 + epoch_percentage = (current_epoch / total_epochs) * 100 + + # 如果有step信息,在当前epoch内计算step进度 + if progress['total_steps'] > 0 and progress['current_step'] > 0: + # 计算当前epoch内的step进度 + step_percentage_in_epoch = (progress['current_step'] / progress['total_steps']) * 100 + # 将step进度加到epoch进度上(每个epoch占总进度的1/total_epochs) + step_contribution = step_percentage_in_epoch / total_epochs + percentage = min(100, max(0, int(epoch_percentage + step_contribution))) + else: + # 只有epoch信息的传统计算方式 + percentage = min(100, max(0, int(epoch_percentage))) + + # 更新进度字典 + progress['percentage'] = percentage + progress['current_epoch'] = current_epoch + progress['total_epochs'] = total_epochs + progress['current_loss'] = current_loss + progress['current_lr'] = current_lr # 估算剩余时间(增强计算) remaining_time = '计算中...' @@ -398,7 +439,7 @@ def add_test_process(): process_id = f"test_process_{int(time.time())}" - # 创建测试训练命令 + # 创建测试训练命令 - 包含step进度 test_command = [ 'python', '-c', ''' import time @@ -416,23 +457,28 @@ print("2024-11-21 14:30:02 - Model initialized with 108M parameters") sys.stdout.flush() time.sleep(2) -for epoch in range(1, 6): - print(f"2024-11-21 14:30:{5 + epoch*5} - Starting epoch {epoch}/5") - sys.stdout.flush() - time.sleep(1) - - loss = 4.5 - epoch * 0.3 - lr = 1e-4 * (0.9 ** epoch) - print(f"2024-11-21 14:30:{6 + epoch*5} - Loss: {loss:.4f}, lr: {lr:.2e}") - sys.stdout.flush() - time.sleep(2) - - remaining = (5 - epoch) * 15 - print(f"2024-11-21 14:30:{8 + epoch*5} - Epoch {epoch}/5 completed, remaining: 0:0{remaining}:00") - sys.stdout.flush() - time.sleep(1) +# 测试单epoch但多step的情况 +print("2024-11-21 14:30:03 - Starting epoch 1/1") +sys.stdout.flush() +time.sleep(1) -print("2024-11-21 14:30:35 - Training completed successfully") +total_steps = 20 +for step in range(1, total_steps + 1): + # 模拟step进度 + if step % 5 == 0 or step == total_steps: + print(f"2024-11-21 14:30:{4 + step} - Step {step}/{total_steps}") + sys.stdout.flush() + + # 模拟训练过程 + loss = 4.5 - step * 0.1 + lr = 1e-4 * (0.95 ** step) + if step % 3 == 0: + print(f"2024-11-21 14:30:{4 + step} - Loss: {loss:.4f}, lr: {lr:.2e}") + sys.stdout.flush() + + time.sleep(0.5) + +print("2024-11-21 14:30:25 - Training completed successfully") sys.stdout.flush() ''' ] diff --git a/trainer_web/training_processes.json b/trainer_web/training_processes.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/trainer_web/training_processes.json @@ -0,0 +1 @@ +{} \ No newline at end of file