{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "47d2a8ca"
      },
      "source": [
        "# Use SparkNLP with Langchain\n",
        "\n",
        "![JohnSnowLabs](https://nlp.johnsnowlabs.com/assets/images/logo.png)\n",
        "\n",
        "<img src=\"https://cdn.analyticsvidhya.com/wp-content/uploads/2023/07/langchain3.png\" width=\"300\"/>         \n",
        "https://www.langchain.com\n",
        "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/JohnSnowLabs/johnsnowlabs/blob/master/notebooks/langchain_with_johnsnowlabs.ipynb)\n",
        "\n",
        "\n",
        "This tutorial showcase how to use [Johnsnowlabs Components with Langchain](https://nlp.johnsnowlabs.com/docs/en/jsl/langchain-utils) for Scalable Pre-Processing and Embedding computation on clusters\n",
        "\n",
        "If you want to scale this, you can re-use this code in a spark-cluster created with [nlp.install_to_databricks()](https://nlp.johnsnowlabs.com/docs/en/jsl/install_advanced#into-a-freshly-created-databricks-cluster-automatically)"
      ],
      "id": "47d2a8ca"
    },
    {
      "cell_type": "markdown",
      "source": [
        "# Installing dependencies & Downloading the jsl_embedder"
      ],
      "metadata": {
        "id": "Ll5vk27UNgCD"
      },
      "id": "Ll5vk27UNgCD"
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "GASkYNwoaW6Z"
      },
      "outputs": [],
      "source": [
        "! pip install johnsnowlabs\n",
        "from johnsnowlabs import nlp\n",
        "nlp.start()\n",
        "! pip install langchain openai tiktoken faiss-cpu\n",
        "\n",
        "# restart session after installing evertything\n",
        "import os\n",
        "os.kill(os.getpid(), 9)\n"
      ],
      "id": "GASkYNwoaW6Z"
    },
    {
      "cell_type": "markdown",
      "source": [
        "# Langchain based JSL-Embedder and Text Splitters\n",
        "based on this [conversational_retrieval_agents tutorial](https://python.langchain.com/docs/use_cases/question_answering/conversational_retrieval_agents) building a mini RAG system"
      ],
      "metadata": {
        "id": "amC-VYnzbtih"
      },
      "id": "amC-VYnzbtih"
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Download some Sample Data"
      ],
      "metadata": {
        "id": "ADv47UUhngtN"
      },
      "id": "ADv47UUhngtN"
    },
    {
      "cell_type": "code",
      "source": [
        "# Download some sample data we use as a mini-db\n",
        "! wget https://raw.githubusercontent.com/langchain-ai/langchain/master/docs/docs/modules/state_of_the_union.txt"
      ],
      "metadata": {
        "id": "gV6-sHwMlyHZ",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "14633f0a-df1a-4a66-f756-cb1c30997d1c"
      },
      "id": "gV6-sHwMlyHZ",
      "execution_count": 1,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "--2023-11-17 03:56:24--  https://raw.githubusercontent.com/langchain-ai/langchain/master/docs/docs/modules/state_of_the_union.txt\n",
            "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...\n",
            "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.\n",
            "HTTP request sent, awaiting response... 200 OK\n",
            "Length: 39028 (38K) [text/plain]\n",
            "Saving to: ‘state_of_the_union.txt’\n",
            "\n",
            "state_of_the_union. 100%[===================>]  38.11K  --.-KB/s    in 0.007s  \n",
            "\n",
            "2023-11-17 03:56:25 (5.11 MB/s) - ‘state_of_the_union.txt’ saved [39028/39028]\n",
            "\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Load data as Langchain Docs"
      ],
      "metadata": {
        "id": "wLmeVOr9niNq"
      },
      "id": "wLmeVOr9niNq"
    },
    {
      "cell_type": "code",
      "source": [
        "from langchain.document_loaders import TextLoader\n",
        "loader = TextLoader('/content/state_of_the_union.txt')\n",
        "documents = loader.load()\n"
      ],
      "metadata": {
        "id": "E2do2KPonk1F"
      },
      "id": "E2do2KPonk1F",
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Create Pre-Processor which is connected to Spark-Cluster and **pre-processes documents** distributed"
      ],
      "metadata": {
        "id": "FbNTjSeenpDM"
      },
      "id": "FbNTjSeenpDM"
    },
    {
      "cell_type": "code",
      "source": [
        "from johnsnowlabs.llm import embedding_retrieval\n",
        "jsl_splitter = embedding_retrieval.JohnSnowLabsLangChainCharSplitter(\n",
        "        chunk_overlap=2,\n",
        "        chunk_size=20,\n",
        "        explode_splits=True,\n",
        "        keep_seperators=True,\n",
        "        patterns_are_regex=False,\n",
        "        split_patterns=[\"\\n\\n\", \"\\n\", \" \", \"\"],\n",
        "        trim_whitespace=True,\n",
        "\n",
        ")\n",
        "texts = jsl_splitter.split_documents(documents)"
      ],
      "metadata": {
        "id": "GrUZfwYOm49V",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "729dfe7c-ebbf-442b-d3dc-0408debb6df0"
      },
      "id": "GrUZfwYOm49V",
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Spark Session already created, some configs may not take.\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Create Pre-Processor which is connected to Spark-Cluster and **Embeds documents** distributed"
      ],
      "metadata": {
        "id": "Qd2GA3-nn38L"
      },
      "id": "Qd2GA3-nn38L"
    },
    {
      "cell_type": "code",
      "source": [
        "from langchain.vectorstores import FAISS\n",
        "embeddings =  embedding_retrieval.JohnSnowLabsLangChainEmbedder('en.embed_sentence.bert_base_uncased')\n",
        "db = FAISS.from_documents(texts, embeddings)\n",
        "retriever = db.as_retriever()"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "eqO8Gqhdn2XA",
        "outputId": "e5bd1935-4614-4d3a-cc59-2f853bd41b4c"
      },
      "id": "eqO8Gqhdn2XA",
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Spark Session already created, some configs may not take.\n",
            "Warning::Spark Session already created, some configs may not take.\n",
            "Warning::Spark Session already created, some configs may not take.\n",
            "sent_bert_base_uncased download started this may take some time.\n",
            "Approximate size to download 392.5 MB\n",
            "[OK!]\n",
            "Warning::Spark Session already created, some configs may not take.\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Create a Tool with the Distributed Embedding Retriever"
      ],
      "metadata": {
        "id": "8YkeV-jYoJTS"
      },
      "id": "8YkeV-jYoJTS"
    },
    {
      "cell_type": "code",
      "source": [
        "from langchain.agents.agent_toolkits import create_retriever_tool\n",
        "tool = create_retriever_tool(\n",
        "    retriever,\n",
        "    \"search_state_of_union\",\n",
        "    \"Searches and returns documents regarding the state-of-the-union.\"\n",
        ")\n",
        "tools = [tool]\n"
      ],
      "metadata": {
        "id": "YASZZUrcm5DR"
      },
      "id": "YASZZUrcm5DR",
      "execution_count": 5,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Create an agent with access to the Tool"
      ],
      "metadata": {
        "id": "305VsUk_oOy4"
      },
      "id": "305VsUk_oOy4"
    },
    {
      "cell_type": "code",
      "source": [
        "from langchain.agents.agent_toolkits import create_conversational_retrieval_agent\n",
        "from langchain.chat_models import ChatOpenAI\n",
        "\n",
        "open_api_key = 'YOUR API KEY'\n",
        "llm = ChatOpenAI(temperature = 0,openai_api_key=open_api_key)\n",
        "agent_executor = create_conversational_retrieval_agent(llm, tools, verbose=True)"
      ],
      "metadata": {
        "id": "aPijWx86m5MX"
      },
      "id": "aPijWx86m5MX",
      "execution_count": 12,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Query the Agent"
      ],
      "metadata": {
        "id": "InRURraHoQvN"
      },
      "id": "InRURraHoQvN"
    },
    {
      "cell_type": "code",
      "source": [
        "result = agent_executor({\"input\": \"what did the president say about going to east of Columbus?\"})\n",
        "result['output']"
      ],
      "metadata": {
        "id": "D77Ayn29m5Sn",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 229
        },
        "outputId": "1c9aaa48-fdd2-425e-e1e9-6f74b2a97597"
      },
      "id": "D77Ayn29m5Sn",
      "execution_count": 7,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "\n",
            "\n",
            "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
            "\u001b[32;1m\u001b[1;3m\n",
            "Invoking: `search_state_of_union` with `{'query': 'going to east of Columbus'}`\n",
            "\n",
            "\n",
            "\u001b[0m\u001b[36;1m\u001b[1;3m[Document(page_content='miles east of', metadata={'source': '/content/state_of_the_union.txt'}), Document(page_content='in America.', metadata={'source': '/content/state_of_the_union.txt'}), Document(page_content='out of America.', metadata={'source': '/content/state_of_the_union.txt'}), Document(page_content='upside down.', metadata={'source': '/content/state_of_the_union.txt'})]\u001b[0m\u001b[32;1m\u001b[1;3mI'm sorry, but I couldn't find any specific information about the president's statement regarding going to the east of Columbus in the State of the Union address.\u001b[0m\n",
            "\n",
            "\u001b[1m> Finished chain.\u001b[0m\n"
          ]
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "\"I'm sorry, but I couldn't find any specific information about the president's statement regarding going to the east of Columbus in the State of the Union address.\""
            ],
            "application/vnd.google.colaboratory.intrinsic+json": {
              "type": "string"
            }
          },
          "metadata": {},
          "execution_count": 7
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [],
      "metadata": {
        "id": "AVfc4HZ_ZDYw"
      },
      "id": "AVfc4HZ_ZDYw",
      "execution_count": null,
      "outputs": []
    }
  ],
  "metadata": {
    "colab": {
      "provenance": []
    },
    "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.10"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}