mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-09-09 13:39:26 +00:00
feat(models): add GLM-5.3-Flash thinking workaround (#5074)
This commit is contained in:
parent
23d8e4b3a3
commit
bf3e792a6a
@ -186,6 +186,8 @@ That prompt is intended for coding agents. It tells the agent to clone the repo
|
||||
|
||||
To route OpenAI models through `/v1/responses`, keep using `langchain_openai:ChatOpenAI` and set `use_responses_api: true` with `output_version: responses/v1`.
|
||||
|
||||
The setup wizard includes a Z.AI GLM-5.3-Flash profile. Because that model requires thinking and only accepts its own restricted effort levels, the compatibility profile keeps thinking enabled for every foreground and background call and temporarily suppresses DeerFlow's generic effort selector. See `config.example.yaml` for the equivalent manual configuration.
|
||||
|
||||
For vLLM 0.19.0, use `deerflow.models.vllm_provider:VllmChatModel`. For Qwen-style reasoning models, DeerFlow toggles reasoning with `extra_body.chat_template_kwargs.enable_thinking` and preserves vLLM's non-standard `reasoning` field across multi-turn tool-call conversations. Legacy `thinking` configs are normalized automatically for backward compatibility. If the endpoint reports a cumulative usage snapshot on every streaming chunk, set `cumulative_stream_usage: true` so DeerFlow converts those snapshots into per-chunk deltas; the option is disabled by default and leaves usage unchanged when a stable completion id is unavailable. Reasoning models may also require the server to be started with `--reasoning-parser ...`. If your local vLLM deployment accepts any non-empty API key, you can still set `VLLM_API_KEY` to a placeholder value.
|
||||
|
||||
CLI-backed provider examples:
|
||||
|
||||
@ -172,6 +172,8 @@ DeerFlow 新近集成了 BytePlus 自研的智能搜索与抓取工具集——[
|
||||
|
||||
如果要让 OpenAI 模型走 `/v1/responses`,继续使用 `langchain_openai:ChatOpenAI`,并设置 `use_responses_api: true` 和 `output_version: responses/v1`。
|
||||
|
||||
Setup Wizard 已内置 Z.AI GLM-5.3-Flash 配置。由于该模型强制开启 thinking,且只接受自身限定的 effort 档位,当前兼容配置会在前台和后台调用中始终保持 thinking 开启,并暂时屏蔽 DeerFlow 的通用 effort 选择器。等价的手动配置见 `config.example.yaml`。
|
||||
|
||||
对于 vLLM 0.19.0,请使用 `deerflow.models.vllm_provider:VllmChatModel`。对于 Qwen 风格的推理模型,DeerFlow 通过 `extra_body.chat_template_kwargs.enable_thinking` 开关推理,并在多轮 tool-call 对话中保留 vLLM 非标准的 `reasoning` 字段。旧版 `thinking` 配置会自动规范化以保持向后兼容。推理模型可能还需要在启动 vLLM 服务时加上 `--reasoning-parser ...` 参数。如果你的本地 vLLM 部署接受任意非空 API key,可以把 `VLLM_API_KEY` 设为一个占位值。
|
||||
|
||||
CLI-backed provider 配置示例:
|
||||
|
||||
@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
from langchain.chat_models import BaseChatModel
|
||||
from langchain_core.messages import HumanMessage
|
||||
|
||||
from deerflow.config.app_config import AppConfig
|
||||
from deerflow.config.model_config import ModelConfig
|
||||
@ -297,6 +298,49 @@ def test_thinking_disabled_no_when_thinking_enabled_does_nothing(monkeypatch):
|
||||
assert captured.get("reasoning_effort") is None
|
||||
|
||||
|
||||
def test_required_thinking_profile_keeps_base_payload_when_runtime_requests_disabled():
|
||||
"""Always-thinking models keep their base payload on every call.
|
||||
|
||||
Required-thinking models such as GLM-5.3-Flash intentionally declare no
|
||||
conditional thinking settings. A runtime ``thinking_enabled=False`` must
|
||||
therefore leave the profile's unconditional ``extra_body.thinking`` block
|
||||
untouched, while the capability guard drops DeerFlow's generic effort value.
|
||||
"""
|
||||
model = ModelConfig(
|
||||
name="glm-5.3-flash",
|
||||
display_name="GLM-5.3-Flash",
|
||||
description=None,
|
||||
use="deerflow.models.patched_deepseek:PatchedChatDeepSeek",
|
||||
model="glm-5.3-flash",
|
||||
api_base="https://api.z.ai/api/paas/v4",
|
||||
api_key="test-key",
|
||||
supports_thinking=True,
|
||||
supports_reasoning_effort=False,
|
||||
supports_vision=True,
|
||||
stream_usage=False,
|
||||
extra_body={
|
||||
"thinking": {"type": "enabled", "clear_thinking": True},
|
||||
"tool_stream": True,
|
||||
},
|
||||
)
|
||||
cfg = _make_app_config([model])
|
||||
chat_model = factory_module.create_chat_model(
|
||||
name="glm-5.3-flash",
|
||||
thinking_enabled=False,
|
||||
reasoning_effort="medium",
|
||||
app_config=cfg,
|
||||
attach_tracing=False,
|
||||
)
|
||||
payload = chat_model._get_request_payload([HumanMessage(content="ping")])
|
||||
|
||||
assert payload["extra_body"] == {
|
||||
"thinking": {"type": "enabled", "clear_thinking": True},
|
||||
"tool_stream": True,
|
||||
}
|
||||
assert "reasoning_effort" not in payload
|
||||
assert chat_model.stream_usage is False
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# when_thinking_disabled config
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@ -29,6 +29,7 @@ class TestProviders:
|
||||
|
||||
expected = {
|
||||
"volcengine",
|
||||
"zai",
|
||||
"openai",
|
||||
"openai_responses",
|
||||
"ollama_qwen",
|
||||
@ -56,6 +57,42 @@ class TestProviders:
|
||||
assert providers["deepseek"].use == "deerflow.models.patched_deepseek:PatchedChatDeepSeek"
|
||||
assert providers["volcengine"].extra_config["api_base"] == "https://ark.cn-beijing.volces.com/api/v3"
|
||||
|
||||
def test_zai_glm_flash_uses_required_thinking_workaround(self):
|
||||
provider = next(p for p in LLM_PROVIDERS if p.name == "zai")
|
||||
config = provider.extra_config_for("glm-5.3-flash")
|
||||
|
||||
assert provider.use == "deerflow.models.patched_deepseek:PatchedChatDeepSeek"
|
||||
assert provider.env_var == "ZAI_API_KEY"
|
||||
assert config["api_base"] == "https://api.z.ai/api/paas/v4"
|
||||
assert config["supports_thinking"] is True
|
||||
assert config["supports_reasoning_effort"] is False
|
||||
assert "when_thinking_enabled" not in config
|
||||
assert "when_thinking_disabled" not in config
|
||||
assert config["extra_body"] == {
|
||||
"thinking": {"type": "enabled", "clear_thinking": True},
|
||||
"tool_stream": True,
|
||||
}
|
||||
|
||||
def test_zai_glm_flash_workaround_is_preserved_in_generated_config(self):
|
||||
provider = next(p for p in LLM_PROVIDERS if p.name == "zai")
|
||||
content = build_minimal_config(
|
||||
provider_use=provider.use,
|
||||
model_name=provider.default_model,
|
||||
display_name=provider.display_name,
|
||||
api_key_field=provider.api_key_field,
|
||||
env_var=provider.env_var,
|
||||
extra_model_config=provider.extra_config,
|
||||
)
|
||||
|
||||
model = yaml.safe_load(content)["models"][0]
|
||||
assert model["model"] == "glm-5.3-flash"
|
||||
assert model["api_key"] == "$ZAI_API_KEY"
|
||||
assert model["supports_reasoning_effort"] is False
|
||||
assert model["extra_body"]["thinking"] == {
|
||||
"type": "enabled",
|
||||
"clear_thinking": True,
|
||||
}
|
||||
|
||||
def test_minimax_vision_is_per_model(self):
|
||||
"""M3 supports vision; M2.7 variants are text-only.
|
||||
|
||||
|
||||
@ -184,6 +184,40 @@ models:
|
||||
# extra_body:
|
||||
# thinking:
|
||||
# type: disabled
|
||||
|
||||
# Example: Z.AI GLM-5.3-Flash (required-thinking workaround)
|
||||
#
|
||||
# GLM-5.3-Flash cannot disable thinking and only accepts low/high/max effort.
|
||||
# DeerFlow's current generic UI may request disabled thinking or emit
|
||||
# minimal/medium, so this profile keeps thinking enabled unconditionally and
|
||||
# suppresses generic effort forwarding. Keep the thinking block in the base
|
||||
# extra_body: moving it to when_thinking_enabled would let background calls
|
||||
# synthesize the invalid thinking.type=disabled + reasoning_effort=minimal pair.
|
||||
# clear_thinking=true is intentional for this compatibility workaround: it
|
||||
# avoids requiring exact historical reasoning replay after summarization.
|
||||
#
|
||||
# - name: glm-5.3-flash
|
||||
# display_name: GLM-5.3-Flash
|
||||
# use: deerflow.models.patched_deepseek:PatchedChatDeepSeek
|
||||
# model: glm-5.3-flash
|
||||
# api_base: https://api.z.ai/api/paas/v4
|
||||
# api_key: $ZAI_API_KEY
|
||||
# timeout: 600.0
|
||||
# max_retries: 2
|
||||
# temperature: 1.0
|
||||
# top_p: 0.95
|
||||
# max_tokens: 131072
|
||||
# context_window: 1000000
|
||||
# supports_thinking: true
|
||||
# supports_reasoning_effort: false
|
||||
# supports_vision: true
|
||||
# stream_usage: false
|
||||
# extra_body:
|
||||
# thinking:
|
||||
# type: enabled
|
||||
# clear_thinking: true
|
||||
# tool_stream: true
|
||||
|
||||
# Example: OpenAI model
|
||||
# - name: gpt-4
|
||||
# display_name: GPT-4
|
||||
|
||||
@ -175,6 +175,47 @@ LLM_PROVIDERS: list[LLMProvider] = [
|
||||
"kimi-k2.7-code": False,
|
||||
},
|
||||
),
|
||||
LLMProvider(
|
||||
name="zai",
|
||||
display_name="Z.AI GLM-5.3-Flash",
|
||||
description="GLM-5.3-Flash with required thinking and native vision",
|
||||
use="deerflow.models.patched_deepseek:PatchedChatDeepSeek",
|
||||
models=["glm-5.3-flash"],
|
||||
default_model="glm-5.3-flash",
|
||||
env_var="ZAI_API_KEY",
|
||||
package="langchain-deepseek",
|
||||
extra_config={
|
||||
"api_base": "https://api.z.ai/api/paas/v4",
|
||||
"timeout": 600.0,
|
||||
"max_retries": 2,
|
||||
"temperature": 1.0,
|
||||
"top_p": 0.95,
|
||||
"max_tokens": 131072,
|
||||
"context_window": 1000000,
|
||||
"supports_thinking": True,
|
||||
# GLM-5.3-Flash only accepts low/high/max, while DeerFlow's current
|
||||
# generic UI can emit minimal/medium. Keep provider effort control
|
||||
# disabled until model-specific reasoning capabilities are exposed.
|
||||
"supports_reasoning_effort": False,
|
||||
"supports_vision": True,
|
||||
# The model cannot disable thinking. This unconditional base payload
|
||||
# deliberately avoids when_thinking_enabled/disabled so background
|
||||
# callers that request thinking_enabled=False cannot synthesize an
|
||||
# invalid disabled/minimal combination in the model factory.
|
||||
"extra_body": {
|
||||
"thinking": {
|
||||
"type": "enabled",
|
||||
# Avoid preserved-thinking history requirements until the
|
||||
# reasoning-history abstraction handles summarization.
|
||||
"clear_thinking": True,
|
||||
},
|
||||
"tool_stream": True,
|
||||
},
|
||||
# Z.AI streams terminal usage without requiring OpenAI's undocumented
|
||||
# stream_options.include_usage request field.
|
||||
"stream_usage": False,
|
||||
},
|
||||
),
|
||||
LLMProvider(
|
||||
name="openai",
|
||||
display_name="OpenAI",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user