`, don't forget to activate it before running commands.
-You must do so in every new shell.
+First, you'll need to install Lightning (make sure you use Python 3.8+).
-.. tip:: We highly recommend using virtual environments.
+.. code:: bash
-.. code:: python
+ python -m pip install -U lightning
- pip install lightning
+(pip and conda install coming soon)
----
-****************************************
-Step 2: Install the *Train and Demo* App
-****************************************
-The first Lightning App we'll explore is an App to train and demo a machine learning model.
+********************************
+Step 2: Install Train Deploy App
+********************************
+The first Lightning app we'll explore is an app to train and deploy a machine learning model.
..
[|qs_code|], [|qs_live_app|].
@@ -50,65 +89,70 @@ The first Lightning App we'll explore is an App to train and demo a machine lear
.. |qs_code| raw:: html
- code
+ code
-Install this App by typing:
+Install this app by typing:
.. code-block:: bash
lightning install app lightning/quick-start
-Verify the App was succesfully installed:
+Verify the app was succesfully installed:
.. code-block:: bash
cd lightning-quick-start
+ ls
----
***************************
-Step 3: Run the App locally
+Step 3: Run the app locally
***************************
-
-Run the app locally with the ``run`` command 🤯
+Run the app locally with the ``run`` command
.. code:: bash
lightning run app app.py
+🤯
+
----
********************************
-Step 4: Run the App in the cloud
+Step 4: Run the app on the cloud
********************************
-
-Add the ``--cloud`` argument to run on the `Lightning.AI cloud `_. 🤯🤯🤯
+Add the ``--cloud`` argument to run on the `Lightning.AI cloud `_.
.. code:: bash
lightning run app app.py --cloud
+🤯🤯🤯
+
..
Your app should look like this one (|qs_live_app|)
+
----
*******************
Understand the code
*******************
-The App that we just launched trained a PyTorch Lightning model (although any framework works), then added an interactive demo.
+The app that we just launched trained a PyTorch Lightning model (although any framework works), then added an interactive demo.
-This is the App's code:
+This is the app code:
.. code:: python
# lightning-quick-start/app.py
import os.path as ops
- import lightning as L
+ import lightning_app as la
from quick_start.components import PyTorchLightningScript, ImageServeGradio
- class TrainDeploy(L.LightningFlow):
+
+ class TrainDeploy(lapp.LightningFlow):
def __init__(self):
super().__init__()
self.train_work = PyTorchLightningScript(
@@ -116,7 +160,7 @@ This is the App's code:
script_args=["--trainer.max_epochs=5"],
)
- self.serve_work = ImageServeGradio(L.CloudCompute())
+ self.serve_work = ImageServeGradio(lapp.CloudCompute())
def run(self):
# 1. Run the python script that trains the model
@@ -131,18 +175,18 @@ This is the App's code:
tab_2 = {"name": "Interactive demo", "content": self.serve_work}
return [tab_1, tab_2]
- app = L.LightningApp(TrainDeploy())
-Let's break down the code section by section to understand what it is doing.
+ app = lapp.LightningApp(TrainDeploy())
+
+Let's break down the app code by each section to understand what it is doing.
----
1: Define root component
^^^^^^^^^^^^^^^^^^^^^^^^
+A Lightning app provides a cohesive product experience for a set of unrelated components.
-A Lightning App provides a cohesive product experience for a set of unrelated components.
-
-The top-level component (Root) must subclass ``L.LightningFlow``
+The top-level component (Root) must subclass lapp.LightningFlow
.. code:: python
@@ -150,10 +194,11 @@ The top-level component (Root) must subclass ``L.LightningFlow``
# lightning-quick-start/app.py
import os.path as ops
- import lightning as L
+ import lightning_app as la
from quick_start.components import PyTorchLightningScript, ImageServeGradio
- class TrainDeploy(L.LightningFlow):
+
+ class TrainDeploy(lapp.LightningFlow):
def __init__(self):
super().__init__()
self.train_work = PyTorchLightningScript(
@@ -161,7 +206,7 @@ The top-level component (Root) must subclass ``L.LightningFlow``
script_args=["--trainer.max_epochs=5"],
)
- self.serve_work = ImageServeGradio(L.CloudCompute("cpu-small"))
+ self.serve_work = ImageServeGradio(lapp.CloudCompute("cpu-small"))
def run(self):
# 1. Run the python script that trains the model
@@ -176,25 +221,27 @@ The top-level component (Root) must subclass ``L.LightningFlow``
tab_2 = {"name": "Interactive demo", "content": self.serve_work}
return [tab_1, tab_2]
- app = L.LightningApp(TrainDeploy())
+
+ app = lapp.LightningApp(TrainDeploy())
----
2: Define components
^^^^^^^^^^^^^^^^^^^^
-In the __init__ method, we define the components that make up the App. In this case, we have 2 components,
-a component to execute any PyTorch Lightning script (model training) and a second component to
-start a Gradio server for demo purposes.
+In the __init__ method, we define the components that make up the app. In this case, we have 2 components,
+a component to execute any pytorch lightning script (model training) and a second component to
+start a gradio server for demo purposes.
.. code:: python
:emphasize-lines: 9, 14
# lightning-quick-start/app.py
import os.path as ops
- import lightning as L
+ import lightning_app as la
from quick_start.components import PyTorchLightningScript, ImageServeGradio
- class TrainDeploy(L.LightningFlow):
+
+ class TrainDeploy(lapp.LightningFlow):
def __init__(self):
super().__init__()
self.train_work = PyTorchLightningScript(
@@ -202,7 +249,7 @@ start a Gradio server for demo purposes.
script_args=["--trainer.max_epochs=5"],
)
- self.serve_work = ImageServeGradio(L.CloudCompute("cpu-small"))
+ self.serve_work = ImageServeGradio(lapp.CloudCompute("cpu-small"))
def run(self):
# 1. Run the python script that trains the model
@@ -217,13 +264,14 @@ start a Gradio server for demo purposes.
tab_2 = {"name": "Interactive demo", "content": self.serve_work}
return [tab_1, tab_2]
- app = L.LightningApp(TrainDeploy())
+
+ app = lapp.LightningApp(TrainDeploy())
----
-3: Define how components Flow
+3: Define how components flow
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Every component has a ``run`` method. The run method defines the 🌊 Flow 🌊 of how components interact together.
+Every component has a `run` method. The run method defines the 🌊 flow 🌊 of how components interact together.
In this case, we train a model (until completion). When it's done AND there exists a checkpoint, we launch a
demo server:
@@ -233,10 +281,11 @@ demo server:
# lightning-quick-start/app.py
import os.path as ops
- import lightning as L
+ import lightning_app as la
from quick_start.components import PyTorchLightningScript, ImageServeGradio
- class TrainDeploy(L.LightningFlow):
+
+ class TrainDeploy(lapp.LightningFlow):
def __init__(self):
super().__init__()
self.train_work = PyTorchLightningScript(
@@ -244,7 +293,7 @@ demo server:
script_args=["--trainer.max_epochs=5"],
)
- self.serve_work = ImageServeGradio(L.CloudCompute("cpu-small"))
+ self.serve_work = ImageServeGradio(lapp.CloudCompute("cpu-small"))
def run(self):
# 1. Run the python script that trains the model
@@ -259,9 +308,12 @@ demo server:
tab_2 = {"name": "Interactive demo", "content": self.serve_work}
return [tab_1, tab_2]
- app = L.LightningApp(TrainDeploy())
-.. note:: If you've used other ML systems you'll be pleasantly surprised to not find decorators or YAML files.
+ app = lapp.LightningApp(TrainDeploy())
+
+..
+ If you've used other ML systems you'll be pleasantly surprised to not find decorators or YAML files.
+ Read here to understand the benefits more.
----
@@ -269,17 +321,18 @@ demo server:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
All our favorite tools normally have their own web user interfaces (UI).
-Implement the ``configure_layout`` method to connect them together:
+Implement the `configure_layout` method to connect them together:
.. code:: python
:emphasize-lines: 24-27
# lightning-quick-start/app.py
import os.path as ops
- import lightning as L
+ import lightning_app as la
from quick_start.components import PyTorchLightningScript, ImageServeGradio
- class TrainDeploy(L.LightningFlow):
+
+ class TrainDeploy(lapp.LightningFlow):
def __init__(self):
super().__init__()
self.train_work = PyTorchLightningScript(
@@ -287,7 +340,7 @@ Implement the ``configure_layout`` method to connect them together:
script_args=["--trainer.max_epochs=5"],
)
- self.serve_work = ImageServeGradio(L.CloudCompute("cpu-small"))
+ self.serve_work = ImageServeGradio(lapp.CloudCompute("cpu-small"))
def run(self):
# 1. Run the python script that trains the model
@@ -302,23 +355,25 @@ Implement the ``configure_layout`` method to connect them together:
tab_2 = {"name": "Interactive demo", "content": self.serve_work}
return [tab_1, tab_2]
- app = L.LightningApp(TrainDeploy())
+
+ app = lapp.LightningApp(TrainDeploy())
----
-5: Init the ``app`` object
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-Initalize an ``app`` object with the ``TrainDeploy`` component (this won't run the App yet):
+5: Init the app object
+^^^^^^^^^^^^^^^^^^^^^^
+Initalize an app object with the `TrainDeploy` component (this won't run the app yet):
.. code:: python
:emphasize-lines: 29
# lightning-quick-start/app.py
import os.path as ops
- import lightning as L
+ import lightning_app as la
from quick_start.components import PyTorchLightningScript, ImageServeGradio
- class TrainDeploy(L.LightningFlow):
+
+ class TrainDeploy(lapp.LightningFlow):
def __init__(self):
super().__init__()
self.train_work = PyTorchLightningScript(
@@ -326,7 +381,7 @@ Initalize an ``app`` object with the ``TrainDeploy`` component (this won't run t
script_args=["--trainer.max_epochs=5"],
)
- self.serve_work = ImageServeGradio(L.CloudCompute("cpu-small"))
+ self.serve_work = ImageServeGradio(lapp.CloudCompute("cpu-small"))
def run(self):
# 1. Run the python script that trains the model
@@ -341,7 +396,8 @@ Initalize an ``app`` object with the ``TrainDeploy`` component (this won't run t
tab_2 = {"name": "Interactive demo", "content": self.serve_work}
return [tab_1, tab_2]
- app = L.LightningApp(TrainDeploy())
+
+ app = lapp.LightningApp(TrainDeploy())
----
@@ -357,8 +413,9 @@ Any component can work with Lightning AI!
----
**********
-Next Steps
+Next steps
**********
+Depending on your use case, you might want to check one of these out next.
.. raw:: html
@@ -366,8 +423,8 @@ Next Steps
.. displayitem::
- :header: Add components to your App
- :description: Expand your App by adding components.
+ :header: Add components to your app
+ :description: Expand your app by adding components.
:col_css: col-md-4
:button_link: ../workflows/extend_app.html
:height: 180
@@ -380,22 +437,22 @@ Next Steps
:height: 180
.. displayitem::
- :header: Explore more Apps
+ :header: Explore more apps
:description: Explore more apps for inspiration.
:col_css: col-md-4
:button_link: https://lightning.ai/apps
:height: 180
.. displayitem::
- :header: Under the hood
+ :header: How it works under the hood
:description: Explore how it works under the hood.
:col_css: col-md-4
- :button_link: ../core_api/lightning_app/index.html
+ :button_link: core_api/lightning_app/index.html
:height: 180
-.. displayitem::
+.. displayitem::workflo
:header: Run on your private cloud
- :description: Run Lightning Apps on your private VPC or on-prem.
+ :description: Run lightning apps on your private VPC or on-prem.
:button_link: ../workflows/run_on_private_cloud.html
:col_css: col-md-4
:height: 180
diff --git a/docs/source-app/moving_to_the_cloud.rst b/docs/source-app/pages/moving_to_the_cloud.rst
similarity index 85%
rename from docs/source-app/moving_to_the_cloud.rst
rename to docs/source-app/pages/moving_to_the_cloud.rst
index 210fe32db8..27d01c11a1 100644
--- a/docs/source-app/moving_to_the_cloud.rst
+++ b/docs/source-app/pages/moving_to_the_cloud.rst
@@ -2,9 +2,9 @@
.. _moving_to_the_cloud:
-####################
+*******************
Moving to the Cloud
-####################
+*******************
.. warning:: This is in progress and not yet fully supported.
@@ -14,12 +14,8 @@ that trains an image classifier and serve it once trained.
In this tutorial, you'll learn how to extend that application so that it works seamlessly
both locally and in the cloud.
-----
-
-********************************
Step 1: Distributed Application
-********************************
-
+===============================
Distributed Storage
^^^^^^^^^^^^^^^^^^^
@@ -40,17 +36,18 @@ Without doing this conscientiously for every single path, your application will
In the example below, a file written by **SourceFileWork** is being transferred by the flow
to the **DestinationFileAndServeWork** work. The Path object is the reference to the file.
-.. literalinclude:: ../examples/app_boring/app.py
+.. literalinclude:: ../../../examples/boring_app/app.py
:emphasize-lines: 5, 22, 28, 48
-In the ``scripts/serve.py`` file, we are creating a **FastApi Service** running on port ``1111``
+In the ``../scripts/serve.py`` file, we are creating a **FastApi Service** running on port ``1111``
that returns the content of the file received from **SourceFileWork** when
a post request is sent to ``/file``.
-.. literalinclude:: ../examples/app_boring/scripts/serve.py
+.. literalinclude:: ../../../examples/boring_app/scripts/serve.py
:emphasize-lines: 21, 23-26
-----
+
+
Distributed Frontend
^^^^^^^^^^^^^^^^^^^^
@@ -64,14 +61,14 @@ In order to assemble them, you need to do two things:
Here's how to expose the port:
-.. literalinclude:: ../examples/app_boring/app.py
+.. literalinclude:: ../../../examples/boring_app/app.py
:emphasize-lines: 8
:lines: 33-44
And here's how to expose your services within the ``configure_layout`` flow hook:
-.. literalinclude:: ../examples/app_boring/app.py
+.. literalinclude:: ../../../examples/boring_app/app.py
:emphasize-lines: 5
:lines: 53-57
@@ -79,7 +76,7 @@ In this example, we're appending ``/file`` to our **FastApi Service** url.
This means that our ``Boring Tab`` triggers the ``get_file_content`` from the **FastAPI Service**
and embeds its content as an `IFrame `_.
-.. literalinclude:: ../examples/app_boring/scripts/serve.py
+.. literalinclude:: ../../../examples/boring_app/scripts/serve.py
:lines: 23-26
@@ -89,11 +86,9 @@ Here's a visualization of the application described above:
:alt: Storage API Animation
:width: 100 %
-----
-*****************************
Step 2: Scalable Application
-*****************************
+============================
The benefit of defining long-running code inside a
:class:`~lightning_app.core.work.LightningWork`
@@ -106,11 +101,8 @@ By adapting the :ref:`quick_start` example as follows, you can easily run your c
Without doing much, you’re now running a script on its own cluster of machines! 🤯
-----
-
-*****************************
Step 3: Resilient Application
-*****************************
+=============================
We designed Lightning with a strong emphasis on supporting failure cases.
The framework shines when the developer embraces our fault-tolerance best practices,
diff --git a/docs/source-app/quickstart.rst b/docs/source-app/pages/quickstart.rst
similarity index 90%
rename from docs/source-app/quickstart.rst
rename to docs/source-app/pages/quickstart.rst
index f14ba98e18..4ea358fa65 100644
--- a/docs/source-app/quickstart.rst
+++ b/docs/source-app/pages/quickstart.rst
@@ -2,23 +2,20 @@
.. _quick_start:
-############
+***********
Quick Start
-############
+***********
In this guide, we'll run an application that trains
an image classification model with the `MNIST Dataset `_,
and uses `FastAPI `_ to serve it.
-----
-
-**********************
Step 1 - Installation
-**********************
+=====================
First, you'll need to install Lightning from source. You can find the complete guide here: :ref:`install`.
-Then, you'll need to install the `Lightning Quick Start package `_.
+Then, you'll need to install the `Lightning Quick Start package `_.
.. code-block:: bash
@@ -30,11 +27,8 @@ And download the training script used by the App:
curl https://gist.githubusercontent.com/tchaton/b81c8d8ba0f4dd39a47bfa607d81d6d5/raw/8d9d70573a006d95bdcda8492e798d0771d7e61b/train_script.py > train_script.py
-----
-
-**********************
Step 2 - Run the app
-**********************
+====================
To run your app, copy the following command to your local terminal:
@@ -83,10 +77,8 @@ The build command will launch the app admin panel UI. In your app admin, you can
:alt: Quick Start UI
:width: 100 %
-----
-
This app behind the scenes
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
+--------------------------
This application has one flow component which coordinates two works executing their own python script.
Once the training is finished, the trained model weights are passed to the serve component.
@@ -104,13 +96,11 @@ Here is the application timeline:
:alt: Quick Start Timeline Application
:width: 100 %
-----
-**************************************
Steps 3 - Build your app in the cloud
-**************************************
+=====================================
-Simply add ``--cloud`` to run this application in the cloud 🤯
+Simply add **--cloud** to run this application in the cloud 🤯
.. code-block:: bash
@@ -125,11 +115,9 @@ And with just one line of code, run on cloud GPUs!
Congratulations! You've now run your first application with Lightning.
-----
-***********
-Next Steps
-***********
+Next steps
+==========
To learn how to build and modify apps, go to the :ref:`basics`.
diff --git a/docs/source-app/testing.rst b/docs/source-app/pages/testing.rst
similarity index 95%
rename from docs/source-app/testing.rst
rename to docs/source-app/pages/testing.rst
index 51ec1841a4..8b38f21096 100644
--- a/docs/source-app/testing.rst
+++ b/docs/source-app/pages/testing.rst
@@ -10,11 +10,8 @@ TODO: Cleanup
At the core of our system is an integration testing framework that will allow for a first-class experience creating integration tests for Lightning Apps. This document will explain how we can create a lightning app test, how we can execute it, and where to find more information.
-----
-
-***********
Philosophy
-***********
+----------
Testing a Lightning app is unique. It is a superset of an application that converges machine learning, API development, and UI development. With that in mind, there are several philosophies (or "best practices") that you should adhere to:
@@ -26,11 +23,8 @@ Testing a Lightning app is unique. It is a superset of an application that conve
#. **Use your framework** - Testing apps should be framework agnostic.
#. **Have fun!** - At the heart of testing is experimentation. Like any experiment, tests begin with a hypothesis of workability, but you can extend that to be more inclusive. Ask the question, write the test to answer your question, and make sure you have fun while doing it.
-----
-
-****************************************
Anatomy of a Lightning integration test
-****************************************
+---------------------------------------
The following is a PyTest example of an integration test using the ``lightning_app.testing.testing`` module.
@@ -54,7 +48,7 @@ The following is a PyTest example of an integration test using the ``lightning_a
def test_v0_app_example():
command_line = [
- os.path.join(_PROJECT_ROOT, "examples/app_v0/app.py"),
+ os.path.join(_PROJECT_ROOT, "examples/v0_app/app.py"),
"--blocking",
"False",
"--multiprocess",
@@ -65,8 +59,6 @@ The following is a PyTest example of an integration test using the ``lightning_a
assert "V0 App End" in str(result.stdout_bytes)
assert result.exit_code == 0
-----
-
Setting up the app
^^^^^^^^^^^^^^^^^^
@@ -80,10 +72,8 @@ To get started, you simply need to import the following:
We will discuss ``application_testing`` in a bit, but first let's review the structure of ``TestLightningApp``.
-----
-
TestLightningApp
-^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~
The :class:`lightning_app.testing.testing.TestingLightningApp` class is available to use for provisioning and setting up your testing needs. Note that you do not need this class to move forward with testing. Any application that inherits ``LightningApp`` should suffice as long as you override the correct methods. Reviewing the TestLightnigApp we see some overrides that are already there. Please revuew the class for more information.
@@ -107,8 +97,6 @@ Besides ``run_once`` there are a few other overrides available:
These methods will skew your tests, so use them when needed.
-----
-
The Test
^^^^^^^^
@@ -117,7 +105,7 @@ We provide ``application_testing`` as a helper funtion to get your application u
.. code-block::
command_line = [
- os.path.join(_PROJECT_ROOT, "examples/app_v0/app.py"),
+ os.path.join(_PROJECT_ROOT, "examples/v0_app/app.py"),
"--blocking",
"False",
"--multiprocess",
@@ -149,10 +137,7 @@ As mentioned earlier, ``application_testing`` is a helper method that allows you
Since we injected "V0 App End" to the end of our test flow. The state was changed to ``AppStatus.STOPPING`` which means the process is done. Finally, we check the result's exit code to make sure that we did not throw an error during execution.
-----
-
-************
End to End
-************
+----------
TODO
diff --git a/docs/source-app/ui_and_frontends.rst b/docs/source-app/pages/ui_and_frontends.rst
similarity index 82%
rename from docs/source-app/ui_and_frontends.rst
rename to docs/source-app/pages/ui_and_frontends.rst
index 53e50cd534..0db452fdfb 100644
--- a/docs/source-app/ui_and_frontends.rst
+++ b/docs/source-app/pages/ui_and_frontends.rst
@@ -14,8 +14,8 @@ You can easily embed other tools and services (like a GitHub repo, a `FastAPI Se
To get started, you can use built-in templates for the following frameworks:
-* `React.js `_
-* `StreamLit `_
+* `React.js `_
+* `StreamLit `_
diff --git a/docs/source-app/examples/hpo/hpo.py b/docs/source-app/tutorials/hpo/hpo.py
similarity index 70%
rename from docs/source-app/examples/hpo/hpo.py
rename to docs/source-app/tutorials/hpo/hpo.py
index fd05cc2e32..69bccf67ac 100644
--- a/docs/source-app/examples/hpo/hpo.py
+++ b/docs/source-app/tutorials/hpo/hpo.py
@@ -1,6 +1,5 @@
import optuna
from objective import ObjectiveWork
-from optuna.distributions import CategoricalDistribution, LogUniformDistribution
TOTAL_TRIALS = 6
SIMULTANEOUS_TRIALS = 2
@@ -9,16 +8,14 @@ DONE = False
STUDY = optuna.create_study()
DISTRIBUTIONS = {
- "backbone": CategoricalDistribution(["resnet18", "resnet34"]),
- "learning_rate": LogUniformDistribution(0.0001, 0.1),
+ "backbone": optuna.distributions.CategoricalDistribution(["resnet18", "resnet34"]),
+ "learning_rate": optuna.distributions.LogUniformDistribution(0.0001, 0.1),
}
TRIALS = [ObjectiveWork() for _ in range(TOTAL_TRIALS)]
-# Lightning Infinite Loop
-while not DONE:
+while not DONE: # Lightning Infinite Loop
- # Finish the Hyperparameter Optimization
- if NUM_TRIALS >= TOTAL_TRIALS:
+ if NUM_TRIALS > TOTAL_TRIALS: # Finish the Hyperparameter Optimization
DONE = True
continue
@@ -31,12 +28,10 @@ while not DONE:
# If a work has already started, it won't be started again.
if not objective_work.has_started:
- # Sample a new trial from the distributions
- trial = STUDY.ask(DISTRIBUTIONS)
- # Run the work
- objective_work.run(trial_id=trial._trial_id, **trial.params)
+ trial = STUDY.ask(DISTRIBUTIONS) # Sample a new trial from the distributions
+ objective_work.run(trial_id=trial._trial_id, **trial.params) # Run the work
- # With Lightning, the `objective_work` will run asynchronously
+ # With Lighting, the `objective_work` will run asynchronously
# and the metric will be prodcued after X amount of time.
# The Lightning Infinite Loop would have run a very large number of times by then.
if objective_work.metric and not objective_work.has_told_study:
diff --git a/docs/source-app/tutorials/hpo/hpo.rst b/docs/source-app/tutorials/hpo/hpo.rst
new file mode 100644
index 0000000000..d6567194ae
--- /dev/null
+++ b/docs/source-app/tutorials/hpo/hpo.rst
@@ -0,0 +1,146 @@
+.. hpo:
+
+******************
+Build a Sweeps App
+******************
+
+Introduction
+============
+
+Traditionally, developing ML Products requires to choose among a large space of
+hyperparameters while creating and training the ML models. Hyperparameter Optimization
+(HPO) aims at finding a well-performing hyperparameter configuration of a given machine
+learning model on a dataset at hand, including the machine learning model,
+its hyperparameters and other data processing steps.
+
+Thus, HPO frees the human expert from a tedious and error-prone hyperparameter tuning process.
+
+As an example, in the famous `scikit-learn `_, hyperparameter are passed as arguments to the constructor of
+the estimator classes such as ``C`` kernel for
+`Support Vector Classifier `_, etc.
+
+It is possible and recommended to search the hyper-parameter space for the best validation score.
+
+An HPO search consists of:
+
+* an objective method
+* a parameter space defined
+* a method for searching or sampling candidates
+
+A naive method for sampling candidates is Grid Search which exhaustively considers all parameter combinations.
+
+Hopefully, the field of Hyperparameter Optimization is very active and many methods have been developed to
+optimize the time required to get strong candidates.
+
+In the following tutorial, you will learn how to use Lightning together with the `Optuna `_.
+
+`Optuna `_ is an open source hyperparameter optimization framework to automate hyperparameter search.
+Out-of-the-box, it provides efficient algorithms to search large spaces and prune unpromising trials for faster results.
+
+First, you will learn about the best practices on how to implement HPO without the Lightning Framework.
+Secondly, we will dive into a working HPO application with Lightning and finally create a neat
+`HiPlot UI `_
+for our application.
+
+HPO Example Without Lightning
+=============================
+
+In the example below, we are emulating the Lightning Infinite Loop.
+
+We are assuming have already defined an ``ObjectiveWork`` component which is responsible to run the objective method and track the metric through its state.
+
+We are running ``TOTAL_TRIALS`` trials by series of ``SIMULTANEOUS_TRIALS`` trials.
+When starting, ``TOTAL_TRIALS`` ``ObjectiveWork`` are created.
+
+The entire code runs within an infinite loop as it would within Lightning.
+
+When iterating through the works, if the current ``objective_work`` hasn't started,
+some new parameters are sampled from the Optuna Study with our custom distributions
+and then passed to run method of the ``objective_work``.
+
+The condition ``not objective_work.has_started`` will be ``False`` once ``objective_work.run()`` starts.
+
+Also, the second condition will be ``True`` when the metric finally is defined within the state of the work,
+which happens after many iterations of the Lightning Infinite Loop.
+
+Finally, once the current ``SIMULTANEOUS_TRIALS`` have both registered their
+metric to the Optuna Study, simply increments ``NUM_TRIALS`` by ``SIMULTANEOUS_TRIALS`` to launch the next trials.
+
+.. literalinclude:: ./hpo.py
+ :language: python
+ :emphasize-lines: 14, 16, 30-32, 37-40, 43, 46-47
+
+Below, you can find the simplified version of the ``ObjectiveWork`` where the metric is randomly sampled using numpy.
+
+In realistic use case, the work executes some user defined code.
+
+.. literalinclude:: ./objective.py
+ :language: python
+ :emphasize-lines: 8, 19-21
+
+Here are the logs produced when running the application above:
+
+.. code-block:: console
+
+ $ python docs/source/tutorials/hpo/hpo.py
+ INFO: Your app has started. View it in your browser: http://127.0.0.1:7501/view
+ # After you have clicked `run` on the UI.
+ [I 2022-03-01 12:32:50,050] A new study created in memory with name: ...
+ {0: 13.994859806481264, 1: 59.866743330127825, ..., 5: 94.65919769609225}
+
+In the cloud, here is an animation how this application works:
+
+.. image:: https://pl-flash-data.s3.amazonaws.com/assets_lightning/hpo.gif
+ :alt: Animation showing how to HPO works UI in a distributed manner.
+
+
+HPO Example With Lightning
+==========================
+
+Thanks the simplified version, you should have a good grasp on how to implement HPO with Optuna
+
+As the :class:`~lightning_app.core.app.LightningApp` handles the Infinite Loop,
+it has been removed from within the run method of the HPORootFlow.
+
+However, the run method code is the same as the one defined above.
+
+.. literalinclude:: ../../../../examples/hpo/app_wo_ui.py
+ :language: python
+ :emphasize-lines: 5, 17-23, 52-59
+
+The ``ObjectiveWork`` is sub-classing
+the built-in :class:`~lightning_app.components.python.TracerPythonScript`
+which enables to launch scripts and more.
+
+.. literalinclude:: ../../../../examples/hpo/objective.py
+ :language: python
+ :emphasize-lines: 9, 11, 15, 21-30, 40-46
+
+Finally, let's add ``HiPlotFlow`` component to visualize our hyperparameter optimization.
+
+The metric and sampled parameters are added to the ``self.hi_plot.data`` list, enabling
+to get the dashboard updated in near-realtime.
+
+.. literalinclude:: ../../../../examples/hpo/app_wi_ui.py
+ :diff: ../../../../examples/hpo/app_wo_ui.py
+
+Here is the associated code with the ``HiPlotFlow`` component.
+
+In the ``render_fn`` method, the state of the ``HiPlotFlow`` is passed.
+The ``state.data`` is accessed as it contains the metric and sampled parameters.
+
+.. literalinclude:: ../../../../examples/hpo/hyperplot.py
+
+Run the HPO application with the following command:
+
+.. code-block:: console
+
+ $ lightning run app examples/hpo/app_wi_ui.py
+ INFO: Your app has started. View it in your browser: http://127.0.0.1:7501/view
+ {0: ..., 1: ..., ..., 5: ...}
+
+Here is how the UI looks like when launched:
+
+.. image:: https://pl-flash-data.s3.amazonaws.com/assets_lightning/hpo_ui_2.gif
+ :width: 100 %
+ :alt: Alternative text
diff --git a/docs/source-app/examples/hpo/objective.py b/docs/source-app/tutorials/hpo/objective.py
similarity index 55%
rename from docs/source-app/examples/hpo/objective.py
rename to docs/source-app/tutorials/hpo/objective.py
index d20232fb10..7e83551a14 100644
--- a/docs/source-app/examples/hpo/objective.py
+++ b/docs/source-app/tutorials/hpo/objective.py
@@ -1,11 +1,12 @@
import numpy as np
-import lightning as L
+from lightning_app import LightningWork
-class ObjectiveWork(L.LightningWork):
+class ObjectiveWork(LightningWork):
def __init__(self):
super().__init__(parallel=True)
+ self.has_started = False
self.metric = None
self.trial_id = None
self.params = None
@@ -13,9 +14,8 @@ class ObjectiveWork(L.LightningWork):
def run(self, trial_id, **params):
self.trial_id = trial_id
- # Received suggested `backbone` and `learning_rate`
- self.params = params
- # Emulate metric computation would be
- # computed once a script has been completed.
+ self.params = params # Received suggested `backbone` and `learning_rate`
+ self.has_started = True
+ # Emulate metric computation would be computed once a script has been completed.
# In reality, this would excute a user defined script.
self.metric = np.random.uniform(0, 100)
diff --git a/docs/source-app/workflows/access_app_state.rst b/docs/source-app/workflows/access_app_state.rst
new file mode 100644
index 0000000000..881d2c6840
--- /dev/null
+++ b/docs/source-app/workflows/access_app_state.rst
@@ -0,0 +1,61 @@
+.. _access_app_state:
+
+################
+Access App State
+################
+
+**Audience:** Users who want to know how the app state can be accessed.
+
+**Level:** Basic
+
+***********************
+What is the App State ?
+***********************
+
+In Lightning, each component is stateful and their state are composed of all attributes defined within their **__init__** method.
+
+The **App State** is the collection of all the components state forming the application.
+
+*****************************************
+What is the special about the App State ?
+*****************************************
+
+The **App State** is always up-to-date, even running an application in the cloud on multiple machines.
+
+This means that every time an attribute is modified in a work, that information is automatically broadcasted to the flow.
+
+With this mechanism, any component can **react** to any other component **state changes** through the flow and complex system can be easily implemented.
+
+Lightning requires a state based driven mindset when implementing the flow.
+
+************************************
+When do I need to access the state ?
+************************************
+
+As a user, you are interacting with your component attributes, so most likely,
+you won't need to access the component state directly, but it can be helpful to
+understand how the state works under the hood.
+
+For example, here we define a **Flow** component and **Work** component, where the work increments a counter indefinitely and the flow prints its state which contains the work.
+
+You can easily check the state of your entire app as follows:
+
+.. literalinclude:: ../code_samples/quickstart/app_01.py
+
+Run the app with:
+
+.. code-block:: bash
+
+ lightning run app docs/quickstart/app_01.py
+
+And here's the output you get when running the above application using **Lightning CLI**:
+
+.. code-block:: console
+
+ INFO: Your app has started. View it in your browser: http://127.0.0.1:7501/view
+ State: {'works': {'w': {'vars': {'counter': 1}}}}
+ State: {'works': {'w': {'vars': {'counter': 2}}}}
+ State: {'works': {'w': {'vars': {'counter': 3}}}}
+ State: {'works': {'w': {'vars': {'counter': 3}}}}
+ State: {'works': {'w': {'vars': {'counter': 4}}}}
+ ...
diff --git a/docs/source-app/workflows/add_components/index.rst b/docs/source-app/workflows/add_components/index.rst
index ca95e44e18..c0656a81a6 100644
--- a/docs/source-app/workflows/add_components/index.rst
+++ b/docs/source-app/workflows/add_components/index.rst
@@ -1,5 +1,3 @@
-:orphan:
-
###########################
Add a component to your app
###########################
@@ -13,7 +11,7 @@ Install a component
Any Lightning component can be installed with:
-.. code:: python
+.. code:: bash
lightning install component org/the-component-name
diff --git a/docs/source-app/workflows/add_server/any_server.rst b/docs/source-app/workflows/add_server/any_server.rst
index 398951276c..bdf09c67ee 100644
--- a/docs/source-app/workflows/add_server/any_server.rst
+++ b/docs/source-app/workflows/add_server/any_server.rst
@@ -21,7 +21,6 @@ Add a server to a component
Any server that listens on a port, can be enabled via a work. For example, here's a plain python server:
.. code:: python
- :emphasize-lines: 11-12
import socketserver
from http import HTTPStatus, server
@@ -31,8 +30,7 @@ Any server that listens on a port, can be enabled via a work. For example, here'
def do_GET(self):
self.send_response(HTTPStatus.OK)
self.end_headers()
- html = " Hello lit world
"
- self.wfile.write(html)
+ self.wfile.write(b" Hello lit world