202 lines
8.1 KiB
JavaScript
202 lines
8.1 KiB
JavaScript
/**
|
||
* 训练服务模块
|
||
* 处理训练任务相关的操作和进度跟踪
|
||
*/
|
||
|
||
// 训练进度缓存
|
||
window.trainingProgressCache = window.trainingProgressCache || {};
|
||
// 使用 window 避免重复声明
|
||
if (typeof window._progressRefreshTimer === 'undefined') {
|
||
window._progressRefreshTimer = null;
|
||
}
|
||
|
||
// 渲染训练进度
|
||
function renderTrainingProgress(val, row) {
|
||
const progressData = window.trainingProgressCache[row.id];
|
||
if (progressData && progressData.status === 'running') {
|
||
if (progressData.progress > 0) {
|
||
return `
|
||
<div class="flex flex-col">
|
||
<span class="text-sm font-medium text-primary">${progressData.progress}%</span>
|
||
<span class="text-xs text-gray-500">${progressData.step || ''} ${progressData.speed || ''}</span>
|
||
<span class="text-xs text-gray-400">ETA: ${progressData.eta || '--:--'}</span>
|
||
</div>
|
||
`;
|
||
}
|
||
}
|
||
return `${val || 0}%`;
|
||
}
|
||
|
||
// 刷新训练进度
|
||
async function refreshTrainingProgress() {
|
||
if (typeof window.currentPage !== 'string' || window.currentPage !== 'fine-tune') return;
|
||
|
||
try {
|
||
const response = await fetch(`${window.API_BASE}/fine-tune`);
|
||
const result = await response.json();
|
||
|
||
if (result.code === 0 && result.data) {
|
||
// 刷新运行中或已完成的任务(有进度信息)
|
||
const activeTasks = result.data.filter(task =>
|
||
task.status === 'running' || task.status === 'pending'
|
||
);
|
||
|
||
for (const task of activeTasks) {
|
||
try {
|
||
// 并行获取进度和PID状态
|
||
const [progressResponse, statusResponse] = await Promise.all([
|
||
fetch(`${window.API_BASE}/fine-tune/progress/${task.id}`),
|
||
fetch(`${window.API_BASE}/fine-tune/${task.id}`)
|
||
]);
|
||
const progressResult = await progressResponse.json();
|
||
const statusResult = await statusResponse.json();
|
||
|
||
if (progressResult.code === 0 && progressResult.data) {
|
||
window.trainingProgressCache[task.id] = progressResult.data;
|
||
}
|
||
|
||
// 如果状态已改变(PID已结束),更新表格中的状态显示
|
||
if (statusResult.code === 0 && statusResult.data) {
|
||
const actualStatus = statusResult.data.status;
|
||
if (task.status !== actualStatus) {
|
||
// 找到对应的行并更新状态
|
||
const row = document.querySelector(`tr[data-id="${task.id}"]`);
|
||
if (row) {
|
||
const statusCell = row.querySelector('td:nth-child(3)');
|
||
if (statusCell) {
|
||
statusCell.innerHTML = `<span class="px-2 py-1 rounded text-xs ${actualStatus === 'running' ? 'bg-green-100 text-green-700' : actualStatus === 'failed' ? 'bg-red-100 text-red-700' : 'bg-blue-100 text-blue-700'}">${actualStatus}</span>`;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} catch (e) {
|
||
console.warn(`获取任务 ${task.id} 信息失败:`, e);
|
||
}
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.warn('刷新训练进度失败:', error);
|
||
}
|
||
}
|
||
|
||
// 检查并更新任务状态(用于 fine-tune 页面)
|
||
async function checkAndUpdateTaskStatus() {
|
||
if (typeof window.currentPage !== 'string' || window.currentPage !== 'fine-tune') return;
|
||
|
||
try {
|
||
const response = await fetch(`${window.API_BASE}/fine-tune`);
|
||
const result = await response.json();
|
||
|
||
if (result.code === 0 && result.data) {
|
||
// 获取所有 running 状态的任务
|
||
const runningTasks = result.data.filter(task => task.status === 'running');
|
||
|
||
for (const task of runningTasks) {
|
||
try {
|
||
// 调用 status API 获取实际状态(会检查 PID)
|
||
const statusResponse = await fetch(`${window.API_BASE}/fine-tune/${task.id}`);
|
||
const statusResult = await statusResponse.json();
|
||
|
||
if (statusResult.code === 0 && statusResult.data) {
|
||
const actualStatus = statusResult.data.status;
|
||
// 如果实际状态不是 running,更新表格显示
|
||
if (actualStatus !== 'running') {
|
||
const row = document.querySelector(`tr[data-id="${task.id}"]`);
|
||
if (row) {
|
||
const statusCell = row.querySelector('td:nth-child(3)');
|
||
if (statusCell) {
|
||
const statusClass = actualStatus === 'failed'
|
||
? 'bg-red-100 text-red-700'
|
||
: 'bg-blue-100 text-blue-700';
|
||
statusCell.innerHTML = `<span class="px-2 py-1 rounded text-xs ${statusClass}">${actualStatus}</span>`;
|
||
console.log(`[Status] 任务 ${task.id} 状态已更新: running -> ${actualStatus}`);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} catch (e) {
|
||
console.warn(`检查任务 ${task.id} 状态失败:`, e);
|
||
}
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.warn('检查任务状态失败:', error);
|
||
}
|
||
}
|
||
|
||
// 启动训练进度自动刷新
|
||
function startProgressRefresh() {
|
||
stopProgressRefresh();
|
||
window._progressRefreshTimer = setInterval(() => {
|
||
refreshTrainingProgress();
|
||
checkAndUpdateTaskStatus();
|
||
}, 5000);
|
||
}
|
||
|
||
// 停止训练进度刷新
|
||
function stopProgressRefresh() {
|
||
if (window._progressRefreshTimer) {
|
||
clearInterval(window._progressRefreshTimer);
|
||
window._progressRefreshTimer = null;
|
||
}
|
||
}
|
||
|
||
// 停止训练任务
|
||
async function stopItem(taskId) {
|
||
window.showConfirm('确认停止', '确定要停止这个训练任务吗?进程将被终止。', async () => {
|
||
try {
|
||
const response = await fetch(`${window.API_BASE}/fine-tune/stop/${taskId}`, {
|
||
method: 'POST'
|
||
});
|
||
const result = await response.json();
|
||
if (result.code === 0) {
|
||
window.showMessage('成功', '训练任务已停止', 'success');
|
||
// 刷新当前页面
|
||
const activeLink = document.querySelector('.nav-link.sidebar-item-active');
|
||
if (activeLink && typeof window.loadPage === 'function') {
|
||
window.loadPage(activeLink.dataset.page);
|
||
}
|
||
} else {
|
||
window.showMessage('错误', result.message || '停止失败', 'error');
|
||
}
|
||
} catch (error) {
|
||
window.showMessage('错误', '停止失败: ' + error.message, 'error');
|
||
}
|
||
});
|
||
}
|
||
|
||
// 查看训练日志 - 跳转到日志页面
|
||
async function viewTrainingLog(taskId, taskName) {
|
||
window.loadPage('logs');
|
||
}
|
||
|
||
// 查看调优任务日志 - 跳转到training-log.html页面
|
||
function viewFineTuneLogs(taskId, taskName) {
|
||
// 保存 taskId 到 sessionStorage
|
||
sessionStorage.setItem('trainingLogTaskId', taskId.toString());
|
||
sessionStorage.setItem('trainingLogTaskName', taskName);
|
||
// 跳转到日志页面
|
||
window.navigateToPage('training-log');
|
||
}
|
||
|
||
// 跳转到训练日志二级页面
|
||
function navigateToTrainingLog(taskId) {
|
||
// 传递 taskId 到 sessionStorage
|
||
sessionStorage.setItem('trainingLogTaskId', taskId.toString());
|
||
// 跳转到日志页面
|
||
window.navigateToPage('training-log');
|
||
}
|
||
|
||
// 导出训练服务
|
||
window.TrainingService = {
|
||
renderTrainingProgress,
|
||
refreshTrainingProgress,
|
||
checkAndUpdateTaskStatus,
|
||
startProgressRefresh,
|
||
stopProgressRefresh,
|
||
stopItem,
|
||
viewTrainingLog,
|
||
viewFineTuneLogs,
|
||
navigateToTrainingLog
|
||
};
|