mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-26 01:12:21 +00:00
fix(oci,httpx): normalize finish_reason, preserve response_format, fix sync embed JSON content-type
- cohere.py / generic.py: normalize unknown OCI finishReason values (ERROR, ERROR_TOXIC, CONTENT_FILTERED, USER_CANCEL, ...) to 'stop' in non-streaming and streaming generic handlers, matching the streaming Cohere handler so downstream consumers switching on finish_reason aren't broken by raw OCI values. - transformation.py: restore the dual-key alias so optional_params still carries the original 'response_format' key alongside the OCI-mapped 'responseFormat'. Downstream litellm framework code (json_mode detection, logging) inspects 'response_format' after map_openai_params runs. - llm_http_handler.py: make the sync embedding path mirror the async path — when sign_request returns no signed_body, send via json=data (which sets Content-Type: application/json) instead of data=json.dumps(data) which doesn't. Removes a sync/async behavioural asymmetry for non-OCI providers that adopt the sign_request pattern. Co-authored-by: Yassin Kortam <yassin@berri.ai>
This commit is contained in:
parent
b295514489
commit
489f7c146b
4 changed files with 39 additions and 9 deletions
|
|
@ -939,12 +939,20 @@ class BaseLLMHTTPHandler:
|
|||
sync_httpx_client = client
|
||||
|
||||
try:
|
||||
response = sync_httpx_client.post(
|
||||
url=api_base,
|
||||
headers=headers,
|
||||
data=signed_body if signed_body is not None else json.dumps(data),
|
||||
timeout=timeout,
|
||||
)
|
||||
if signed_body is not None:
|
||||
response = sync_httpx_client.post(
|
||||
url=api_base,
|
||||
headers=headers,
|
||||
data=signed_body,
|
||||
timeout=timeout,
|
||||
)
|
||||
else:
|
||||
response = sync_httpx_client.post(
|
||||
url=api_base,
|
||||
headers=headers,
|
||||
json=data,
|
||||
timeout=timeout,
|
||||
)
|
||||
except Exception as e:
|
||||
raise self._handle_error(
|
||||
e=e,
|
||||
|
|
|
|||
|
|
@ -216,8 +216,15 @@ def handle_cohere_response(
|
|||
finish_reason = "length"
|
||||
elif oci_finish_reason == "TOOL_CALL":
|
||||
finish_reason = "tool_calls"
|
||||
elif oci_finish_reason is not None:
|
||||
# OCI Cohere can emit error/cancel finish reasons (e.g. ``ERROR``,
|
||||
# ``ERROR_TOXIC``, ``ERROR_LIMIT``, ``USER_CANCEL``) that aren't part
|
||||
# of OpenAI's standard set. Normalize them to ``"stop"`` so downstream
|
||||
# consumers switching on ``finish_reason`` keep working — matches the
|
||||
# streaming handler below.
|
||||
finish_reason = "stop"
|
||||
else:
|
||||
finish_reason = oci_finish_reason
|
||||
finish_reason = None
|
||||
|
||||
tool_calls: Optional[List[Dict[str, Any]]] = None
|
||||
if cohere_response.chatResponse.toolCalls:
|
||||
|
|
|
|||
|
|
@ -332,7 +332,11 @@ def handle_generic_response(
|
|||
elif oci_finish_reason == "TOOL_CALLS":
|
||||
model_response.choices[0].finish_reason = "tool_calls" # type: ignore[union-attr]
|
||||
elif oci_finish_reason is not None:
|
||||
model_response.choices[0].finish_reason = oci_finish_reason # type: ignore[union-attr,assignment]
|
||||
# OCI GENERIC can emit non-OpenAI finish reasons (e.g. ``ERROR``,
|
||||
# ``CONTENT_FILTERED``, ``CANCELLED``). Normalize to ``"stop"`` so
|
||||
# downstream consumers switching on ``finish_reason`` keep working —
|
||||
# matches the streaming handler.
|
||||
model_response.choices[0].finish_reason = "stop" # type: ignore[union-attr]
|
||||
|
||||
oci_usage = completion_response.chatResponse.usage
|
||||
reasoning_tokens: Optional[int] = None
|
||||
|
|
@ -398,8 +402,13 @@ def handle_generic_stream_chunk(dict_chunk: dict) -> ModelResponseStream:
|
|||
finish_reason = "length"
|
||||
elif oci_finish_reason == "TOOL_CALLS":
|
||||
finish_reason = "tool_calls"
|
||||
elif oci_finish_reason is not None:
|
||||
# OCI GENERIC can emit non-OpenAI finish reasons (e.g. ``ERROR``,
|
||||
# ``CONTENT_FILTERED``, ``CANCELLED``). Normalize to ``"stop"`` so
|
||||
# downstream consumers switching on ``finish_reason`` keep working.
|
||||
finish_reason = "stop"
|
||||
else:
|
||||
finish_reason = oci_finish_reason
|
||||
finish_reason = None
|
||||
|
||||
return ModelResponseStream(
|
||||
choices=[
|
||||
|
|
|
|||
|
|
@ -252,6 +252,12 @@ class OCIChatConfig(BaseConfig):
|
|||
adapted_params[key] = value
|
||||
continue
|
||||
adapted_params[alias] = value
|
||||
# Preserve the original OpenAI ``response_format`` key alongside the
|
||||
# OCI-mapped ``responseFormat`` so downstream litellm framework code
|
||||
# (e.g. ``json_mode`` detection, logging) that inspects
|
||||
# ``optional_params["response_format"]`` continues to work.
|
||||
if alias == "responseFormat":
|
||||
adapted_params["response_format"] = value
|
||||
|
||||
return adapted_params
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue