Skip to content
Open
Show file tree
Hide file tree
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 @@ -524,7 +524,7 @@ async def _get_response() -> ChatResponse:
raise
except Exception as ex:
raise _wrap_gemini_error(ex) from ex
return self._process_generate_response(raw, response_format=validated.get("response_format"))
return self._process_generate_response(raw, model=model, response_format=validated.get("response_format"))

return _get_response()

Expand Down Expand Up @@ -1065,12 +1065,14 @@ def _process_generate_response(
self,
response: types.GenerateContentResponse,
*,
model: str | None = None,
response_format: type[BaseModel] | None = None,
) -> ChatResponse:
"""Convert a Gemini generate_content response to a framework ChatResponse.

Args:
response: The raw ``GenerateContentResponse`` from the Gemini API.
model: The model the request was sent to, reported when the response carries no model version.
response_format: Optional Pydantic model type for structured output parsing.
When provided, the response text is parsed into the given model and
made available via ``ChatResponse.value``.
Expand All @@ -1085,7 +1087,7 @@ def _process_generate_response(
response_id=None,
messages=[Message(role="assistant", contents=contents, raw_representation=candidate)],
usage_details=self._parse_usage(response.usage_metadata),
model=response.model_version or self.model,
model=response.model_version or model or self.model,
finish_reason=self._map_finish_reason(
candidate.finish_reason.name if candidate and candidate.finish_reason else None
),
Expand Down
32 changes: 32 additions & 0 deletions python/packages/gemini/tests/test_gemini_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,38 @@ async def test_get_response_model_from_response() -> None:
assert response.model == "gemini-2.5-pro-002"


async def test_get_response_model_falls_back_to_configured_model() -> None:
"""Falls back to the configured model when the response carries no model_version."""
client, mock = _make_gemini_client()
raw = _make_response([_make_part(text="Hi")])
raw.model_version = None
mock.aio.models.generate_content = AsyncMock(return_value=raw)

response = await client.get_response(messages=[Message(role="user", contents=[Content.from_text("Hi")])])

assert response.model == "gemini-2.5-flash"


@pytest.mark.parametrize("stream", [False, True])
async def test_get_response_reports_requested_model_on_both_paths(stream: bool) -> None:
"""Without a model_version, both paths report the model requested in options, not the client default."""
client, mock = _make_gemini_client(model="gemini-2.5-flash")
raw = _make_response([_make_part(text="Hi")])
raw.model_version = None
mock.aio.models.generate_content = AsyncMock(return_value=raw)
mock.aio.models.generate_content_stream = AsyncMock(return_value=_async_iter([raw]))
messages = [Message(role="user", contents=[Content.from_text("Hi")])]

if stream:
response = await client.get_response(
messages=messages, options={"model": "gemini-2.5-pro"}, stream=True
).get_final_response()
else:
response = await client.get_response(messages=messages, options={"model": "gemini-2.5-pro"})

assert response.model == "gemini-2.5-pro"


async def test_get_response_streaming_model_from_chunk() -> None:
"""Populates the update model from the model_version field on each chunk."""
client, mock = _make_gemini_client()
Expand Down
Loading