feat: 模型推理异步加载与对话链路修复,同步基线
模型推理全异步化改造: - 计算节点 InferenceSession 改为后台线程异步加载模型,load 立即返回, 加载期间事件循环保持响应(/inference/status 与 /health 不阻塞) - 后端模型加载改为异步派发 + 轮询对账器(reconcile_inference_loads), 任务状态由 starting 自动推进到 ready/error,解决多节点启动超时 (timeout of 120000ms exceeded) - 推理删除/卸载改为任务感知 + 短超时,删除先删记录再 best-effort 卸载, 不再被不可达节点阻塞;同节点新模型替换旧任务标记失效 - 流式对话透传 task_id/node_id 路由到真正加载模型的算力节点, useStreamChat 解析 SSE 错误帧以干净文案展示 - 对话历史按任务 id 本地持久化,退出重进可恢复;移除页脚提示文本 - 新增后端推理异步加载与计算节点异步状态机单元测试 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { get, post, del } from '../request'
|
||||
import type { CompareTask, CompareModelRef } from '@/types'
|
||||
|
||||
const INFERENCE_START_TIMEOUT_MS = 15 * 60 * 1000
|
||||
|
||||
/** 推理/对比任务列表 */
|
||||
export const getCompareList = () => get<CompareTask[]>('/model-compare')
|
||||
|
||||
@@ -12,7 +14,7 @@ export const createCompare = (data: Partial<CompareTask>) =>
|
||||
post<{ id: string | number }>('/model-compare', data)
|
||||
|
||||
/** 删除任务 */
|
||||
export const deleteCompare = (id: string | number) => del(`/model-compare/${id}`)
|
||||
export const deleteCompare = (id: string | number) => del(`/model-compare/${id}`, undefined, { timeout: 60_000 })
|
||||
|
||||
/** 更新任务加载状态 */
|
||||
export const updateLoadStatus = (id: string | number, load_status: any) =>
|
||||
@@ -34,7 +36,8 @@ export const stopModelByPid = (pid: number) =>
|
||||
post('/model-compare/stop-by-pid', { pid })
|
||||
|
||||
/** 加载任务 */
|
||||
export const loadCompare = (id: string | number) => post(`/model-compare/${id}/load`)
|
||||
export const loadCompare = (id: string | number) =>
|
||||
post(`/model-compare/${id}/load`, undefined, { timeout: INFERENCE_START_TIMEOUT_MS })
|
||||
|
||||
/** 卸载任务 */
|
||||
export const unloadCompare = (id: string | number) => post(`/model-compare/${id}/unload`)
|
||||
@@ -81,6 +84,10 @@ export const streamChatReal = (data: any): Promise<Response> => {
|
||||
temperature: data.temperature ?? 0.7,
|
||||
top_p: data.top_p ?? 0.95,
|
||||
max_tokens: data.max_tokens ?? 2048,
|
||||
// 透传 task_id/node_id,让后端按 load_status 路由到真正加载了模型的算力节点,
|
||||
// 避免在多节点时回退到“第一个在线节点”导致连接失败
|
||||
task_id: data.task_id,
|
||||
node_id: data.node_id,
|
||||
}),
|
||||
})
|
||||
}
|
||||
@@ -94,8 +101,8 @@ export const batchChat = (data: any) => post('/model-chat/batch', data)
|
||||
/** 本地 transformers 模型对话 */
|
||||
export const localChat = (data: any) => post('/model-chat/local/chat', data)
|
||||
|
||||
/** 预加载本地模型(模型加载耗时长,超时 5 分钟) */
|
||||
export const preloadLocalModel = (data: any) => post('/model-chat/local/preload', data, { timeout: 300000 })
|
||||
/** 预加载本地模型(模型加载耗时长,超时 15 分钟) */
|
||||
export const preloadLocalModel = (data: any) => post('/model-chat/local/preload', data, { timeout: INFERENCE_START_TIMEOUT_MS })
|
||||
|
||||
/** 预加载已训练模型(超时 5 分钟) */
|
||||
export const preloadTrainedModel = (data: any) => post('/model-chat/trained/preload', data, { timeout: 300000 })
|
||||
/** 预加载已训练模型(超时 15 分钟) */
|
||||
export const preloadTrainedModel = (data: any) => post('/model-chat/trained/preload', data, { timeout: INFERENCE_START_TIMEOUT_MS })
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
import { get, post, put, del } from '../request'
|
||||
import type { FineTuneStartPayload, FineTuneTask, TrainingProgress, LogContent } from '@/types'
|
||||
|
||||
export interface FineTuneMetricPoint {
|
||||
step: number
|
||||
epoch?: number | null
|
||||
loss?: number | null
|
||||
grad_norm?: number | null
|
||||
learning_rate?: number | null
|
||||
raw?: string
|
||||
create_time?: string
|
||||
}
|
||||
|
||||
export interface TrainingDiagnostic {
|
||||
level: string
|
||||
title: string
|
||||
@@ -80,6 +90,10 @@ export const getFineTuneLogs = (
|
||||
params: { tail_lines?: number; offset?: number; limit?: number } = {},
|
||||
) => get<LogContent & { job_id?: string; source?: string }>(`/fine-tune/${id}/logs`, params)
|
||||
|
||||
/** 获取训练指标曲线数据 */
|
||||
export const getFineTuneMetrics = (id: string | number) =>
|
||||
get<FineTuneMetricPoint[]>(`/fine-tune/${id}/metrics`)
|
||||
|
||||
/** 启动 TensorBoard */
|
||||
export const startTensorboard = () => post('/fine-tune/tensorboard/start')
|
||||
|
||||
|
||||
@@ -88,10 +88,14 @@ export const updateModelPurpose = (id: string | number, purpose: string) =>
|
||||
|
||||
/** 合并 LoRA 权重 */
|
||||
export const mergeModel = (data: {
|
||||
trained_model_id?: string | number
|
||||
model_name: string
|
||||
train_method: string
|
||||
base_model_path: string
|
||||
}) => post('/model-manage/merge', data)
|
||||
adapter_path?: string
|
||||
compute_node_id?: string
|
||||
output_model_name?: string
|
||||
}) => post('/model-manage/merge', data, { timeout: 15 * 60 * 1000 })
|
||||
|
||||
/** 导出已训练模型权重 */
|
||||
export const exportModelUrl = (modelName: string) =>
|
||||
|
||||
Reference in New Issue
Block a user