Spaces:
Runtime error
Runtime error
File size: 12,334 Bytes
e2769d5 2bf3313 e2769d5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Blocher Basic Interaction Exercise\n",
"\n",
"In this notebook, we create a minimized version of the current app to be deployed onto Huggingface Space, which has the following components: \n",
"\n",
"- Student interface: \n",
" A chat interface where students interact with the chatbot that has had the instructor-designed prompt given to it but they cannot see the prompt. At the end of the conversation, entire convo is made available as downloadable JSON such that students can download it and turn it in to Brightspace.\n",
"\n",
"- Instructor interface:\n",
" A file upload and check content interface which allows instructor to involve files in the HuggingFace Space - i.e. copying and pasting hidden prompt in a txt file or .py file. The prompt will serve as the input to the chatbot, and is not visible by students. "
]
},
{
"cell_type": "code",
# "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#| default_exp BasicInteraction"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First, we'll start by loading our own libraries. Keep in mind that if you're on Colab, you need to replace \"token\" below with your GitHub token."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# run this code only if you're using Google Colab\n",
"#! pip install pip install git+https://<token>@github.com/vanderbilt-data-science/lo-achievement.git"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"## run this code only if you're local and developing\n",
"import os, sys\n",
"\n",
"# get parent of current working directory\n",
"parent_dir = os.path.dirname(os.getcwd())\n",
"\n",
"#append to path\n",
"sys.path.append(parent_dir)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#| export\n",
"import os\n",
"import gradio as gr\n",
"import pandas as pd\n",
"from functools import partial\n",
"from ai_classroom_suite.UIBaseComponents import *"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Interface Helpers and Functionality\n",
"\n",
"In the next section, we'll create some helper functions to make sure we're able to create the interface we want, and that it behaves nicely. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Student Interface Chatbot Functions ###"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#| export\n",
"# overwrites the original method since we don't deal with any vector stores here\n",
"def get_tutor_reply(chat_tutor):\n",
" chat_tutor.get_tutor_reply()\n",
" return gr.update(value=\"\", interactive=True), chat_tutor.conversation_memory, chat_tutor\n",
"\n",
"def get_conversation_history(chat_tutor):\n",
" return chat_tutor.conversation_memory, chat_tutor"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Instructor Interface Helper Functions ###\n",
"\n",
"Instructor needs to upload a .txt or .py file as the secret prompt provided to the chatbot.\n",
"\n",
"- **get_instructor_prompt(fileobj)** receives the instructor uploaded file and return the content of the file. \n",
"\n",
"- **embed_prompt(prompt)** receives a prompt and update the ``SECRET_PROMPT`` secret and the learning objectives of the chatbot with this prompt. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#| export\n",
"def get_instructor_prompt(fileobj):\n",
" # get file path\n",
" file_path = fileobj.name\n",
" # read file content\n",
" with open(file_path, \"r\") as f: \n",
" instructor_prompt = f.read()\n",
" return instructor_prompt\n",
"\n",
"def embed_prompt(prompt, chat_tutor):\n",
" # update secret\n",
" os.environ[\"SECRET_PROMPT\"] = prompt\n",
" # update tutor\n",
" chat_tutor.learning_objectives = prompt\n",
" return os.environ.get(\"SECRET_PROMPT\"), chat_tutor"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# The User Interface\n",
"\n",
"Below, we put all of this information together with the actual formatting of the user interface."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Note for Instructors ###\n",
"\n",
"You need to provide an OpenAI API Key to initialize the model. If you haven't created one already, visit [platform.openai.com/account/api-keys](https://platform.openai.com/account/api-keys) to sign up for an account and get your personal API key. \n",
"\n",
"To permanently set the key, in the hosted app on Huggingface Space, go to ``Settings -> Variables and Secrets -> Secrets``, then replace ``OPENAI_API_KEY`` value with your key."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#| export\n",
"with gr.Blocks() as BasicInteractionDemo:\n",
" #initialize tutor (with state)\n",
" study_tutor = gr.State(SlightlyDelusionalTutor())\n",
"\n",
" # Student interface\n",
" with gr.Tab(\"For Students\"): \n",
" \n",
" # Chatbot interface\n",
" gr.Markdown(\"\"\"\n",
" ## Chat with the Model\n",
" Description here\n",
" \"\"\")\n",
" \n",
" with gr.Row(equal_height=True):\n",
" with gr.Column(scale=2):\n",
" chatbot = gr.Chatbot()\n",
" with gr.Row():\n",
" user_chat_input = gr.Textbox(label=\"User input\", scale=9)\n",
" user_chat_submit = gr.Button(\"Ask/answer model\", scale=1)\n",
"\n",
" # First add user's message to the conversation history\n",
" # Then get reply from the tutor and add that to the conversation history\n",
" user_chat_submit.click(\n",
" fn = add_user_message, inputs = [user_chat_input, study_tutor], outputs = [user_chat_input, chatbot, study_tutor], queue=False\n",
" ).then(\n",
" fn = get_tutor_reply, inputs = [study_tutor], outputs = [user_chat_input, chatbot, study_tutor], queue=True\n",
" )\n",
" \n",
" # Testing the chat history storage, can be deleted at deployment\n",
" with gr.Blocks():\n",
" test_btn = gr.Button(\"View your chat history\")\n",
" chat_history = gr.JSON(label = \"conversation history\")\n",
" test_btn.click(get_conversation_history, inputs=[study_tutor], outputs=[chat_history, study_tutor])\n",
"\n",
" # Download conversation history file\n",
" with gr.Blocks():\n",
" gr.Markdown(\"\"\"\n",
" ## Export Your Chat History\n",
" Export your chat history as a .json, .txt, or .csv file\n",
" \"\"\")\n",
" with gr.Row():\n",
" export_dialogue_button_json = gr.Button(\"JSON\")\n",
" export_dialogue_button_txt = gr.Button(\"TXT\")\n",
" export_dialogue_button_csv = gr.Button(\"CSV\")\n",
" \n",
" file_download = gr.Files(label=\"Download here\", file_types=['.json', '.txt', '.csv'], type=\"file\", visible=False)\n",
" \n",
" export_dialogue_button_json.click(save_json, study_tutor, file_download, show_progress=True)\n",
" export_dialogue_button_txt.click(save_txt, study_tutor, file_download, show_progress=True)\n",
" export_dialogue_button_csv.click(save_csv, study_tutor, file_download, show_progress=True)\n",
"\n",
"\n",
" # Instructor interface\n",
" with gr.Tab(\"Instructor Only\"):\n",
" # API Authentication functionality\n",
" # Instead of ask students to provide key, the key is now provided by the instructor. \n",
" api_input = gr.Textbox(show_label=False, type=\"password\", visible=False, value=os.environ.get(\"OPENAI_API_KEY\"))\n",
"\n",
" # Upload secret prompt functionality\n",
" # The instructor will provide a secret prompt/persona to the tutor\n",
" with gr.Blocks():\n",
" # testing purpose, change visible to False at deployment\n",
" view_secret = gr.Textbox(label=\"Current secret prompt\", value=os.environ.get(\"SECRET_PROMPT\"), visible=False)\n",
"\n",
" # Prompt instructor to upload the secret file\n",
" file_input = gr.File(label=\"Load a .txt or .py file\", file_types=['.py', '.txt'], type=\"file\", elem_classes=\"short-height\")\n",
" \n",
" # Verify prompt content\n",
" instructor_prompt = gr.Textbox(label=\"Verify your prompt content\", visible=True)\n",
" file_input.upload(fn=get_instructor_prompt, inputs=file_input, outputs=instructor_prompt)\n",
"\n",
" # Placeholders components\n",
" text_input_none = gr.Textbox(visible=False)\n",
" file_input_none = gr.File(visible=False)\n",
" instructor_input_none = gr.TextArea(visible=False)\n",
" learning_objectives_none = gr.Textbox(visible=False)\n",
"\n",
" # Set the secret prompt in this session and embed it to the study tutor\n",
" prompt_submit_btn = gr.Button(\"Submit\")\n",
" prompt_submit_btn.click(\n",
" fn=embed_prompt, inputs=[instructor_prompt, study_tutor], outputs=[view_secret, study_tutor]\n",
" ).then(\n",
" fn=create_reference_store, \n",
" inputs=[study_tutor, prompt_submit_btn, instructor_prompt, file_input_none, instructor_input_none, api_input, instructor_prompt],\n",
" outputs=[study_tutor, prompt_submit_btn]\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"BasicInteractionDemo.queue().launch(server_name='0.0.0.0', server_port=7860)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A little helper in case your ports are open and you just want to close them all. If this doesn't work, restart your IDE."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"gr.close_all()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# TODO: The instructor prompt is now only set in session if not go to Settings/secret, \n",
"# to \"permanently\" set the secret prompt not seen by the students who use this space, \n",
"# one possible way is to recreate the instructor interface in another space, \n",
"# and load it here to chain with the student interface. \n",
" \n",
"# TODO: Currently, the instructor prompt is handled as text input and stored in the vector store (and in the learning objective),\n",
"# which means the tutor now is still a question-answering tutor who viewed the prompt as context (but not really acting based on it). \n",
"# We need to find a way to provide the prompt directly to the model and set its status. "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.12"
}
},
"nbformat": 4,
"nbformat_minor": 2
} |