{ "cells": [ { "cell_type": "markdown", "id": "6dd9d763", "metadata": {}, "source": [ "# **Amazon Lookout for Equipment** - Time series annotation with LabelStudio\n", "\n", "*Part 1 - Initialization*" ] }, { "cell_type": "markdown", "id": "edaf9926", "metadata": {}, "source": [ "## Initialization\n", "---\n", "### Imports" ] }, { "cell_type": "code", "execution_count": 1, "id": "f6e8eb0a", "metadata": {}, "outputs": [], "source": [ "import boto3\n", "\n", "from binascii import hexlify\n", "from json import load\n", "from os import urandom\n", "from uuid import uuid4" ] }, { "cell_type": "markdown", "id": "fb50982a", "metadata": {}, "source": [ "### Helper functions" ] }, { "cell_type": "code", "execution_count": 2, "id": "15b841c7", "metadata": {}, "outputs": [], "source": [ "def get_notebook_name():\n", " log_path = '/opt/ml/metadata/resource-metadata.json'\n", " with open(log_path, 'r') as logs:\n", " _logs = load(logs)\n", " return _logs['ResourceName']" ] }, { "cell_type": "markdown", "id": "7363ff7f", "metadata": {}, "source": [ "### Parameters\n", "Run the following cell to collect the parameters needed to run the LabelStudio container:" ] }, { "cell_type": "code", "execution_count": 4, "id": "53c58666", "metadata": {}, "outputs": [], "source": [ "notebook_name = get_notebook_name()\n", "session = boto3.session.Session()\n", "current_region = session.region_name" ] }, { "cell_type": "markdown", "id": "052d247b", "metadata": {}, "source": [ "### Setup authentication\n", "You will need to authenticate yourself against LabelStudio. Update the following cell before running it to setup your `user`, `password` and `token`:" ] }, { "cell_type": "code", "execution_count": 3, "id": "156ef82b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "GenerateAnAPIToken\n" ] } ], "source": [ "# Must follow a valid email address format:\n", "username = 'username@domain.com'\n", "\n", "# Fill in a password for your LabelStudio user:\n", "password = 'ChooseAPassword'\n", "\n", "# You can uncomment the following line to generate a unique token:\n", "# token = hexlify(urandom(20)).decode()\n", "token = 'GenerateAnAPIToken'\n", "print(token)" ] }, { "cell_type": "markdown", "id": "de4aed59", "metadata": {}, "source": [ "Let's store these variables in the Jupyter environment so that we can use them in the next notebook:" ] }, { "cell_type": "code", "execution_count": 5, "id": "cab4edd8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Stored 'token' (str)\n", "Stored 'notebook_name' (str)\n", "Stored 'current_region' (str)\n" ] } ], "source": [ "%store token\n", "%store notebook_name\n", "%store current_region" ] }, { "cell_type": "markdown", "id": "e066e150", "metadata": {}, "source": [ "## Run LabelStudio\n", "---\n", "Run the following cell to create a shell script which will download a Docker image for LabelStudio and run it:" ] }, { "cell_type": "code", "execution_count": 7, "id": "c2c3301f", "metadata": {}, "outputs": [], "source": [ "with open('label-studio.sh', 'w') as f:\n", " f.write('#!/bin/bash\\n')\n", " f.write(f\"\"\"docker run \\\n", " -it \\\n", " -p 8080:8080 \\\n", " -v /home/ec2-user/SageMaker/label-studio-data:/label-studio/data \\\n", " heartexlabs/label-studio:latest label-studio start --username {username} --password {password} --user-token {token} \\\n", " --host https://{notebook_name}.notebook.{current_region}.sagemaker.aws/proxy/8080\"\"\")" ] }, { "cell_type": "markdown", "id": "6b8ebb5b", "metadata": {}, "source": [ "The following cell will run the script you just created and launch LabelStudio. Once you see the following message, you can cruise over the next notebook:\n", "\n", "```\n", "Django version 3.1.14, using settings 'core.settings.label_studio'\n", "Starting development server at http://0.0.0.0:8080/\n", "Quit the server with CONTROL-C.\n", "```\n", "\n", "The following cell will stay in a running state (note the `[*]` next to it) until you forcefully stop it (note that this will also stop LabelStudio):" ] }, { "cell_type": "code", "execution_count": 8, "id": "771d4e13", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "./deploy/docker-entrypoint.sh: Looking for init scripts in /label-studio/deploy/docker-entrypoint.d/\n", "./deploy/docker-entrypoint.sh: Launching /label-studio/deploy/docker-entrypoint.d/10-copy-static-data.sh\n", "=> Skipping copy data.\n", "./deploy/docker-entrypoint.sh: Launching /label-studio/deploy/docker-entrypoint.d/20-wait-for-db.sh\n", "=> Skipping wait for database.\n", "./deploy/docker-entrypoint.sh: Launching /label-studio/deploy/docker-entrypoint.d/30-run-db-migrations.sh\n", "=> Skipping run db migrations.\n", "./deploy/docker-entrypoint.sh: Configuration complete; ready for start up\n", "=> Hostname correctly is set to: https://lookout-equipment.notebook.eu-west-1.sagemaker.aws/proxy/8080\n", "=> Django URL prefix is set to: /proxy/8080\n", "=> Database and media directory: /label-studio/data\n", "=> Static URL is set to: /static/\n", "Starting new HTTPS connection (1): pypi.org:443\n", "https://pypi.org:443 \"GET /pypi/label-studio/json HTTP/1.1\" 200 46133\n", "Initializing database..\n", "Performing system checks...\n", "\n", "System check identified no issues (1 silenced).\n", "May 25, 2022 - 11:44:35\n", "Django version 3.1.14, using settings 'core.settings.label_studio'\n", "Starting development server at http://0.0.0.0:8080/\n", "Quit the server with CONTROL-C.\n", "[25/May/2022 11:44:45] \u001b[m\"POST /api/projects/ HTTP/1.1\" 201 4160\u001b[0m\n", "[25/May/2022 11:45:30] \u001b[m\"POST /api/storages/s3 HTTP/1.1\" 201 1170\u001b[0m\n", "[25/May/2022 11:45:34] \u001b[m\"POST /api/storages/s3/1/sync HTTP/1.1\" 200 1192\u001b[0m\n", "[25/May/2022 11:45:37] \u001b[32m\"GET / HTTP/1.1\" 302 0\u001b[0m\n", "[2022-05-25 11:45:37,191] [ldclient.util::all_flags_state::367] [WARNING] all_flags_state() called, but client is in offline mode. Returning empty state\n", "[25/May/2022 11:45:37] \u001b[m\"GET /user/login/ HTTP/1.1\" 200 2511\u001b[0m\n", "[25/May/2022 11:45:37] \u001b[m\"GET /static/css/main.de66392810e2.css HTTP/1.1\" 200 15353\u001b[0m\n", "[25/May/2022 11:45:37] \u001b[m\"GET /static/css/login.b79a5e51b1bf.css HTTP/1.1\" 200 2319\u001b[0m\n", "[25/May/2022 11:45:37] \u001b[m\"GET /react-app/main.css?v=3239a3 HTTP/1.1\" 200 68374\u001b[0m\n", "[25/May/2022 11:45:37] \u001b[m\"GET /static/images/opossum_hanging.2fa77848bd0c.svg HTTP/1.1\" 200 131567\u001b[0m\n", "[25/May/2022 11:45:51] \u001b[32m\"POST /user/login/?next=/proxy/8080/projects/ HTTP/1.1\" 302 0\u001b[0m\n", "[2022-05-25 11:45:51,783] [ldclient.util::all_flags_state::367] [WARNING] all_flags_state() called, but client is in offline mode. Returning empty state\n", "[25/May/2022 11:45:51] \u001b[m\"GET /projects/ HTTP/1.1\" 200 4952\u001b[0m\n", "[25/May/2022 11:45:51] \u001b[m\"GET /static/fonts/roboto/roboto.css HTTP/1.1\" 200 3431\u001b[0m\n", "[25/May/2022 11:45:51] \u001b[m\"GET /static/css/uikit.e49a7a43adbd.css HTTP/1.1\" 200 3892\u001b[0m\n", "[25/May/2022 11:45:51] \u001b[m\"GET /static/js/jquery.min.220afd743d9e.js HTTP/1.1\" 200 88145\u001b[0m\n", "[25/May/2022 11:45:51] \u001b[m\"GET /static/js/helpers.9a01b074ff58.js HTTP/1.1\" 200 13336\u001b[0m\n", "[25/May/2022 11:45:51] \u001b[m\"GET /react-app/index.js?v=3239a3 HTTP/1.1\" 200 789345\u001b[0m\n", "[25/May/2022 11:45:52] \u001b[m\"GET /static/icons/logo-black.svg HTTP/1.1\" 200 10236\u001b[0m\n", "[25/May/2022 11:45:52] \u001b[m\"GET /api/version HTTP/1.1\" 200 1053\u001b[0m\n", "[25/May/2022 11:45:52] \u001b[m\"GET /api/projects?page=1&page_size=30 HTTP/1.1\" 200 4191\u001b[0m\n", "[25/May/2022 11:45:52] \u001b[m\"GET /static/fonts/roboto/roboto-v20-latin_cyrillic-500.woff2 HTTP/1.1\" 200 22880\u001b[0m\n", "[2022-05-25 11:45:52,355] [ldclient.util::all_flags_state::367] [WARNING] all_flags_state() called, but client is in offline mode. Returning empty state\n", "[25/May/2022 11:45:52] \u001b[m\"GET /projects/ HTTP/1.1\" 200 4952\u001b[0m\n", "[25/May/2022 11:45:52] \u001b[m\"GET /static/fonts/roboto/roboto-v20-latin_cyrillic-regular.woff2 HTTP/1.1\" 200 22428\u001b[0m\n", "[25/May/2022 11:47:23] \u001b[m\"GET /dm/css/main.css?v=97e33a HTTP/1.1\" 200 65813\u001b[0m\n", "[25/May/2022 11:47:23] \u001b[m\"GET /api/projects/1 HTTP/1.1\" 200 4139\u001b[0m\n", "[25/May/2022 11:47:23] \u001b[m\"GET /label-studio-frontend/css/main.css?v=ee38e7 HTTP/1.1\" 200 636451\u001b[0m\n", "[25/May/2022 11:47:23] \u001b[m\"GET /dm/js/main.js?v=97e33a HTTP/1.1\" 200 1385022\u001b[0m\n", "[25/May/2022 11:47:23] \u001b[m\"GET /label-studio-frontend/js/main.js?v=ee38e7 HTTP/1.1\" 200 2400608\u001b[0m\n", "[25/May/2022 11:47:23] \u001b[m\"GET /api/ml?project=1 HTTP/1.1\" 200 2\u001b[0m\n", "[25/May/2022 11:47:24] \u001b[m\"GET /api/dm/columns?project=1 HTTP/1.1\" 200 3371\u001b[0m\n", "[25/May/2022 11:47:24] \u001b[m\"GET /api/users?project=1 HTTP/1.1\" 200 196\u001b[0m\n", "[25/May/2022 11:47:24] \u001b[m\"GET /api/dm/views?project=1 HTTP/1.1\" 200 2\u001b[0m\n", "[25/May/2022 11:47:24] \u001b[m\"GET /api/dm/actions?project=1 HTTP/1.1\" 200 1537\u001b[0m\n", "[25/May/2022 11:47:24] \u001b[m\"GET /api/dm/project?project=1 HTTP/1.1\" 200 4320\u001b[0m\n", "[25/May/2022 11:47:24] \u001b[m\"POST /api/dm/views?tabID=0&project=1 HTTP/1.1\" 201 850\u001b[0m\n", "[25/May/2022 11:47:24] \u001b[m\"GET /api/tasks?page=1&page_size=30&view=1&project=1 HTTP/1.1\" 200 1737\u001b[0m\n", "[25/May/2022 11:47:24] \u001b[m\"GET /api/tasks?page=1&page_size=30&view=1&project=1 HTTP/1.1\" 200 1737\u001b[0m\n", "[25/May/2022 11:47:24] \u001b[m\"GET /api/tasks?page=1&page_size=30&view=1&project=1 HTTP/1.1\" 200 1737\u001b[0m\n", "[25/May/2022 11:47:56] \u001b[m\"GET /api/tasks/1?project=1 HTTP/1.1\" 200 1751\u001b[0m\n", "/usr/local/lib/python3.8/dist-packages/rest_framework/pagination.py:200: UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list: QuerySet.\n", " paginator = self.django_paginator_class(queryset, page_size)\n", "[25/May/2022 11:47:56] \u001b[m\"GET /api/label_links?project=1&expand=label HTTP/1.1\" 200 52\u001b[0m\n", "[2022-05-25 11:47:57,967] [ldclient.util::all_flags_state::367] [WARNING] all_flags_state() called, but client is in offline mode. Returning empty state\n", "[25/May/2022 11:47:57] \u001b[m\"GET /projects/1/data?tab=1 HTTP/1.1\" 200 4952\u001b[0m\n", "[25/May/2022 11:47:57] \u001b[m\"GET /api/projects/1 HTTP/1.1\" 200 4139\u001b[0m\n", "[25/May/2022 11:48:05] \u001b[m\"POST /api/dm/views?tabID=2&project=1 HTTP/1.1\" 201 852\u001b[0m\n", "[25/May/2022 11:48:06] \u001b[m\"GET /api/tasks?page=1&page_size=30&view=2&project=1 HTTP/1.1\" 200 1737\u001b[0m\n", "[25/May/2022 11:48:09] \u001b[m\"DELETE /api/dm/views/2?project=1 HTTP/1.1\" 204 0\u001b[0m\n", "[25/May/2022 11:48:09] \u001b[m\"GET /api/tasks?page=1&page_size=30&view=1&project=1 HTTP/1.1\" 200 1737\u001b[0m\n", "[25/May/2022 11:50:33] \u001b[m\"GET /api/tasks/1?project=1 HTTP/1.1\" 200 1751\u001b[0m\n", "[25/May/2022 11:50:33] \u001b[m\"GET /api/label_links?project=1&expand=label HTTP/1.1\" 200 52\u001b[0m\n", "[25/May/2022 11:50:44] \u001b[m\"GET /api/label_links?project=1&expand=label HTTP/1.1\" 200 52\u001b[0m\n", "[25/May/2022 11:50:44] \u001b[m\"GET /api/tasks/1?project=1 HTTP/1.1\" 200 1751\u001b[0m\n", "[25/May/2022 11:51:30] \u001b[m\"POST /api/tasks/1/drafts?project=1 HTTP/1.1\" 201 463\u001b[0m\n", "[25/May/2022 11:53:29] \u001b[m\"GET /api/label_links?project=1&expand=label HTTP/1.1\" 200 52\u001b[0m\n", "[25/May/2022 11:53:29] \u001b[m\"GET /api/tasks/1?project=1 HTTP/1.1\" 200 2213\u001b[0m\n", "[25/May/2022 11:53:37] \u001b[m\"GET /api/label_links?project=1&expand=label HTTP/1.1\" 200 52\u001b[0m\n", "[25/May/2022 11:53:37] \u001b[m\"GET /api/tasks/1?project=1 HTTP/1.1\" 200 2214\u001b[0m\n", "[25/May/2022 11:54:03] \u001b[m\"POST /api/tasks/1/annotations?project=1 HTTP/1.1\" 201 528\u001b[0m\n", "[25/May/2022 11:54:04] \u001b[m\"GET /api/tasks/1?project=1 HTTP/1.1\" 200 2516\u001b[0m\n", "[25/May/2022 11:54:06] \u001b[m\"GET /api/label_links?project=1&expand=label HTTP/1.1\" 200 52\u001b[0m\n", "[25/May/2022 11:56:14] \u001b[m\"GET /api/tasks/1/annotations HTTP/1.1\" 200 530\u001b[0m\n", "[25/May/2022 11:56:19] \u001b[m\"GET /api/tasks/1/annotations HTTP/1.1\" 200 530\u001b[0m\n", "^C\n" ] } ], "source": [ "!source ./label-studio.sh" ] }, { "cell_type": "markdown", "id": "951e8ae8", "metadata": {}, "source": [ "## Cleanup\n", "---\n", "If you want to stop LabelStudio, just click on the `Interrupt the kernel` button in this notebooks toolbar.\n", "\n", "If you don't want to keep your labeling projects with your ongoing label work, you can safely delete the `/home/ec2-user/SageMaker/label-studio-data` folder where all the label data is stored.\n", "\n", "**Do not delete** this folder if you want to continue your labeling work later, or isn't done processing the labeling job outputs." ] } ], "metadata": { "kernelspec": { "display_name": "conda_python3", "language": "python", "name": "conda_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.6.13" } }, "nbformat": 4, "nbformat_minor": 5 }