{ "cells": [ { "cell_type": "markdown", "id": "8ec2fef2", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Creating a Functional Conversational Chatbot\n", "* **Created by:** Eric Martinez\n", "* **For:** Software Engineering 2\n", "* **At:** University of Texas Rio-Grande Valley" ] }, { "cell_type": "markdown", "id": "cd292e78", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Tutorial: A Basic Conversational Chatbot with LLM (has limitations)" ] }, { "cell_type": "markdown", "id": "dce44841", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "#### Installing Dependencies" ] }, { "cell_type": "code", "execution_count": 8, "id": "1bae55e3", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "!pip -q install --upgrade gradio\n", "!pip -q install --upgrade openai" ] }, { "cell_type": "markdown", "id": "f762bbca", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "#### Creating a basic Chatbot UI using Gradio" ] }, { "cell_type": "code", "execution_count": 30, "id": "feb92318", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Running on local URL: http://127.0.0.1:7884\n", "Running on public URL: https://0f4cb905f030007a42.gradio.live\n", "\n", "This share link expires in 72 hours. For free permanent hosting and GPU upgrades (NEW!), check out Spaces: https://huggingface.co/spaces\n" ] }, { "data": { "text/html": [ "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import gradio as gr\n", "import openai\n", "from dotenv import load_dotenv\n", "\n", "load_dotenv() # take environment variables from .env.\n", "\n", "# Define a function to get the AI's reply using the OpenAI API\n", "def get_ai_reply(message, model=\"gpt-3.5-turbo\", system_message=None, temperature=0, message_history=[]):\n", " # Initialize the messages list\n", " messages = []\n", " \n", " # Add the system message to the messages list\n", " if system_message is not None:\n", " messages += [{\"role\": \"system\", \"content\": system_message}]\n", "\n", " # Add the message history to the messages list\n", " if message_history is not None:\n", " messages += message_history\n", " \n", " # Add the user's message to the messages list\n", " messages += [{\"role\": \"user\", \"content\": message}]\n", " \n", " # Make an API call to the OpenAI ChatCompletion endpoint with the model and messages\n", " completion = openai.ChatCompletion.create(\n", " model=model,\n", " messages=messages,\n", " temperature=temperature\n", " )\n", " \n", " # Extract and return the AI's response from the API response\n", " return completion.choices[0].message.content.strip()\n", "\n", "def chat(message, history):\n", " history = history or []\n", " ai_reply = get_ai_reply(message) \n", " history.append((message, ai_reply))\n", " return None, history, history\n", " \n", "with gr.Blocks() as demo:\n", " with gr.Tab(\"Conversation\"):\n", " with gr.Row():\n", " with gr.Column():\n", " chatbot = gr.Chatbot(label=\"Conversation\")\n", " message = gr.Textbox(label=\"Message\")\n", " history_state = gr.State()\n", " btn = gr.Button(value =\"Send\")\n", " btn.click(chat, inputs = [message, history_state], outputs = [message, chatbot, history_state])\n", " demo.launch(share=True)\n" ] }, { "cell_type": "markdown", "id": "77c9ec20", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "#### Limitations\n", "* Hardcoded to 'gpt-3.5-turbo' in the UI\n", "* No error-handling on the API request\n", "* While the OpenAI function takes message history, the UI doesn't pass it through\n", "* Doesn't use or allow prompt or 'system' message customization" ] }, { "cell_type": "markdown", "id": "66215904", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Tutorial: Improved Chatbot" ] }, { "cell_type": "markdown", "id": "99f57faf", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "The following snippet adds conversation history to the Gradio chat functionality, handles errors, and passes along the system message." ] }, { "cell_type": "code", "execution_count": 31, "id": "9e55e844", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# Define a function to handle the chat interaction with the AI model\n", "def chat(model, system_message, message, chatbot_messages, history_state):\n", " # Initialize chatbot_messages and history_state if they are not provided\n", " chatbot_messages = chatbot_messages or []\n", " history_state = history_state or []\n", " \n", " # Try to get the AI's reply using the get_ai_reply function\n", " try:\n", " ai_reply = get_ai_reply(message, model=model, system_message=system_message, message_history=history_state)\n", " except Exception as e:\n", " # If an error occurs, raise a Gradio error\n", " raise gr.Error(e)\n", " \n", " # Append the user's message and the AI's reply to the chatbot_messages list\n", " chatbot_messages.append((message, ai_reply))\n", " \n", " # Append the user's message and the AI's reply to the history_state list\n", " history_state.append({\"role\": \"user\", \"content\": message})\n", " history_state.append({\"role\": \"assistant\", \"content\": ai_reply})\n", " \n", " # Return None (empty out the user's message textbox), the updated chatbot_messages, and the updated history_state\n", " return None, chatbot_messages, history_state" ] }, { "cell_type": "markdown", "id": "44d9fde1", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "The following snippet adjusts the Gradio interface to include examples (included in a separate file in this repo), model selection, prompts or 'system' messages, storing conversation history." ] }, { "cell_type": "code", "execution_count": 32, "id": "d45439f3", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "import examples as chatbot_examples\n", "\n", "# Define a function to return a chatbot app using Gradio\n", "def get_chatbot_app(additional_examples=[], share=False):\n", " # Load chatbot examples and merge with any additional examples provided\n", " examples = chatbot_examples.load_examples(additional=additional_examples)\n", " \n", " # Define a function to get the names of the examples\n", " def get_examples():\n", " return [example[\"name\"] for example in examples]\n", "\n", " # Define a function to choose an example based on the index\n", " def choose_example(index):\n", " system_message = examples[index][\"system_message\"].strip()\n", " user_message = examples[index][\"message\"].strip()\n", " return system_message, user_message, [], []\n", "\n", " # Create the Gradio interface using the Blocks layout\n", " with gr.Blocks() as app:\n", " with gr.Tab(\"Conversation\"):\n", " with gr.Row():\n", " with gr.Column():\n", " # Create a dropdown to select examples\n", " example_dropdown = gr.Dropdown(get_examples(), label=\"Examples\", type=\"index\")\n", " # Create a button to load the selected example\n", " example_load_btn = gr.Button(value=\"Load\")\n", " # Create a textbox for the system message (prompt)\n", " system_message = gr.Textbox(label=\"System Message (Prompt)\", value=\"You are a helpful assistant.\")\n", " with gr.Column():\n", " # Create a dropdown to select the AI model\n", " model_selector = gr.Dropdown(\n", " [\"gpt-3.5-turbo\", \"gpt-4\"],\n", " label=\"Model\",\n", " value=\"gpt-3.5-turbo\"\n", " )\n", " # Create a chatbot interface for the conversation\n", " chatbot = gr.Chatbot(label=\"Conversation\")\n", " # Create a textbox for the user's message\n", " message = gr.Textbox(label=\"Message\")\n", " # Create a state object to store the conversation history\n", " history_state = gr.State()\n", " # Create a button to send the user's message\n", " btn = gr.Button(value=\"Send\")\n", "\n", " # Connect the example load button to the choose_example function\n", " example_load_btn.click(choose_example, inputs=[example_dropdown], outputs=[system_message, message, chatbot, history_state])\n", " # Connect the send button to the chat function\n", " btn.click(chat, inputs=[model_selector, system_message, message, chatbot, history_state], outputs=[message, chatbot, history_state])\n", " # Return the app\n", " return app" ] }, { "cell_type": "code", "execution_count": 33, "id": "e166c472", "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Running on local URL: http://127.0.0.1:7885\n", "\n", "To create a public link, set `share=True` in `launch()`.\n" ] }, { "data": { "text/html": [ "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Call the launch_chatbot function to start the chatbot interface using Gradio\n", "# Set the share parameter to False, meaning the interface will not be publicly accessible\n", "get_chatbot_app().launch()" ] }, { "cell_type": "code", "execution_count": null, "id": "1c1f3b03", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.8" } }, "nbformat": 4, "nbformat_minor": 5 }