code: import logging
  from pathlib import Path
  from typing import List, Optional, Tuple
  
  from dotenv import load_dotenv
  
  load_dotenv()
  
  from queue import Empty, Queue
  from threading import Thread
  
  import gradio as gr
  from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
  from langchain.chat_models import ChatOpenAI
  from langchain.prompts import HumanMessagePromptTemplate
  from langchain.schema import AIMessage, BaseMessage, HumanMessage, SystemMessage
  
  from callback import QueueCallback
  
  MODELS_NAMES = ["gpt-3.5-turbo", "gpt-4"]
  DEFAULT_TEMPERATURE = 0.7
  
  ChatHistory = List[str]
  
  logging.basicConfig(
      format="[%(asctime)s %(levelname)s]: %(message)s", level=logging.INFO
  )
  # load up our system prompt
  default_system_prompt = Path("prompts/system.prompt").read_text()
  # for the human, we will just inject the text
  human_message_prompt_template = HumanMessagePromptTemplate.from_template("{text}")
  
  
  def on_message_button_click(
      chat: Optional[ChatOpenAI],
      message: str,
      chatbot_messages: ChatHistory,
      messages: List[BaseMessage],
  ) -> Tuple[ChatOpenAI, str, ChatHistory, List[BaseMessage]]:
      if chat is None:
          # in the queue we will store our streamed tokens
          queue = Queue()
          # let's create our default chat
          chat = ChatOpenAI(
              model_name=MODELS_NAMES[0],
              temperature=DEFAULT_TEMPERATURE,
              streaming=True,
              callbacks=([QueueCallback(queue)]),
          )
      else:
          # hacky way to get the queue back
          queue = chat.callbacks[0].queue
  
      job_done = object()
  
      logging.info(f"Asking question to GPT, messages={messages}")
      # let's add the messages to our stuff
      messages.append(HumanMessage(content=message))
      chatbot_messages.append((message, ""))
      # this is a little wrapper we need cuz we have to add the job_done
      def task():
          chat(messages)
          queue.put(job_done)
  
      # now let's start a thread and run the generation inside it
      t = Thread(target=task)
      t.start()
      # this will hold the content as we generate
      content = ""
      # now, we read the next_token from queue and do what it has to be done
      while True:
          try:
              next_token = queue.get(True, timeout=1)
              if next_token is job_done:
                  break
              content += next_token
              chatbot_messages[-1] = (message, content)
              yield chat, "", chatbot_messages, messages
          except Empty:
              continue
      # finally we can add our reply to messsages
      messages.append(AIMessage(content=content))
      logging.debug(f"reply = {content}")
      logging.info(f"Done!")
      return chat, "", chatbot_messages, messages
  
  
  def system_prompt_handler(value: str) -> str:
      return value
  
  
  def on_clear_button_click(system_prompt: str) -> Tuple[str, List, List]:
      return "", [], [SystemMessage(content=system_prompt)]
  
  
  def on_apply_settings_button_click(
      system_prompt: str, model_name: str, temperature: float
  ):
      logging.info(
          f"Applying settings: model_name={model_name}, temperature={temperature}"
      )
      chat = ChatOpenAI(
          model_name=model_name,
          temperature=temperature,
          streaming=True,
          callbacks=[QueueCallback(Queue())],
      )
      # don't forget to nuke our queue
      chat.callbacks[0].queue.empty()
      return chat, *on_clear_button_click(system_prompt)
  
  
  # some css why not, "borrowed" from https://huggingface.co/spaces/ysharma/Gradio-demo-streaming/blob/main/app.py
  with gr.Blocks(
      css="""#col_container {width: 700px; margin-left: auto; margin-right: auto;}
                  #chatbot {height: 400px; overflow: auto;}"""
  ) as demo:
      system_prompt = gr.State(default_system_prompt)
      # here we keep our state so multiple user can use the app at the same time!
      messages = gr.State([SystemMessage(content=default_system_prompt)])
      # same thing for the chat, we want one chat per use so callbacks are unique I guess
      chat = gr.State(None)
  
      with gr.Column(elem_id="col_container"):
          gr.Markdown("# Welcome to GradioGPT! 🌟🚀")
          gr.Markdown(
              "An easy to use template. It comes with state and settings managment"
          )
          with gr.Column():
              system_prompt_area = gr.TextArea(
                  default_system_prompt, lines=4, label="system prompt", interactive=True
              )
              # we store the value into the state to avoid re rendering of the area
              system_prompt_area.input(
                  system_prompt_handler,
                  inputs=[system_prompt_area],
                  outputs=[system_prompt],
              )
              system_prompt_button = gr.Button("Set")
  
          chatbot = gr.Chatbot()
          with gr.Column():
              message = gr.Textbox(label="chat input")
              message.submit(
                  on_message_button_click,
                  [chat, message, chatbot, messages],
                  [chat, message, chatbot, messages],
                  queue=True,
              )
              message_button = gr.Button("Submit", variant="primary")
              message_button.click(
                  on_message_button_click,
                  [chat, message, chatbot, messages],
                  [chat, message, chatbot, messages],
              )
          with gr.Row():
              with gr.Column():
                  clear_button = gr.Button("Clear")
                  clear_button.click(
                      on_clear_button_click,
                      [system_prompt],
                      [message, chatbot, messages],
                      queue=False,
                  )
              with gr.Accordion("Settings", open=False):
                  model_name = gr.Dropdown(
                      choices=MODELS_NAMES, value=MODELS_NAMES[0], label="model"
                  )
                  temperature = gr.Slider(
                      minimum=0.0,
                      maximum=1.0,
                      value=0.7,
                      step=0.1,
                      label="temperature",
                      interactive=True,
                  )
                  apply_settings_button = gr.Button("Apply")
                  apply_settings_button.click(
                      on_apply_settings_button_click,
                      [system_prompt, model_name, temperature],
                      [chat, message, chatbot, messages],
                  )
  
          system_prompt_button.click(
              on_apply_settings_button_click,
              [system_prompt, model_name, temperature],
              [chat, message, chatbot, messages],
          )
  
  demo.queue()
  demo.launch()
  
apis: langchain.schema.AIMessage langchain.prompts.HumanMessagePromptTemplate.from_template langchain.schema.HumanMessage langchain.schema.SystemMessage
extract_api: [((114, 127), 'dotenv.load_dotenv', 'load_dotenv', ([], {}), '()\n', (125, 127), False, 'from dotenv import load_dotenv\n'), ((604, 698), 'logging.basicConfig', 'logging.basicConfig', ([], {'format': '"""[%(asctime)s %(levelname)s]: %(message)s"""', 'level': 'logging.INFO'}), "(format='[%(asctime)s %(levelname)s]: %(message)s',\n    level=logging.INFO)\n", (623, 698), False, 'import logging\n'), ((873, 923), 'langchain.prompts.HumanMessagePromptTemplate.from_template', 'HumanMessagePromptTemplate.from_template', (['"""{text}"""'], {}), "('{text}')\n", (913, 923), False, 'from langchain.prompts import HumanMessagePromptTemplate\n'), ((1596, 1656), 'logging.info', 'logging.info', (['f"""Asking question to GPT, messages={messages}"""'], {}), "(f'Asking question to GPT, messages={messages}')\n", (1608, 1656), False, 'import logging\n'), ((2004, 2023), 'threading.Thread', 'Thread', ([], {'target': 'task'}), '(target=task)\n', (2010, 2023), False, 'from threading import Thread\n'), ((2606, 2641), 'logging.debug', 'logging.debug', (['f"""reply = {content}"""'], {}), "(f'reply = {content}')\n", (2619, 2641), False, 'import logging\n'), ((2646, 2668), 'logging.info', 'logging.info', (['f"""Done!"""'], {}), "(f'Done!')\n", (2658, 2668), False, 'import logging\n'), ((3020, 3111), 'logging.info', 'logging.info', (['f"""Applying settings: model_name={model_name}, temperature={temperature}"""'], {}), "(\n    f'Applying settings: model_name={model_name}, temperature={temperature}')\n", (3032, 3111), False, 'import logging\n'), ((3530, 3688), 'gradio.Blocks', 'gr.Blocks', ([], {'css': '"""#col_container {width: 700px; margin-left: auto; margin-right: auto;}\n                #chatbot {height: 400px; overflow: auto;}"""'}), '(css=\n    """#col_container {width: 700px; margin-left: auto; margin-right: auto;}\n                #chatbot {height: 400px; overflow: auto;}"""\n    )\n', (3539, 3688), True, 'import gradio as gr\n'), ((3714, 3745), 'gradio.State', 'gr.State', (['default_system_prompt'], {}), '(default_system_prompt)\n', (3722, 3745), True, 'import gradio as gr\n'), ((3997, 4011), 'gradio.State', 'gr.State', (['None'], {}), '(None)\n', (4005, 4011), True, 'import gradio as gr\n'), ((753, 782), 'pathlib.Path', 'Path', (['"""prompts/system.prompt"""'], {}), "('prompts/system.prompt')\n", (757, 782), False, 'from pathlib import Path\n'), ((1228, 1235), 'queue.Queue', 'Queue', ([], {}), '()\n', (1233, 1235), False, 'from queue import Empty, Queue\n'), ((1719, 1748), 'langchain.schema.HumanMessage', 'HumanMessage', ([], {'content': 'message'}), '(content=message)\n', (1731, 1748), False, 'from langchain.schema import AIMessage, BaseMessage, HumanMessage, SystemMessage\n'), ((2574, 2600), 'langchain.schema.AIMessage', 'AIMessage', ([], {'content': 'content'}), '(content=content)\n', (2583, 2600), False, 'from langchain.schema import AIMessage, BaseMessage, HumanMessage, SystemMessage\n'), ((4022, 4056), 'gradio.Column', 'gr.Column', ([], {'elem_id': '"""col_container"""'}), "(elem_id='col_container')\n", (4031, 4056), True, 'import gradio as gr\n'), ((4066, 4107), 'gradio.Markdown', 'gr.Markdown', (['"""# Welcome to GradioGPT! 🌟🚀"""'], {}), "('# Welcome to GradioGPT! 🌟🚀')\n", (4077, 4107), True, 'import gradio as gr\n'), ((4116, 4203), 'gradio.Markdown', 'gr.Markdown', (['"""An easy to use template. It comes with state and settings managment"""'], {}), "(\n    'An easy to use template. It comes with state and settings managment')\n", (4127, 4203), True, 'import gradio as gr\n'), ((4725, 4737), 'gradio.Chatbot', 'gr.Chatbot', ([], {}), '()\n', (4735, 4737), True, 'import gradio as gr\n'), ((2877, 2913), 'langchain.schema.SystemMessage', 'SystemMessage', ([], {'content': 'system_prompt'}), '(content=system_prompt)\n', (2890, 2913), False, 'from langchain.schema import AIMessage, BaseMessage, HumanMessage, SystemMessage\n'), ((3851, 3895), 'langchain.schema.SystemMessage', 'SystemMessage', ([], {'content': 'default_system_prompt'}), '(content=default_system_prompt)\n', (3864, 3895), False, 'from langchain.schema import AIMessage, BaseMessage, HumanMessage, SystemMessage\n'), ((4234, 4245), 'gradio.Column', 'gr.Column', ([], {}), '()\n', (4243, 4245), True, 'import gradio as gr\n'), ((4280, 4368), 'gradio.TextArea', 'gr.TextArea', (['default_system_prompt'], {'lines': '(4)', 'label': '"""system prompt"""', 'interactive': '(True)'}), "(default_system_prompt, lines=4, label='system prompt',\n    interactive=True)\n", (4291, 4368), True, 'import gradio as gr\n'), ((4689, 4705), 'gradio.Button', 'gr.Button', (['"""Set"""'], {}), "('Set')\n", (4698, 4705), True, 'import gradio as gr\n'), ((4751, 4762), 'gradio.Column', 'gr.Column', ([], {}), '()\n', (4760, 4762), True, 'import gradio as gr\n'), ((4786, 4816), 'gradio.Textbox', 'gr.Textbox', ([], {'label': '"""chat input"""'}), "(label='chat input')\n", (4796, 4816), True, 'import gradio as gr\n'), ((5061, 5099), 'gradio.Button', 'gr.Button', (['"""Submit"""'], {'variant': '"""primary"""'}), "('Submit', variant='primary')\n", (5070, 5099), True, 'import gradio as gr\n'), ((5306, 5314), 'gradio.Row', 'gr.Row', ([], {}), '()\n', (5312, 5314), True, 'import gradio as gr\n'), ((5333, 5344), 'gradio.Column', 'gr.Column', ([], {}), '()\n', (5342, 5344), True, 'import gradio as gr\n'), ((5377, 5395), 'gradio.Button', 'gr.Button', (['"""Clear"""'], {}), "('Clear')\n", (5386, 5395), True, 'import gradio as gr\n'), ((5630, 5666), 'gradio.Accordion', 'gr.Accordion', (['"""Settings"""'], {'open': '(False)'}), "('Settings', open=False)\n", (5642, 5666), True, 'import gradio as gr\n'), ((5697, 5768), 'gradio.Dropdown', 'gr.Dropdown', ([], {'choices': 'MODELS_NAMES', 'value': 'MODELS_NAMES[0]', 'label': '"""model"""'}), "(choices=MODELS_NAMES, value=MODELS_NAMES[0], label='model')\n", (5708, 5768), True, 'import gradio as gr\n'), ((5837, 5937), 'gradio.Slider', 'gr.Slider', ([], {'minimum': '(0.0)', 'maximum': '(1.0)', 'value': '(0.7)', 'step': '(0.1)', 'label': '"""temperature"""', 'interactive': '(True)'}), "(minimum=0.0, maximum=1.0, value=0.7, step=0.1, label=\n    'temperature', interactive=True)\n", (5846, 5937), True, 'import gradio as gr\n'), ((6112, 6130), 'gradio.Button', 'gr.Button', (['"""Apply"""'], {}), "('Apply')\n", (6121, 6130), True, 'import gradio as gr\n'), ((1440, 1460), 'callback.QueueCallback', 'QueueCallback', (['queue'], {}), '(queue)\n', (1453, 1460), False, 'from callback import QueueCallback\n'), ((3265, 3272), 'queue.Queue', 'Queue', ([], {}), '()\n', (3270, 3272), False, 'from queue import Empty, Queue\n')]