docstr: Handles completion for an arbitrary amount of rows.
  Additionally, single completion calls are done with exponential backoff to guarantee all prompts are processed,
  because even with previous checks the tokens-per-minute limit may apply.
docstr_tok: ["Handles","completion","for","an","arbitrary","amount","of","rows",".","Additionally",",","single","completion","calls","are","done","with","exponential","backoff","to","guarantee","all","prompts","are","processed",",","because","even","with","previous","checks","the","tokens-per-minute","limit","may","apply","."]
code: def _completion(
      self, model_name, prompts, api_key, api_args, args_model, df
  ):
      """
      Handles completion for an arbitrary amount of rows.
      Additionally, single completion calls are done with exponential backoff to guarantee all prompts are processed,
      because even with previous checks the tokens-per-minute limit may apply.
      """
  
      def _submit_completion(
          model_name, prompts, api_key, api_args, args_model, df
      ):
          kwargs = {
              "model": model_name,
          }
  
          # configure the PaLM SDK with the provided API KEY
          palm.configure(api_key=api_key)
  
          if model_name == "models/embedding-gecko-001":
              prompts = "".join(prompts)
              return _submit_embedding_completion(
                  kwargs, prompts, api_args
              )
          elif model_name == args_model.model_name:
              return _submit_chat_completion(
                  kwargs,
                  prompts,
                  api_args,
                  df,
                  mode=args_model.mode,
              )
          else:
              prompts = "".join(prompts)
              return _submit_normal_completion(
                  kwargs, prompts, api_args
              )
  
      def _log_api_call(params, response):
          after_palm_query(params, response)
  
          params2 = params.copy()
          params2.pop("api_key", None)
          params2.pop("user", None)
          logger.debug(f">>>palm call: {params2}:\n{response}")
  
      def _submit_normal_completion(kwargs, prompts, api_args):
          def _tidy(comp):
              tidy_comps = []
              if comp.candidates and len(comp.candidates) == 0:
                  return ["No completions found"]
              for c in comp.candidates:
                  if "output" in c:
                      tidy_comps.append(
                          c["output"].strip("\n").strip("")
                      )
              return tidy_comps
  
          kwargs["prompt"] = prompts
          kwargs = {**kwargs, **api_args}
  
          before_palm_query(kwargs)
  
          # call the palm sdk with text-bison-001 model
          resp = _tidy(palm.generate_text(**kwargs))
          _log_api_call(kwargs, resp)
          return resp
  
      def _submit_embedding_completion(kwargs, prompts, api_args):
          def _tidy(comp):
              tidy_comps = []
              if not "embedding" in comp:
                  return [f"No completion found, err {comp}"]
              for c in comp["embedding"]:
                  tidy_comps.append([c])
              return tidy_comps
  
          kwargs = {}
          kwargs["model"] = api_args["model"]
          kwargs["text"] = prompts
  
          before_palm_query(kwargs)
  
          # call the palm sdk with embedding-gecko-001 model
          resp = _tidy(palm.generate_embeddings(**kwargs))
          _log_api_call(kwargs, resp)
          return resp
  
      def _submit_chat_completion(
          kwargs, prompts, api_args, df, mode="conversational"
      ):
          def _tidy(comp):
              tidy_comps = []
              if comp.candidates and len(comp.candidates) == 0:
                  return ["No completions found"]
  
              for c in comp.candidates:
                  if "content" in c:
                      tidy_comps.append(
                          c["content"].strip("\n").strip("")
                      )
                  if "output" in c:
                      tidy_comps.append(
                          c["output"].strip("\n").strip("")
                      )
              return tidy_comps
  
          completions = []
          if mode != "conversational":
              initial_prompt = {
                  "author": "system",
                  "content": "You are a helpful assistant. Your task is to continue the chat.",
              }  # noqa
          else:
              # get prompt from model
              prompt = "".join(prompts)
              initial_prompt = {
                  "author": "system",
                  "content": prompt,
              }  # noqa
              kwargs["messages"] = [initial_prompt]
  
          last_completion_content = None
  
          for pidx in range(len(prompts)):
              if mode == "conversational":
                  kwargs["messages"].append(
                      {"author": "user", "content": prompts[pidx]}
                  )
  
              if mode == "conversational-full" or (
                  mode == "conversational" and pidx == len(prompts) - 1
              ):
                  pkwargs = {**kwargs, **api_args}
                  pkwargs["candidate_count"] = 3
                  pkwargs.pop("max_output_tokens")
                  before_palm_query(kwargs)
  
                  # call the palm sdk with chat-bison-001 model
                  resp = _tidy(palm.chat(**pkwargs))
  
                  _log_api_call(pkwargs, resp)
  
                  completions.extend(resp)
              elif mode == "default":
                  pkwargs = {**kwargs, **api_args}
  
                  pkwargs["model"] = "models/text-bison-001"
                  pkwargs["prompt"] = prompts[pidx]
                  before_palm_query(kwargs)
                  if pkwargs["prompt"] == "":
                      return ["No prompt provided"]
  
                  # call the palm sdk with text-bison-001 model
                  resp = _tidy(palm.generate_text(**pkwargs))
                  _log_api_call(pkwargs, resp)
  
                  completions.extend(resp)
              else:
                  # in "normal" conversational mode, we request completions only for the last row
                  last_completion_content = None
                  if args_model.answer_column in df.columns:
                      # insert completion if provided, which saves redundant API calls
                      completions.extend(
                          [df.iloc[pidx][args_model.answer_column]]
                      )
                  else:
                      completions.extend([""])
  
              if args_model.answer_column in df.columns:
                  kwargs["messages"].append(
                      {
                          "author": "assistant",
                          "content": df.iloc[pidx][
                              args_model.answer_column
                          ],
                      }
                  )
              elif last_completion_content:
                  # interleave assistant responses with user input
                  kwargs["messages"].append(
                      {
                          "author": "assistant",
                          "content": last_completion_content[0],
                      }
                  )
  
          return completions
  
      try:
          completion = _submit_completion(
              model_name, prompts, api_key, api_args, args_model, df
          )
          return completion
      except Exception as e:
          completion = []
          logger.exception(e)
          completion.extend({"error": str(e)})
  
      return completion
  
file_path: mindsdb/mindsdb/integrations/handlers/palm_handler/palm_handler.py
imports: import textwrap
  from pydantic import BaseModel, Extra
  import google.generativeai
  import numpy
  import pandas
  from mindsdb.utilities.hooks import before_palm_query, after_palm_query
  from mindsdb.utilities import log
  from mindsdb.integrations.libs.base import BaseMLEngine
  from mindsdb.integrations.utilities.handler_utils import get_api_key
  from mindsdb.integrations.libs.llm_utils import get_completed_prompts
label_desc: Use image node_id 5 for calling the PalmHandler obj's underlying member method code with example usage: obj._completion(model_name, prompts, api_key, api_args, args_model, df) and returns: completion, resp, resp, completions, completion, _submit_embedding_completion, tidy_comps, tidy_comps, tidy_comps, _submit_chat_completion, _submit_normal_completion, list, list, list, list