core: generate mermaid syntax and render visual graph (#19599)

- **Description:** Add functionality to generate Mermaid syntax and
render flowcharts from graph data. This includes support for custom node
colors and edge curve styles, as well as the ability to export the
generated graphs to PNG images using either the Mermaid.INK API or
Pyppeteer for local rendering.
- **Dependencies:** Optional dependencies are `pyppeteer` if rendering
wants to be done using Pypeteer and Javascript code.

---------

Co-authored-by: Angel Igareta <angel.igareta@klarna.com>
Co-authored-by: Bagatur <22008038+baskaryan@users.noreply.github.com>
This commit is contained in:
Ángel Igareta
2024-04-01 17:14:46 +02:00
committed by GitHub
parent 8711a05a51
commit c2ccf22dfd
4 changed files with 465 additions and 6 deletions

View File

@@ -1,5 +1,5 @@
# serializer version: 1
# name: test_graph_sequence
# name: test_graph_sequence[ascii]
'''
+-------------+
| PromptInput |
@@ -30,7 +30,26 @@
+--------------------------------------+
'''
# ---
# name: test_graph_sequence_map
# name: test_graph_sequence[mermaid]
'''
%%{init: {'flowchart': {'curve': 'linear'}}}%%
graph TD;
PromptInput[PromptInput]:::startclass;
PromptTemplate([PromptTemplate]):::otherclass;
FakeListLLM([FakeListLLM]):::otherclass;
CommaSeparatedListOutputParser([CommaSeparatedListOutputParser]):::otherclass;
CommaSeparatedListOutputParserOutput[CommaSeparatedListOutputParserOutput]:::endclass;
PromptInput --> PromptTemplate;
PromptTemplate --> FakeListLLM;
CommaSeparatedListOutputParser --> CommaSeparatedListOutputParserOutput;
FakeListLLM --> CommaSeparatedListOutputParser;
classDef startclass fill:#ffdfba;
classDef endclass fill:#baffc9;
classDef otherclass fill:#fad7de;
'''
# ---
# name: test_graph_sequence_map[ascii]
'''
+-------------+
| PromptInput |
@@ -79,7 +98,38 @@
+--------------------------------+
'''
# ---
# name: test_graph_single_runnable
# name: test_graph_sequence_map[mermaid]
'''
%%{init: {'flowchart': {'curve': 'linear'}}}%%
graph TD;
PromptInput[PromptInput]:::startclass;
PromptTemplate([PromptTemplate]):::otherclass;
FakeListLLM([FakeListLLM]):::otherclass;
Parallel_as_list_as_str_Input([Parallel_as_list_as_str_Input]):::otherclass;
Parallel_as_list_as_str_Output[Parallel_as_list_as_str_Output]:::endclass;
CommaSeparatedListOutputParser([CommaSeparatedListOutputParser]):::otherclass;
conditional_str_parser_input([conditional_str_parser_input]):::otherclass;
conditional_str_parser_output([conditional_str_parser_output]):::otherclass;
StrOutputParser([StrOutputParser]):::otherclass;
XMLOutputParser([XMLOutputParser]):::otherclass;
PromptInput --> PromptTemplate;
PromptTemplate --> FakeListLLM;
Parallel_as_list_as_str_Input --> CommaSeparatedListOutputParser;
CommaSeparatedListOutputParser --> Parallel_as_list_as_str_Output;
conditional_str_parser_input --> StrOutputParser;
StrOutputParser --> conditional_str_parser_output;
conditional_str_parser_input --> XMLOutputParser;
XMLOutputParser --> conditional_str_parser_output;
Parallel_as_list_as_str_Input --> conditional_str_parser_input;
conditional_str_parser_output --> Parallel_as_list_as_str_Output;
FakeListLLM --> Parallel_as_list_as_str_Input;
classDef startclass fill:#ffdfba;
classDef endclass fill:#baffc9;
classDef otherclass fill:#fad7de;
'''
# ---
# name: test_graph_single_runnable[ascii]
'''
+----------------------+
| StrOutputParserInput |
@@ -98,3 +148,18 @@
+-----------------------+
'''
# ---
# name: test_graph_single_runnable[mermaid]
'''
%%{init: {'flowchart': {'curve': 'linear'}}}%%
graph TD;
StrOutputParserInput[StrOutputParserInput]:::startclass;
StrOutputParser([StrOutputParser]):::otherclass;
StrOutputParserOutput[StrOutputParserOutput]:::endclass;
StrOutputParserInput --> StrOutputParser;
StrOutputParser --> StrOutputParserOutput;
classDef startclass fill:#ffdfba;
classDef endclass fill:#baffc9;
classDef otherclass fill:#fad7de;
'''
# ---

View File

@@ -21,7 +21,8 @@ def test_graph_single_runnable(snapshot: SnapshotAssertion) -> None:
assert len(graph.edges) == 2
assert graph.edges[0].source == first_node.id
assert graph.edges[1].target == last_node.id
assert graph.draw_ascii() == snapshot
assert graph.draw_ascii() == snapshot(name="ascii")
assert graph.draw_mermaid() == snapshot(name="mermaid")
def test_graph_sequence(snapshot: SnapshotAssertion) -> None:
@@ -88,7 +89,8 @@ def test_graph_sequence(snapshot: SnapshotAssertion) -> None:
{"source": 2, "target": 3},
],
}
assert graph.draw_ascii() == snapshot
assert graph.draw_ascii() == snapshot(name="ascii")
assert graph.draw_mermaid() == snapshot(name="mermaid")
def test_graph_sequence_map(snapshot: SnapshotAssertion) -> None:
@@ -482,4 +484,5 @@ def test_graph_sequence_map(snapshot: SnapshotAssertion) -> None:
{"source": 2, "target": 3},
],
}
assert graph.draw_ascii() == snapshot
assert graph.draw_ascii() == snapshot(name="ascii")
assert graph.draw_mermaid() == snapshot(name="mermaid")