# app.py : Multimodal Chatbot import os import time import logging from dotenv import load_dotenv import gradio as gr ################################################################ # Load .env and logging ################################################################ load_dotenv() # take environment variables from .env. logging.basicConfig(level=logging.WARN, format='%(asctime)-15s] %(message)s', datefmt="%m/%d/%Y %I:%M:%S %p %Z") def print(*args, **kwargs): sep = kwargs['sep'] if 'sep' in kwargs else ' ' logging.warning(sep.join([str(val) for val in args])) # use level WARN for print, as gradio level INFO print unwanted messages ################################################################ # Extra loading ################################################################ from llms import _openai_stream_bot_fn as _llm_call_stream # from prompts import PROMPTS PROMPTS = {} ################################################################ # Global variables ################################################################ TITLE = "AI Chat" DESCRIPTION = """ # AI Chat Simply enter text and press ENTER in the textbox to interact with the chatbot. """ ATTACHMENTS = { 'openai_api_key' : dict(cls='Textbox', interactive=True, label="OpenAI API Key", info='Please input your OpenAI API key here.'), 'chat_role': dict(cls='Dropdown', choices=list(PROMPTS.keys()), value="", interactive=True, label='Awesome ChatGPT Prompt', info='Set system prompt to act as the specified role.'), 'system_prompt': dict(cls='Textbox', interactive=True, lines=5, label="System prompt"), } SETTINGS = { 'chat_engine': dict(cls='Radio', choices=['auto', 'gpt-3.5-turbo-16k', 'gpt-4'], value='auto', interactive=True, label="Chat engine"), } PARAMETERS = { 'temperature': dict(cls='Slider', minimum=0, maximum=1, value=0.7, step=0.1, interactive=True, label="Temperature", info="Lower temperator for determined output; hight temperate for randomness"), } KWARGS = {} # use for chatbot additional_inputs, do NOT change ################################################################ # utils ################################################################ def _create_from_dict(PARAMS, tabbed=False): params = {} for name, kwargs in PARAMS.items(): cls_ = kwargs['cls']; del kwargs['cls'] if not tabbed: params[name] = getattr(gr, cls_)(**kwargs) else: tab_name = kwargs['label'] if 'label' in kwargs else name with gr.Tab(tab_name): params[name] = getattr(gr, cls_)(**kwargs) return params ################################################################ # Bot fn ################################################################ def bot_fn(message, history, *args): __TIC = time.time() kwargs = {name: value for name, value in zip(KWARGS.keys(), args)} kwargs['verbose'] = True # auto print llm calls AUTOS = {'chat_engine': 'gpt-3.5-turbo-16k'} # set param to default value if param is "auto" for param, default_value in AUTOS.items(): kwargs[param] = default_value if kwargs[param] == 'auto' else kwargs[param] if 'openai_api_key' in kwargs: if kwargs['openai_api_key'].startswith('sk-'): os.environ['OPENAI_API_KEY'] = kwargs['openai_api_key'] else: import base64 os.environ['OPENAI_API_KEY'] = base64.b64decode(kwargs['openai_api_key'].encode('ascii')).decode('ascii') if 'OPENAI_API_KEY' in os.environ and os.environ['OPENAI_API_KEY']: bot_message = _llm_call_stream(message, history, **kwargs) else: bot_message = f'**ERROR**: Please input your OpenAI API key and retry!\nYou can obtain an API key from https://platform.openai.com/account/api-keys' if isinstance(bot_message, str): yield bot_message else: for m in bot_message: yield m bot_message = m print(kwargs) __TOC = time.time() print(f'Elapsed time: {__TOC-__TIC}') ################################################################ # Gradio app ################################################################ def get_demo(): # use css and elem_id to format css="""#chatbot { min-height: 600px; }""" with gr.Blocks(css=css) as demo: # title gr.HTML(f"

{TITLE}

") # description with gr.Accordion("Expand to see Introduction and Usage", open=False): gr.Markdown(f"{DESCRIPTION}") with gr.Row(): # attachments, settings, and parameters with gr.Column(scale=1): attachments = _create_from_dict(ATTACHMENTS) with gr.Accordion("Settings", open=False) as settings_accordin: settings = _create_from_dict(SETTINGS) with gr.Accordion("Parameters", open=False) as parameters_accordin: parameters = _create_from_dict(PARAMETERS) with gr.Column(scale=9): # chatbot global KWARGS KWARGS = {**attachments, **settings, **parameters} KWARGS = {k: v for k, v in KWARGS.items() if not isinstance(v, (gr.Markdown, gr.HTML, gr.JSON))} chatbot = gr.ChatInterface(bot_fn, # chatbot=_chatbot, textbox=_textbox, additional_inputs=list(KWARGS.values()), retry_btn="Retry", undo_btn="Undo", clear_btn="Clear", ) chatbot.chatbot.elem_id = 'chatbot' # for css chatbot.chatbot.avatar_images = ("assets/user.png", "assets/openai.png") # examples with gr.Accordion("Examples", open=False) as examples_accordin: chat_examples = gr.Examples( ["What's the Everett interpretation of quantum mechanics?", 'Give me a list of the top 10 dive sites you would recommend around the world.', 'Write a Python code to calculate Fibonacci numbers.' ], inputs=chatbot.textbox, label="AI Chat Examples", ) # additional handlers for name, attach in attachments.items(): if hasattr(chatbot, '_upload_fn') and isinstance(attach, (gr.Image, gr.Audio, gr.Video, gr.File)): attach.change(chatbot._upload_fn, [chatbot.textbox, attach], [chatbot.textbox], queue=False, api_name=False) if 'chat_role' in attachments and 'system_prompt' in attachments: chat_role = attachments['chat_role'] system_prompt = attachments['system_prompt'] chat_role.change(lambda x: PROMPTS[x]['prompt'].strip(), chat_role, system_prompt) return demo def parse_args(): """Parse input arguments.""" import argparse parser = argparse.ArgumentParser( description='Multimodal Chatbot', formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument( '-p', '--port', default=7860, type=int, help='port number.') parser.add_argument( '--debug', action='store_true', help='debug mode.') args = parser.parse_args() return args if __name__ == '__main__': args = parse_args() if 'OPENAI_API_KEY' in os.environ: del ATTACHMENTS['openai_api_key'] demo = get_demo() demo.queue().launch(server_name='0.0.0.0', server_port=args.port)