Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,13 @@ def _prepare_options(self, messages: Sequence[Message], options: Mapping[str, An

def _parse_response_from_openai(self, response: ChatCompletion, options: Mapping[str, Any]) -> ChatResponse:
"""Parse a response from OpenAI into a ChatResponse."""
if isinstance(response, str):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we covering the new branch? Couldn't find a test exercising the str -> ChatClientException path in python/packages/openai/tests/openai/test_openai_chat_completion_client.py. Existing direct-call tests make it nearly free: client._parse_response_from_openai("some string", {}) inside pytest.raises(ChatClientException), asserting substring "str instead of ChatCompletion" rather than the full message (Azure suffix is env-dependent). Pins the contract so a refactor can't quietly regress it back to the AttributeError.

raise ChatClientException(
maybe_append_azure_endpoint_guidance(
f"{type(self)} service returned an invalid response (str instead of ChatCompletion): {response!r}",
azure_endpoint=self.azure_endpoint,
),
)
Comment on lines +687 to +693
response_metadata = self._get_metadata_from_chat_response(response)
messages: list[Message] = []
finish_reason: FinishReason | None = None
Expand Down Expand Up @@ -788,7 +795,7 @@ def _parse_text_from_openai(self, choice: Choice | ChunkChoice) -> Content | Non
def _get_metadata_from_chat_response(self, response: ChatCompletion) -> dict[str, Any]:
"""Get metadata from a chat response."""
return {
"system_fingerprint": response.system_fingerprint,
"system_fingerprint": getattr(response, "system_fingerprint", None),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we mirror this onto the streaming path too? The fix hardens non-streaming, but here response.system_fingerprint is still a direct deref, and _parse_response_update_from_openai has no str guard. A provider returning the same malformed payload while streaming hits the cryptic AttributeError again. The outer except Exception still wraps it into ChatClientException, so it's loud, just without the specific "str instead of ..." message this PR adds for non-streaming. Same contract on both paths?

}

def _get_metadata_from_streaming_chat_response(self, response: ChatCompletionChunk) -> dict[str, Any]:
Expand Down