{ "cells": [ { "cell_type": "markdown", "id": "53ba4306", "metadata": {}, "source": [ "AWL Human-in-the-Loop Workflow Demo - [Open this notebook in JupyterLite](https://repolab.github.io/jupyterlite-playground/lab/index.html?fromURL=https://raw.githubusercontent.com/OO-LD/awl-python/refs/heads/main/examples/human_in_the_loop_async.ipynb)" ] }, { "cell_type": "markdown", "id": "aba1eb16", "metadata": {}, "source": [ "Install required packages. In a pyodide/jupyterlite environment this may take ~30 seconds" ] }, { "cell_type": "code", "execution_count": null, "id": "6427c868", "metadata": {}, "outputs": [], "source": [ "import sys\n", "if sys.platform == 'emscripten':\n", " # see: https://github.com/pyodide/pyodide/issues/5834\n", " import micropip\n", " micropip.uninstall(['typing-extensions'])\n", "%pip install 'bokeh==3.7.3' 'jupyter_bokeh' 'panel==1.7.5' 'awl[hitl]'" ] }, { "cell_type": "markdown", "id": "44cc4e76", "metadata": {}, "source": [ "Define data models and a workflow. Functions / steps decorated with hitl (human in the loop) will prompt the user for input by an auto-generated UI (see also [OO-LD UI Demo](https://github.com/OO-LD/oold-python/blob/main/examples/linked_data_editor.ipynb)).\n", "\n", "*Note: async workflow only required for pyodide/jupyterlite. In a regular jupyter or python environment you can also use sync code, see [here](https://github.com/OO-LD/awl-python/blob/main/examples/human_in_the_loop.ipynb)* " ] }, { "cell_type": "code", "execution_count": null, "id": "1705973e", "metadata": {}, "outputs": [], "source": [ "from enum import Enum\n", "import json\n", "from typing import Any, Optional\n", "from oold.model import LinkedBaseModel\n", "from pydantic import Field\n", "from awl.hitl import entry_point, hitl\n", "\n", "class MachineParams(LinkedBaseModel):\n", " \"\"\"Parameters transferred to the machine\"\"\"\n", " model_config = {\n", " \"json_schema_extra\": {\n", " \"required\": [\"param1\"],\n", " },\n", " }\n", " param1: int = Field(50, ge=0, le=100)\n", "\n", "class Quality(str, Enum):\n", " good = \"Good\"\n", " bad = \"Bad\"\n", " worse = \"Worse\"\n", "\n", "class ProcessDocumentation(LinkedBaseModel):\n", " \"\"\"Visual result inspection\"\"\"\n", " quality: Quality\n", " \"\"\"Good is defined as...\"\"\"\n", "\n", "class YesNoEnum(Enum):\n", " yes = True\n", " no = False\n", "\n", "class YesNo(LinkedBaseModel):\n", " answer: bool # YesNoEnum\n", "\n", "@hitl\n", "async def set_machine_params(params: MachineParams):\n", " # transfer params to machine\n", " return params\n", "\n", "@hitl\n", "async def document_result(params: ProcessDocumentation):\n", " # validate documentation\n", " return params\n", "\n", "@hitl\n", "async def document_more(params: YesNo) -> YesNo:\n", " return params\n", "\n", "def archive_data(params: Any):\n", " # store documentation in database\n", " pass\n", "\n", "@entry_point(gui=True, jupyter=True)\n", "async def workflow():\n", " print(\"Enter\")\n", " machine_params = await set_machine_params() # prompts user\n", " do_document_more = True\n", " while(do_document_more):\n", " result_evaluation = await document_result() # prompts user\n", " do_document_more = (await document_more()).answer\n", " \n", " print(\"Machine parameters: \", machine_params)\n", " print(\"Result evaluation: \", result_evaluation)\n", " archive_data(machine_params) # runs automatically\n", " archive_data(result_evaluation) # runs automatically\n", " \n", "await workflow()\n", "print(\"Done\")" ] } ], "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.11.6" } }, "nbformat": 4, "nbformat_minor": 5 }