chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
import openai
|
||||
import pytest
|
||||
import requests
|
||||
|
||||
|
||||
class TestOpenAICompatibility:
|
||||
"""Test that the rayllm are compatible with the OpenAI API"""
|
||||
|
||||
def test_models(self, testing_model): # noqa: F811
|
||||
client, model = testing_model
|
||||
models = client.models.list()
|
||||
assert len(models.data) == 1, "Only the test model should be returned"
|
||||
assert models.data[0].id == model, "The test model id should match"
|
||||
assert models.data[0].metadata["input_modality"] == "text"
|
||||
|
||||
def test_completions(self, testing_model): # noqa: F811
|
||||
client, model = testing_model
|
||||
completion = client.completions.create(
|
||||
model=model,
|
||||
prompt="Hello world",
|
||||
max_tokens=2,
|
||||
)
|
||||
assert completion.model == model
|
||||
assert completion.model
|
||||
assert completion.choices[0].text == "test_0 test_1"
|
||||
|
||||
def test_chat(self, testing_model): # noqa: F811
|
||||
client, model = testing_model
|
||||
# create a chat completion
|
||||
chat_completion = client.chat.completions.create(
|
||||
model=model,
|
||||
messages=[{"role": "user", "content": "Hello world"}],
|
||||
)
|
||||
assert chat_completion
|
||||
assert chat_completion.usage
|
||||
assert chat_completion.id
|
||||
assert isinstance(chat_completion.choices, list)
|
||||
assert chat_completion.choices[0].message.content
|
||||
|
||||
def test_completions_missing_model(self, testing_model): # noqa: F811
|
||||
client, _ = testing_model
|
||||
with pytest.raises(openai.NotFoundError) as exc_info:
|
||||
client.completions.create(
|
||||
model="notarealmodel",
|
||||
prompt="Hello world",
|
||||
)
|
||||
assert "Could not find" in str(exc_info.value)
|
||||
|
||||
def test_chat_missing_model(self, testing_model): # noqa: F811
|
||||
client, _ = testing_model
|
||||
with pytest.raises(openai.NotFoundError) as exc_info:
|
||||
client.chat.completions.create(
|
||||
model="notarealmodel",
|
||||
messages=[{"role": "user", "content": "Hello world"}],
|
||||
)
|
||||
assert "Could not find" in str(exc_info.value)
|
||||
|
||||
def test_completions_stream(self, testing_model): # noqa: F811
|
||||
client, model = testing_model
|
||||
i = 0
|
||||
for completion in client.completions.create(
|
||||
model=model,
|
||||
prompt="Hello world",
|
||||
stream=True,
|
||||
):
|
||||
i += 1
|
||||
assert completion
|
||||
assert completion.id
|
||||
assert isinstance(completion.choices, list)
|
||||
assert isinstance(completion.choices[0].text, str)
|
||||
assert i > 4
|
||||
|
||||
def test_chat_stream(self, testing_model): # noqa: F811
|
||||
client, model = testing_model
|
||||
i = 0
|
||||
for chat_completion in client.chat.completions.create(
|
||||
model=model,
|
||||
messages=[{"role": "user", "content": "Hello world"}],
|
||||
stream=True,
|
||||
stream_options=dict(
|
||||
include_usage=True,
|
||||
),
|
||||
temperature=0.4,
|
||||
frequency_penalty=0.02,
|
||||
max_tokens=5,
|
||||
):
|
||||
if i == 0:
|
||||
assert chat_completion
|
||||
assert chat_completion.id
|
||||
assert isinstance(chat_completion.choices, list)
|
||||
assert chat_completion.choices[0].delta.role
|
||||
else:
|
||||
assert chat_completion
|
||||
assert chat_completion.id
|
||||
assert isinstance(chat_completion.choices, list)
|
||||
assert chat_completion.choices[0].delta == {} or hasattr(
|
||||
chat_completion.choices[0].delta, "content"
|
||||
)
|
||||
i += 1
|
||||
|
||||
def test_completions_stream_missing_model(self, testing_model): # noqa: F811
|
||||
client, _ = testing_model
|
||||
with pytest.raises(openai.NotFoundError) as exc_info:
|
||||
for _chat_completion in client.completions.create(
|
||||
model="notarealmodel",
|
||||
prompt="Hello world",
|
||||
stream=True,
|
||||
):
|
||||
pass
|
||||
assert "Could not find" in str(exc_info.value)
|
||||
|
||||
def test_chat_stream_missing_model(self, testing_model): # noqa: F811
|
||||
client, _ = testing_model
|
||||
with pytest.raises(openai.NotFoundError) as exc_info:
|
||||
for _chat_completion in client.chat.completions.create(
|
||||
model="notarealmodel",
|
||||
messages=[{"role": "user", "content": "Hello world"}],
|
||||
stream=True,
|
||||
):
|
||||
pass
|
||||
assert "Could not find" in str(exc_info.value)
|
||||
|
||||
def test_chat_without_model_parameter(self, testing_model): # noqa: F811
|
||||
"""Test that chat completions work without model parameter when single model configured.
|
||||
|
||||
This follows vLLM's behavior from PR https://github.com/vllm-project/vllm/pull/13568
|
||||
"""
|
||||
client, expected_model = testing_model
|
||||
# Use requests directly since OpenAI client requires model parameter
|
||||
response = requests.post(
|
||||
f"{client.base_url}chat/completions",
|
||||
json={
|
||||
"messages": [{"role": "user", "content": "Hello world"}],
|
||||
},
|
||||
headers={"Authorization": f"Bearer {client.api_key}"},
|
||||
)
|
||||
assert (
|
||||
response.status_code == 200
|
||||
), f"Expected 200, got {response.status_code}: {response.text}"
|
||||
data = response.json()
|
||||
assert data["model"] == expected_model
|
||||
assert data["choices"][0]["message"]["content"]
|
||||
|
||||
@pytest.mark.skipif(
|
||||
os.environ.get("RAY_SERVE_LLM_ENABLE_DIRECT_STREAMING") == "1",
|
||||
reason="Direct streaming currently supports one LLM config.",
|
||||
)
|
||||
def test_chat_without_model_parameter_multiple_models(
|
||||
self, testing_multiple_models
|
||||
): # noqa: F811
|
||||
"""Test that chat completions return 400 when model not specified with multiple models.
|
||||
|
||||
When multiple models are configured and the model parameter is not specified,
|
||||
an HTTP 400 Bad Request should be returned.
|
||||
"""
|
||||
client, model_ids = testing_multiple_models
|
||||
assert len(model_ids) > 1, "This test requires multiple models"
|
||||
# Use requests directly since OpenAI client requires model parameter
|
||||
response = requests.post(
|
||||
f"{client.base_url}chat/completions",
|
||||
json={
|
||||
"messages": [{"role": "user", "content": "Hello world"}],
|
||||
},
|
||||
headers={"Authorization": f"Bearer {client.api_key}"},
|
||||
)
|
||||
assert (
|
||||
response.status_code == 400
|
||||
), f"Expected 400, got {response.status_code}: {response.text}"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(pytest.main(["-v", __file__]))
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestOpenAICompatibilityNoAcceleratorType:
|
||||
"""Test that rayllm is compatible with OpenAI API without specifying accelerator_type"""
|
||||
|
||||
def test_models_no_accelerator_type(
|
||||
self, testing_model_no_accelerator
|
||||
): # noqa: F811
|
||||
"""Check model listing without accelerator_type"""
|
||||
client, model = testing_model_no_accelerator
|
||||
models = client.models.list()
|
||||
assert len(models.data) == 1, "Only the test model should be returned"
|
||||
assert models.data[0].id == model, "The test model id should match"
|
||||
|
||||
def test_completions_no_accelerator_type(
|
||||
self, testing_model_no_accelerator
|
||||
): # noqa: F811
|
||||
"""Check completions without accelerator_type"""
|
||||
client, model = testing_model_no_accelerator
|
||||
completion = client.completions.create(
|
||||
model=model,
|
||||
prompt="Hello world",
|
||||
max_tokens=2,
|
||||
)
|
||||
assert completion.model == model
|
||||
assert completion.model
|
||||
assert completion.choices[0].text == "test_0 test_1"
|
||||
|
||||
def test_chat_no_accelerator_type(self, testing_model_no_accelerator): # noqa: F811
|
||||
"""Check chat completions without accelerator_type"""
|
||||
client, model = testing_model_no_accelerator
|
||||
chat_completion = client.chat.completions.create(
|
||||
model=model,
|
||||
messages=[{"role": "user", "content": "Hello world"}],
|
||||
)
|
||||
assert chat_completion
|
||||
assert chat_completion.usage
|
||||
assert chat_completion.id
|
||||
assert isinstance(chat_completion.choices, list)
|
||||
assert chat_completion.choices[0].message.content
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(pytest.main(["-v", __file__]))
|
||||
Reference in New Issue
Block a user