code: def completion(
      self,
      model_response: ModelResponse,
      timeout: float,
      model: Optional[str] = None,
      messages: Optional[list] = None,
      print_verbose: Optional[Callable] = None,
      api_key: Optional[str] = None,
      api_base: Optional[str] = None,
      acompletion: bool = False,
      logging_obj=None,
      optional_params=None,
      litellm_params=None,
      logger_fn=None,
      headers: Optional[dict] = None,
      custom_prompt_dict: dict = {},
      client=None,
  ):
      super().completion()
      exception_mapping_worked = False
      try:
          if headers:
              optional_params["extra_headers"] = headers
          if model is None or messages is None:
              raise OpenAIError(
                  status_code=422, message=f"Missing model or messages"
              )
  
          if not isinstance(timeout, float):
              raise OpenAIError(
                  status_code=422,
                  message=f"Timeout needs to be a float",
              )
  
          for _ in range(
              2
          ):  # if call fails due to alternating messages, retry with reformatted message
              data = {
                  "model": model,
                  "messages": messages,
                  **optional_params,
              }
  
              try:
                  max_retries = data.pop("max_retries", 2)
                  if acompletion is True:
                      if optional_params.get("stream", False):
                          return self.async_streaming(
                              logging_obj=logging_obj,
                              headers=headers,
                              data=data,
                              model=model,
                              api_base=api_base,
                              api_key=api_key,
                              timeout=timeout,
                              client=client,
                              max_retries=max_retries,
                          )
                      else:
                          return self.acompletion(
                              data=data,
                              headers=headers,
                              logging_obj=logging_obj,
                              model_response=model_response,
                              api_base=api_base,
                              api_key=api_key,
                              timeout=timeout,
                              client=client,
                              max_retries=max_retries,
                          )
                  elif optional_params.get("stream", False):
                      return self.streaming(
                          logging_obj=logging_obj,
                          headers=headers,
                          data=data,
                          model=model,
                          api_base=api_base,
                          api_key=api_key,
                          timeout=timeout,
                          client=client,
                          max_retries=max_retries,
                      )
                  else:
                      if not isinstance(max_retries, int):
                          raise OpenAIError(
                              status_code=422,
                              message="max retries must be an int",
                          )
                      if client is None:
                          openai_client = OpenAI(
                              api_key=api_key,
                              base_url=api_base,
                              http_client=litellm.client_session,
                              timeout=timeout,
                              max_retries=max_retries,
                          )
                      else:
                          openai_client = client
  
                      ## LOGGING
                      logging_obj.pre_call(
                          input=messages,
                          api_key=openai_client.api_key,
                          additional_args={
                              "headers": headers,
                              "api_base": openai_client._base_url._uri_reference,
                              "acompletion": acompletion,
                              "complete_input_dict": data,
                          },
                      )
  
                      response = openai_client.chat.completions.create(**data, timeout=timeout)  # type: ignore
                      stringified_response = response.model_dump()
                      logging_obj.post_call(
                          input=messages,
                          api_key=api_key,
                          original_response=stringified_response,
                          additional_args={"complete_input_dict": data},
                      )
                      return convert_to_model_response_object(
                          response_object=stringified_response,
                          model_response_object=model_response,
                      )
              except Exception as e:
                  if "Conversation roles must alternate user/assistant" in str(
                      e
                  ) or "user and assistant roles should be alternating" in str(
                      e
                  ):
                      # reformat messages to ensure user/assistant are alternating, if there's either 2 consecutive 'user' messages or 2 consecutive 'assistant' message, add a blank 'user' or 'assistant' message to ensure compatibility
                      new_messages = []
                      for i in range(len(messages) - 1):
                          new_messages.append(messages[i])
                          if (
                              messages[i]["role"]
                              == messages[i + 1]["role"]
                          ):
                              if messages[i]["role"] == "user":
                                  new_messages.append(
                                      {
                                          "role": "assistant",
                                          "content": "",
                                      }
                                  )
                              else:
                                  new_messages.append(
                                      {"role": "user", "content": ""}
                                  )
                      new_messages.append(messages[-1])
                      messages = new_messages
                  elif "Last message must have role `user`" in str(e):
                      new_messages = messages
                      new_messages.append(
                          {"role": "user", "content": ""}
                      )
                      messages = new_messages
                  else:
                      raise e
      except OpenAIError as e:
          exception_mapping_worked = True
          raise e
      except Exception as e:
          if hasattr(e, "status_code"):
              raise OpenAIError(
                  status_code=e.status_code, message=str(e)
              )
          else:
              raise OpenAIError(status_code=500, message=str(e))
  
imports: from typing import Optional, Union, Any
  import types, time, json
  import httpx
  from .base import BaseLLM
  from litellm.utils import ModelResponse, Choices, Message, CustomStreamWrapper, convert_to_model_response_object, Usage
  from typing import Callable, Optional
  import aiohttp, requests
  import litellm
  from .prompt_templates.factory import prompt_factory, custom_prompt
  from openai import OpenAI, AsyncOpenAI
label_desc: Use image node_id 2 for calling the OpenAIChatCompletion obj's underlying member method code with example usage: obj.completion(model_response, timeout, model, messages, print_verbose, api_key, api_base, acompletion, logging_obj, optional_params, litellm_params, logger_fn, headers, custom_prompt_dict, client) and returns: self, self, self, convert_to_model_response_object