fix(#188): bot_qa 审核修正——nginx 改无 URI proxy_pass 真透传 + 健康探针 /health 无前缀

打回问题 1:proxy_pass 带末尾 / 是去前缀语义(与声称相反),/v1/models
会被转发成 /models 导致 404。改为不带 URI 的 proxy_pass(无末尾 /),
请求 URI 原样透传;另新增 location = /health 精确透传健康探针。
打回问题 2:serve.py 健康路由是 GET /health(无 /v1 前缀),fetchHealth
由 /v1/health 改回 /health;同步修正 chat/NlQuery/cockpit 三处文案注释。
构建验证:pnpm --filter @vben/web-antdv-next build 通过(10.3s)。
This commit is contained in:
2026-08-06 16:48:14 +08:00
parent 5667fad3e1
commit 9994fb75e7
5 changed files with 29 additions and 13 deletions
@@ -1,16 +1,17 @@
/**
* iAOP LLM 网关客户端(Epic #163 / issue #166 [A3])
*
* 对齐旧 `web/` 各模块的 INFER_BASE(nginx 反代 /v1/ → 推理服务 :30800):
* GET /v1/health —— 健康巡检
* 对齐旧 `web/` 各模块的 INFER_BASE(nginx 反代 → 推理服务 :30800):
* GET /health —— 健康巡检(serve.py 探针路由无前缀)
* GET /v1/models —— 模型列表
* POST /v1/chat/completions —— OpenAI 兼容对话(dry-run 占位 / 真实推理)
*
* 推理服务为 iAOP 独立通道(不要求 FBA JWT),故用原生 fetch 封装,
* 统一超时 / 错误信息 / 结果结构;FBA requestClient 仅用于 /fba/* 接口。
*
* issue #188:推理服务真实路径即 :30800/v1/*,nginx 反代 /v1/ 不去前缀直接透传,
* 故 BASE_URL 为空串,调用方统一写 /v1/models、/v1/chat/completions,
* issue #188(bot_qa 审核修正):nginx 反代使用不带 URI 的 proxy_pass
* 原样透传,故 BASE_URL 为空串,调用方按后端真实路由写
* /v1/models、/v1/chat/completions、/health(健康探针无 /v1 前缀),
* 避免出现 /v1/v1 双前缀对 nginx rewrite 的隐式耦合。
*/
const BASE_URL = '';
@@ -65,7 +66,7 @@ async function fetchJson<T>(path: string, init?: RequestInit): Promise<T> {
/** 健康巡检(前端徽标展示;失败不抛出,由调用方降级) */
export async function fetchHealth(): Promise<Record<string, unknown> | null> {
try {
return await fetchJson<Record<string, unknown>>('/v1/health');
return await fetchJson<Record<string, unknown>>('/health');
} catch {
return null;
}
@@ -68,7 +68,7 @@ async function send() {
messages.value.push({ role: 'assistant', content: r.text, meta, citations: hits });
} catch {
offline.value = true;
messages.value.push({ role: 'assistant', content: '推理服务请求失败,请检查网关(/v1/health)。' });
messages.value.push({ role: 'assistant', content: '推理服务请求失败,请检查网关(/health)。' });
} finally {
loading.value = false;
scrollBottom();
@@ -45,7 +45,7 @@ async function submit() {
<a-button type="primary" :loading="loading" @click="submit">查询</a-button>
</div>
<a-alert v-if="offline" type="warning" show-icon style="margin-top: 8px">
<template #message>推理服务离线 / dry-run 占位:请检查后端推理服务(/v1/health)</template>
<template #message>推理服务离线 / dry-run 占位:请检查后端推理服务(/health)</template>
</a-alert>
<div v-if="answer" class="nl-answer">{{ answer }}</div>
</div>
@@ -54,7 +54,7 @@ onUnmounted(() => window.clearInterval(timer));
const inferOnline = ref(false);
async function refreshHealth() {
// issue #188:健康检查改走 infer.ts 的 fetchHealth 封装,路径口径统一(/v1/health)
// issue #188:健康检查改走 infer.ts 的 fetchHealth 封装,路径口径统一(/health,无前缀)
const d = await fetchHealth();
const status = d?.status;
inferOnline.value = status === 'ok' || status === 'dry-run';