From bd60a15acbb7b8f05a501a5c9664da870e626057 Mon Sep 17 00:00:00 2001 From: MT-Fire <798521692@qq.com> Date: Thu, 5 Mar 2026 11:56:33 +0800 Subject: [PATCH] =?UTF-8?q?feat(config):=20=E5=AE=9E=E7=8E=B0=E6=B7=B1?= =?UTF-8?q?=E5=BA=A6=E6=90=9C=E7=B4=A2=E4=B8=8E=E7=BD=91=E7=BB=9C=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E7=9A=84=E4=BA=92=E6=96=A5=E9=80=89=E6=8B=A9=E6=9C=BA?= =?UTF-8?q?=E5=88=B6=EF=BC=8C=E4=BB=A5=E9=81=BF=E5=85=8D=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=86=B2=E7=AA=81=20[=E4=BC=98=E5=8C=96=EF=BC=9A=E6=A0=B9?= =?UTF-8?q?=E6=8D=AE=E7=94=A8=E6=88=B7=E9=80=89=E5=9E=8B=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E5=AF=B9=E5=BA=94=E5=B7=A5=E5=85=B7=E9=85=8D?= =?UTF-8?q?=E7=BD=AE]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/api/chat_routes_glm.py | 8 +++- server/utils/glm_adapter.py | 63 +++++++++++++++++++++++------- src/components/input/ChatInput.vue | 10 ++++- 3 files changed, 65 insertions(+), 16 deletions(-) diff --git a/server/api/chat_routes_glm.py b/server/api/chat_routes_glm.py index c0c10ca..d8eae69 100644 --- a/server/api/chat_routes_glm.py +++ b/server/api/chat_routes_glm.py @@ -43,7 +43,13 @@ async def chat_handler(body: dict): stream = body.get("stream", True) temperature = body.get("temperature", 0.7) max_tokens = body.get("max_tokens", body.get("maxTokens", 2000)) - web_search = body.get("webSearch", False) or body.get("deepSearch", False) + # 区分搜索模式:深度搜索 > 简单搜索 > 不搜索 + if body.get("deepSearch", False): + web_search = "deep" + elif body.get("webSearch", False): + web_search = "simple" + else: + web_search = False deep_think = body.get("deepThinking", False) files = body.get("files", []) diff --git a/server/utils/glm_adapter.py b/server/utils/glm_adapter.py index 68a614a..ac7c56d 100644 --- a/server/utils/glm_adapter.py +++ b/server/utils/glm_adapter.py @@ -234,6 +234,40 @@ def build_glm_messages(messages: list, files: list | None = None) -> tuple[list, return glm_messages, has_vision +# ── 网络搜索 tool 构建 ────────────────────────────────────────────── +def _build_web_search_tool(mode: str | bool) -> dict: + """ + 根据搜索模式构建 web_search tool 配置。 + + mode: + - True / "simple" : 简单搜索(search_std + medium, 10条) + - "deep" : 深度搜索(search_pro + high, 20条) + """ + if mode == "deep": + # 深度搜索:高阶搜索引擎 + 详细内容 + 更多结果 + return { + "type": "web_search", + "web_search": { + "enable": True, + "search_result": True, + "search_engine": "search_pro", + "content_size": "high", + "count": 20, + }, + } + # 简单搜索(默认):基础搜索引擎 + 摘要内容 + return { + "type": "web_search", + "web_search": { + "enable": True, + "search_result": True, + "search_engine": "search_std", + "content_size": "medium", + "count": 10, + }, + } + + # ── 哨兵对象 ───────────────────────────────────────────────────────── _SENTINEL = object() @@ -245,13 +279,18 @@ async def glm_stream_generator( temperature: float, max_tokens: int, files: list | None = None, - web_search: bool = False, + web_search: str | bool = False, deep_thinking: bool = False, ) -> AsyncGenerator[str, None]: """ GLM 流式 SSE 生成器。 使用 queue.Queue + 专用线程(生产者)+ asyncio 消费者模式, 让 zai-sdk 同步迭代器在单一线程内安全运行。 + + web_search: + - False / "" : 不启用联网搜索 + - True / "simple" : 简单搜索(search_std + medium) + - "deep" : 深度搜索(search_pro + high + 更多结果) """ import asyncio import queue @@ -263,12 +302,7 @@ async def glm_stream_generator( extra_kwargs: dict = {} if web_search: - extra_kwargs["tools"] = [ - { - "type": "web_search", - "web_search": {"enable": True, "search_result": True}, - } - ] + extra_kwargs["tools"] = [_build_web_search_tool(web_search)] if not deep_thinking: # 智普默认开启思考模式,所以要用非门(不知道“非门”描述是否准确。前端选择开启思考模式,这里不做变动。前端选择关闭思考模式,这里关闭。) extra_kwargs["thinking"] = {"type": "disabled"} @@ -412,20 +446,21 @@ def glm_chat_sync( temperature: float, max_tokens: int, files: list | None = None, - web_search: bool = False, + web_search: str | bool = False, deep_thinking: bool = False, ) -> dict: + """ + web_search: + - False / "" : 不启用联网搜索 + - True / "simple" : 简单搜索(search_std + medium) + - "deep" : 深度搜索(search_pro + high + 更多结果) + """ glm_msgs, has_vision = build_glm_messages(messages, files) actual_model = resolve_model(model, has_vision) extra_kwargs: dict = {} if web_search: - extra_kwargs["tools"] = [ - { - "type": "web_search", - "web_search": {"enable": True, "search_result": True}, - } - ] + extra_kwargs["tools"] = [_build_web_search_tool(web_search)] if deep_thinking: extra_kwargs["thinking"] = {"type": "enabled"} diff --git a/src/components/input/ChatInput.vue b/src/components/input/ChatInput.vue index bfbb964..ba2d560 100644 --- a/src/components/input/ChatInput.vue +++ b/src/components/input/ChatInput.vue @@ -389,9 +389,13 @@ function removeAttachment(id: string) { } } -// 切换功能 +// 切换功能(深度搜索与联网搜索互斥) function toggleDeepSearch() { isDeepSearch.value = !isDeepSearch.value; + if (isDeepSearch.value) { + isWebSearch.value = false; + localStorage.setItem("isWebSearch", "false"); + } localStorage.setItem("isDeepSearch", String(isDeepSearch.value)); } @@ -402,6 +406,10 @@ function toggleDeepThink() { function toggleWebSearch() { isWebSearch.value = !isWebSearch.value; + if (isWebSearch.value) { + isDeepSearch.value = false; + localStorage.setItem("isDeepSearch", "false"); + } localStorage.setItem("isWebSearch", String(isWebSearch.value)); }