Repository: jerryjliu/gpt_index
File: llama-index-integrations/llms/llama-index-llms-google-genai/llama_index/llms/google_genai/base.py (Python)

Code before:
            ):
                if candidates := r.candidates:
                    if not candidates:
                        continue

                    top_candidate = candidates[0]
                    if response_content := top_candidate.content:
                        if parts := response_content.parts:
                            content_delta = parts[0].text
                            if content_delta:
                                if parts[0].thought:
                                    thoughts += content_delta
                                else:
                                    content += content_delta
                            llama_resp = chat_from_gemini_response(r)
                            llama_resp.delta = content_delta
                            llama_resp.message.blocks.append(TextBlock(text=content))
                            llama_resp.message.blocks.append(
                                ThinkingBlock(content=thoughts)
                            )
                            yield llama_resp

            if self.use_file_api:
                await delete_uploaded_files(
                    [*chat_kwargs["history"], next_msg], self._client
                )

        return gen()

    @llm_chat_callback()
    async def astream_chat(
        self, messages: Sequence[ChatMessage], **kwargs: Any
    ) -> ChatResponseAsyncGen:
        return await self._astream_chat(messages, **kwargs)

    def _prepare_chat_with_tools(
        self,
        tools: Sequence["BaseTool"],
        user_msg: Optional[Union[str, ChatMessage]] = None,
        chat_history: Optional[List[ChatMessage]] = None,
        verbose: bool = False,
        allow_parallel_tool_calls: bool = False,
        tool_required: bool = False,
        tool_choice: Optional[Union[str, dict]] = None,
        strict: Optional[bool] = None,
        **kwargs: Any,
    ) -> Dict[str, Any]:
        """Predict and call the tool."""
        if tool_choice is None:
            tool_choice = "any" if tool_required else "auto"


Review comment (refactor):
I think this change is causing duplicated content in the chat history?

I added a print just before creating the stream to print the `next_msg` and `chat_kwargs['history']` and noticed a decent amount of duplication

For example, while running an agent:
```
Next message: 
parts=[Part(
  text='Good day sir, top of the morning to ye.'
)] role='user'

History: 
[Content(
  parts=[
    Part(
      text='Hello! I am a new user!'
    ),
  ],
  role='user'
), Content(
  parts=[
    Part(
      function_call=FunctionCall(
        args={},
        name='get_the_greeting'
      )
    ),
    Part(
      function_call=FunctionCall(
        args={},
        name='get_the_greeting'
      )
    ),
    Part(
      function_call=FunctionCall(
        args={},
        name='get_the_greeting'
      )
    ),
  ],
  role='model'
)]
```

Code after:
                next_msg.parts if isinstance(next_msg, types.Content) else next_msg
            ):
                if candidates := r.candidates:
                    if not candidates:
                        continue

                    top_candidate = candidates[0]
                    if response_content := top_candidate.content:
                        if parts := response_content.parts:
                            content_delta = parts[0].text
                            if content_delta:
                                if parts[0].thought:
                                    thoughts += content_delta
                                else:
                                    content += content_delta
                            llama_resp = chat_from_gemini_response(r)
                            llama_resp.delta = content_delta
                            if content:
                                llama_resp.message.blocks.append(
                                    TextBlock(text=content)
                                )
                            if thoughts:
                                llama_resp.message.blocks.append(
                                    ThinkingBlock(content=thoughts)
                                )
                            yield llama_resp

            if self.use_file_api:
                await delete_uploaded_files(
                    [*chat_kwargs["history"], next_msg], self._client
                )

        return gen()

    @llm_chat_callback()
    async def astream_chat(
        self, messages: Sequence[ChatMessage], **kwargs: Any
    ) -> ChatResponseAsyncGen:
        return await self._astream_chat(messages, **kwargs)

    def _prepare_chat_with_tools(
        self,
        tools: Sequence["BaseTool"],
        user_msg: Optional[Union[str, ChatMessage]] = None,
        chat_history: Optional[List[ChatMessage]] = None,
        verbose: bool = False,
        allow_parallel_tool_calls: bool = False,
        tool_required: bool = False,
        tool_choice: Optional[Union[str, dict]] = None,
        strict: Optional[bool] = None,
        **kwargs: Any,