def _prepare_chat_with_tools(
        self,
        tools: List["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]:
        """
        Prepare the chat input with tools for function calling.

        Args:
            tools (List[BaseTool]): A list of tools to use.
            user_msg (Optional[Union[str, ChatMessage]]): The user's message.
            chat_history (Optional[List[ChatMessage]]): The chat history.
            verbose (bool): Whether to output verbose logs.
            allow_parallel_tool_calls (bool): Whether to allow parallel tool calls.
            tool_required (bool): Whether to require a tool call. tool_choice supersedes this if provided.
            tool_choice (Union[str, dict]): Tool choice strategy.
            strict (Optional[bool]): Whether to enforce strict mode.
            **kwargs: Additional keyword arguments.

        Returns:
            Dict[str, Any]: The prepared parameters for the chat request.

        """
        tool_specs = [tool.metadata.to_openai_tool() for tool in tools]

        logger.debug(
            f"Preparing chat with tools. Tools: {tool_specs}, User message: {user_msg}, "
            f"Chat history: {chat_history}"
        )

        # Determine strict mode
        strict = strict or self.strict

        if self.metadata.is_function_calling_model:
            for tool_spec in tool_specs:
                if tool_spec["type"] == "function":
                    if strict:
                        tool_spec["function"]["strict"] = strict
                    tool_spec["function"]["parameters"]["additionalProperties"] = False

        if isinstance(user_msg, str):
            user_msg = ChatMessage(role=MessageRole.USER, content=user_msg)

        messages = chat_history or []
        if user_msg:
            messages.append(user_msg)

        return {
            "messages": messages,
            "tools": tool_specs or None,
            "tool_choice": (
                _resolve_tool_choice(tool_choice, tool_required) if tool_specs else None
            ),
            **kwargs,
        }

        Prepare the chat input with tools for function calling.

        Args:
            tools (List[BaseTool]): A list of tools to use.
            user_msg (Optional[Union[str, ChatMessage]]): The user's message.
            chat_history (Optional[List[ChatMessage]]): The chat history.
            verbose (bool): Whether to output verbose logs.
            allow_parallel_tool_calls (bool): Whether to allow parallel tool calls.
            tool_required (bool): Whether to require a tool call. tool_choice supersedes this if provided.
            tool_choice (Union[str, dict]): Tool choice strategy.
            strict (Optional[bool]): Whether to enforce strict mode.
            **kwargs: Additional keyword arguments.

        Returns:
            Dict[str, Any]: The prepared parameters for the chat request.

        
llama-index-integrations/llms/llama-index-llms-oci-data-science/llama_index/llms/oci_data_science/base.py