From aa965ba0a92a02dcb2431f958933a5e4be6e94dd Mon Sep 17 00:00:00 2001 From: Jiao Date: Mon, 6 Jun 2022 11:05:58 -0700 Subject: [PATCH] [Deployment Graph] Add visualization cookbook (#25112) --- ci/env/install-dependencies.sh | 7 ++++ doc/source/_toc.yml | 1 + doc/source/serve/deployment-graph.md | 2 +- .../visualize_dag_during_development.md | 33 +++++++++++++++++ ...loyment_graph_same_class_different_args.py | 2 +- .../visualize_dag_during_deployment.py | 37 +++++++++++++++++++ 6 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 doc/source/serve/deployment-graph/visualize_dag_during_development.md create mode 100644 doc/source/serve/doc_code/visualize_dag_during_deployment.py diff --git a/ci/env/install-dependencies.sh b/ci/env/install-dependencies.sh index 8e6c6a640..2b1dfe92f 100755 --- a/ci/env/install-dependencies.sh +++ b/ci/env/install-dependencies.sh @@ -350,6 +350,13 @@ install_dependencies() { fi fi + # Additional default doc testing dependencies. + if [ "${DOC_TESTING-}" = 1 ]; then + # For Ray Core and Ray Serve DAG visualization docs test + sudo apt-get install -y graphviz + pip install -U pydot # For DAG visualization + fi + # Additional RLlib test dependencies. if [ "${RLLIB_TESTING-}" = 1 ] || [ "${DOC_TESTING-}" = 1 ]; then pip install -r "${WORKSPACE_DIR}"/python/requirements/ml/requirements_rllib.txt diff --git a/doc/source/_toc.yml b/doc/source/_toc.yml index d7572d1a9..c0f615695 100644 --- a/doc/source/_toc.yml +++ b/doc/source/_toc.yml @@ -139,6 +139,7 @@ parts: - file: serve/deployment-graph/chain_nodes_same_class_different_args - file: serve/deployment-graph/combine_two_nodes_with_passing_input_parallel - file: serve/deployment-graph/control_flow_based_on_user_inputs + - file: serve/deployment-graph/visualize_dag_during_development - file: serve/deployment-graph/http_endpoint_for_dag_graph - file: serve/architecture - file: serve/tutorials/index diff --git a/doc/source/serve/deployment-graph.md b/doc/source/serve/deployment-graph.md index 5fb14cfa5..803aa3100 100644 --- a/doc/source/serve/deployment-graph.md +++ b/doc/source/serve/deployment-graph.md @@ -13,5 +13,5 @@ Jump striaght into a common design patterns using deployment graph: - [Chain nodes with same class and different args](deployment-graph/chain_nodes_same_class_different_args.md) - [Combine two nodes with passing same input in parallel](deployment-graph/combine_two_nodes_with_passing_input_parallel.md) - [Control flow based on user inputs](deployment-graph/control_flow_based_on_user_inputs.md) +- [Visualize DAG during development](deployment-graph/visualize_dag_during_development.md) - [Http endpoint for dag graph](deployment-graph/http_endpoint_for_dag_graph.md) - diff --git a/doc/source/serve/deployment-graph/visualize_dag_during_development.md b/doc/source/serve/deployment-graph/visualize_dag_during_development.md new file mode 100644 index 000000000..ebc0369df --- /dev/null +++ b/doc/source/serve/deployment-graph/visualize_dag_during_development.md @@ -0,0 +1,33 @@ +# Pattern: Visualize DAG during development + +The example shows how to iteratively develop and visualize your deployment graph. For a runnable DAG, we will show both full and partial DAG depending on your choice of root node. + +Please ensure do install dependencies in order to generate visualizations `sudo apt-get install -y graphviz` and `pip install -U pydot`. + +## Code + ++++ + +```{eval-rst} +.. literalinclude:: ../doc_code/visualize_dag_during_deployment.py + :language: python +``` + +## Outputs + +```{note} +The node of user choice will become the root of the graph for both execution as well as visualization, where non-reachable nodes from root will be ignored regardless if they appeared in user code. +``` +In the development phase, when we picked `m1_output` as the root, we can see a visualization of the underlying execution path that's partial of the entire graph. + +![pic](https://raw.githubusercontent.com/ray-project/images/master/docs/serve/deployment-graph/visualize_partial.svg) + +Similarly, when we choose the final dag output, we will capture all nodes used in execution as they're reachable from the root. + +![pic](https://raw.githubusercontent.com/ray-project/images/master/docs/serve/deployment-graph/visualize_full.svg) + +```{tip} +If you run the code above within Jupyter notebook, we will automatically display it within cell. Otherwise you can either print the dot file as string and render it in graphviz tools such as https://dreampuf.github.io/GraphvizOnline, or save it as .dot file on disk with your choice of path. +``` + ++++ \ No newline at end of file diff --git a/doc/source/serve/doc_code/deployment_graph_same_class_different_args.py b/doc/source/serve/doc_code/deployment_graph_same_class_different_args.py index a94cdb82f..b3f1d0b50 100644 --- a/doc/source/serve/doc_code/deployment_graph_same_class_different_args.py +++ b/doc/source/serve/doc_code/deployment_graph_same_class_different_args.py @@ -1,6 +1,6 @@ import ray from ray import serve -from ray.experimental.dag.input_node import InputNode +from ray.serve.deployment_graph import InputNode ray.init() diff --git a/doc/source/serve/doc_code/visualize_dag_during_deployment.py b/doc/source/serve/doc_code/visualize_dag_during_deployment.py new file mode 100644 index 000000000..626e19594 --- /dev/null +++ b/doc/source/serve/doc_code/visualize_dag_during_deployment.py @@ -0,0 +1,37 @@ +import ray +from ray import serve +from ray.serve.deployment_graph import InputNode + +ray.init() + + +@serve.deployment +class Model: + def __init__(self, weight): + self.weight = weight + + def forward(self, input): + return input + self.weight + + +@serve.deployment +def combine(output_1, output_2, kwargs_output=0): + return output_1 + output_2 + kwargs_output + + +with InputNode() as user_input: + m1 = Model.bind(1) + m2 = Model.bind(2) + m1_output = m1.forward.bind(user_input[0]) + m2_output = m2.forward.bind(user_input[1]) + dag = combine.bind(m1_output, m2_output, kwargs_output=user_input[2]) + +# Partial DAG visualization +graph = ray.experimental.dag.vis_utils.dag_to_dot(m1_output) +to_string = graph.to_string() +print(to_string) + +# Entire DAG visualization +graph = ray.experimental.dag.vis_utils.dag_to_dot(dag) +to_string = graph.to_string() +print(to_string)