litellm/tests/unit/llms/sambanova/test_chat.py
devin-ai-integration[bot] e2971e0af4
refactor(llms): expose public names for private provider helpers (#45037)
* refactor(litellm): migrate private usage in llms

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(litellm): preserve Bedrock batch signature marker

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* refactor(litellm): migrate llms private usage symbols

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(litellm): preserve UUID Watsonx project IDs

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(litellm): retarget llms mocks to public names

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* refactor(litellm): limit llms changes to renames and forwarders

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(litellm): keep GCS mock client patching private Vertex auth methods

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(litellm): assert forwarder arguments and type forwarder signatures

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: mateo <mateo@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-07 08:49:25 -07:00

176 lines
5.6 KiB
Python

"""
Unit tests for SambaNova chat message transformation
"""
import asyncio
import importlib
import pytest
import litellm
from litellm.llms.sambanova.chat import SambanovaConfig
from tests._vcr_conftest_common import install_live_call_probe, record_vcr_outcome
class TestSambanovaContentListHandling:
"""
Test that SambaNova properly transforms content lists to strings
"""
def test_content_list_to_string_transformation(self):
"""
Test content list with text objects is converted to string.
SambaNova API doesn't support content as a list - only string content.
"""
config = SambanovaConfig()
messages = [
{
"role": "user",
"content": [{"type": "text", "text": "Hello, how are you?"}],
}
]
transformed_messages = config.transform_messages(
messages=messages, model="sambanova/gpt-oss-120b", is_async=False
)
assert len(transformed_messages) == 1
assert transformed_messages[0]["role"] == "user"
assert isinstance(transformed_messages[0]["content"], str)
assert transformed_messages[0]["content"] == "Hello, how are you?"
def test_content_list_multiple_text_blocks(self):
"""
Test content list with multiple text blocks is converted to concatenated string.
"""
config = SambanovaConfig()
messages = [
{
"role": "user",
"content": [
{"type": "text", "text": "Hello, "},
{"type": "text", "text": "how are you?"},
],
}
]
transformed_messages = config.transform_messages(
messages=messages, model="sambanova/gpt-oss-120b", is_async=False
)
assert transformed_messages[0]["content"] == "Hello, how are you?"
def test_string_content_unchanged(self):
"""
Test that string content is passed through unchanged.
"""
config = SambanovaConfig()
messages = [{"role": "user", "content": "Hello, how are you?"}]
transformed_messages = config.transform_messages(
messages=messages, model="sambanova/gpt-oss-120b", is_async=False
)
assert transformed_messages[0]["content"] == "Hello, how are you?"
def test_multiple_messages_transformation(self):
"""
Test transformation of multiple messages with mixed content types.
"""
config = SambanovaConfig()
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{
"role": "user",
"content": [{"type": "text", "text": "What is the weather?"}],
},
{"role": "assistant", "content": "I need your location."},
{
"role": "user",
"content": [
{"type": "text", "text": "I'm in "},
{"type": "text", "text": "San Francisco"},
],
},
]
transformed_messages = config.transform_messages(
messages=messages, model="sambanova/gpt-oss-120b", is_async=False
)
assert len(transformed_messages) == 4
assert transformed_messages[0]["content"] == "You are a helpful assistant."
assert transformed_messages[1]["content"] == "What is the weather?"
assert transformed_messages[2]["content"] == "I need your location."
assert transformed_messages[3]["content"] == "I'm in San Francisco"
@pytest.fixture(autouse=True)
def _vcr_outcome_gate(request, vcr):
install_live_call_probe(request, vcr)
yield
record_vcr_outcome(request, vcr)
@pytest.fixture(scope="session")
def event_loop():
try:
loop = asyncio.get_running_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
yield loop
loop.close()
@pytest.fixture(scope="function", autouse=True)
def setup_and_teardown(event_loop):
import litellm
original_state = {}
for attr in (
"callbacks",
"success_callback",
"failure_callback",
"_async_success_callback",
"_async_failure_callback",
):
if hasattr(litellm, attr):
val = getattr(litellm, attr)
original_state[attr] = val.copy() if val else []
for attr in _SCALAR_DEFAULTS:
if hasattr(litellm, attr):
original_state[attr] = getattr(litellm, attr)
from litellm.litellm_core_utils.logging_worker import GLOBAL_LOGGING_WORKER
asyncio.run(GLOBAL_LOGGING_WORKER.clear_queue())
importlib.reload(litellm)
asyncio.set_event_loop(event_loop)
yield
for attr, original_value in original_state.items():
if hasattr(litellm, attr):
setattr(litellm, attr, original_value)
pending = asyncio.all_tasks(event_loop)
for task in pending:
task.cancel()
if pending:
event_loop.run_until_complete(asyncio.gather(*pending, return_exceptions=True))
_SCALAR_DEFAULTS = {
"num_retries": getattr(litellm, "num_retries", None),
"set_verbose": getattr(litellm, "set_verbose", False),
"cache": getattr(litellm, "cache", None),
"allowed_fails": getattr(litellm, "allowed_fails", 3),
"disable_aiohttp_transport": getattr(litellm, "disable_aiohttp_transport", False),
"force_ipv4": getattr(litellm, "force_ipv4", False),
"drop_params": getattr(litellm, "drop_params", None),
"modify_params": getattr(litellm, "modify_params", False),
"api_base": getattr(litellm, "api_base", None),
"api_key": getattr(litellm, "api_key", None),
"cohere_key": getattr(litellm, "cohere_key", None),
}