Files
plyngent/tests/test_runtime/test_client_factory.py
T

153 lines
5.6 KiB
Python

from __future__ import annotations
import pytest
from plyngent.config.models import (
AnthropicProvider,
DeepseekProvider,
ModelConfig,
OpenAICompatibleProvider,
OpenAIProvider,
)
from plyngent.lmproto.deepseek import DeepseekOpenAIClient
from plyngent.lmproto.openai import OpenAIClient
from plyngent.lmproto.openai_compatible import OpenAICompatibleClient
from plyngent.runtime import ProviderNotSupportedError, create_client, provider_to_openai_config
def test_openai_provider_defaults_base_url() -> None:
provider = OpenAIProvider(access_key_or_token="sk-test")
config = provider_to_openai_config(provider)
assert config.access_key_or_token == "sk-test"
assert config.base_url == "https://api.openai.com/v1"
from plyngent.lmproto.openai import OpenAIClient
client = create_client(provider)
assert isinstance(client, OpenAIClient)
assert client.kind == "responses"
def test_openai_provider_tools_passed_to_wrapper() -> None:
from plyngent.lmproto.openai import OpenAIClient
provider = OpenAIProvider(
access_key_or_token="sk-test",
provider_tools=[{"type": "web_search"}],
)
client = create_client(provider)
assert isinstance(client, OpenAIClient)
def test_openai_compatible_requires_url() -> None:
provider = OpenAICompatibleProvider(access_key_or_token="sk-test")
with pytest.raises(ProviderNotSupportedError, match="url"):
_ = create_client(provider)
def test_openai_compatible_client() -> None:
provider = OpenAICompatibleProvider(
access_key_or_token="sk-test",
url="https://example.com/v1",
)
client = create_client(provider)
assert isinstance(client, OpenAICompatibleClient)
assert not isinstance(client, OpenAIClient)
assert provider_to_openai_config(provider).base_url == "https://example.com/v1"
def test_deepseek_openai_convention() -> None:
provider = DeepseekProvider(access_key_or_token="sk-test")
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-v4-pro" in provider.models
def test_deepseek_ignores_legacy_convention_extra() -> None:
provider = DeepseekProvider(
access_key_or_token="sk-test",
extras={"convention": "anthropic"},
)
client = create_client(provider)
assert isinstance(client, DeepseekOpenAIClient)
def test_deepseek_responses_convention() -> None:
from plyngent.lmproto.deepseek import DeepseekResponsesClient
provider = DeepseekProvider(access_key_or_token="sk-test", convention="responses")
client = create_client(provider)
assert isinstance(client, DeepseekResponsesClient)
assert client.kind == "responses"
assert provider_to_openai_config(provider).base_url == "https://api.deepseek.com"
def test_deepseek_default_and_legacy_conventions_stay_chat() -> None:
from plyngent.lmproto.deepseek import DeepseekResponsesClient
default_client = create_client(DeepseekProvider(access_key_or_token="sk-test"))
assert isinstance(default_client, DeepseekOpenAIClient)
assert not isinstance(default_client, DeepseekResponsesClient)
legacy = DeepseekProvider(access_key_or_token="sk-test", convention="anthropic")
assert isinstance(create_client(legacy), DeepseekOpenAIClient)
def test_deepseek_model_level_convention_override() -> None:
from plyngent.lmproto.deepseek import DeepseekResponsesClient
provider = DeepseekProvider(
access_key_or_token="sk-test",
models={
"deepseek-v4-flash": ModelConfig(convention="responses"),
"deepseek-v4-pro": ModelConfig(),
},
)
flash = create_client(provider, model="deepseek-v4-flash")
assert isinstance(flash, DeepseekResponsesClient)
assert flash.kind == "responses"
pro = create_client(provider, model="deepseek-v4-pro")
assert isinstance(pro, DeepseekOpenAIClient)
def test_anthropic_client_created() -> None:
from plyngent.lmproto.anthropic import AnthropicClient
provider = AnthropicProvider(access_key_or_token="sk-test", timeout=30)
client = create_client(provider)
assert isinstance(client, AnthropicClient)
assert client.kind == "messages"
# timeout is passed through to the niquests session
assert client.session.timeout == 30
def test_model_level_preset_url_overrides_parent() -> None:
provider = OpenAICompatibleProvider(
access_key_or_token="sk-test",
url="https://gateway.example/v1",
models={
"gpt": ModelConfig(preset="openai", url="https://api.openai.com/v1"),
"qwen": ModelConfig(),
},
)
openai_client = create_client(provider, model="gpt")
assert openai_client.kind == "responses"
assert provider_to_openai_config(provider, model="gpt").base_url == "https://api.openai.com/v1"
compat_client = create_client(provider, model="qwen")
assert isinstance(compat_client, OpenAICompatibleClient)
assert provider_to_openai_config(provider, model="qwen").base_url == "https://gateway.example/v1"
def test_model_level_anthropic_preset() -> None:
from plyngent.lmproto.anthropic import AnthropicClient
provider = OpenAICompatibleProvider(
access_key_or_token="sk-test",
url="https://gateway.example/v1",
models={"claude": ModelConfig(preset="anthropic", url="https://api.anthropic.com/v1")},
)
client = create_client(provider, model="claude")
assert isinstance(client, AnthropicClient)
assert client.kind == "messages"