{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "BART_with_JS_UI.ipynb",
      "provenance": [],
      "collapsed_sections": [],
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/mrm8488/shared_colab_notebooks/blob/master/BART_with_JS_UI.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ZMMtepKIwxR8",
        "colab_type": "text"
      },
      "source": [
        "# BART (a new Seq2Seq model with SoTA summarization performance) that runs from colab with Javascript UI\n",
        "\n",
        "> [Original Colab and article by Sam Shleifer](https://github.com/sshleifer/blog_v2/blob/master/_notebooks/2020-03-12-bart.ipynb)\n",
        "\n",
        "> [JavaScript UI in Colab idea](https://github.com/gpt2ent/gpt2colab-js)\n",
        "\n",
        "\n",
        "**STEPS:**\n",
        "\n",
        "1. Runtime -> Reset all runtimes\n",
        "2. Runtime -> Run all\n",
        "3. Scroll down and wait until you see the little window with a from\n",
        "5. Type text the text to be summarized and click on **Summarize** button\n",
        "6. After a while, the summary will be shown in the form and downloaded!\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "31AcrglIvBjM",
        "colab": {}
      },
      "source": [
        "!git clone https://github.com/huggingface/transformers \\\n",
        "&& cd transformers \\"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "-DcmOk-0UPvv",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "!pip install -q ./transformers"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "yCCdKowrpsms",
        "colab_type": "code",
        "outputId": "c2935a34-fd82-4d2a-aa8f-158c2fe37c9d",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 62
        }
      },
      "source": [
        "import torch\n",
        "import transformers\n",
        "from transformers import BartTokenizer, BartForConditionalGeneration"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<p style=\"color: red;\">\n",
              "The default version of TensorFlow in Colab will soon switch to TensorFlow 2.x.<br>\n",
              "We recommend you <a href=\"https://www.tensorflow.org/guide/migrate\" target=\"_blank\">upgrade</a> now \n",
              "or ensure your notebook will continue to use TensorFlow 1.x via the <code>%tensorflow_version 1.x</code> magic:\n",
              "<a href=\"https://colab.research.google.com/notebooks/tensorflow_version.ipynb\" target=\"_blank\">more info</a>.</p>\n"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "OSWwtcZvo2jj",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "tokenizer = BartTokenizer.from_pretrained('facebook/bart-large-cnn')\n",
        "model = BartForConditionalGeneration.from_pretrained('facebook/bart-large-cnn')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ONkcYLnfvQLE",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "#torch_device = 'cuda' if torch.cuda.is_available() else 'cpu '# failing when device is gpu\n",
        "torch_device = 'cpu'"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "3Oc-U7cIDnnP",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "import google.colab.output\n",
        "\n",
        "def bart_summarize(text, num_beams, length_penalty, max_length, min_length, no_repeat_ngram_size):\n",
        "  \n",
        "  text = text.replace('\\n','')\n",
        "  text_input_ids = tokenizer.batch_encode_plus([text], return_tensors='pt', max_length=1024)['input_ids'].to(torch_device)\n",
        "  summary_ids = model.generate(text_input_ids, num_beams=int(num_beams), length_penalty=float(length_penalty), max_length=int(max_length), min_length=int(min_length), no_repeat_ngram_size=int(no_repeat_ngram_size))           \n",
        "  summary_txt = tokenizer.decode(summary_ids.squeeze(), skip_special_tokens=True)\n",
        "  return summary_txt\n",
        "\n",
        "#register callback for Javascript\n",
        "google.colab.output.register_callback('bart_summarize', bart_summarize)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "CdyRipC0o8vR",
        "colab_type": "code",
        "outputId": "658e0b78-8329-4aab-b769-e0f605a52aae",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 791
        }
      },
      "source": [
        "from IPython.display import HTML\n",
        "\n",
        "#spinner from https://codepen.io/vovchisko/pen/vROoYQ\n",
        "spinner_css = \"\"\"\n",
        "<style>\n",
        "@keyframes c-inline-spinner-kf {\n",
        "  0% {\n",
        "    transform: rotate(0deg);\n",
        "  }\n",
        "  100% {\n",
        "    transform: rotate(360deg);\n",
        "  }\n",
        "}\n",
        "\n",
        ".c-inline-spinner,\n",
        ".c-inline-spinner:before {\n",
        "  display: inline-block;\n",
        "  width: 11px;\n",
        "  height: 11px;\n",
        "  transform-origin: 50%;\n",
        "  border: 2px solid transparent;\n",
        "  border-color: #74a8d0 #74a8d0 transparent transparent;\n",
        "  border-radius: 50%;\n",
        "  content: \"\";\n",
        "  animation: linear c-inline-spinner-kf 300ms infinite;\n",
        "  position: relative;\n",
        "  vertical-align: inherit;\n",
        "  line-height: inherit;\n",
        "}\n",
        ".c-inline-spinner {\n",
        "  top: 3px;\n",
        "  margin: 0 3px;\n",
        "}\n",
        ".c-inline-spinner:before {\n",
        "  border-color: #74a8d0 #74a8d0 transparent transparent;\n",
        "  position: absolute;\n",
        "  left: -2px;\n",
        "  top: -2px;\n",
        "  border-style: solid;\n",
        "}\n",
        "</style>\n",
        "\"\"\"\n",
        "\n",
        "input_form = \"\"\"\n",
        "<link rel=\"stylesheet\" href=\"https://unpkg.com/purecss@1.0.1/build/pure-min.css\" integrity=\"sha384-oAOxQR6DkCoMliIh8yFnu25d7Eq/PHS21PClpwjOTeU2jRSq11vu66rf90/cZr47\" crossorigin=\"anonymous\">\n",
        "\n",
        "<div style=\"background-color:white; border:solid #ccc; width:800px; padding:20px; color: black;\">\n",
        "<p><strong>BART</strong> Seq2Seq model with SoTA summarization performance</p>\n",
        "<textarea id=\"main_textarea\" cols=\"75\" rows=\"20\" placeholder=\"Paste your text here...\" style=\"font-family: 'Liberation Serif', 'DejaVu Serif', Georgia, 'Times New Roman', Times, serif; font-size: 13pt; padding:10px;\"></textarea><br>\n",
        "<div class=\"pure-form pure-form-aligned\">\n",
        "   <div class=\"pure-control-group\">\n",
        "     <label for=\"no_repeat_ngram_size\"><strong>no_repeat_ngram_size:</strong></label>\n",
        "     <input type=\"number\" id=\"no_repeat_ngram_size\" value=\"3\" style=\"background-color: white;\">\n",
        "    </div>\n",
        "    <div class=\"pure-control-group\">\n",
        "      <label for=\"num_beams\"><strong>num_beams:</strong></label>\n",
        "      <input type=\"number\" min=\"0\" max=\"10\" step=\"1\" id=\"num_beams\" value=\"4\" style=\"background-color: white;\">\n",
        "    </div>\n",
        "    <div class=\"pure-control-group\">\n",
        "        <label for=\"length_penalty\"><strong>length_penalty:</strong></label>\n",
        "        <input type=\"number\" min=\"0.0\" max=\"10.0\" step=\"0.1\" id=\"length_penalty\" value=\"2.0\" style=\"background-color: white;\">\n",
        "    </div>\n",
        "    <div class=\"pure-control-group\">\n",
        "        <label for=\"max_length\"><strong>max_length:</strong></label>\n",
        "        <input type=\"number\" id=\"max_length\" value=\"142\" style=\"background-color: white;\">\n",
        "    </div>\n",
        "     <div class=\"pure-control-group\">\n",
        "        <label for=\"min_length\"><strong>min_length:</strong></label>\n",
        "        <input type=\"number\" id=\"min_length\" value=\"56\" style=\"background-color: white;\">\n",
        "    </div>\n",
        "    <p><a target=\"_blank\" href='https://pastebin.com/raw/BMPcUS6v'>Try to summarize this example article</a></p>\n",
        "    <div style=\"width: 300px; display: block; margin-left: auto !important; margin-right: auto !important;\">\n",
        "        <p><button class=\"pure-button pure-button-primary\" style=\"font-size: 125%%;\" onclick=\"summarize()\">Summarize</button>\n",
        "        <span class=\"c-inline-spinner\" style=\"visibility: hidden;\" id=\"spinner\"></span></p>\n",
        "    </div>\n",
        "</div>\n",
        "</div>\n",
        "\"\"\"\n",
        "\n",
        "javascript = \"\"\"\n",
        "<script type=\"text/Javascript\">\n",
        "\n",
        "\n",
        "       function saveTextAsFile(textToWrite, fileNameToSaveAs)\n",
        "    {\n",
        "    \tvar textFileAsBlob = new Blob([textToWrite], {type:'text/plain'}); \n",
        "    \tvar downloadLink = document.createElement(\"a\");\n",
        "    \tdownloadLink.download = fileNameToSaveAs;\n",
        "    \tdownloadLink.innerHTML = \"Download File\";\n",
        "    \tif (window.webkitURL != null)\n",
        "    \t{\n",
        "    \t\t// Chrome allows the link to be clicked\n",
        "    \t\t// without actually adding it to the DOM.\n",
        "    \t\tdownloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);\n",
        "    \t}\n",
        "    \telse\n",
        "    \t{\n",
        "    \t\t// Firefox requires the link to be added to the DOM\n",
        "    \t\t// before it can be clicked.\n",
        "    \t\tdownloadLink.href = window.URL.createObjectURL(textFileAsBlob);\n",
        "    \t\tdownloadLink.onclick = destroyClickedElement;\n",
        "    \t\tdownloadLink.style.display = \"none\";\n",
        "    \t\tdocument.body.appendChild(downloadLink);\n",
        "    \t}\n",
        "    \n",
        "    \tdownloadLink.click();\n",
        "    }\n",
        "\n",
        "\n",
        "    function summarize(){\n",
        "        \n",
        "        var text = document.getElementById('main_textarea').value;\n",
        "        var no_repeat_ngram_size = document.getElementById('no_repeat_ngram_size').value;\n",
        "        var num_beams = document.getElementById('num_beams').value;\n",
        "        var length_penalty = document.getElementById('length_penalty').value;\n",
        "        var max_length = document.getElementById('max_length').value;\n",
        "        var min_length = document.getElementById('min_length').value;\n",
        "        \n",
        "        var kernel = google.colab.kernel;\n",
        "\n",
        "        var resultPromise = kernel.invokeFunction(\"bart_summarize\", [text,num_beams,length_penalty,max_length,min_length,no_repeat_ngram_size]); // developer, look here\n",
        "        resultPromise.then(\n",
        "            function(result) {\n",
        "              document.getElementById('main_textarea').value = 'da resultado';\n",
        "              document.getElementById('main_textarea').value = result.data[\"text/plain\"];\n",
        "              document.getElementById('spinner').style = \"visibility: hidden;\";\n",
        "              saveTextAsFile(result.data[\"text/plain\"], 'summary.txt')\n",
        "        }).catch(function(error){document.getElementById('main_textarea').value = error;});\n",
        "        document.getElementById('spinner').style = \"visibility: visible;\";\n",
        "    };\n",
        "</script>\n",
        "\"\"\" \n",
        "\n",
        "\n",
        "HTML(spinner_css + input_form + javascript)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "\n",
              "<style>\n",
              "@keyframes c-inline-spinner-kf {\n",
              "  0% {\n",
              "    transform: rotate(0deg);\n",
              "  }\n",
              "  100% {\n",
              "    transform: rotate(360deg);\n",
              "  }\n",
              "}\n",
              "\n",
              ".c-inline-spinner,\n",
              ".c-inline-spinner:before {\n",
              "  display: inline-block;\n",
              "  width: 11px;\n",
              "  height: 11px;\n",
              "  transform-origin: 50%;\n",
              "  border: 2px solid transparent;\n",
              "  border-color: #74a8d0 #74a8d0 transparent transparent;\n",
              "  border-radius: 50%;\n",
              "  content: \"\";\n",
              "  animation: linear c-inline-spinner-kf 300ms infinite;\n",
              "  position: relative;\n",
              "  vertical-align: inherit;\n",
              "  line-height: inherit;\n",
              "}\n",
              ".c-inline-spinner {\n",
              "  top: 3px;\n",
              "  margin: 0 3px;\n",
              "}\n",
              ".c-inline-spinner:before {\n",
              "  border-color: #74a8d0 #74a8d0 transparent transparent;\n",
              "  position: absolute;\n",
              "  left: -2px;\n",
              "  top: -2px;\n",
              "  border-style: solid;\n",
              "}\n",
              "</style>\n",
              "\n",
              "<link rel=\"stylesheet\" href=\"https://unpkg.com/purecss@1.0.1/build/pure-min.css\" integrity=\"sha384-oAOxQR6DkCoMliIh8yFnu25d7Eq/PHS21PClpwjOTeU2jRSq11vu66rf90/cZr47\" crossorigin=\"anonymous\">\n",
              "\n",
              "<div style=\"background-color:white; border:solid #ccc; width:800px; padding:20px; color: black;\">\n",
              "<p><strong>BART</strong> Seq2Seq model with SoTA summarization performance</p>\n",
              "<textarea id=\"main_textarea\" cols=\"75\" rows=\"20\" placeholder=\"Paste your text here...\" style=\"font-family: 'Liberation Serif', 'DejaVu Serif', Georgia, 'Times New Roman', Times, serif; font-size: 13pt; padding:10px;\"></textarea><br>\n",
              "<div class=\"pure-form pure-form-aligned\">\n",
              "   <div class=\"pure-control-group\">\n",
              "     <label for=\"no_repeat_ngram_size\"><strong>no_repeat_ngram_size:</strong></label>\n",
              "     <input type=\"number\" id=\"no_repeat_ngram_size\" value=\"3\" style=\"background-color: white;\">\n",
              "    </div>\n",
              "    <div class=\"pure-control-group\">\n",
              "      <label for=\"num_beams\"><strong>num_beams:</strong></label>\n",
              "      <input type=\"number\" min=\"0\" max=\"10\" step=\"1\" id=\"num_beams\" value=\"4\" style=\"background-color: white;\">\n",
              "    </div>\n",
              "    <div class=\"pure-control-group\">\n",
              "        <label for=\"length_penalty\"><strong>length_penalty:</strong></label>\n",
              "        <input type=\"number\" min=\"0.0\" max=\"10.0\" step=\"0.1\" id=\"length_penalty\" value=\"2.0\" style=\"background-color: white;\">\n",
              "    </div>\n",
              "    <div class=\"pure-control-group\">\n",
              "        <label for=\"max_length\"><strong>max_length:</strong></label>\n",
              "        <input type=\"number\" id=\"max_length\" value=\"142\" style=\"background-color: white;\">\n",
              "    </div>\n",
              "     <div class=\"pure-control-group\">\n",
              "        <label for=\"min_length\"><strong>min_length:</strong></label>\n",
              "        <input type=\"number\" id=\"min_length\" value=\"56\" style=\"background-color: white;\">\n",
              "    </div>\n",
              "    <p><a target=\"_blank\" href='https://pastebin.com/raw/BMPcUS6v'>Try to summarize this example article</a></p>\n",
              "    <div style=\"width: 300px; display: block; margin-left: auto !important; margin-right: auto !important;\">\n",
              "        <p><button class=\"pure-button pure-button-primary\" style=\"font-size: 125%%;\" onclick=\"summarize()\">Summarize</button>\n",
              "        <span class=\"c-inline-spinner\" style=\"visibility: hidden;\" id=\"spinner\"></span></p>\n",
              "    </div>\n",
              "</div>\n",
              "</div>\n",
              "\n",
              "<script type=\"text/Javascript\">\n",
              "\n",
              "\n",
              "       function saveTextAsFile(textToWrite, fileNameToSaveAs)\n",
              "    {\n",
              "    \tvar textFileAsBlob = new Blob([textToWrite], {type:'text/plain'}); \n",
              "    \tvar downloadLink = document.createElement(\"a\");\n",
              "    \tdownloadLink.download = fileNameToSaveAs;\n",
              "    \tdownloadLink.innerHTML = \"Download File\";\n",
              "    \tif (window.webkitURL != null)\n",
              "    \t{\n",
              "    \t\t// Chrome allows the link to be clicked\n",
              "    \t\t// without actually adding it to the DOM.\n",
              "    \t\tdownloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);\n",
              "    \t}\n",
              "    \telse\n",
              "    \t{\n",
              "    \t\t// Firefox requires the link to be added to the DOM\n",
              "    \t\t// before it can be clicked.\n",
              "    \t\tdownloadLink.href = window.URL.createObjectURL(textFileAsBlob);\n",
              "    \t\tdownloadLink.onclick = destroyClickedElement;\n",
              "    \t\tdownloadLink.style.display = \"none\";\n",
              "    \t\tdocument.body.appendChild(downloadLink);\n",
              "    \t}\n",
              "    \n",
              "    \tdownloadLink.click();\n",
              "    }\n",
              "\n",
              "\n",
              "    function summarize(){\n",
              "        \n",
              "        var text = document.getElementById('main_textarea').value;\n",
              "        var no_repeat_ngram_size = document.getElementById('no_repeat_ngram_size').value;\n",
              "        var num_beams = document.getElementById('num_beams').value;\n",
              "        var length_penalty = document.getElementById('length_penalty').value;\n",
              "        var max_length = document.getElementById('max_length').value;\n",
              "        var min_length = document.getElementById('min_length').value;\n",
              "        \n",
              "        var kernel = google.colab.kernel;\n",
              "\n",
              "        var resultPromise = kernel.invokeFunction(\"bart_summarize\", [text,num_beams,length_penalty,max_length,min_length,no_repeat_ngram_size]); // developer, look here\n",
              "        resultPromise.then(\n",
              "            function(result) {\n",
              "              document.getElementById('main_textarea').value = 'da resultado';\n",
              "              document.getElementById('main_textarea').value = result.data[\"text/plain\"];\n",
              "              document.getElementById('spinner').style = \"visibility: hidden;\";\n",
              "              saveTextAsFile(result.data[\"text/plain\"], 'summary.txt')\n",
              "        }).catch(function(error){document.getElementById('main_textarea').value = error;});\n",
              "        document.getElementById('spinner').style = \"visibility: visible;\";\n",
              "    };\n",
              "</script>\n"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 7
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Advk1qpXdal5",
        "colab_type": "code",
        "outputId": "4b1a547e-4363-4da9-a140-26fa49e5a689",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        }
      },
      "source": [
        "model.config.output_past"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "True"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 8
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LKx0i94oKS0L",
        "colab_type": "text"
      },
      "source": [
        "> Colab made by [Manuel Romero/mrm8488](https://twitter.com/mrm8488)"
      ]
    }
  ]
}