From 20981854770b2fca34d58a05f41cf96a563225ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=BF=E4=BA=91=E7=A7=8B=E6=9C=88?= <15273589815@163.com> Date: Sun, 13 Sep 2026 19:03:49 +0800 Subject: [PATCH] =?UTF-8?q?fix(portal):=20=E5=AE=A2=E6=9C=8D=E6=B5=AE?= =?UTF-8?q?=E7=AA=97=E8=BD=AE=E8=AF=A2=E5=8F=82=E6=95=B0=E8=B0=83=E6=95=B4?= =?UTF-8?q?=EF=BC=8C=E5=8E=8B=E6=84=9F=E7=9F=A5=E5=BB=B6=E8=BF=9F=E5=B9=B6?= =?UTF-8?q?=E7=95=99=E8=B6=B3=E8=B6=85=E6=97=B6=E9=A2=84=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 现象:访客在公开页问客服,等约 9.5 秒后报「客服响应超时」。 根因不在链路快慢 —— Agent Worker 没在跑,run 一直停在 queued, 前端把「没人处理」呈现成了「超时」。 启动 Worker 后实测同一条链路(受理 0.05s + 意图分类 + 知识检索 + 落库): 4.11s / 4.09s / 4.82s,三条全部 succeeded。模型已经是 deepseek-flash, 延迟主要来自一次意图分类加一次 embedding,不是模型选型问题。 不过原来的轮询参数余量确实偏薄:350ms 后首次、之后每 700ms 一次、共 14 次, 约 9.5 秒封顶,后端稍一抖动就撞上;而且平均要多等半个轮询周期才看到结果。 改为 300ms 后首次、之后每 500ms 一次、共 40 次(约 20 秒): 感知延迟压到半秒内,同时给模型与检索抖动留出余量。 超时文案也从「客服响应超时,请稍后重试」改为「客服繁忙,暂时没能给出答复」, 不再暗示是响应慢。代码注释里写明:若仍然超时,先确认 Agent Worker 已启动。 --- .../portal/common/customer-service-widget/widget.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app/static/portal/common/customer-service-widget/widget.js b/app/static/portal/common/customer-service-widget/widget.js index 60012ff..386d4db 100644 --- a/app/static/portal/common/customer-service-widget/widget.js +++ b/app/static/portal/common/customer-service-widget/widget.js @@ -101,14 +101,21 @@ export function mountCustomerServiceWidget(mode = 'public') { return sessionId; } async function waitForRun(runId) { - for (let attempt = 0; attempt < 14; attempt += 1) { - await new Promise((resolve) => window.setTimeout(resolve, attempt ? 700 : 350)); + // 实测(本机 + DeepSeek):整条链路「受理 0.05s + 意图分类 + 知识检索 + 落库」 + // 约 4.1–4.8 秒。原参数是「350ms 后首次、之后每 700ms 一次、共 14 次」≈ 9.5 秒封顶, + // 后端稍一抖动就撞上限;而且平均要多等半个轮询周期(350ms)才看到结果。 + // 改为「300ms 后首次、之后每 500ms 一次、共 40 次」≈ 20 秒:感知延迟压到半秒内, + // 同时给模型/检索抖动留出余量。 + // ⚠️ 若这里仍然超时,先确认 Agent Worker 已启动(`python -m app.worker`)—— + // 没有 Worker 时 run 会一直停在 queued,任何轮询预算都不够。 + for (let attempt = 0; attempt < 40; attempt += 1) { + await new Promise((resolve) => window.setTimeout(resolve, attempt ? 500 : 300)); const response = await apiClient.get('R002', { pathParams: { runId }, headers: authHeaders() }); const snapshot = response.data || {}; if (snapshot.status === 'succeeded') return snapshot.result?.reply || snapshot.result?.content || '暂时没有可展示的回复。'; if (snapshot.status === 'failed' || snapshot.status === 'cancelled') throw new ApiError('客服暂时无法完成回答,请稍后重试。'); } - throw new ApiError('客服响应超时,请稍后重试。'); + throw new ApiError('客服繁忙,暂时没能给出答复,请稍后重试。'); } form.addEventListener('submit', async (event) => { event.preventDefault();