Skip to content

Commit c017521

Browse files
authored
Pipeline viz (#122)
* Save input configs in the Pipeline class while validating, and reuse this dict when fetching the component inputs * Split the parameter connection validation and the user input validation to prepare for drawing pipelines (without user inputs) * WIP: pipeline visualization * Invalidate the pipeline param mapping if the graph structure changes * Hide unused outputs by default but add option to display them * Install graphviz during CI * Install graphviz-dev in CI to fix installation error * Update changelog and doc * Add a few tests for data validation * Fix error message * This is a change of behavior that will be implemented in a separate PR * Add UT for pipeline to pygraphviz format and pipeline draw method * Fix docstring * Improve naming and docstrings * Update CHANGELOG.md
1 parent b65b34f commit c017521

File tree

13 files changed

+1103
-783
lines changed

13 files changed

+1103
-783
lines changed

.github/workflows/pr-e2e-tests.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ jobs:
4747
- 7474:7474
4848

4949
steps:
50+
- name: Install graphviz package
51+
run: sudo apt install graphviz graphviz-dev
5052
- name: Check out repository code
5153
uses: actions/checkout@v4
5254
- name: Docker Prune

.github/workflows/pr.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ jobs:
88
matrix:
99
python-version: [ '3.8', '3.9', '3.10', '3.11', '3.12' ]
1010
steps:
11+
- name: Install graphviz package
12+
run: sudo apt install graphviz graphviz-dev
1113
- name: Check out repository code
1214
uses: actions/checkout@v4
1315
- name: Set up Python ${{ matrix.python-version }}

.github/workflows/scheduled-e2e-tests.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ jobs:
5454
password: ${{ secrets.DOCKERHUB_TOKEN }}
5555

5656
steps:
57+
- name: Install graphviz package
58+
run: sudo apt install graphviz graphviz-dev
5759
- name: Check out repository code
5860
uses: actions/checkout@v4
5961
- name: Docker Prune

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,16 @@
22

33
## Next
44

5-
## Fixed
5+
### Added
6+
- Ability to visualise pipeline with `my_pipeline.draw("pipeline.png")`
7+
8+
### Fixed
69
- Pipelines now return correct results when the same pipeline is run in parallel.
710

11+
### Changed
12+
- Pipeline run method now return a PipelineResult object.
13+
14+
815
## 0.5.0
916

1017
### Added

docs/source/images/pipeline_full.png

55.4 KB
Loading
Loading

docs/source/user_guide_pipeline.rst

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,38 @@ The data flow is illustrated in the diagram below:
9696
asyncio.run(pipe.run({"a": {"number1": 10, "number2": 1}, "b": {"number1": 4, "number2": 42}}))
9797
9898
The result will still be **15** because the user input `"number2": 42` is ignored.
99+
100+
101+
**********************
102+
Visualising a Pipeline
103+
**********************
104+
105+
Pipelines can be visualized using the `draw` method:
106+
107+
.. code:: python
108+
109+
import asyncio
110+
from neo4j_genai.experimental.pipeline import Pipeline
111+
112+
pipe = Pipeline()
113+
# ... define components and connections
114+
115+
pipe.draw("pipeline.png")
116+
117+
Here is an example pipeline rendering:
118+
119+
.. image:: images/pipeline_no_unused_outputs.png
120+
:alt: Pipeline visualisation with hidden outputs if unused
121+
122+
123+
By default, output fields which are not mapped to any component are hidden. They
124+
can be added to the canvas by setting `hide_unused_outputs` to `False`:
125+
126+
.. code:: python
127+
128+
pipe.draw("pipeline.png", hide_unused_outputs=False)
129+
130+
Here is an example of final result:
131+
132+
.. image:: images/pipeline_full.png
133+
:alt: Pipeline visualisation

examples/pipeline/visualization.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Copyright (c) "Neo4j"
2+
# Neo4j Sweden AB [https://neo4j.com]
3+
# #
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
# #
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
# #
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
"""This example illustrates how to visualize a Pipeline"""
16+
17+
from neo4j_genai.experimental.pipeline import Component, Pipeline
18+
from neo4j_genai.experimental.pipeline.component import DataModel
19+
from pydantic import validate_call
20+
21+
22+
class IntDataModel(DataModel):
23+
value: int
24+
message: str
25+
26+
27+
class Addition(Component):
28+
async def run(self, a: int, b: int) -> IntDataModel:
29+
return IntDataModel(value=a + b, message="addition complete")
30+
31+
32+
class Duplicate(Component):
33+
def __init__(self, factor: int = 2) -> None:
34+
self.factor = factor
35+
36+
async def run(self, number: int) -> IntDataModel:
37+
return IntDataModel(
38+
value=number * self.factor, message=f"multiplication by {self.factor} done"
39+
)
40+
41+
42+
class Save(Component):
43+
@validate_call
44+
async def run(self, number: IntDataModel) -> IntDataModel:
45+
return IntDataModel(value=number.value, message="saved")
46+
47+
48+
if __name__ == "__main__":
49+
pipe = Pipeline()
50+
pipe.add_component(Duplicate(), "times_two")
51+
pipe.add_component(Duplicate(factor=10), "times_ten")
52+
pipe.add_component(Addition(), "addition")
53+
pipe.add_component(Save(), "save")
54+
pipe.connect("times_two", "addition", {"a": "times_two.value"})
55+
pipe.connect("times_ten", "addition", {"b": "times_ten.value"})
56+
pipe.connect("addition", "save", {"number": "addition"})
57+
pipe.draw("graph.png")
58+
pipe.draw("graph_full.png", hide_unused_outputs=False)

poetry.lock

Lines changed: 745 additions & 684 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ pinecone-client = {version = "^4.1.0", optional = true}
3737
types-mock = "^5.1.0.20240425"
3838
eval-type-backport = "^0.2.0"
3939
pypdf = "^4.3.1"
40+
pygraphviz = [
41+
{version = "^1.13.0", python = ">=3.10,<4.0.0"},
42+
{version = "^1.0.0", python = "<3.10"}
43+
]
4044

4145
[tool.poetry.group.dev.dependencies]
4246
pylint = "^3.1.0"

0 commit comments

Comments
 (0)