mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-10-26 13:16:24 +00:00
fix(managed-models): map DeepSeek "minimal" effort to "low" (#6717)
The official DeepSeek Chat Completions endpoint rejects the generic "minimal" effort token (issue #4514). The declared effort contract for DeepSeek models now advertises the provider's real vocabulary (low/medium/high/max/xhigh), defaults to "low", and aliases the generic "minimal" preset onto "low" so the "flash" dialogue mode serializes a value the endpoint accepts. Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
This commit is contained in:
parent
5a9a8042b4
commit
3aa144a377
@ -95,7 +95,7 @@ def _capabilities(provider: str, model: str) -> dict[str, Any]:
|
||||
when_thinking_enabled={"extra_body": {"thinking": {"type": "enabled"}}},
|
||||
when_thinking_disabled={"extra_body": {"thinking": {"type": "disabled"}}},
|
||||
)
|
||||
result["reasoning"]["effort"] = {"values": ["high", "max"], "default": "high", "aliases": {"minimal": "high", "low": "high", "medium": "high"}}
|
||||
result["reasoning"]["effort"] = {"values": ["low", "medium", "high", "max", "xhigh"], "default": "low", "aliases": {"minimal": "low"}}
|
||||
elif provider in {"zai", "zhipu-cn"} and model in {"glm-4.5", "glm-4.6", "glm-4.7", "glm-5.3-flash"}:
|
||||
result.update(
|
||||
reasoning={"thinking": "optional", "dialect": "openai_extra_body", "history": "preserve"},
|
||||
|
||||
@ -218,7 +218,7 @@ Direct `AppConfig.from_file()` continues to read only operator configuration.
|
||||
`config/managed_model_providers.py` is the sole registry for provider IDs, labels,
|
||||
endpoints, protocols, authentication parameter mappings, adapters and request
|
||||
defaults. Capability rules match exact verified model IDs; unknown preset IDs
|
||||
have an unsupported-thinking contract, no vision and no inferred context window.
|
||||
have an unsupported-thinking contract, no vision and no inferred context window. Verified DeepSeek presets declare an effort vocabulary of `low`/`medium`/`high`/`max`/`xhigh` (default `low`) and alias the generic `minimal` preset onto `low`, so a saved per-agent `minimal` default serializes as a value the official endpoint accepts (issue #4514).
|
||||
Preset drafts cannot supply endpoints or adapter paths. Legacy custom
|
||||
`openai-compatible` records retain endpoint-based official DeepSeek detection;
|
||||
never infer that adapter from a model-name substring. Reads do not migrate the
|
||||
|
||||
@ -212,6 +212,36 @@ async def test_saved_model_streaming_replays_reasoning_and_honors_token_limit(st
|
||||
assert model_config.supports_reasoning_effort is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"effort,expected",
|
||||
[("minimal", "low"), ("low", "low"), ("medium", "medium"), ("high", "high"), ("max", "max"), ("xhigh", "xhigh")],
|
||||
)
|
||||
async def test_deepseek_effort_contract_maps_generic_effort_values(store, provider, effort, expected):
|
||||
saved = store.save(ManagedModel(provider="deepseek", model="deepseek-flash", api_key=_KEY), expected_revision=None)
|
||||
config = merge_managed_models(_base_config())
|
||||
model_config = config.get_model_config(saved.name)
|
||||
|
||||
# The official endpoint rejects the generic "minimal" token (issue #4514),
|
||||
# so the declared contract advertises the provider's real vocabulary and
|
||||
# aliases "minimal" onto "low". Parametrized over every accepted value so
|
||||
# a future rename/drop fails here, not at request time.
|
||||
assert model_config.reasoning is not None
|
||||
assert model_config.reasoning.effort is not None
|
||||
assert model_config.reasoning.effort.values == ["low", "medium", "high", "max", "xhigh"]
|
||||
assert model_config.reasoning.effort.default == "low"
|
||||
assert model_config.reasoning.effort.aliases == {"minimal": "low"}
|
||||
assert model_config.supports_reasoning_effort is True
|
||||
|
||||
model = create_chat_model(saved.name, thinking_enabled=False, reasoning_effort=effort, app_config=config, attach_tracing=False)
|
||||
await _collect(model, [HumanMessage(content="Hello")])
|
||||
|
||||
assert len(provider.requests) == 1
|
||||
body = provider.requests[0][1]
|
||||
assert body["reasoning_effort"] == expected
|
||||
assert body["thinking"] == {"type": "disabled"}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"base_url",
|
||||
[
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user