code: def http_bot(
      state,
      model_selector,
      temperature,
      top_p,
      max_new_tokens,
      refer_input_state,
      request: gr.Request,
  ):
      # def http_bot(state, model_selector, temperature, top_p, max_new_tokens, request: gr.Request):
      logger.info(f"http_bot. ip: {request.client.host}")
      start_tstamp = time.time()
      model_name = model_selector
  
      if state.skip_next:
          # This generate call is skipped due to invalid inputs
          yield (state, state.to_gradio_chatbot()) + (
              no_change_btn,
          ) * 5
          return
  
      if len(state.messages) == state.offset + 2:
          # First round of conversation
          template_name = "ferret_v1"
          # Below is LLaVA's original templates.
          # if "llava" in model_name.lower():
          #     if 'llama-2' in model_name.lower():
          #         template_name = "llava_llama_2"
          #     elif "v1" in model_name.lower():
          #         if 'mmtag' in model_name.lower():
          #             template_name = "v1_mmtag"
          #         elif 'plain' in model_name.lower() and 'finetune' not in model_name.lower():
          #             template_name = "v1_mmtag"
          #         else:
          #             template_name = "llava_v1"
          #     elif "mpt" in model_name.lower():
          #         template_name = "mpt"
          #     else:
          #         if 'mmtag' in model_name.lower():
          #             template_name = "v0_mmtag"
          #         elif 'plain' in model_name.lower() and 'finetune' not in model_name.lower():
          #             template_name = "v0_mmtag"
          #         else:
          #             template_name = "llava_v0"
          # elif "mpt" in model_name:
          #     template_name = "mpt_text"
          # elif "llama-2" in model_name:
          #     template_name = "llama_2"
          # else:
          #     template_name = "vicuna_v1"
          new_state = conv_templates[template_name].copy()
          new_state.append_message(
              new_state.roles[0], state.messages[-2][1]
          )
          new_state.append_message(new_state.roles[1], None)
          state = new_state
          state.first_round = False
  
      # Query worker address
      controller_url = args.controller_url
      ret = requests.post(
          controller_url + "/get_worker_address",
          json={"model": model_name},
      )
      worker_addr = ret.json()["address"]
      logger.info(
          f"model_name: {model_name}, worker_addr: {worker_addr}"
      )
  
      # No available worker
      if worker_addr == "":
          state.messages[-1][-1] = server_error_msg
          yield (
              state,
              state.to_gradio_chatbot(),
              disable_btn,
              disable_btn,
              disable_btn,
              enable_btn,
              enable_btn,
          )
          return
  
      # Construct prompt
      prompt = state.get_prompt()
      if args.add_region_feature:
          prompt = format_region_prompt(prompt, refer_input_state)
  
      all_images = state.get_images(return_pil=True)
      all_image_hash = [
          hashlib.md5(image.tobytes()).hexdigest()
          for image in all_images
      ]
      for image, hash in zip(all_images, all_image_hash):
          t = datetime.datetime.now()
          filename = os.path.join(
              LOGDIR,
              "serve_images",
              f"{t.year}-{t.month:02d}-{t.day:02d}",
              f"{hash}.jpg",
          )
          if not os.path.isfile(filename):
              os.makedirs(os.path.dirname(filename), exist_ok=True)
              image.save(filename)
  
      # Make requests
      pload = {
          "model": model_name,
          "prompt": prompt,
          "temperature": float(temperature),
          "top_p": float(top_p),
          "max_new_tokens": min(int(max_new_tokens), 1536),
          "stop": state.sep
          if state.sep_style
          in [SeparatorStyle.SINGLE, SeparatorStyle.MPT]
          else state.sep2,
          "images": f"List of {len(state.get_images())} images: {all_image_hash}",
      }
      logger.info(f"==== request ====\n{pload}")
      if args.add_region_feature:
          pload["region_masks"] = refer_input_state[
              "region_masks_in_prompts"
          ]
          logger.info(
              f"==== add region_masks_in_prompts to request ====\n"
          )
  
      pload["images"] = state.get_images()
      print(f"Input Prompt: {prompt}")
  
      state.messages[-1][-1] = "▌"
      yield (state, state.to_gradio_chatbot()) + (disable_btn,) * 5
  
      try:
          # Stream output
          response = requests.post(
              worker_addr + "/worker_generate_stream",
              headers=headers,
              json=pload,
              stream=True,
              timeout=10,
          )
          for chunk in response.iter_lines(
              decode_unicode=False, delimiter=b"\0"
          ):
              if chunk:
                  data = json.loads(chunk.decode())
                  if data["error_code"] == 0:
                      output = data["text"][len(prompt) :].strip()
                      output = post_process_code(output)
                      state.messages[-1][-1] = output + "▌"
                      yield (state, state.to_gradio_chatbot()) + (
                          disable_btn,
                      ) * 5
                  else:
                      output = (
                          data["text"]
                          + f" (error_code: {data['error_code']})"
                      )
                      state.messages[-1][-1] = output
                      yield (state, state.to_gradio_chatbot()) + (
                          disable_btn,
                          disable_btn,
                          disable_btn,
                          enable_btn,
                          enable_btn,
                      )
                      return
                  time.sleep(0.03)
      except requests.exceptions.RequestException as e:
          state.messages[-1][-1] = server_error_msg
          yield (state, state.to_gradio_chatbot()) + (
              disable_btn,
              disable_btn,
              disable_btn,
              enable_btn,
              enable_btn,
          )
          return
  
      state.messages[-1][-1] = state.messages[-1][-1][:-1]
      yield (state, state.to_gradio_chatbot()) + (enable_btn,) * 5
  
      finish_tstamp = time.time()
      logger.info(f"{output}")
  
      with open(get_conv_log_filename(), "a") as fout:
          data = {
              "tstamp": round(finish_tstamp, 4),
              "type": "chat",
              "model": model_name,
              "start": round(start_tstamp, 4),
              "finish": round(start_tstamp, 4),
              "state": state.dict(),
              "images": all_image_hash,
              "ip": request.client.host,
          }
          fout.write(json.dumps(data) + "\n")
  
imports: import argparse
  import datetime
  import json
  import os
  import time
  import gradio
  import requests
  from ferret.conversation import default_conversation, conv_templates, SeparatorStyle
  from ferret.constants import LOGDIR
  from ferret.utils import build_logger, server_error_msg, violates_moderation, moderation_msg
  import hashlib
  import re
  from copy import deepcopy
  from PIL import ImageDraw, ImageFont
  from gradio import processing_utils
  import numpy
  import torch
  import torch.nn.functional
  from scipy.ndimage import binary_dilation, binary_erosion
  import pdb
  from ferret.serve.gradio_css import code_highlight_css
label_desc: Use image node_id 19 for calling a global function with example usage: http_bot(state, model_selector, temperature, top_p, max_new_tokens, refer_input_state, request) without return types