├── .chainlit ├── config.toml └── translations │ ├── en-US.json │ └── pt-BR.json ├── .gitignore ├── README.md ├── agent_action_schema.png ├── app_flow_diagram.png ├── chainlit.md ├── chatbot.py └── requirements.txt /.chainlit/config.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | # Whether to enable telemetry (default: true). No personal data is collected. 3 | enable_telemetry = true 4 | 5 | 6 | # List of environment variables to be provided by each user to use the app. 7 | user_env = [] 8 | 9 | # Duration (in seconds) during which the session is saved when the connection is lost 10 | session_timeout = 3600 11 | 12 | # Enable third parties caching (e.g LangChain cache) 13 | cache = false 14 | 15 | # Authorized origins 16 | allow_origins = ["*"] 17 | 18 | # Follow symlink for asset mount (see https://github.com/Chainlit/chainlit/issues/317) 19 | # follow_symlink = false 20 | 21 | [features] 22 | # Show the prompt playground 23 | prompt_playground = true 24 | 25 | # Process and display HTML in messages. This can be a security risk (see https://stackoverflow.com/questions/19603097/why-is-it-dangerous-to-render-user-generated-html-or-javascript) 26 | unsafe_allow_html = false 27 | 28 | # Process and display mathematical expressions. This can clash with "$" characters in messages. 29 | latex = false 30 | 31 | # Authorize users to upload files with messages 32 | multi_modal = true 33 | 34 | # Allows user to use speech to text 35 | [features.speech_to_text] 36 | enabled = false 37 | # See all languages here https://github.com/JamesBrill/react-speech-recognition/blob/HEAD/docs/API.md#language-string 38 | # language = "en-US" 39 | 40 | [UI] 41 | # Name of the app and chatbot. 42 | name = "Chatbot" 43 | 44 | # Show the readme while the thread is empty. 45 | show_readme_as_default = true 46 | 47 | # Description of the app and chatbot. This is used for HTML tags. 48 | # description = "" 49 | 50 | # Large size content are by default collapsed for a cleaner ui 51 | default_collapse_content = true 52 | 53 | # The default value for the expand messages settings. 54 | default_expand_messages = false 55 | 56 | # Hide the chain of thought details from the user in the UI. 57 | hide_cot = false 58 | 59 | # Link to your github repo. This will add a github button in the UI's header. 60 | # github = "" 61 | 62 | # Specify a CSS file that can be used to customize the user interface. 63 | # The CSS file can be served from the public directory or via an external link. 64 | # custom_css = "/public/test.css" 65 | 66 | # Specify a Javascript file that can be used to customize the user interface. 67 | # The Javascript file can be served from the public directory. 68 | # custom_js = "/public/test.js" 69 | 70 | # Specify a custom font url. 71 | # custom_font = "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" 72 | 73 | # Override default MUI light theme. (Check theme.ts) 74 | [UI.theme] 75 | #font_family = "Inter, sans-serif" 76 | [UI.theme.light] 77 | #background = "#FAFAFA" 78 | #paper = "#FFFFFF" 79 | 80 | [UI.theme.light.primary] 81 | #main = "#F80061" 82 | #dark = "#980039" 83 | #light = "#FFE7EB" 84 | 85 | # Override default MUI dark theme. (Check theme.ts) 86 | [UI.theme.dark] 87 | #background = "#FAFAFA" 88 | #paper = "#FFFFFF" 89 | 90 | [UI.theme.dark.primary] 91 | #main = "#F80061" 92 | #dark = "#980039" 93 | #light = "#FFE7EB" 94 | 95 | 96 | [meta] 97 | generated_by = "1.0.401" 98 | -------------------------------------------------------------------------------- /.chainlit/translations/en-US.json: -------------------------------------------------------------------------------- 1 | { 2 | "components": { 3 | "atoms": { 4 | "buttons": { 5 | "userButton": { 6 | "menu": { 7 | "settings": "Settings", 8 | "settingsKey": "S", 9 | "APIKeys": "API Keys", 10 | "logout": "Logout" 11 | } 12 | } 13 | } 14 | }, 15 | "molecules": { 16 | "newChatButton": { 17 | "newChat": "New Chat" 18 | }, 19 | "tasklist": { 20 | "TaskList": { 21 | "title": "\ud83d\uddd2\ufe0f Task List", 22 | "loading": "Loading...", 23 | "error": "An error occured" 24 | } 25 | }, 26 | "attachments": { 27 | "cancelUpload": "Cancel upload", 28 | "removeAttachment": "Remove attachment" 29 | }, 30 | "newChatDialog": { 31 | "createNewChat": "Create new chat?", 32 | "clearChat": "This will clear the current messages and start a new chat.", 33 | "cancel": "Cancel", 34 | "confirm": "Confirm" 35 | }, 36 | "settingsModal": { 37 | "expandMessages": "Expand Messages", 38 | "hideChainOfThought": "Hide Chain of Thought", 39 | "darkMode": "Dark Mode" 40 | } 41 | }, 42 | "organisms": { 43 | "chat": { 44 | "history": { 45 | "index": { 46 | "lastInputs": "Last Inputs", 47 | "noInputs": "Such empty...", 48 | "loading": "Loading..." 49 | } 50 | }, 51 | "inputBox": { 52 | "input": { 53 | "placeholder": "Type your message here..." 54 | }, 55 | "speechButton": { 56 | "start": "Start recording", 57 | "stop": "Stop recording" 58 | }, 59 | "SubmitButton": { 60 | "sendMessage": "Send message", 61 | "stopTask": "Stop Task" 62 | }, 63 | "UploadButton": { 64 | "attachFiles": "Attach files" 65 | }, 66 | "waterMark": { 67 | "text": "Built with" 68 | } 69 | }, 70 | "Messages": { 71 | "index": { 72 | "running": "Running", 73 | "executedSuccessfully": "executed successfully", 74 | "failed": "failed", 75 | "feedbackUpdated": "Feedback updated", 76 | "updating": "Updating" 77 | } 78 | }, 79 | "dropScreen": { 80 | "dropYourFilesHere": "Drop your files here" 81 | }, 82 | "index": { 83 | "failedToUpload": "Failed to upload", 84 | "cancelledUploadOf": "Cancelled upload of", 85 | "couldNotReachServer": "Could not reach the server", 86 | "continuingChat": "Continuing previous chat" 87 | }, 88 | "settings": { 89 | "settingsPanel": "Settings panel", 90 | "reset": "Reset", 91 | "cancel": "Cancel", 92 | "confirm": "Confirm" 93 | } 94 | }, 95 | "threadHistory": { 96 | "sidebar": { 97 | "filters": { 98 | "FeedbackSelect": { 99 | "feedbackAll": "Feedback: All", 100 | "feedbackPositive": "Feedback: Positive", 101 | "feedbackNegative": "Feedback: Negative" 102 | }, 103 | "SearchBar": { 104 | "search": "Search" 105 | } 106 | }, 107 | "DeleteThreadButton": { 108 | "confirmMessage": "This will delete the thread as well as it's messages and elements.", 109 | "cancel": "Cancel", 110 | "confirm": "Confirm", 111 | "deletingChat": "Deleting chat", 112 | "chatDeleted": "Chat deleted" 113 | }, 114 | "index": { 115 | "pastChats": "Past Chats" 116 | }, 117 | "ThreadList": { 118 | "empty": "Empty..." 119 | }, 120 | "TriggerButton": { 121 | "closeSidebar": "Close sidebar", 122 | "openSidebar": "Open sidebar" 123 | } 124 | }, 125 | "Thread": { 126 | "backToChat": "Go back to chat", 127 | "chatCreatedOn": "This chat was created on" 128 | } 129 | }, 130 | "header": { 131 | "chat": "Chat", 132 | "readme": "Readme" 133 | } 134 | } 135 | }, 136 | "hooks": { 137 | "useLLMProviders": { 138 | "failedToFetchProviders": "Failed to fetch providers:" 139 | } 140 | }, 141 | "pages": { 142 | "Design": {}, 143 | "Env": { 144 | "savedSuccessfully": "Saved successfully", 145 | "requiredApiKeys": "Required API Keys", 146 | "requiredApiKeysInfo": "To use this app, the following API keys are required. The keys are stored on your device's local storage." 147 | }, 148 | "Page": { 149 | "notPartOfProject": "You are not part of this project." 150 | }, 151 | "ResumeButton": { 152 | "resumeChat": "Resume Chat" 153 | } 154 | } 155 | } -------------------------------------------------------------------------------- /.chainlit/translations/pt-BR.json: -------------------------------------------------------------------------------- 1 | { 2 | "components": { 3 | "atoms": { 4 | "buttons": { 5 | "userButton": { 6 | "menu": { 7 | "settings": "Configura\u00e7\u00f5es", 8 | "settingsKey": "S", 9 | "APIKeys": "Chaves de API", 10 | "logout": "Sair" 11 | } 12 | } 13 | } 14 | }, 15 | "molecules": { 16 | "newChatButton": { 17 | "newChat": "Nova Conversa" 18 | }, 19 | "tasklist": { 20 | "TaskList": { 21 | "title": "\ud83d\uddd2\ufe0f Lista de Tarefas", 22 | "loading": "Carregando...", 23 | "error": "Ocorreu um erro" 24 | } 25 | }, 26 | "attachments": { 27 | "cancelUpload": "Cancelar envio", 28 | "removeAttachment": "Remover anexo" 29 | }, 30 | "newChatDialog": { 31 | "createNewChat": "Criar novo chat?", 32 | "clearChat": "Isso limpar\u00e1 as mensagens atuais e iniciar\u00e1 uma nova conversa.", 33 | "cancel": "Cancelar", 34 | "confirm": "Confirmar" 35 | }, 36 | "settingsModal": { 37 | "expandMessages": "Expandir Mensagens", 38 | "hideChainOfThought": "Esconder Sequ\u00eancia de Pensamento", 39 | "darkMode": "Modo Escuro" 40 | } 41 | }, 42 | "organisms": { 43 | "chat": { 44 | "history": { 45 | "index": { 46 | "lastInputs": "\u00daltimas Entradas", 47 | "noInputs": "Vazio...", 48 | "loading": "Carregando..." 49 | } 50 | }, 51 | "inputBox": { 52 | "input": { 53 | "placeholder": "Digite sua mensagem aqui..." 54 | }, 55 | "speechButton": { 56 | "start": "Iniciar grava\u00e7\u00e3o", 57 | "stop": "Parar grava\u00e7\u00e3o" 58 | }, 59 | "SubmitButton": { 60 | "sendMessage": "Enviar mensagem", 61 | "stopTask": "Parar Tarefa" 62 | }, 63 | "UploadButton": { 64 | "attachFiles": "Anexar arquivos" 65 | }, 66 | "waterMark": { 67 | "text": "Constru\u00eddo com" 68 | } 69 | }, 70 | "Messages": { 71 | "index": { 72 | "running": "Executando", 73 | "executedSuccessfully": "executado com sucesso", 74 | "failed": "falhou", 75 | "feedbackUpdated": "Feedback atualizado", 76 | "updating": "Atualizando" 77 | } 78 | }, 79 | "dropScreen": { 80 | "dropYourFilesHere": "Solte seus arquivos aqui" 81 | }, 82 | "index": { 83 | "failedToUpload": "Falha ao enviar", 84 | "cancelledUploadOf": "Envio cancelado de", 85 | "couldNotReachServer": "N\u00e3o foi poss\u00edvel conectar ao servidor", 86 | "continuingChat": "Continuando o chat anterior" 87 | }, 88 | "settings": { 89 | "settingsPanel": "Painel de Configura\u00e7\u00f5es", 90 | "reset": "Redefinir", 91 | "cancel": "Cancelar", 92 | "confirm": "Confirmar" 93 | } 94 | }, 95 | "threadHistory": { 96 | "sidebar": { 97 | "filters": { 98 | "FeedbackSelect": { 99 | "feedbackAll": "Feedback: Todos", 100 | "feedbackPositive": "Feedback: Positivo", 101 | "feedbackNegative": "Feedback: Negativo" 102 | }, 103 | "SearchBar": { 104 | "search": "Buscar" 105 | } 106 | }, 107 | "DeleteThreadButton": { 108 | "confirmMessage": "Isso deletar\u00e1 a conversa, assim como suas mensagens e elementos.", 109 | "cancel": "Cancelar", 110 | "confirm": "Confirmar", 111 | "deletingChat": "Deletando conversa", 112 | "chatDeleted": "Conversa deletada" 113 | }, 114 | "index": { 115 | "pastChats": "Conversas Anteriores" 116 | }, 117 | "ThreadList": { 118 | "empty": "Vazio..." 119 | }, 120 | "TriggerButton": { 121 | "closeSidebar": "Fechar barra lateral", 122 | "openSidebar": "Abrir barra lateral" 123 | } 124 | }, 125 | "Thread": { 126 | "backToChat": "Voltar para a conversa", 127 | "chatCreatedOn": "Esta conversa foi criada em" 128 | } 129 | }, 130 | "header": { 131 | "chat": "Conversa", 132 | "readme": "Leia-me" 133 | } 134 | }, 135 | "hooks": { 136 | "useLLMProviders": { 137 | "failedToFetchProviders": "Falha ao buscar provedores:" 138 | } 139 | }, 140 | "pages": { 141 | "Design": {}, 142 | "Env": { 143 | "savedSuccessfully": "Salvo com sucesso", 144 | "requiredApiKeys": "Chaves de API necess\u00e1rias", 145 | "requiredApiKeysInfo": "Para usar este aplicativo, as seguintes chaves de API s\u00e3o necess\u00e1rias. As chaves s\u00e3o armazenadas localmente em seu dispositivo." 146 | }, 147 | "Page": { 148 | "notPartOfProject": "Voc\u00ea n\u00e3o faz parte deste projeto." 149 | }, 150 | "ResumeButton": { 151 | "resumeChat": "Continuar Conversa" 152 | } 153 | } 154 | } 155 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .idea/ 3 | __pycache__/ 4 | questions.txt 5 | out.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Math App using LangChain Agents, OpenAI and Chainlit 2 | 3 | You can read further [here in this medium article.](https://medium.com/@tahreemrasul/how-to-build-your-own-chatbot-with-langchain-and-openai-f092822b6ba6) 4 | 5 | ## Overview 6 | This repo contains the code for a math app, Math Wiz, a custom chatbot that answers a user's arithmetic and reasoning questions. Chainlit is used for the web application portion. 7 | LLMs can be quite bad at general math questions, even the simplistic ones. This can be due to a variety of reasons, such 8 | as not having been trained on sufficient mathematical data, difficulty in carrying out numeric operations, as well as 9 | the fact that LLMs are text generators, and can struggle to come up with logic-based formulations. Having said that, they 10 | do contain a large corpus of trained dataset, and can offer superior text understanding and generation qualities. In this 11 | tutorial, we will demonstrate how the use of LangChain agents can significantly increase an LLM's performance when working with 12 | numerical or reasoning-based questions. 13 | 14 | ## Application Process Diagram 15 | LangChain Agents are comprised of one or more tools that can be used by the agent to get to the final decision. These 16 | tools can be online search, or chains carrying out modular tasks in an application flow. Below is the process 17 | diagram for the app designed in this tutorial: 18 | ![alt text for screen readers](app_flow_diagram.png "Process Diagram for Math Wiz App") 19 | 20 | For each user query, the agent uses the LLM to decide which tool to use. The flow of the agent can be visualized with 21 | this flow diagram: 22 | ![alt text for screen readers](agent_action_schema.png "How LangChain Agents Work") 23 | 24 | ## Getting Started 25 | ### Prerequisites 26 | - Python 3.8 or later 27 | - An OpenAI API key 28 | 29 | ### Installation 30 | 31 | 1. **Clone the Repository** 32 | ```bash 33 | git clone git@github.com:tahreemrasul/simple_chatbot_langchain.git 34 | cd ./simple_chatbot_langchain 35 | 36 | 2. **Set Up a Conda Environment (Recommended)** 37 | * If you don't have Conda, install it first. 38 | * Create a new Conda environment: 39 | ```bash 40 | conda create -n math_assistant python=3.11 41 | * Activate the environment: 42 | ```bash 43 | conda activate math_assistant 44 | 45 | 3. **Install Dependencies** 46 | * Install the required packages using the `requirements.txt` file: 47 | ```bash 48 | pip install -r requirements.txt 49 | 50 | 4. **Set Up Your OpenAI API Key** 51 | * Create a .env file in the root directory of the project. 52 | * Add your OpenAI API key to the `.env` file: 53 | ```bash 54 | OPENAI_API_KEY='Your-OpenAI-API-Key-Here' 55 | 56 | ### Usage 57 | To run the Math Wiz app, simply execute the `chatbot.py` script using: 58 | ```bash 59 | chainlit run chatbot.py -w --port 8000 60 | ``` 61 | 62 | This will run the application at http://localhost:8000 63 | 64 | -------------------------------------------------------------------------------- /agent_action_schema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tahreemrasul/math_app_langchain/a5af16ff2635d4f580e37cfe91e24ea705808a9b/agent_action_schema.png -------------------------------------------------------------------------------- /app_flow_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tahreemrasul/math_app_langchain/a5af16ff2635d4f580e37cfe91e24ea705808a9b/app_flow_diagram.png -------------------------------------------------------------------------------- /chainlit.md: -------------------------------------------------------------------------------- 1 | # Welcome to Math Wiz! 🤖 2 | 3 | Hi there! 👋 I am a reasoning tool to help you with your math or logic-based reasoning questions. How can I 4 | help today? 5 | -------------------------------------------------------------------------------- /chatbot.py: -------------------------------------------------------------------------------- 1 | import chainlit as cl 2 | from langchain_openai import OpenAI 3 | from langchain.chains import LLMMathChain, LLMChain 4 | from langchain.prompts import PromptTemplate 5 | from langchain_community.utilities import WikipediaAPIWrapper 6 | from langchain.agents.agent_types import AgentType 7 | from langchain.agents import Tool, initialize_agent 8 | from dotenv import load_dotenv 9 | 10 | load_dotenv() 11 | 12 | 13 | @cl.on_chat_start 14 | def math_chatbot(): 15 | llm = OpenAI(model='gpt-3.5-turbo-instruct', 16 | temperature=0) 17 | 18 | word_problem_template = """You are a reasoning agent tasked with solving the user's logic-based questions. 19 | Logically arrive at the solution, and be factual. In your answers, clearly detail the steps involved and give 20 | the final answer. Provide the response in bullet points. Question {question} Answer""" 21 | 22 | math_assistant_prompt = PromptTemplate( 23 | input_variables=["question"], 24 | template=word_problem_template 25 | ) 26 | 27 | word_problem_chain = LLMChain(llm=llm, 28 | prompt=math_assistant_prompt) 29 | word_problem_tool = Tool.from_function(name="Reasoning Tool", 30 | func=word_problem_chain.run, 31 | description="Useful for when you need to answer logic-based/reasoning " 32 | "questions.", 33 | ) 34 | 35 | problem_chain = LLMMathChain.from_llm(llm=llm) 36 | math_tool = Tool.from_function(name="Calculator", 37 | func=problem_chain.run, 38 | description="Useful for when you need to answer numeric questions. This tool is " 39 | "only for math questions and nothing else. Only input math " 40 | "expressions, without text", 41 | ) 42 | 43 | wikipedia = WikipediaAPIWrapper() 44 | # Wikipedia Tool 45 | wikipedia_tool = Tool( 46 | name="Wikipedia", 47 | func=wikipedia.run, 48 | description="A useful tool for searching the Internet to find information on world events, issues, dates, " 49 | "years, etc. Worth using for general topics. Use precise questions.", 50 | ) 51 | 52 | agent = initialize_agent( 53 | tools=[wikipedia_tool, math_tool, word_problem_tool], 54 | llm=llm, 55 | agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, 56 | verbose=False, 57 | handle_parsing_errors=True 58 | ) 59 | cl.user_session.set("agent", agent) 60 | 61 | 62 | @cl.on_message 63 | async def process_user_query(message: cl.Message): 64 | agent = cl.user_session.get("agent") 65 | 66 | response = await agent.acall(message.content, 67 | callbacks=[cl.AsyncLangchainCallbackHandler()]) 68 | 69 | await cl.Message(response["output"]).send() -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | langchain-groq 2 | langchain 3 | langchain_community 4 | langchain-openai 5 | chainlit 6 | nbconvert 7 | python-dotenv 8 | numexpr 9 | wikipedia --------------------------------------------------------------------------------