{ "cells": [ { "cell_type": "markdown", "id": "8c68f03e-620c-46a9-a7ec-a6cde27043cd", "metadata": {}, "source": [ "# Hugging Face Spaces From A Notebook\n", "\n", "> A demo of using nbdev with Hugging Face Spaces" ] }, { "cell_type": "markdown", "id": "96483373-4ae1-49b2-85ed-ceee8456df19", "metadata": {}, "source": [ "## 1. Create a Gradio-enabled Space on Hugging Face\n", "\n", "The first step is to create a space and select the appropriate sdk (which is Gradio in this example), per [these instructions](https://huggingface.co/docs/hub/spaces-overview#creating-a-new-space):" ] }, { "cell_type": "markdown", "id": "b34d7ec6-69b8-48c4-a68b-fad6db3c2fab", "metadata": {}, "source": [ "![](./create_space.png)" ] }, { "cell_type": "markdown", "id": "c25e8e7a-52d9-4305-a107-ba03e3d6a5f3", "metadata": {}, "source": [ "After you are done creating the space, **clone the repo per the instructions provided in the app.** In this example, I ran the command `git clone https://huggingface.co/spaces/hamel/hfspace_demo`." ] }, { "cell_type": "markdown", "id": "ff26114c-329b-4a97-98b5-c652554b0114", "metadata": {}, "source": [ "## 2. Make an app with Gradio" ] }, { "cell_type": "markdown", "id": "14a884fc-36e2-43ec-8e42-ca2903aaa4de", "metadata": {}, "source": [ "Below, we will create a [gradio](https://gradio.app/) app in a notebook and show you how to deploy it to [Hugging Face Spaces](https://huggingface.co/docs/hub/spaces).\n", "\n", "First, lets specify the libraries we need, which in this case are `gradio` and `fastcore`:" ] }, { "cell_type": "code", "execution_count": null, "id": "e5e5d597-19ad-46e5-81ad-8f646d8a1c21", "metadata": {}, "outputs": [], "source": [ "#|export\n", "import gradio as gr\n", "from fastcore.net import urljson, HTTPError" ] }, { "cell_type": "code", "execution_count": null, "id": "38a4389f-ef53-4626-a6f5-a859354f854b", "metadata": {}, "outputs": [], "source": [ "#|export\n", "def size(repo:str):\n", " \"Returns the size in GB of a HuggingFace Dataset.\"\n", " url = f'https://huggingface.co/api/datasets/{repo}'\n", " try: resp = urljson(f'{url}/treesize/main')\n", " except HTTPError: return f'Did not find repo: {url}'\n", " gb = resp['size'] / 1e9\n", " return f'{gb:.2f} GB'" ] }, { "cell_type": "markdown", "id": "9ff9f84d-7744-46ad-80ed-2cf1fa6d0643", "metadata": {}, "source": [ "`size` take as an input a [Hugging Face Dataset](https://huggingface.co/docs/datasets/index) repo and returns the total size in GB of the data.\n", "\n", "For example, we can check the size of [tglcourse/CelebA-faces-cropped-128](https://huggingface.co/datasets/tglcourse/CelebA-faces-cropped-128) like so:" ] }, { "cell_type": "code", "execution_count": null, "id": "95bc32b8-d8ff-4761-a2d7-0880c51d0a42", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'5.49 GB'" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "size(\"tglcourse/CelebA-faces-cropped-128\")" ] }, { "cell_type": "markdown", "id": "cb13747b-ea48-4146-846d-deb9e855d32d", "metadata": {}, "source": [ "You can construct a simple UI with the `gradio.interface` and then call the `launch` method of that interface to display a preview in a notebook. This is a great way to test your app to see if it works" ] }, { "cell_type": "code", "execution_count": null, "id": "7b20e2a1-b622-4970-9069-0202ce10a2ce", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Running on local URL: http://127.0.0.1:7860\n", "\n", "To create a public link, set `share=True` in `launch()`.\n" ] }, { "data": { "text/html": [ "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "(, 'http://127.0.0.1:7860/', None)" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#|export\n", "iface = gr.Interface(fn=size, inputs=gr.Text(value=\"tglcourse/CelebA-faces-cropped-128\"), outputs=\"text\")\n", "iface.launch(width=500)" ] }, { "cell_type": "markdown", "id": "59926b18-a9af-4387-9fcc-f88e588da577", "metadata": {}, "source": [ "Note how running the `launch()` method in a notebook runs a webserver in the background. Below, we call the `close()` method to close the webserver." ] }, { "cell_type": "code", "execution_count": null, "id": "39d7be72-9389-42cf-91b1-78e8f4bbd083", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Closing server running on port: 7860\n" ] } ], "source": [ "# this is only necessary in a notebook\n", "iface.close()" ] }, { "cell_type": "markdown", "id": "249b2cd7-3123-45bf-945f-882b8a964cf5", "metadata": {}, "source": [ "## 3. Converting This Notebook Into A Gradio App" ] }, { "cell_type": "markdown", "id": "5c18ca6e-8de8-49e1-b95a-304070bbc171", "metadata": {}, "source": [ "In order to host this code on Hugging Faces spaces, you will export parts of this notebook to a script named `app.py`. That is what the special `#|export` comment that you have seen in cells above do! You can export code from this notebook like so:" ] }, { "cell_type": "code", "execution_count": null, "id": "6706d92c-5785-4f09-9773-b9a944c493a5", "metadata": {}, "outputs": [], "source": [ "from nbdev.export import nb_export\n", "nb_export('app.ipynb', lib_path='.', name='app')" ] }, { "cell_type": "markdown", "id": "0182403f-d1d6-48c0-8e66-46aefb23a9ab", "metadata": {}, "source": [ "
\n", "\n", "
\n", "\n", "\n", "
" ] }, { "cell_type": "markdown", "id": "84d5fd19-7880-459c-8382-b3574ed11141", "metadata": {}, "source": [ "### Understanding what is generated" ] }, { "cell_type": "markdown", "id": "9ea562e7-b67a-45df-b822-2f4528a307c2", "metadata": {}, "source": [ "Notice how the contents of app.py only contains the exported cells from this notebook:" ] }, { "cell_type": "code", "execution_count": null, "id": "4bae6a5c-58bc-4a0f-9aac-34c092150fdc", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "\u001b[0;31m# AUTOGENERATED! DO NOT EDIT! File to edit: app.ipynb.\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m\u001b[0;31m# %% auto 0\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m\u001b[0m__all__\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m'iface'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'size'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m\u001b[0;31m# %% app.ipynb 7\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m\u001b[0;32mdef\u001b[0m \u001b[0msize\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrepo\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0mstr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0;34m\"Returns the size in GB of a HuggingFace Dataset.\"\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0murl\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34mf'https://huggingface.co/api/datasets/{repo}'\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mresp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0murljson\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf'{url}/treesize/main'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mHTTPError\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;34mf'Did not find repo: {url}'\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0mgb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mresp\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'size'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0;36m1e9\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;34mf'{gb:.2f} GB'\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m\u001b[0;31m# %% app.ipynb 11\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m\u001b[0miface\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mInterface\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfn\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0msize\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minputs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mgr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mText\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"tglcourse/CelebA-faces-cropped-128\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moutputs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"text\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m\u001b[0miface\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlaunch\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mwidth\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m500\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%pycat app.py" ] }, { "cell_type": "markdown", "id": "a081bb0f-5cad-4b99-962b-4dd49cee61a2", "metadata": {}, "source": [ "### Fill out `requirements.txt`\n", "\n", "You must supply a requirements.txt file so the gradio app knows how to build your dependencies. In this example, the only depdency other than gradio is `fastcore`. You don't need to specify gradio itself as a depdendency in `requirements.txt` so our `requirements.txt` file has only one dependency:" ] }, { "cell_type": "code", "execution_count": null, "id": "0b611d9c-d262-4124-9e9e-4fe754ac4378", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "fastcore" ] } ], "source": [ "!cat requirements.txt" ] }, { "cell_type": "markdown", "id": "f15d9c78-1f55-449e-8058-9af1832367a0", "metadata": {}, "source": [ "## 4. Launch Your Gradio App\n", "\n", "To launch your gradio app, you need to commit the changes in the Hugging Face repo:\n", "\n", "```\n", "git add -A; git commit -m \"Add application files\"; git push\n", "```" ] }, { "cell_type": "markdown", "id": "fa661f93-73b4-465a-9c22-cc38197505cb", "metadata": {}, "source": [ "## 5. VoilĂ ! Enjoy your Gradio App" ] }, { "cell_type": "markdown", "id": "9b20ff94-6842-4078-9ec1-be740944e721", "metadata": {}, "source": [ "After a couple of minutes, you will see your app published! " ] }, { "cell_type": "code", "execution_count": null, "id": "958174fe-537e-4635-90b8-22ac11eae396", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 5 }