diff --git a/litellm/llms/fireworks_ai/responses/transformation.py b/litellm/llms/fireworks_ai/responses/transformation.py index 7f29e03ff0f..9265d12e75e 100644 --- a/litellm/llms/fireworks_ai/responses/transformation.py +++ b/litellm/llms/fireworks_ai/responses/transformation.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Final from urllib.parse import unquote import httpx +from openai.types.responses import EasyInputMessageParam, ResponseInputItemParam from litellm.llms.fireworks_ai.common_utils import ( resolve_fireworks_api_key, @@ -30,6 +31,18 @@ def _session_params(litellm_params: GenericLiteLLMParams) -> Mapping[str, object ) +def _developer_item_as_system(item: ResponseInputItemParam) -> ResponseInputItemParam: + if "role" not in item or item["role"] != "developer": + return item + return EasyInputMessageParam(role="system", content=item["content"], type="message") + + +def _developer_items_as_system(input: str | ResponseInputParam) -> str | ResponseInputParam: + if isinstance(input, str): + return input + return [_developer_item_as_system(item) for item in input] + + class FireworksAIResponsesAPIConfig(OpenAIResponsesAPIConfig): @property def custom_llm_provider(self) -> LlmProviders: @@ -65,7 +78,7 @@ class FireworksAIResponsesAPIConfig(OpenAIResponsesAPIConfig): ) -> dict: # mutable-ok: overrides the base class signature return super().transform_responses_api_request( model=resolve_fireworks_resource_name(model), - input=input, + input=_developer_items_as_system(input), response_api_optional_request_params=response_api_optional_request_params, litellm_params=litellm_params, headers=headers, diff --git a/tests/test_litellm/llms/fireworks_ai/responses/test_fireworks_ai_responses_transformation.py b/tests/test_litellm/llms/fireworks_ai/responses/test_fireworks_ai_responses_transformation.py index 8fac91ee475..e6e92824ee1 100644 --- a/tests/test_litellm/llms/fireworks_ai/responses/test_fireworks_ai_responses_transformation.py +++ b/tests/test_litellm/llms/fireworks_ai/responses/test_fireworks_ai_responses_transformation.py @@ -160,6 +160,26 @@ def test_responses_call_forwards_previous_response_id_and_store() -> None: assert body["input"][0]["call_id"] == "call_abc123" +def test_responses_call_sends_developer_items_as_system_messages() -> None: + client: Final = _mock_http_client(_fireworks_response("accounts/fireworks/models/kimi-k3")) + with patch(HTTPX_CLIENT_FACTORY, return_value=client): + litellm.responses( + model="fireworks_ai/accounts/fireworks/models/kimi-k3", + input=[ # mutable-ok: the Responses API takes input as a JSON list + {"role": "user", "content": "Hi there"}, + {"role": "developer", "content": "Answer with exactly one word."}, + {"role": "user", "content": [{"type": "input_text", "text": "What is the capital of France?"}]}, + ], + api_key="fw-test-key", + ) + _, _, body = _sent_request(client) + assert tuple(body["input"]) == ( + {"role": "user", "content": "Hi there"}, + {"role": "system", "content": "Answer with exactly one word.", "type": "message"}, + {"role": "user", "content": [{"type": "input_text", "text": "What is the capital of France?"}]}, + ) + + def test_responses_call_sends_session_affinity_for_caller_session_id() -> None: client: Final = _mock_http_client(_fireworks_response("accounts/fireworks/models/kimi-k3")) with patch(HTTPX_CLIENT_FACTORY, return_value=client):