code: def completion(
      model: str,
      messages: list,
      model_response: ModelResponse,
      print_verbose: Callable,
      encoding,
      logging_obj,
      vertex_project=None,
      vertex_location=None,
      optional_params=None,
      litellm_params=None,
      logger_fn=None,
      acompletion: bool = False,
  ):
      try:
          import vertexai
      except:
          raise VertexAIError(
              status_code=400,
              message="vertexai import failed please run `pip install google-cloud-aiplatform`",
          )
  
      if not (
          hasattr(vertexai, "preview")
          or hasattr(vertexai.preview, "language_models")
      ):
          raise VertexAIError(
              status_code=400,
              message="""Upgrade vertex ai. Run `pip install "google-cloud-aiplatform>=1.38"`""",
          )
      try:
          from vertexai.preview.language_models import (
              ChatModel,
              CodeChatModel,
              InputOutputTextPair,
          )
          from vertexai.language_models import (
              TextGenerationModel,
              CodeGenerationModel,
          )
          from vertexai.preview.generative_models import (
              GenerativeModel,
              Part,
              GenerationConfig,
          )
          from google.cloud.aiplatform_v1beta1.types import (
              content as gapic_content_types,
          )
  
          vertexai.init(
              project=vertex_project, location=vertex_location
          )
  
          ## Load Config
          config = litellm.VertexAIConfig.get_config()
          for k, v in config.items():
              if k not in optional_params:
                  optional_params[k] = v
  
          ## Process safety settings into format expected by vertex AI
          safety_settings = None
          if "safety_settings" in optional_params:
              safety_settings = optional_params.pop("safety_settings")
              if not isinstance(safety_settings, list):
                  raise ValueError("safety_settings must be a list")
              if len(safety_settings) > 0 and not isinstance(
                  safety_settings[0], dict
              ):
                  raise ValueError(
                      "safety_settings must be a list of dicts"
                  )
              safety_settings = [
                  gapic_content_types.SafetySetting(x)
                  for x in safety_settings
              ]
  
          # vertexai does not use an API key, it looks for credentials.json in the environment
  
          prompt = " ".join(
              [
                  message["content"]
                  for message in messages
                  if isinstance(message["content"], str)
              ]
          )
  
          mode = ""
  
          request_str = ""
          response_obj = None
          if (
              model in litellm.vertex_language_models
              or model in litellm.vertex_vision_models
          ):
              llm_model = GenerativeModel(model)
              mode = "vision"
              request_str += f"llm_model = GenerativeModel({model})\n"
          elif model in litellm.vertex_chat_models:
              llm_model = ChatModel.from_pretrained(model)
              mode = "chat"
              request_str += (
                  f"llm_model = ChatModel.from_pretrained({model})\n"
              )
          elif model in litellm.vertex_text_models:
              llm_model = TextGenerationModel.from_pretrained(model)
              mode = "text"
              request_str += f"llm_model = TextGenerationModel.from_pretrained({model})\n"
          elif model in litellm.vertex_code_text_models:
              llm_model = CodeGenerationModel.from_pretrained(model)
              mode = "text"
              request_str += f"llm_model = CodeGenerationModel.from_pretrained({model})\n"
          else:  # vertex_code_llm_models
              llm_model = CodeChatModel.from_pretrained(model)
              mode = "chat"
              request_str += f"llm_model = CodeChatModel.from_pretrained({model})\n"
  
          if (
              acompletion == True
          ):  # [TODO] expand support to vertex ai chat + text models
              if optional_params.get("stream", False) is True:
                  # async streaming
                  return async_streaming(
                      llm_model=llm_model,
                      mode=mode,
                      prompt=prompt,
                      logging_obj=logging_obj,
                      request_str=request_str,
                      model=model,
                      model_response=model_response,
                      messages=messages,
                      print_verbose=print_verbose,
                      **optional_params,
                  )
              return async_completion(
                  llm_model=llm_model,
                  mode=mode,
                  prompt=prompt,
                  logging_obj=logging_obj,
                  request_str=request_str,
                  model=model,
                  model_response=model_response,
                  encoding=encoding,
                  messages=messages,
                  print_verbose=print_verbose,
                  **optional_params,
              )
  
          if mode == "vision":
              print_verbose("\nMaking VertexAI Gemini Pro Vision Call")
              print_verbose(f"\nProcessing input messages = {messages}")
              tools = optional_params.pop("tools", None)
              prompt, images = _gemini_vision_convert_messages(
                  messages=messages
              )
              content = [prompt] + images
              if (
                  "stream" in optional_params
                  and optional_params["stream"] == True
              ):
                  stream = optional_params.pop("stream")
                  request_str += f"response = llm_model.generate_content({content}, generation_config=GenerationConfig(**{optional_params}), safety_settings={safety_settings}, stream={stream})\n"
                  logging_obj.pre_call(
                      input=prompt,
                      api_key=None,
                      additional_args={
                          "complete_input_dict": optional_params,
                          "request_str": request_str,
                      },
                  )
  
                  model_response = llm_model.generate_content(
                      contents=content,
                      generation_config=GenerationConfig(
                          **optional_params
                      ),
                      safety_settings=safety_settings,
                      stream=True,
                      tools=tools,
                  )
                  optional_params["stream"] = True
                  return model_response
  
              request_str += (
                  f"response = llm_model.generate_content({content})\n"
              )
              ## LOGGING
              logging_obj.pre_call(
                  input=prompt,
                  api_key=None,
                  additional_args={
                      "complete_input_dict": optional_params,
                      "request_str": request_str,
                  },
              )
  
              ## LLM Call
              response = llm_model.generate_content(
                  contents=content,
                  generation_config=GenerationConfig(**optional_params),
                  safety_settings=safety_settings,
                  tools=tools,
              )
  
              if tools is not None and hasattr(
                  response.candidates[0].content.parts[0],
                  "function_call",
              ):
                  function_call = (
                      response.candidates[0]
                      .content.parts[0]
                      .function_call
                  )
                  args_dict = {}
                  for k, v in function_call.args.items():
                      args_dict[k] = v
                  args_str = json.dumps(args_dict)
                  message = litellm.Message(
                      content=None,
                      tool_calls=[
                          {
                              "id": f"call_{str(uuid.uuid4())}",
                              "function": {
                                  "arguments": args_str,
                                  "name": function_call.name,
                              },
                              "type": "function",
                          }
                      ],
                  )
                  completion_response = message
              else:
                  completion_response = response.text
              response_obj = response._raw_response
              optional_params["tools"] = tools
          elif mode == "chat":
              chat = llm_model.start_chat()
              request_str += f"chat = llm_model.start_chat()\n"
  
              if (
                  "stream" in optional_params
                  and optional_params["stream"] == True
              ):
                  # NOTE: VertexAI does not accept stream=True as a param and raises an error,
                  # we handle this by removing 'stream' from optional params and sending the request
                  # after we get the response we add optional_params["stream"] = True, since main.py needs to know it's a streaming response to then transform it for the OpenAI format
                  optional_params.pop(
                      "stream", None
                  )  # vertex ai raises an error when passing stream in optional params
                  request_str += f"chat.send_message_streaming({prompt}, **{optional_params})\n"
                  ## LOGGING
                  logging_obj.pre_call(
                      input=prompt,
                      api_key=None,
                      additional_args={
                          "complete_input_dict": optional_params,
                          "request_str": request_str,
                      },
                  )
                  model_response = chat.send_message_streaming(
                      prompt, **optional_params
                  )
                  optional_params["stream"] = True
                  return model_response
  
              request_str += f"chat.send_message({prompt}, **{optional_params}).text\n"
              ## LOGGING
              logging_obj.pre_call(
                  input=prompt,
                  api_key=None,
                  additional_args={
                      "complete_input_dict": optional_params,
                      "request_str": request_str,
                  },
              )
              completion_response = chat.send_message(
                  prompt, **optional_params
              ).text
          elif mode == "text":
              if (
                  "stream" in optional_params
                  and optional_params["stream"] == True
              ):
                  optional_params.pop(
                      "stream", None
                  )  # See note above on handling streaming for vertex ai
                  request_str += f"llm_model.predict_streaming({prompt}, **{optional_params})\n"
                  ## LOGGING
                  logging_obj.pre_call(
                      input=prompt,
                      api_key=None,
                      additional_args={
                          "complete_input_dict": optional_params,
                          "request_str": request_str,
                      },
                  )
                  model_response = llm_model.predict_streaming(
                      prompt, **optional_params
                  )
                  optional_params["stream"] = True
                  return model_response
  
              request_str += f"llm_model.predict({prompt}, **{optional_params}).text\n"
              ## LOGGING
              logging_obj.pre_call(
                  input=prompt,
                  api_key=None,
                  additional_args={
                      "complete_input_dict": optional_params,
                      "request_str": request_str,
                  },
              )
              completion_response = llm_model.predict(
                  prompt, **optional_params
              ).text
  
          ## LOGGING
          logging_obj.post_call(
              input=prompt,
              api_key=None,
              original_response=completion_response,
          )
  
          ## RESPONSE OBJECT
          if isinstance(completion_response, litellm.Message):
              model_response["choices"][0][
                  "message"
              ] = completion_response
          elif len(str(completion_response)) > 0:
              model_response["choices"][0]["message"]["content"] = str(
                  completion_response
              )
          model_response["choices"][0]["message"]["content"] = str(
              completion_response
          )
          model_response["created"] = int(time.time())
          model_response["model"] = model
          ## CALCULATING USAGE
          if (
              model in litellm.vertex_language_models
              and response_obj is not None
          ):
              model_response["choices"][
                  0
              ].finish_reason = response_obj.candidates[
                  0
              ].finish_reason.name
              usage = Usage(
                  prompt_tokens=response_obj.usage_metadata.prompt_token_count,
                  completion_tokens=response_obj.usage_metadata.candidates_token_count,
                  total_tokens=response_obj.usage_metadata.total_token_count,
              )
          else:
              # init prompt tokens
              # this block attempts to get usage from response_obj if it exists, if not it uses the litellm token counter
              prompt_tokens, completion_tokens, total_tokens = 0, 0, 0
              if response_obj is not None:
                  if hasattr(
                      response_obj, "usage_metadata"
                  ) and hasattr(
                      response_obj.usage_metadata, "prompt_token_count"
                  ):
                      prompt_tokens = (
                          response_obj.usage_metadata.prompt_token_count
                      )
                      completion_tokens = (
                          response_obj.usage_metadata.candidates_token_count
                      )
              else:
                  prompt_tokens = len(encoding.encode(prompt))
                  completion_tokens = len(
                      encoding.encode(
                          model_response["choices"][0]["message"].get(
                              "content", ""
                          )
                      )
                  )
  
              usage = Usage(
                  prompt_tokens=prompt_tokens,
                  completion_tokens=completion_tokens,
                  total_tokens=prompt_tokens + completion_tokens,
              )
          model_response.usage = usage
          return model_response
      except Exception as e:
          raise VertexAIError(status_code=500, message=str(e))
  
file_path: litellm/litellm/llms/vertex_ai.py
imports: import os, types
  import json
  from enum import Enum
  import requests
  import time
  from typing import Callable, Optional
  from litellm.utils import ModelResponse, Usage, CustomStreamWrapper
  import litellm, uuid
  import httpx
label_desc: Use image node_id 4 for calling a global function with example usage: completion(model, messages, model_response, print_verbose, encoding, logging_obj, vertex_project, vertex_location, optional_params, litellm_params, logger_fn, acompletion) and returns: model_response, async_completion, async_streaming, model_response, model_response, model_response