mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-14 09:03:16 +00:00
Merge d7ccd939ba into 08f2a98250
This commit is contained in:
commit
a816e19951
2 changed files with 89 additions and 0 deletions
|
|
@ -151,6 +151,36 @@ class ChatGPTResponsesAPIConfig(OpenAIResponsesAPIConfig):
|
|||
filtered["service_tier"] = service_tier
|
||||
return filtered
|
||||
|
||||
def sign_request(
|
||||
self,
|
||||
headers: dict, # mutable-ok: mirrors the base hook signature
|
||||
optional_params: dict, # mutable-ok: mirrors the base hook signature
|
||||
request_data: dict, # mutable-ok: the hook contract allows in-place body fixes
|
||||
api_base: str,
|
||||
api_key: str | None = None,
|
||||
model: str | None = None,
|
||||
stream: bool | None = None,
|
||||
fake_stream: bool | None = None,
|
||||
) -> tuple[dict, bytes | None]: # mutable-ok: mirrors the base hook signature
|
||||
# extra_body is merged into the payload after transform_responses_api_request
|
||||
# (llm_http_handler does data.update(transform_extra_body(...)) after the
|
||||
# transform), so a string input carried in extra_body re-introduces the
|
||||
# shorthand the entry wrap removed and the backend 400s again. sign_request
|
||||
# runs after the body is final, so re-apply the entry wrap's list form here.
|
||||
request_input: Final[object] = request_data.get("input")
|
||||
if isinstance(request_input, str):
|
||||
request_data["input"] = [{"role": "user", "content": request_input}] # rebind-ok: in-place final-body fix
|
||||
return super().sign_request(
|
||||
headers=headers,
|
||||
optional_params=optional_params,
|
||||
request_data=request_data,
|
||||
api_base=api_base,
|
||||
api_key=api_key,
|
||||
model=model,
|
||||
stream=stream,
|
||||
fake_stream=fake_stream,
|
||||
)
|
||||
|
||||
def transform_response_api_response(
|
||||
self,
|
||||
model: str,
|
||||
|
|
|
|||
|
|
@ -128,6 +128,65 @@ class TestChatGPTResponsesAPITransformation:
|
|||
assert isinstance(config, ChatGPTResponsesAPIConfig)
|
||||
assert config.custom_llm_provider == LlmProviders.CHATGPT
|
||||
|
||||
def test_sign_request_rewraps_string_input_reintroduced_after_transform(self):
|
||||
"""extra_body merges after transform_responses_api_request, so a string
|
||||
input merged there re-introduces the shorthand the entry wrap removed."""
|
||||
config: Final = ChatGPTResponsesAPIConfig()
|
||||
request: Final = config.transform_responses_api_request(
|
||||
model="chatgpt/gpt-6.1-sol",
|
||||
input="Reply with exactly the word: pong",
|
||||
response_api_optional_request_params={},
|
||||
litellm_params=GenericLiteLLMParams(),
|
||||
headers={},
|
||||
)
|
||||
assert request["input"] == [{"role": "user", "content": "Reply with exactly the word: pong"}]
|
||||
|
||||
# llm_http_handler merges extra_body after the transform:
|
||||
# data.update(config.transform_extra_body(extra_body=..., request=data, ...))
|
||||
request.update({"input": "Reply with exactly the word: pong"})
|
||||
|
||||
config.sign_request(
|
||||
headers={},
|
||||
optional_params={},
|
||||
request_data=request,
|
||||
api_base="https://chatgpt.com/backend-api/codex/responses",
|
||||
api_key=None,
|
||||
model="chatgpt/gpt-6.1-sol",
|
||||
)
|
||||
assert request["input"] == [{"role": "user", "content": "Reply with exactly the word: pong"}]
|
||||
|
||||
def test_sign_request_wraps_string_input_without_entry_wrap(self):
|
||||
"""The final signing hook also covers payload paths that never ran the
|
||||
entry wrap (list input fully replaced by a string via extra_body)."""
|
||||
config: Final = ChatGPTResponsesAPIConfig()
|
||||
request: Final = {
|
||||
"model": "chatgpt/gpt-6.1-sol",
|
||||
"input": "standalone shorthand",
|
||||
}
|
||||
config.sign_request(
|
||||
headers={},
|
||||
optional_params={},
|
||||
request_data=request,
|
||||
api_base="https://chatgpt.com/backend-api/codex/responses",
|
||||
api_key=None,
|
||||
model="chatgpt/gpt-6.1-sol",
|
||||
)
|
||||
assert request["input"] == [{"role": "user", "content": "standalone shorthand"}]
|
||||
|
||||
def test_sign_request_leaves_list_input_unchanged(self):
|
||||
config: Final = ChatGPTResponsesAPIConfig()
|
||||
list_input: Final = [{"role": "user", "content": [{"type": "input_text", "text": "hi"}]}]
|
||||
request: Final = {"model": "chatgpt/gpt-6.1-sol", "input": list_input}
|
||||
config.sign_request(
|
||||
headers={},
|
||||
optional_params={},
|
||||
request_data=request,
|
||||
api_base="https://chatgpt.com/backend-api/codex/responses",
|
||||
api_key=None,
|
||||
model="chatgpt/gpt-6.1-sol",
|
||||
)
|
||||
assert request["input"] == list_input
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"model_name",
|
||||
[
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue