{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Gmail\n", "\n", "This notebook walks through connecting a LangChain email to the `Gmail API`.\n", "\n", "To use this toolkit, you will need to set up your credentials explained in the [Gmail API docs](https://developers.google.com/gmail/api/quickstart/python#authorize_credentials_for_a_desktop_application). Once you've downloaded the `credentials.json` file, you can start using the Gmail API. Once this is done, we'll install the required libraries." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%pip install --upgrade --quiet google-api-python-client > /dev/null\n", "%pip install --upgrade --quiet google-auth-oauthlib > /dev/null\n", "%pip install --upgrade --quiet google-auth-httplib2 > /dev/null\n", "%pip install --upgrade --quiet beautifulsoup4 > /dev/null # This is optional but is useful for parsing HTML messages" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You also need to install the `langchain-community` package where the integration lives:\n", "\n", "```bash\n", "pip install -U langchain-community\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It's also helpful (but not needed) to set up [LangSmith](https://smith.langchain.com/) for best-in-class observability" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n", "# os.environ[\"LANGCHAIN_API_KEY\"] = getpass.getpass()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Create the Toolkit\n", "\n", "By default the toolkit reads the local `credentials.json` file. You can also manually provide a `Credentials` object." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "from langchain_community.agent_toolkits import GmailToolkit\n", "\n", "toolkit = GmailToolkit()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Customizing Authentication\n", "\n", "Behind the scenes, a `googleapi` resource is created using the following methods. \n", "you can manually build a `googleapi` resource for more auth control. " ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "tags": [] }, "outputs": [], "source": [ "from langchain_community.tools.gmail.utils import (\n", " build_resource_service,\n", " get_gmail_credentials,\n", ")\n", "\n", "# Can review scopes here https://developers.google.com/gmail/api/auth/scopes\n", "# For instance, readonly scope is 'https://www.googleapis.com/auth/gmail.readonly'\n", "credentials = get_gmail_credentials(\n", " token_file=\"token.json\",\n", " scopes=[\"https://mail.google.com/\"],\n", " client_secrets_file=\"credentials.json\",\n", ")\n", "api_resource = build_resource_service(credentials=credentials)\n", "toolkit = GmailToolkit(api_resource=api_resource)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "[GmailCreateDraft(name='create_gmail_draft', description='Use this tool to create a draft email with the provided message fields.', args_schema=, return_direct=False, verbose=False, callbacks=None, callback_manager=None, api_resource=),\n", " GmailSendMessage(name='send_gmail_message', description='Use this tool to send email messages. The input is the message, recipents', args_schema=None, return_direct=False, verbose=False, callbacks=None, callback_manager=None, api_resource=),\n", " GmailSearch(name='search_gmail', description=('Use this tool to search for email messages or threads. The input must be a valid Gmail query. The output is a JSON list of the requested resource.',), args_schema=, return_direct=False, verbose=False, callbacks=None, callback_manager=None, api_resource=),\n", " GmailGetMessage(name='get_gmail_message', description='Use this tool to fetch an email by message ID. Returns the thread ID, snipet, body, subject, and sender.', args_schema=, return_direct=False, verbose=False, callbacks=None, callback_manager=None, api_resource=),\n", " GmailGetThread(name='get_gmail_thread', description=('Use this tool to search for email messages. The input must be a valid Gmail query. The output is a JSON list of messages.',), args_schema=, return_direct=False, verbose=False, callbacks=None, callback_manager=None, api_resource=)]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tools = toolkit.get_tools()\n", "tools" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Usage\n", "\n", "We show here how to use it as part of an [agent](/docs/modules/agents). We use the OpenAI Functions Agent, so we will need to setup and install the required dependencies for that. We will also use [LangSmith Hub](https://smith.langchain.com/hub) to pull the prompt from, so we will need to install that.\n", "\n", "```bash\n", "pip install -U langchain-openai langchainhub\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import getpass\n", "import os\n", "\n", "os.environ[\"OPENAI_API_KEY\"] = getpass.getpass()" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "tags": [] }, "outputs": [], "source": [ "from langchain import hub\n", "from langchain.agents import AgentExecutor, create_openai_functions_agent\n", "from langchain_openai import ChatOpenAI" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "instructions = \"\"\"You are an assistant.\"\"\"\n", "base_prompt = hub.pull(\"langchain-ai/openai-functions-template\")\n", "prompt = base_prompt.partial(instructions=instructions)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "llm = ChatOpenAI(temperature=0)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "agent = create_openai_functions_agent(llm, toolkit.get_tools(), prompt)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "agent_executor = AgentExecutor(\n", " agent=agent,\n", " tools=toolkit.get_tools(),\n", " # This is set to False to prevent information about my email showing up on the screen\n", " # Normally, it is helpful to have it set to True however.\n", " verbose=False,\n", ")" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'input': 'Create a gmail draft for me to edit of a letter from the perspective of a sentient parrot who is looking to collaborate on some research with her estranged friend, a cat. Under no circumstances may you send the message, however.',\n", " 'output': 'I have created a draft email for you to edit. Please find the draft in your Gmail drafts folder. Remember, under no circumstances should you send the message.'}" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "agent_executor.invoke(\n", " {\n", " \"input\": \"Create a gmail draft for me to edit of a letter from the perspective of a sentient parrot\"\n", " \" who is looking to collaborate on some research with her\"\n", " \" estranged friend, a cat. Under no circumstances may you send the message, however.\"\n", " }\n", ")" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'input': 'Could you search in my drafts for the latest email? what is the title?',\n", " 'output': 'The latest email in your drafts is titled \"Collaborative Research Proposal\".'}" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "agent_executor.invoke(\n", " {\"input\": \"Could you search in my drafts for the latest email? what is the title?\"}\n", ")" ] }, { "cell_type": "code", "execution_count": null, "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.10.1" } }, "nbformat": 4, "nbformat_minor": 4 }