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:
@@ -44,6 +44,24 @@ export function useStreamChat() {
|
||||
})
|
||||
const loading = ref(false)
|
||||
|
||||
/** 从 SSE 帧中提取错误信息(后端/计算节点错误以 data: {"error": "..."} 形式下发) */
|
||||
function extractSseError(buffer: string): string | null {
|
||||
const trimmed = buffer.trim()
|
||||
if (!trimmed.startsWith('data: ')) return null
|
||||
const lines = trimmed.split(/\r?\n/)
|
||||
for (let i = lines.length - 1; i >= 0; i--) {
|
||||
const line = lines[i].trim()
|
||||
if (!line.startsWith('data: ')) continue
|
||||
try {
|
||||
const obj = JSON.parse(line.slice(6))
|
||||
if (obj && typeof obj.error === 'string' && obj.error) return obj.error
|
||||
} catch {
|
||||
/* 非 JSON 的 data 行忽略 */
|
||||
}
|
||||
}
|
||||
return trimmed
|
||||
}
|
||||
|
||||
/** 从内容中解析 think 标签 */
|
||||
function parseContent(content: string) {
|
||||
const thinkRegex = /<think>([\s\S]*?)(<\/think>)?/g
|
||||
@@ -121,6 +139,16 @@ export function useStreamChat() {
|
||||
}
|
||||
|
||||
// 最终更新
|
||||
// 若整段响应是 SSE 错误帧,提取 error 字段以干净文案展示
|
||||
const sseError = extractSseError(buffer)
|
||||
if (sseError) {
|
||||
message.value.isThinking = false
|
||||
message.value.isStreaming = false
|
||||
message.value.done = true
|
||||
message.value.error = sseError
|
||||
message.value.displayContent = sseError
|
||||
return
|
||||
}
|
||||
const parsed = parseContent(buffer)
|
||||
message.value.thinkContent = parsed.think
|
||||
message.value.displayContent = parsed.display
|
||||
|
||||
Reference in New Issue
Block a user