mirror of
https://ghfast.top/https://github.com/aeroxw/tick-stock-panel.git
synced 2026-09-12 16:44:15 +08:00
fix(ai): base_url 归一化保留非 v1 版本段, 修复 GLM /v4 被 404
normalize_openai_base_url 旧实现只检查「是否以 /v1 结尾」, 不是就强制补 /v1。 智谱 GLM 的 OpenAI 兼容地址是 /api/paas/v4, 被补成 /api/paas/v4/v1, SDK 再拼 /chat/completions → 不存在路径 → 404。 改用正则检测 URL 末尾已有的版本段 (/v1、/v2、/v4、/v1.1 等): - 已有版本段 → 保持原样 - 无版本段 → 补 /v1 (无版本号网关行为不变) - 去 /chat/completions 后缀逻辑保留 补 4 条单测覆盖 GLM /v4 场景, 原有 v1/无版本网关回归不变。 Closes #60
This commit is contained in:
@@ -64,14 +64,22 @@ def normalize_codex_command(command: str | None, *, strict: bool = True) -> str:
|
||||
return CODEX_DEFAULT_COMMAND
|
||||
|
||||
|
||||
_VERSION_SEGMENT_RE = re.compile(r"/v\d+(?:\.\d+)?$", re.IGNORECASE)
|
||||
|
||||
|
||||
def normalize_openai_base_url(url: str) -> str:
|
||||
"""Return the OpenAI-compatible base URL expected by the OpenAI SDK."""
|
||||
"""Return the OpenAI-compatible base URL expected by the OpenAI SDK.
|
||||
|
||||
识别 URL 中已有的版本段 (/v1、/v2、/v4 等) 时保持原样 —— 部分 OpenAI 兼容
|
||||
服务用非 v1 的版本号 (如智谱 GLM 用 /api/paas/v4), 旧实现无条件补 /v1 会拼成
|
||||
不存在的 /api/paas/v4/v1/chat/completions 导致 404。仅在无版本段时才补 /v1。
|
||||
"""
|
||||
base = (url or "").strip().rstrip("/")
|
||||
if base.endswith("/chat/completions"):
|
||||
base = base[: -len("/chat/completions")].rstrip("/")
|
||||
if not base.endswith("/v1"):
|
||||
base = f"{base}/v1"
|
||||
return base
|
||||
if _VERSION_SEGMENT_RE.search(base):
|
||||
return base
|
||||
return f"{base}/v1"
|
||||
|
||||
|
||||
def codex_cli_available() -> bool:
|
||||
|
||||
@@ -18,6 +18,25 @@ def test_normalize_openai_base_url_strips_chat_completions_path():
|
||||
assert normalize_openai_base_url("http://ai.zedbox.cn:8080/v1/chat/completions") == "http://ai.zedbox.cn:8080/v1"
|
||||
|
||||
|
||||
def test_normalize_openai_base_url_preserves_glm_v4():
|
||||
"""智谱 GLM 用 /api/paas/v4, 不能强制补成 /v4/v1 (会 404)。"""
|
||||
assert normalize_openai_base_url("https://open.bigmodel.cn/api/paas/v4") == "https://open.bigmodel.cn/api/paas/v4"
|
||||
|
||||
|
||||
def test_normalize_openai_base_url_strips_chat_completions_from_glm_v4():
|
||||
"""用户填完整 /v4/chat/completions 时, 去掉后缀归一化为 /v4。"""
|
||||
assert normalize_openai_base_url("https://open.bigmodel.cn/api/paas/v4/chat/completions") == "https://open.bigmodel.cn/api/paas/v4"
|
||||
|
||||
|
||||
def test_normalize_openai_base_url_preserves_other_version_segments():
|
||||
"""其它非 v1 版本号 (/v2 等) 也应保持原样。"""
|
||||
assert normalize_openai_base_url("https://example.com/api/v2") == "https://example.com/api/v2"
|
||||
|
||||
|
||||
def test_normalize_openai_base_url_strips_trailing_slash():
|
||||
assert normalize_openai_base_url("https://open.bigmodel.cn/api/paas/v4/") == "https://open.bigmodel.cn/api/paas/v4"
|
||||
|
||||
|
||||
def test_format_openai_error_hides_html_gateway_body():
|
||||
response = httpx.Response(
|
||||
504,
|
||||
|
||||
Reference in New Issue
Block a user