mirror of
https://github.com/NCBM/plyngent.git
synced 2026-11-07 07:17:54 +08:00
config: rename the DeepSeek flash model to deepseek-flash
DeepSeek dropped the `v4` prefix from its flash model, and the old id stays valid only as a compatibility alias. Seed the default catalog with the current name so a provider that omits `models` no longer offers a deprecated id, and follow the rename in the wire fixtures and the minimal config template. An explicit `deepseek-v4-flash` in TOML still passes through unchanged.
This commit is contained in:
@@ -57,7 +57,7 @@ _MINIMAL_CONFIG = """\
|
||||
# [providers.deepseek]
|
||||
# preset = "deepseek"
|
||||
# access_key_or_token = "sk-..."
|
||||
# # models default to deepseek-v4-flash and deepseek-v4-pro if omitted
|
||||
# # models default to deepseek-flash and deepseek-v4-pro if omitted
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -366,7 +366,7 @@ class AnthropicProvider(ProviderConfig, tag="anthropic"):
|
||||
def _default_deepseek_models() -> dict[str, ModelConfig]:
|
||||
"""Current DeepSeek text catalog when TOML omits ``models``."""
|
||||
return {
|
||||
"deepseek-v4-flash": ModelConfig(text=True),
|
||||
"deepseek-flash": ModelConfig(text=True),
|
||||
"deepseek-v4-pro": ModelConfig(text=True),
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ class DeepseekAnthropicClient(AnthropicClient):
|
||||
(see https://api-docs.deepseek.com/guides/anthropic_api). ``x-api-key`` is fully
|
||||
supported; ``anthropic-version`` / ``anthropic-beta`` headers are ignored by the
|
||||
server but harmless. Model ids map server-side: ``claude-opus*`` → ``deepseek-v4-pro``,
|
||||
``claude-haiku*`` / ``claude-sonnet*`` → ``deepseek-v4-flash``, unknown names →
|
||||
``deepseek-v4-flash``; real DeepSeek ids pass through as-is.
|
||||
``claude-haiku*`` / ``claude-sonnet*`` → ``deepseek-flash``, unknown names →
|
||||
``deepseek-flash``; real DeepSeek ids pass through as-is.
|
||||
|
||||
``GET /models`` is not documented on the ``/anthropic`` base, so ``models()``
|
||||
returns an empty list and model selection stays config-driven.
|
||||
|
||||
@@ -167,7 +167,7 @@ def _reasoning_response(
|
||||
return Response(
|
||||
id="resp_r",
|
||||
created_at=1,
|
||||
model="deepseek-v4-flash",
|
||||
model="deepseek-flash",
|
||||
output=output,
|
||||
reasoning=top_level,
|
||||
)
|
||||
|
||||
@@ -430,7 +430,7 @@ async def test_dispatch_stream_failed_raises_with_error_detail() -> None:
|
||||
"id": "resp_1",
|
||||
"object": "response",
|
||||
"created_at": 1,
|
||||
"model": "deepseek-v4-flash",
|
||||
"model": "deepseek-flash",
|
||||
"status": "failed",
|
||||
"output": [],
|
||||
"error": {"code": "rate_limit_exceeded", "message": "slow down"},
|
||||
|
||||
@@ -46,8 +46,8 @@ def test_read_valid_config() -> None:
|
||||
assert isinstance(providers["test3"], AnthropicProvider)
|
||||
assert isinstance(providers["foo1"], DeepseekProvider)
|
||||
# TOML omitted models → DeepSeek defaults.
|
||||
assert set(providers["foo1"].models) == {"deepseek-v4-flash", "deepseek-v4-pro"}
|
||||
assert providers["foo1"].models["deepseek-v4-flash"].text is True
|
||||
assert set(providers["foo1"].models) == {"deepseek-flash", "deepseek-v4-pro"}
|
||||
assert providers["foo1"].models["deepseek-flash"].text is True
|
||||
db = config.database
|
||||
assert db["implementation"] == "sqlite"
|
||||
assert db["url"] == ":memory:"
|
||||
@@ -57,7 +57,7 @@ def test_read_valid_config() -> None:
|
||||
|
||||
def test_deepseek_default_models_on_construct() -> None:
|
||||
provider = DeepseekProvider(access_key_or_token="sk-test")
|
||||
assert set(provider.models) == {"deepseek-v4-flash", "deepseek-v4-pro"}
|
||||
assert set(provider.models) == {"deepseek-flash", "deepseek-v4-pro"}
|
||||
|
||||
|
||||
def test_openai_default_models_on_construct() -> None:
|
||||
@@ -179,7 +179,7 @@ preset = "deepseek"
|
||||
access_key_or_token = "sk-test"
|
||||
|
||||
[providers.ds.models]
|
||||
"deepseek-v4-flash" = { text = true, convention = "responses" }
|
||||
"deepseek-flash" = { text = true, convention = "responses" }
|
||||
"deepseek-v4-pro" = { text = true }
|
||||
""",
|
||||
encoding="utf-8",
|
||||
@@ -187,7 +187,7 @@ access_key_or_token = "sk-test"
|
||||
config = plyngent.config.load(path)
|
||||
provider = config.providers["ds"]
|
||||
assert isinstance(provider, DeepseekProvider)
|
||||
assert provider.models["deepseek-v4-flash"].convention == "responses"
|
||||
assert provider.models["deepseek-flash"].convention == "responses"
|
||||
assert provider.models["deepseek-v4-pro"].convention == ""
|
||||
|
||||
|
||||
@@ -314,7 +314,7 @@ reasoning_effort = "high"
|
||||
|
||||
[providers.ds.models]
|
||||
"deepseek-v4-pro" = { text = true, reasoning_effort = "max", thinking_budget_tokens = 32000 }
|
||||
"deepseek-v4-flash" = { text = true }
|
||||
"deepseek-flash" = { text = true }
|
||||
""",
|
||||
encoding="utf-8",
|
||||
)
|
||||
@@ -327,8 +327,8 @@ reasoning_effort = "high"
|
||||
assert provider.thinking_budget_tokens == 0
|
||||
assert provider.models["deepseek-v4-pro"].reasoning_effort == "max"
|
||||
assert provider.models["deepseek-v4-pro"].thinking_budget_tokens == 32000
|
||||
assert provider.models["deepseek-v4-flash"].reasoning_effort == ""
|
||||
assert provider.models["deepseek-v4-flash"].thinking_budget_tokens == 0
|
||||
assert provider.models["deepseek-flash"].reasoning_effort == ""
|
||||
assert provider.models["deepseek-flash"].thinking_budget_tokens == 0
|
||||
|
||||
|
||||
def test_reasoning_effort_defaults_are_unset(tmp_path: Path) -> None:
|
||||
|
||||
@@ -17,7 +17,7 @@ def _sample_message_body() -> bytes:
|
||||
return msgspec.json.encode(
|
||||
AnthropicMessageResponse(
|
||||
id="msg_1",
|
||||
model="deepseek-v4-flash",
|
||||
model="deepseek-flash",
|
||||
content=[AnthropicResponseText(text="hello world")],
|
||||
stop_reason="end_turn",
|
||||
usage=AnthropicUsage(input_tokens=9, output_tokens=3),
|
||||
@@ -52,7 +52,7 @@ async def test_client_messages_create(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
return _Resp()
|
||||
|
||||
monkeypatch.setattr(client.session, "post", fake_post)
|
||||
result = await client.messages(AnthropicMessagesParam(model="deepseek-v4-flash", messages=[]))
|
||||
result = await client.messages(AnthropicMessagesParam(model="deepseek-flash", messages=[]))
|
||||
assert isinstance(result, AnthropicMessageResponse)
|
||||
assert result.content[0].text == "hello world"
|
||||
assert result.usage.output_tokens == 3
|
||||
@@ -78,7 +78,7 @@ async def test_client_messages_stream(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
return _Resp()
|
||||
|
||||
monkeypatch.setattr(client.session, "post", fake_post)
|
||||
stream = await client.messages(AnthropicMessagesParam(model="deepseek-v4-flash", messages=[]), stream=True)
|
||||
stream = await client.messages(AnthropicMessagesParam(model="deepseek-flash", messages=[]), stream=True)
|
||||
events = [event async for event in stream]
|
||||
assert len(events) == 2
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from plyngent.lmproto.openai_compatible.config import OpenAIConfig
|
||||
|
||||
def _sample_response_body() -> bytes:
|
||||
return (
|
||||
b'{"id":"resp_1","object":"response","created_at":1,"model":"deepseek-v4-flash",'
|
||||
b'{"id":"resp_1","object":"response","created_at":1,"model":"deepseek-flash",'
|
||||
b'"status":"completed","output":['
|
||||
b'{"id":"msg_1","type":"message","role":"assistant","status":"completed",'
|
||||
b'"content":[{"type":"output_text","text":"hello from deepseek","annotations":[]}]}'
|
||||
@@ -40,7 +40,7 @@ async def test_client_responses_create(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
return _Resp()
|
||||
|
||||
monkeypatch.setattr(client.session, "post", fake_post)
|
||||
result = await client.responses(ResponsesCreateParam(model="deepseek-v4-flash", input="hi"))
|
||||
result = await client.responses(ResponsesCreateParam(model="deepseek-flash", input="hi"))
|
||||
assert isinstance(result, Response)
|
||||
assert response_output_text(result) == "hello from deepseek"
|
||||
|
||||
@@ -62,7 +62,7 @@ async def test_client_responses_stream_stops_at_terminal(monkeypatch: pytest.Mon
|
||||
yield (
|
||||
b'data: {"type":"response.completed","sequence_number":2,'
|
||||
b'"response":{"id":"resp_1","object":"response","created_at":1,'
|
||||
b'"model":"deepseek-v4-flash","status":"completed","output":[]}}'
|
||||
b'"model":"deepseek-flash","status":"completed","output":[]}}'
|
||||
)
|
||||
# Anything after the terminal event must not be consumed.
|
||||
yield b'data: {"type":"response.output_text.delta","delta":"ignored"}'
|
||||
@@ -77,7 +77,7 @@ async def test_client_responses_stream_stops_at_terminal(monkeypatch: pytest.Mon
|
||||
|
||||
monkeypatch.setattr(client.session, "post", fake_post)
|
||||
stream = await client.responses(
|
||||
ResponsesCreateParam(model="deepseek-v4-flash", input="hi"),
|
||||
ResponsesCreateParam(model="deepseek-flash", input="hi"),
|
||||
stream=True,
|
||||
)
|
||||
events = [event async for event in stream]
|
||||
|
||||
@@ -169,12 +169,12 @@ async def test_session_llm_remembered(store: MemoryStore) -> None:
|
||||
session = await store.create_session(
|
||||
name="llm",
|
||||
provider_name="deepseek",
|
||||
model="deepseek-v4-flash",
|
||||
model="deepseek-flash",
|
||||
)
|
||||
row = await store.get_session(session.sid)
|
||||
assert row is not None
|
||||
assert row.provider_name == "deepseek"
|
||||
assert row.model == "deepseek-v4-flash"
|
||||
assert row.model == "deepseek-flash"
|
||||
updated = await store.update_session_llm(session.sid, model="deepseek-v4-pro")
|
||||
assert updated.provider_name == "deepseek"
|
||||
assert updated.model == "deepseek-v4-pro"
|
||||
|
||||
@@ -60,7 +60,7 @@ def test_deepseek_openai_convention() -> None:
|
||||
client = create_client(provider)
|
||||
assert isinstance(client, DeepseekOpenAIClient)
|
||||
assert provider_to_openai_config(provider).base_url == "https://api.deepseek.com"
|
||||
assert "deepseek-v4-flash" in provider.models
|
||||
assert "deepseek-flash" in provider.models
|
||||
assert "deepseek-v4-pro" in provider.models
|
||||
|
||||
|
||||
@@ -129,13 +129,13 @@ def test_deepseek_model_level_anthropic_convention() -> None:
|
||||
access_key_or_token="sk-test",
|
||||
models={
|
||||
"claude-proxy": ModelConfig(convention="anthropic"),
|
||||
"deepseek-v4-flash": ModelConfig(),
|
||||
"deepseek-flash": ModelConfig(),
|
||||
},
|
||||
)
|
||||
proxy = create_client(provider, model="claude-proxy")
|
||||
assert isinstance(proxy, DeepseekAnthropicClient)
|
||||
assert proxy.session.base_url == "https://api.deepseek.com/anthropic"
|
||||
flash = create_client(provider, model="deepseek-v4-flash")
|
||||
flash = create_client(provider, model="deepseek-flash")
|
||||
assert isinstance(flash, DeepseekOpenAIClient)
|
||||
|
||||
|
||||
@@ -145,11 +145,11 @@ def test_deepseek_model_level_convention_override() -> None:
|
||||
provider = DeepseekProvider(
|
||||
access_key_or_token="sk-test",
|
||||
models={
|
||||
"deepseek-v4-flash": ModelConfig(convention="responses"),
|
||||
"deepseek-flash": ModelConfig(convention="responses"),
|
||||
"deepseek-v4-pro": ModelConfig(),
|
||||
},
|
||||
)
|
||||
flash = create_client(provider, model="deepseek-v4-flash")
|
||||
flash = create_client(provider, model="deepseek-flash")
|
||||
assert isinstance(flash, DeepseekResponsesClient)
|
||||
assert flash.kind == "responses"
|
||||
pro = create_client(provider, model="deepseek-v4-pro")
|
||||
|
||||
Reference in New Issue
Block a user