diff --git a/environment.yml b/environment.yml index c328db2..a473bc1 100644 --- a/environment.yml +++ b/environment.yml @@ -19,6 +19,8 @@ dependencies: - notebook - sortedcontainers - jupyter-vuetify + - pypdf - pip - pip: - langchain-openai + - unstructured # for loading markdown files diff --git a/jupyter_mentor/_modidx.py b/jupyter_mentor/_modidx.py index e58800b..0820a93 100644 --- a/jupyter_mentor/_modidx.py +++ b/jupyter_mentor/_modidx.py @@ -8,6 +8,18 @@ 'syms': { 'jupyter_mentor.chatbot': { 'jupyter_mentor.chatbot.ChatBot': ('chatbot.html#chatbot', 'jupyter_mentor/chatbot.py'), 'jupyter_mentor.chatbot.ChatBot.__init__': ( 'chatbot.html#chatbot.__init__', 'jupyter_mentor/chatbot.py'), + 'jupyter_mentor.chatbot.ChatBot.on_click': ( 'chatbot.html#chatbot.on_click', + 'jupyter_mentor/chatbot.py'), + 'jupyter_mentor.chatbot.ChatBotModel': ('chatbot.html#chatbotmodel', 'jupyter_mentor/chatbot.py'), + 'jupyter_mentor.chatbot.ChatBotModel.__init__': ( 'chatbot.html#chatbotmodel.__init__', + 'jupyter_mentor/chatbot.py'), + 'jupyter_mentor.chatbot.ChatBotModel.prompt': ( 'chatbot.html#chatbotmodel.prompt', + 'jupyter_mentor/chatbot.py'), + 'jupyter_mentor.chatbot.ChatBotModel.update_bot_template': ( 'chatbot.html#chatbotmodel.update_bot_template', + 'jupyter_mentor/chatbot.py'), + 'jupyter_mentor.chatbot.ChatBotView': ('chatbot.html#chatbotview', 'jupyter_mentor/chatbot.py'), + 'jupyter_mentor.chatbot.ChatBotView.__init__': ( 'chatbot.html#chatbotview.__init__', + 'jupyter_mentor/chatbot.py'), 'jupyter_mentor.chatbot.EducatorChatBot': ( 'chatbot.html#educatorchatbot', 'jupyter_mentor/chatbot.py'), 'jupyter_mentor.chatbot.EducatorChatBot.__init__': ( 'chatbot.html#educatorchatbot.__init__', @@ -20,12 +32,6 @@ 'jupyter_mentor/educator_course_overview.py'), 'jupyter_mentor.educator_course_overview.EducatorCourseOverview.__init__': ( 'educator_course_overview.html#educatorcourseoverview.__init__', 'jupyter_mentor/educator_course_overview.py')}, - 'jupyter_mentor.educator_model': { 'jupyter_mentor.educator_model.EducatorModel': ( 'educator_model.html#educatormodel', - 'jupyter_mentor/educator_model.py'), - 'jupyter_mentor.educator_model.EducatorModel.__init__': ( 'educator_model.html#educatormodel.__init__', - 'jupyter_mentor/educator_model.py'), - 'jupyter_mentor.educator_model.EducatorModel.invoke': ( 'educator_model.html#educatormodel.invoke', - 'jupyter_mentor/educator_model.py')}, 'jupyter_mentor.educator_profile': { 'jupyter_mentor.educator_profile.EducatorProfile': ( 'educator_profile.html#educatorprofile', 'jupyter_mentor/educator_profile.py'), 'jupyter_mentor.educator_profile.EducatorProfile.__init__': ( 'educator_profile.html#educatorprofile.__init__', diff --git a/jupyter_mentor/chatbot.py b/jupyter_mentor/chatbot.py index 084372d..896c376 100644 --- a/jupyter_mentor/chatbot.py +++ b/jupyter_mentor/chatbot.py @@ -1,48 +1,53 @@ # AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/05_chatbot.ipynb. # %% auto 0 -__all__ = ['ChatBot', 'StudentChatBot', 'EducatorChatBot'] +__all__ = ['ChatBotModel', 'ChatBotView', 'ChatBot', 'StudentChatBot', 'EducatorChatBot'] # %% ../nbs/05_chatbot.ipynb 1 import ipywidgets as widgets +import traitlets from ipywidgets import Textarea, Text, Layout, HBox - -# %% ../nbs/05_chatbot.ipynb 2 -class ChatBot(widgets.VBox): +from traitlets import HasTraits +import os +from langchain_openai import ChatOpenAI +from langchain_core.messages import HumanMessage, SystemMessage +from langchain_core.prompts.chat import ( + ChatPromptTemplate, + HumanMessagePromptTemplate, + SystemMessagePromptTemplate, +) +from langchain_openai import ChatOpenAI + +# %% ../nbs/05_chatbot.ipynb 3 +class ChatBotModel(HasTraits): + + def __init__(self, llm, bot_template="You are playing the role of a tutor/educator"): + super().__init__() + self.llm = llm + self.human_template = "{input_text}" + self.update_bot_template(bot_template) + + def update_bot_template(self, bot_template): + self.bot_template = bot_template + self.bot_message_prompt = SystemMessagePromptTemplate.from_template(self.bot_template) + self.human_message_prompt = HumanMessagePromptTemplate.from_template(self.human_template) + self.chat_prompt = ChatPromptTemplate.from_messages([self.bot_message_prompt, self.human_message_prompt]) + + def prompt(self, input_text): + #prompt_val = prompt_template.invoke({"adjective": "funny", "content": "chickens"}) + ret = self.llm.invoke(self.chat_prompt.format_prompt(input_text=input_text)) + return ret.content + +# %% ../nbs/05_chatbot.ipynb 5 +class ChatBotView(widgets.VBox): def __init__(self): # If you forget to call the superconstructor on an extended widget # you will get an AttributeError: object has no attribute '_model_id' super().__init__() - example_convo = ''' -User: Hello, bot! - -Bot: Hi there! How can I assist you today? - -User: I need help setting up my email account. Can you guide me through the process? - -Bot: Of course! Could you please provide me with the email service provider you're using? - -User: I use Gmail. - -Bot: Great! First, go to the Gmail website and click on the "Create account" button. - -User: Okay, I'm there. What's next? - -Bot: Enter your personal information such as your name, desired email address, password, and recovery information. - -User: Done! What's next? - -Bot: Follow the prompts to verify your phone number and agree to the terms of service. - -User: All set! Thank you for your help, bot! - -Bot: You're welcome! If you have any more questions, feel free to ask. -''' self.chat = Textarea( disabled = True, - value = example_convo, layout=Layout(width='90%', height='400px') ) self.user_input_and_submit = HBox() @@ -50,25 +55,48 @@ def __init__(self): placeholder='Message AI chatbot...', #layout=Layout(width='100%') ) - self.submit = widgets.ToggleButton( + self.submit_button = widgets.Button( value=False, disabled=False, button_style='success', icon='arrow-circle-right' ) - self.user_input_and_submit.children = (self.user_input, self.submit) + self.user_input_and_submit.children = (self.user_input, self.submit_button) self.children = (self.chat, self.user_input_and_submit) -# %% ../nbs/05_chatbot.ipynb 4 +# %% ../nbs/05_chatbot.ipynb 7 +class ChatBot(ChatBotView): + + def __init__(self, model): + # If you forget to call the superconstructor on an extended widget + # you will get an AttributeError: object has no attribute '_model_id' + super().__init__() + self.submit_button.on_click(self.on_click) + self.model =model + + def on_click(self, change): + self.chat.value = self.chat.value + "USER: " + self.user_input.value + '\n\n' + self.user_input.value = '' + ret = self.model.prompt(self.user_input.value) + self.chat.value = self.chat.value + "CHATBOT: " + ret + '\n\n' + +# %% ../nbs/05_chatbot.ipynb 9 class StudentChatBot(widgets.VBox): + + #user = traitlets.CUnicode() + #response = traitlets.CUnicode() + #step_by_step = traitlets.Bool() + #metaphor = traitlets.Bool() + #hints = traitlets.Bool() + #guided_questions = traitlets.Bool() - def __init__(self): + def __init__(self, chatbot_model): # If you forget to call the superconstructor on an extended widget # you will get an AttributeError: object has no attribute '_model_id' super().__init__() - self.chat_bot = ChatBot() + self.chat_bot = ChatBot(chatbot_model) self.suggestion_buttons = HBox() self.step_by_step = widgets.Button( @@ -94,15 +122,22 @@ def __init__(self): self.suggestion_buttons.children = (self.step_by_step, self.metaphor, self.hints, self.guided_questions) self.children = (self.chat_bot, self.suggestion_buttons) -# %% ../nbs/05_chatbot.ipynb 6 +# %% ../nbs/05_chatbot.ipynb 11 class EducatorChatBot(widgets.VBox): + + #user = traitlets.CUnicode() + #response = traitlets.CUnicode() + #step_by_step = traitlets.Bool() + #metaphor = traitlets.Bool() + #hints = traitlets.Bool() + #guided_questions = traitlets.Bool() - def __init__(self, ): + def __init__(self, chatbot_model): # If you forget to call the superconstructor on an extended widget # you will get an AttributeError: object has no attribute '_model_id' super().__init__() - self.chat_bot = ChatBot() + self.chat_bot = ChatBot(chatbot_model) self.suggestion_buttons = HBox() self.exam_questions = widgets.Button( diff --git a/jupyter_mentor/educator_model.py b/jupyter_mentor/educator_model.py deleted file mode 100644 index 8c66bc7..0000000 --- a/jupyter_mentor/educator_model.py +++ /dev/null @@ -1,21 +0,0 @@ -# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/07_educator_model.ipynb. - -# %% auto 0 -__all__ = ['EducatorModel'] - -# %% ../nbs/07_educator_model.ipynb 2 -import traitlets -from traitlets import HasTraits - -# %% ../nbs/07_educator_model.ipynb 3 -class EducatorModel(HasTraits): - - user = traitlets.CUnicode() - response = traitlets.CUnicode() - - def __init__(self): - super().__init__() - - def invoke(self, prompt): - # Goal: use langchain invoke and use the return value to update the self.response variable - self.response = "Hi am an AI and I have a response" # TODO: edit this line so the response comes from langchain diff --git a/nbs/00_main.ipynb b/nbs/00_main.ipynb index c1b5412..89f33e4 100644 --- a/nbs/00_main.ipynb +++ b/nbs/00_main.ipynb @@ -32,10 +32,44 @@ "from jupyter_mentor.student_profile import StudentProfile\n", "from jupyter_mentor.educator_course_overview import EducatorCourseOverview\n", "from jupyter_mentor.student_course_overview import StudentCourseOverview\n", - "from jupyter_mentor.chatbot import StudentChatBot, EducatorChatBot\n", + "from jupyter_mentor.chatbot import StudentChatBot, EducatorChatBot, ChatBotModel\n", "from jupyter_mentor.file_viewer import FileViewer" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "af80f333-81cd-4f2d-8f92-195b79a8e307", + "metadata": {}, + "outputs": [], + "source": [ + "import langchain\n", + "from langchain_openai import ChatOpenAI\n", + "from langchain_core.prompts import ChatPromptTemplate\n", + "from langchain_core.output_parsers import StrOutputParser\n", + "from langchain_community.document_loaders import PyPDFLoader\n", + "from langchain_community.vectorstores import FAISS\n", + "from langchain_openai import OpenAIEmbeddings\n", + "import os" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "94f92367-e2c2-4ce5-9c19-48ac5ae357e7", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain_openai import ChatOpenAI\n", + "import os\n", + "# read openapi key and set model\n", + "with open('../OPENAI_API_KEY', 'r') as file:\n", + " env_value = file.read().strip()\n", + "\n", + "os.environ['OPENAI_API_KEY'] = env_value\n", + "llm = ChatOpenAI(model_name=\"gpt-3.5-turbo\")" + ] + }, { "cell_type": "code", "execution_count": null, @@ -46,18 +80,21 @@ "#| export\n", "class EducatorMain(widgets.Tab):\n", " \n", - " def __init__(self):\n", + " def __init__(self, llm):\n", " super().__init__()\n", " \n", " # initialize models\n", + " self.llm = llm\n", " # self.model = DataModel(FILENAME)\n", + " self.educator_chatbot_model = ChatBotModel(llm)\n", + "\n", " \n", " # initialize views\n", " self.first = Login()\n", " self.second = EducatorProfile()\n", " self.file_viewer = FileViewer()\n", " self.third = EducatorCourseOverview(self.file_viewer)\n", - " self.fourth = EducatorChatBot()\n", + " self.fourth = EducatorChatBot(self.educator_chatbot_model)\n", " \n", " # Add tabs to the Tab widget\n", " self.children = (self.first, self.second, self.third, self.fourth)\n", @@ -91,7 +128,7 @@ "metadata": {}, "outputs": [], "source": [ - "educator_main = EducatorMain()\n", + "educator_main = EducatorMain(llm)\n", "educator_main" ] }, @@ -109,15 +146,16 @@ " super().__init__()\n", " \n", " # initialize models\n", + " self.llm = llm\n", " # self.model = EducatorModel(FILENAME)\n", - " \n", + " self.student_chatbot_model = ChatBotModel(llm)\n", + "\n", " # initialize views\n", " self.first = Login()\n", " self.second = StudentProfile()\n", " self.file_viewer = FileViewer()\n", - "\n", " self.third = StudentCourseOverview(self.file_viewer)\n", - " self.fourth = StudentChatBot()\n", + " self.fourth = StudentChatBot(self.student_chatbot_model)\n", "\n", " \n", " # Add tabs to the Tab widget\n", diff --git a/nbs/02_educator_profile.ipynb b/nbs/02_educator_profile.ipynb deleted file mode 100644 index 2208a18..0000000 --- a/nbs/02_educator_profile.ipynb +++ /dev/null @@ -1,105 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "05a3695f-3d73-455d-9a5c-a4ff9cc7fcdd", - "metadata": {}, - "outputs": [], - "source": [ - "#| default_exp educator_profile" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6d1adfd1-1896-42a6-9333-2c610debe906", - "metadata": {}, - "outputs": [], - "source": [ - "#| export\n", - "import ipywidgets as widgets\n", - "from ipywidgets import VBox, HTML, HBox, Label, Tab, Output, Button, Text\n", - "from IPython.display import display, clear_output\n", - "import ipyvuetify as v" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "adc63ca1-f6d9-402f-9e10-d3d7770d401a", - "metadata": {}, - "outputs": [], - "source": [ - "#| export\n", - "class EducatorProfile(widgets.VBox):\n", - " \n", - " def __init__(self):\n", - " super().__init__()\n", - " \n", - " # Username input\n", - " self.username_label = Label('Name:')\n", - " self.username_input = Text(placeholder='Enter your name')\n", - " \n", - " # Password input\n", - " self.key_label = Label('Educator:')\n", - " self.key_input = Text(placeholder='Enter Your Level', password=True)\n", - " \n", - " # Next button\n", - " self.next_button = Button(description='Next')\n", - " \n", - " # Arrange labels and inputs horizontally\n", - " self.username_box = HBox([self.username_label, self.username_input])\n", - " self.key_box = HBox([self.key_label, self.key_input])\n", - " \n", - " # Arrange widgets vertically\n", - " self.children = [\n", - " HTML('

User Profile

'), # Heading\n", - " self.username_box, # Username label and input box\n", - " self.key_box, # Password label and input box\n", - " HBox([self.next_button], layout={'justify_content': 'flex-end'}), # Login button aligned to the right\n", - " ]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5a64bb34-72f7-4ec5-884d-d3ee0899c420", - "metadata": {}, - "outputs": [], - "source": [ - "#| hide\n", - "import nbdev; nbdev.nbdev_export()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5a72bcc8-cf21-4143-9112-a1a17ca02869", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "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.8.19" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/nbs/05_chatbot.ipynb b/nbs/05_chatbot.ipynb index d7e557d..d121d62 100644 --- a/nbs/05_chatbot.ipynb +++ b/nbs/05_chatbot.ipynb @@ -19,53 +19,91 @@ "source": [ "#| export\n", "import ipywidgets as widgets\n", - "from ipywidgets import Textarea, Text, Layout, HBox" + "import traitlets\n", + "from ipywidgets import Textarea, Text, Layout, HBox\n", + "from traitlets import HasTraits\n", + "import os\n", + "from langchain_openai import ChatOpenAI\n", + "from langchain_core.messages import HumanMessage, SystemMessage\n", + "from langchain_core.prompts.chat import (\n", + " ChatPromptTemplate,\n", + " HumanMessagePromptTemplate,\n", + " SystemMessagePromptTemplate,\n", + ")\n", + "from langchain_openai import ChatOpenAI" ] }, { "cell_type": "code", "execution_count": null, - "id": "db5c215f-b20b-4df4-9f5f-ad1bfdb9c64b", + "id": "a57225dd-d6de-43ee-982f-c1467203dcd3", + "metadata": {}, + "outputs": [], + "source": [ + "# read openapi key and set model\n", + "with open('OPENAI_API_KEY', 'r') as file:\n", + " openai_api_key = file.read().strip()\n", + "\n", + "llm = ChatOpenAI(openai_api_key = openai_api_key, model_name=\"gpt-3.5-turbo\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "964405d5-115e-47a8-88ff-8746627ee0b1", "metadata": {}, "outputs": [], "source": [ "#| export\n", + "class ChatBotModel(HasTraits):\n", "\n", - "class ChatBot(widgets.VBox):\n", + " def __init__(self, llm, bot_template=\"You are playing the role of a tutor/educator\"):\n", + " super().__init__()\n", + " self.llm = llm\n", + " self.human_template = \"{input_text}\"\n", + " self.update_bot_template(bot_template)\n", + "\n", + " def update_bot_template(self, bot_template):\n", + " self.bot_template = bot_template\n", + " self.bot_message_prompt = SystemMessagePromptTemplate.from_template(self.bot_template)\n", + " self.human_message_prompt = HumanMessagePromptTemplate.from_template(self.human_template)\n", + " self.chat_prompt = ChatPromptTemplate.from_messages([self.bot_message_prompt, self.human_message_prompt])\n", + " \n", + " def prompt(self, input_text):\n", + " #prompt_val = prompt_template.invoke({\"adjective\": \"funny\", \"content\": \"chickens\"})\n", + " ret = self.llm.invoke(self.chat_prompt.format_prompt(input_text=input_text))\n", + " return ret.content" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1d24447e-7e51-4b99-a1c3-d35e59b7a998", + "metadata": {}, + "outputs": [], + "source": [ + "chatbot_model = ChatBotModel(llm)\n", + "chatbot_model.prompt('hi')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "190256e8-d786-4f6e-963e-7cd4a91a9d82", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "\n", + "class ChatBotView(widgets.VBox):\n", " \n", " def __init__(self):\n", " # If you forget to call the superconstructor on an extended widget\n", " # you will get an AttributeError: object has no attribute '_model_id'\n", " super().__init__()\n", "\n", - " example_convo = '''\n", - "User: Hello, bot!\n", - "\n", - "Bot: Hi there! How can I assist you today?\n", - "\n", - "User: I need help setting up my email account. Can you guide me through the process?\n", - "\n", - "Bot: Of course! Could you please provide me with the email service provider you're using?\n", - "\n", - "User: I use Gmail.\n", - "\n", - "Bot: Great! First, go to the Gmail website and click on the \"Create account\" button.\n", - "\n", - "User: Okay, I'm there. What's next?\n", - "\n", - "Bot: Enter your personal information such as your name, desired email address, password, and recovery information.\n", - "\n", - "User: Done! What's next?\n", - "\n", - "Bot: Follow the prompts to verify your phone number and agree to the terms of service.\n", - "\n", - "User: All set! Thank you for your help, bot!\n", - "\n", - "Bot: You're welcome! If you have any more questions, feel free to ask.\n", - "'''\n", " self.chat = Textarea(\n", " disabled = True,\n", - " value = example_convo,\n", " layout=Layout(width='90%', height='400px')\n", " )\n", " self.user_input_and_submit = HBox()\n", @@ -73,13 +111,13 @@ " placeholder='Message AI chatbot...',\n", " #layout=Layout(width='100%')\n", " )\n", - " self.submit = widgets.ToggleButton(\n", + " self.submit_button = widgets.Button(\n", " value=False,\n", " disabled=False,\n", " button_style='success',\n", " icon='arrow-circle-right' \n", " )\n", - " self.user_input_and_submit.children = (self.user_input, self.submit)\n", + " self.user_input_and_submit.children = (self.user_input, self.submit_button)\n", "\n", " self.children = (self.chat, self.user_input_and_submit) " ] @@ -87,11 +125,46 @@ { "cell_type": "code", "execution_count": null, - "id": "4403118f-7766-43b2-bea5-7ebaa8021806", + "id": "d8f6730f-d2ab-4d2f-b70a-77a4a4ca3e0b", + "metadata": {}, + "outputs": [], + "source": [ + "chatbot_view = ChatBotView()\n", + "chatbot_view" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c637bb15-d20d-4440-936e-8956ac712494", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class ChatBot(ChatBotView):\n", + "\n", + " def __init__(self, model):\n", + " # If you forget to call the superconstructor on an extended widget\n", + " # you will get an AttributeError: object has no attribute '_model_id'\n", + " super().__init__()\n", + " self.submit_button.on_click(self.on_click)\n", + " self.model =model\n", + "\n", + " def on_click(self, change):\n", + " self.chat.value = self.chat.value + \"USER: \" + self.user_input.value + '\\n\\n'\n", + " self.user_input.value = ''\n", + " ret = self.model.prompt(self.user_input.value)\n", + " self.chat.value = self.chat.value + \"CHATBOT: \" + ret + '\\n\\n'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "78f6b62f-0c95-4534-b53d-de957d72284d", "metadata": {}, "outputs": [], "source": [ - "chatbot = ChatBot()\n", + "chatbot = ChatBot(chatbot_model)\n", "chatbot" ] }, @@ -104,13 +177,20 @@ "source": [ "#| export\n", "class StudentChatBot(widgets.VBox):\n", + "\n", + " #user = traitlets.CUnicode()\n", + " #response = traitlets.CUnicode()\n", + " #step_by_step = traitlets.Bool()\n", + " #metaphor = traitlets.Bool()\n", + " #hints = traitlets.Bool()\n", + " #guided_questions = traitlets.Bool() \n", " \n", - " def __init__(self):\n", + " def __init__(self, chatbot_model):\n", " # If you forget to call the superconstructor on an extended widget\n", " # you will get an AttributeError: object has no attribute '_model_id'\n", " super().__init__()\n", "\n", - " self.chat_bot = ChatBot()\n", + " self.chat_bot = ChatBot(chatbot_model)\n", "\n", " self.suggestion_buttons = HBox()\n", " self.step_by_step = widgets.Button(\n", @@ -144,7 +224,7 @@ "metadata": {}, "outputs": [], "source": [ - "student_chatbot = StudentChatBot()\n", + "student_chatbot = StudentChatBot(chatbot_model)\n", "student_chatbot" ] }, @@ -157,13 +237,20 @@ "source": [ "#| export\n", "class EducatorChatBot(widgets.VBox):\n", + "\n", + " #user = traitlets.CUnicode()\n", + " #response = traitlets.CUnicode()\n", + " #step_by_step = traitlets.Bool()\n", + " #metaphor = traitlets.Bool()\n", + " #hints = traitlets.Bool()\n", + " #guided_questions = traitlets.Bool() \n", " \n", - " def __init__(self, ):\n", + " def __init__(self, chatbot_model):\n", " # If you forget to call the superconstructor on an extended widget\n", " # you will get an AttributeError: object has no attribute '_model_id'\n", " super().__init__()\n", "\n", - " self.chat_bot = ChatBot()\n", + " self.chat_bot = ChatBot(chatbot_model)\n", "\n", " self.suggestion_buttons = HBox()\n", " self.exam_questions = widgets.Button(\n", @@ -187,7 +274,7 @@ "metadata": {}, "outputs": [], "source": [ - "educator_chatbot = EducatorChatBot()\n", + "educator_chatbot = EducatorChatBot(chatbot_model)\n", "educator_chatbot" ] }, diff --git a/nbs/07_educator_model.ipynb b/nbs/07_educator_model.ipynb deleted file mode 100644 index 26f943b..0000000 --- a/nbs/07_educator_model.ipynb +++ /dev/null @@ -1,99 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "9103c404-226a-4f0a-bc9c-e9f8fe2e1c40", - "metadata": {}, - "outputs": [], - "source": [ - "#| default_exp educator_model" - ] - }, - { - "cell_type": "markdown", - "id": "5aaeaa38-b469-4788-8a1f-fa645d05d2e3", - "metadata": {}, - "source": [ - "# Educator Model\n", - "\n", - "> This class connects the responses that the educator gave in the user interface to the LLM" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "35ca15a1-3f44-420a-be7f-b640b7538fe7", - "metadata": {}, - "outputs": [], - "source": [ - "#| export\n", - "import traitlets\n", - "from traitlets import HasTraits" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "31b8b980-83b2-4e2c-a684-fd0a4dafe72c", - "metadata": {}, - "outputs": [], - "source": [ - "#| export \n", - "class EducatorModel(HasTraits):\n", - " \n", - " user = traitlets.CUnicode()\n", - " response = traitlets.CUnicode()\n", - " \n", - " def __init__(self):\n", - " super().__init__()\n", - "\n", - " def invoke(self, prompt):\n", - " # Goal: use langchain invoke and use the return value to update the self.response variable\n", - " self.response = \"Hi am an AI and I have a response\" # TODO: edit this line so the response comes from langchain" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3f2c941e-f024-4b31-95e4-01a6ff5d461a", - "metadata": {}, - "outputs": [], - "source": [ - "educator_model = EducatorModel()\n", - "educator_model.response" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "96227938-6583-4cd0-b152-b48f0a80b7bb", - "metadata": {}, - "outputs": [], - "source": [ - "educator_model.invoke(\"Hi I'm an educator and I have a question for you\")\n", - "educator_model.response" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "af064b99-e1be-41fb-84e4-878b20000aeb", - "metadata": {}, - "outputs": [], - "source": [ - "#| hide\n", - "import nbdev; nbdev.nbdev_export()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "python3", - "language": "python", - "name": "python3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/nbs/intro_to_langchain.ipynb b/nbs/intro_to_langchain.ipynb index 1b16616..70442bd 100644 --- a/nbs/intro_to_langchain.ipynb +++ b/nbs/intro_to_langchain.ipynb @@ -8,15 +8,19 @@ "outputs": [], "source": [ "import langchain\n", - "\n", "from langchain_openai import ChatOpenAI\n", - "\n", "from langchain_core.prompts import ChatPromptTemplate\n", "from langchain_core.output_parsers import StrOutputParser\n", "from langchain_community.document_loaders import PyPDFLoader\n", "from langchain_community.vectorstores import FAISS\n", "from langchain_openai import OpenAIEmbeddings\n", - "import os" + "from langchain_core.messages import HumanMessage, SystemMessage\n", + "from langchain_core.prompts.chat import (\n", + " ChatPromptTemplate,\n", + " HumanMessagePromptTemplate,\n", + " SystemMessagePromptTemplate,\n", + ")\n", + "from langchain_openai import ChatOpenAI" ] }, { @@ -26,8 +30,10 @@ "metadata": {}, "outputs": [], "source": [ + "import os\n", "with open('../OPENAI_API_KEY', 'r') as file:\n", - " env_value = file.read().strip()" + " env_value = file.read().strip()\n", + "os.environ['OPENAI_API_KEY'] = env_value" ] }, { @@ -43,31 +49,64 @@ { "cell_type": "code", "execution_count": null, - "id": "1926571e-c06e-4dfe-9bc9-ae7e3526b02e", + "id": "3db5e969-1325-44d3-a3e6-1272330e63ba", "metadata": {}, "outputs": [], "source": [ - "llm = ChatOpenAI()" + "model = ChatOpenAI(model_name=\"gpt-3.5-turbo\")" ] }, { "cell_type": "code", "execution_count": null, - "id": "3db5e969-1325-44d3-a3e6-1272330e63ba", + "id": "f1db3885-d5d2-4dac-ba10-41dd0b8f524a", "metadata": {}, "outputs": [], "source": [ - "model = ChatOpenAI(model_name=\"gpt-3.5\")" + "#model.invoke(\"Explain concept of derivatives in mathematics for kid?\")" ] }, { "cell_type": "code", "execution_count": null, - "id": "f1db3885-d5d2-4dac-ba10-41dd0b8f524a", + "id": "7656ddfb-8e9f-433e-828f-00d37626297c", + "metadata": {}, + "outputs": [], + "source": [ + "template = (\n", + " \"\"\"You are playing the role of an educator. You teach {grade_level} students about {course_subject}. \n", + "\n", + " This is how I want you to interact with my students:\n", + " {ai_policy}\n", + " \"\"\"\n", + ")\n", + "bot_message_prompt = SystemMessagePromptTemplate.from_template(template)\n", + "student_template = \"{text}\"\n", + "student_message_prompt = HumanMessagePromptTemplate.from_template(student_template)\n", + "\n", + "chat_prompt = ChatPromptTemplate.from_messages(\n", + " [bot_message_prompt, student_message_prompt]\n", + ")\n", + "\n", + "# get a chat completion from the formatted messages\n", + "model.invoke(\n", + " chat_prompt.format_prompt(\n", + " grade_level=\"first year undergraduates\", \n", + " course_subject=\"introductory biology\", \n", + " ai_policy= \"I want the students to learn critical thinking. Under no circumstances are you supposed to give the students the full answers to questions on the first try. Try and help the student get to the question on their own three times before giving the answer.\",\n", + " text=\"What is the world's largest animal?\"\n", + " ).to_messages()\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "95e7e49c-4680-4e0d-b5fd-ef1e21ae5b95", "metadata": {}, "outputs": [], "source": [ - "# llm.invoke(\"Explain concept of derivatives in mathematics for kid?\")" + "model.invoke?\n" ] }, { @@ -79,18 +118,65 @@ "source": [ "embeddings = OpenAIEmbeddings()\n", "output_parser = StrOutputParser()\n", - "filepath = \"STP 420 spring 2024 course syllabus\" #file as input\n", + "filepath = \"STP 420 spring 2024 course syllabus.pdf\" #file as input\n", "pages = \"\" #extracting file content here\n", - "def load_content(filepath):\n", - " global pages\n", - " path = filepath+\".pdf\"\n", + "def load_pdf(filepath):\n", + " path = filepath\n", " loader = PyPDFLoader(path) \n", " pages = loader.load_and_split() #loading file content as document with page content\n", " db = FAISS.from_documents(pages, embeddings)\n", " return db\n", "# text_splitter = RecursiveCharacterTextSplitter(chunk_size = 1000, chunk_overlap = 100)\n", - "# docs = text_splitter.split_documents(pages)\n", - "\n" + "# docs = text_splitter.split_documents(pages)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1316cadf-ee0e-4b74-89bd-1f21a1e36440", + "metadata": {}, + "outputs": [], + "source": [ + "db = load_pdf(filepath)\n", + "db.index.ntotal" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "57ff3f4c-3320-4421-9cc6-2905b4b36367", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain_community.document_loaders import UnstructuredMarkdownLoader\n", + "\n", + "def load_pdf(filepath):\n", + " loader = UnstructuredMarkdownLoader(filepath, mode=\"elements\") #mode=elements breaks up the text into chunks\n", + " doc = loader.load()\n", + " db = FAISS.from_documents(doc, embeddings)\n", + " return db" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e39d684e-d370-4dcc-bd07-d8841ddae44b", + "metadata": {}, + "outputs": [], + "source": [ + "db2 = load_pdf(\"2017-01-29-policies.md\")\n", + "db2.index.ntotal" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2d5f9592-0967-4f69-8ed4-392e2fc6903a", + "metadata": {}, + "outputs": [], + "source": [ + "db.merge_from(db2)\n", + "db.index.ntotal" ] }, { @@ -107,7 +193,6 @@ " prompt = ChatPromptTemplate.from_messages([(\"system\",template), (\"user\", query)])\n", " chain = prompt | llm | output_parser\n", " return chain.invoke({\"input\": query, \"docs\": docs_page_content, \"query\": query})\n", - "db = load_content(filepath)\n", "response = get_response_from_query(db, \"when will we learn confidence interval?\")\n", "print(response)" ] @@ -115,17 +200,7 @@ { "cell_type": "code", "execution_count": null, - "id": "d1f295e3-d891-4bbc-bef5-e73f2553c8d3", - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "57ff3f4c-3320-4421-9cc6-2905b4b36367", + "id": "9560c996-d323-4eef-945a-a034cfd347ef", "metadata": {}, "outputs": [], "source": [] @@ -133,21 +208,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "python3", "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.11.8" } }, "nbformat": 4,