Source code for langchain_core.runnables.graph_png

from typing import Any, Optional

from langchain_core.runnables.graph import Graph, LabelsDict


[docs]class PngDrawer: """辅助类,用于将状态图绘制到PNG文件中。 需要安装graphviz和pygraphviz。 :param fontname: 用于标签的字体 :param labels: 标签覆盖的字典。该字典应具有以下格式: { "nodes": { "node1": "CustomLabel1", "node2": "CustomLabel2", "__end__": "End Node" }, "edges": { "continue": "ContinueLabel", "end": "EndLabel" } } 键是原始标签,值是新标签。 用法: drawer = PngDrawer() drawer.draw(state_graph, 'graph.png') """
[docs] def __init__( self, fontname: Optional[str] = None, labels: Optional[LabelsDict] = None ) -> None: """初始化PNG绘图器。 参数: fontname:用于标签的字体 labels:标签覆盖的字典。该字典应具有以下格式: { "nodes": { "node1": "CustomLabel1", "node2": "CustomLabel2", "__end__": "End Node" }, "edges": { "continue": "ContinueLabel", "end": "EndLabel" } } 键是原始标签,值是新标签。 """ self.fontname = fontname or "arial" self.labels = labels or LabelsDict(nodes={}, edges={})
[docs] def get_node_label(self, label: str) -> str: """返回用于节点的标签。 参数: label:原始标签 返回: 新标签。 """ label = self.labels.get("nodes", {}).get(label, label) return f"<<B>{label}</B>>"
[docs] def get_edge_label(self, label: str) -> str: """返回用于边的标签。 参数: label:原始标签 返回: 新标签。 """ label = self.labels.get("edges", {}).get(label, label) return f"<<U>{label}</U>>"
[docs] def add_node(self, viz: Any, node: str) -> None: """将一个节点添加到图中。 参数: viz: graphviz对象 node: 要添加的节点 返回: """ viz.add_node( node, label=self.get_node_label(node), style="filled", fillcolor="yellow", fontsize=15, fontname=self.fontname, )
[docs] def add_edge( self, viz: Any, source: str, target: str, label: Optional[str] = None, conditional: bool = False, ) -> None: """将边添加到图中。 参数: viz:graphviz对象 source:源节点 target:目标节点 label:边的标签。默认为None。 conditional:边是否是有条件的。默认为False。 返回: None """ viz.add_edge( source, target, label=self.get_edge_label(label) if label else "", fontsize=12, fontname=self.fontname, style="dotted" if conditional else "solid", )
[docs] def draw(self, graph: Graph, output_path: Optional[str] = None) -> Optional[bytes]: """将给定的状态图绘制成一个PNG文件。 需要安装graphviz和pygraphviz。 :param graph: 要绘制的图 :param output_path: 保存PNG文件的路径。如果为None,则返回PNG字节。 """ try: import pygraphviz as pgv # type: ignore[import] except ImportError as exc: raise ImportError( "Install pygraphviz to draw graphs: `pip install pygraphviz`." ) from exc # Create a directed graph viz = pgv.AGraph(directed=True, nodesep=0.9, ranksep=1.0) # Add nodes, conditional edges, and edges to the graph self.add_nodes(viz, graph) self.add_edges(viz, graph) # Update entrypoint and END styles self.update_styles(viz, graph) # Save the graph as PNG try: return viz.draw(output_path, format="png", prog="dot") finally: viz.close()
[docs] def add_nodes(self, viz: Any, graph: Graph) -> None: for node in graph.nodes: self.add_node(viz, node)
[docs] def add_edges(self, viz: Any, graph: Graph) -> None: for start, end, label, cond in graph.edges: self.add_edge(viz, start, end, label, cond)
[docs] def update_styles(self, viz: Any, graph: Graph) -> None: if first := graph.first_node(): viz.get_node(first.id).attr.update(fillcolor="lightblue") if last := graph.last_node(): viz.get_node(last.id).attr.update(fillcolor="orange")