mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-13 23:11:40 +00:00
fix(responses): pass extra_body through responses-to-completion bridge (#20982)
extra_body was silently dropped when calling litellm.responses() for models using the completion bridge. The parameter is accepted as an explicit kwarg in responses(), so it's not included in **kwargs, and the handler/transformation functions didn't accept or forward it. Changes: - Pass extra_body from responses() to response_api_handler() - Add extra_body parameter to response_api_handler() and forward it to the transformation function - Add extra_body parameter to transform_responses_api_request_to_chat_completion_request() and include it in the litellm_completion_request dict - Add 5 regression tests verifying extra_body flows correctly
This commit is contained in:
parent
9cee51abb9
commit
557a2defb5
4 changed files with 105 additions and 0 deletions
|
|
@ -31,6 +31,7 @@ class LiteLLMCompletionTransformationHandler:
|
|||
_is_async: bool = False,
|
||||
stream: Optional[bool] = None,
|
||||
extra_headers: Optional[Dict[str, Any]] = None,
|
||||
extra_body: Optional[Dict[str, Any]] = None,
|
||||
**kwargs,
|
||||
) -> Union[
|
||||
ResponsesAPIResponse,
|
||||
|
|
@ -47,6 +48,7 @@ class LiteLLMCompletionTransformationHandler:
|
|||
custom_llm_provider=custom_llm_provider,
|
||||
stream=stream,
|
||||
extra_headers=extra_headers,
|
||||
extra_body=extra_body,
|
||||
**kwargs,
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ class LiteLLMCompletionResponsesConfig:
|
|||
custom_llm_provider: Optional[str] = None,
|
||||
stream: Optional[bool] = None,
|
||||
extra_headers: Optional[Dict[str, Any]] = None,
|
||||
extra_body: Optional[Dict[str, Any]] = None,
|
||||
**kwargs,
|
||||
) -> dict:
|
||||
"""
|
||||
|
|
@ -215,6 +216,7 @@ class LiteLLMCompletionResponsesConfig:
|
|||
# litellm specific params
|
||||
"custom_llm_provider": custom_llm_provider,
|
||||
"extra_headers": extra_headers,
|
||||
"extra_body": extra_body,
|
||||
}
|
||||
|
||||
# Responses API `Completed` events require usage, we pass `stream_options` to litellm.completion to include usage
|
||||
|
|
|
|||
|
|
@ -681,6 +681,7 @@ def responses(
|
|||
_is_async=_is_async,
|
||||
stream=stream,
|
||||
extra_headers=extra_headers,
|
||||
extra_body=extra_body,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
|
|
|
|||
100
tests/test_litellm/test_extra_body_responses_bridge.py
Normal file
100
tests/test_litellm/test_extra_body_responses_bridge.py
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
"""
|
||||
Regression tests for #20982 — ``extra_body`` is not passed through the
|
||||
responses-to-completion bridge.
|
||||
|
||||
When calling ``litellm.responses()`` with ``extra_body`` for a model
|
||||
that uses the completion bridge, the ``extra_body`` parameter was silently
|
||||
dropped because:
|
||||
1. It's an explicit parameter, so it's not in ``**kwargs``
|
||||
2. The handler and transformation functions didn't accept/forward it
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(
|
||||
0, os.path.abspath("../..")
|
||||
) # Adds the parent directory to the system path
|
||||
|
||||
from litellm.responses.litellm_completion_transformation.transformation import (
|
||||
LiteLLMCompletionResponsesConfig,
|
||||
)
|
||||
|
||||
|
||||
class TestExtraBodyResponsesBridge:
|
||||
"""Verify ``extra_body`` flows through the responses-to-completion
|
||||
transformation."""
|
||||
|
||||
def test_extra_body_included_in_completion_request(self):
|
||||
"""extra_body should appear in the transformed completion request."""
|
||||
extra_body = {"provider": {"order": ["Together"], "allow_fallbacks": False}}
|
||||
result = LiteLLMCompletionResponsesConfig.transform_responses_api_request_to_chat_completion_request(
|
||||
model="openrouter/test-model",
|
||||
input="Hello",
|
||||
responses_api_request={},
|
||||
custom_llm_provider="openrouter",
|
||||
stream=False,
|
||||
extra_headers=None,
|
||||
extra_body=extra_body,
|
||||
)
|
||||
assert result.get("extra_body") == extra_body
|
||||
|
||||
def test_extra_body_none_by_default(self):
|
||||
"""When not provided, extra_body should be None in the request."""
|
||||
result = LiteLLMCompletionResponsesConfig.transform_responses_api_request_to_chat_completion_request(
|
||||
model="openrouter/test-model",
|
||||
input="Hello",
|
||||
responses_api_request={},
|
||||
custom_llm_provider="openrouter",
|
||||
stream=False,
|
||||
extra_headers=None,
|
||||
)
|
||||
assert result.get("extra_body") is None
|
||||
|
||||
def test_extra_body_preserved_with_other_params(self):
|
||||
"""extra_body should coexist with other parameters like
|
||||
extra_headers, temperature, etc."""
|
||||
extra_body = {"custom_key": "custom_value"}
|
||||
extra_headers = {"X-Custom": "header"}
|
||||
result = LiteLLMCompletionResponsesConfig.transform_responses_api_request_to_chat_completion_request(
|
||||
model="test-model",
|
||||
input="Hello",
|
||||
responses_api_request={"temperature": 0.7, "max_output_tokens": 100},
|
||||
custom_llm_provider=None,
|
||||
stream=True,
|
||||
extra_headers=extra_headers,
|
||||
extra_body=extra_body,
|
||||
)
|
||||
assert result["extra_body"] == extra_body
|
||||
assert result["extra_headers"] == extra_headers
|
||||
assert result["temperature"] == 0.7
|
||||
assert result["max_tokens"] == 100
|
||||
|
||||
def test_extra_body_empty_dict(self):
|
||||
"""An empty extra_body dict should still be passed through."""
|
||||
result = LiteLLMCompletionResponsesConfig.transform_responses_api_request_to_chat_completion_request(
|
||||
model="test-model",
|
||||
input="Hello",
|
||||
responses_api_request={},
|
||||
extra_body={},
|
||||
)
|
||||
assert result.get("extra_body") == {}
|
||||
|
||||
def test_extra_body_nested_dict(self):
|
||||
"""Deeply nested extra_body should be preserved as-is."""
|
||||
extra_body = {
|
||||
"provider": {
|
||||
"order": ["Together", "Fireworks"],
|
||||
"allow_fallbacks": False,
|
||||
"quantizations": ["fp16"],
|
||||
},
|
||||
"transforms": ["middle-out"],
|
||||
}
|
||||
result = LiteLLMCompletionResponsesConfig.transform_responses_api_request_to_chat_completion_request(
|
||||
model="openrouter/model",
|
||||
input="Test",
|
||||
responses_api_request={},
|
||||
extra_body=extra_body,
|
||||
)
|
||||
assert result["extra_body"] == extra_body
|
||||
assert result["extra_body"]["provider"]["order"] == ["Together", "Fireworks"]
|
||||
Loading…
Add table
Reference in a new issue