refactor: clean up visualization functions by removing unused nodes and improving type hints

This commit is contained in:
Martín Bravo 2025-03-24 09:47:21 +01:00
parent a5b7abe8b4
commit 623063b633
2 changed files with 10 additions and 26 deletions

View file

@ -1,3 +1,5 @@
from typing import Optional
import graphviz import graphviz
from agents import Agent from agents import Agent
@ -20,8 +22,6 @@ def get_main_graph(agent: Agent) -> str:
graph [splines=true]; graph [splines=true];
node [fontname="Arial"]; node [fontname="Arial"];
edge [penwidth=1.5]; edge [penwidth=1.5];
"__start__" [shape=ellipse, style=filled, fillcolor=lightblue];
"__end__" [shape=ellipse, style=filled, fillcolor=lightblue];
""" """
] ]
parts.append(get_all_nodes(agent)) parts.append(get_all_nodes(agent))
@ -30,8 +30,6 @@ def get_main_graph(agent: Agent) -> str:
return "".join(parts) return "".join(parts)
from typing import Optional
def get_all_nodes(agent: Agent, parent: Optional[Agent] = None) -> str: def get_all_nodes(agent: Agent, parent: Optional[Agent] = None) -> str:
""" """
Recursively generates the nodes for the given agent and its handoffs in DOT format. Recursively generates the nodes for the given agent and its handoffs in DOT format.
@ -59,12 +57,14 @@ def get_all_nodes(agent: Agent, parent: Optional[Agent] = None) -> str:
for handoff in agent.handoffs: for handoff in agent.handoffs:
if isinstance(handoff, Handoff): if isinstance(handoff, Handoff):
parts.append( parts.append(
f'"{handoff.agent_name}" [label="{handoff.agent_name}", shape=box, style=filled, style=rounded, ' f'"{handoff.agent_name}" [label="{handoff.agent_name}", shape=box, '
f"shape=box, style=filled, style=rounded, "
f"fillcolor=lightyellow, width=1.5, height=0.8];" f"fillcolor=lightyellow, width=1.5, height=0.8];"
) )
if isinstance(handoff, Agent): if isinstance(handoff, Agent):
parts.append( parts.append(
f'"{handoff.name}" [label="{handoff.name}", shape=box, style=filled, style=rounded, ' f'"{handoff.name}" [label="{handoff.name}", '
f"shape=box, style=filled, style=rounded, "
f"fillcolor=lightyellow, width=1.5, height=0.8];" f"fillcolor=lightyellow, width=1.5, height=0.8];"
) )
parts.append(get_all_nodes(handoff)) parts.append(get_all_nodes(handoff))
@ -85,19 +85,11 @@ def get_all_edges(agent: Agent, parent: Optional[Agent] = None) -> str:
""" """
parts = [] parts = []
if not parent:
parts.append(f"""
"__start__" -> "{agent.name}";""")
for tool in agent.tools: for tool in agent.tools:
parts.append(f""" parts.append(f"""
"{agent.name}" -> "{tool.name}" [style=dotted, penwidth=1.5]; "{agent.name}" -> "{tool.name}" [style=dotted, penwidth=1.5];
"{tool.name}" -> "{agent.name}" [style=dotted, penwidth=1.5];""") "{tool.name}" -> "{agent.name}" [style=dotted, penwidth=1.5];""")
if not agent.handoffs:
parts.append(f"""
"{agent.name}" -> "__end__";""")
for handoff in agent.handoffs: for handoff in agent.handoffs:
if isinstance(handoff, Handoff): if isinstance(handoff, Handoff):
parts.append(f""" parts.append(f"""
@ -110,8 +102,6 @@ def get_all_edges(agent: Agent, parent: Optional[Agent] = None) -> str:
return "".join(parts) return "".join(parts)
from typing import Optional
def draw_graph(agent: Agent, filename: Optional[str] = None) -> graphviz.Source: def draw_graph(agent: Agent, filename: Optional[str] = None) -> graphviz.Source:
""" """
Draws the graph for the given agent and optionally saves it as a PNG file. Draws the graph for the given agent and optionally saves it as a PNG file.

View file

@ -10,6 +10,7 @@ from agents.extensions.visualization import (
get_all_nodes, get_all_nodes,
get_main_graph, get_main_graph,
) )
from agents.handoffs import Handoff
@pytest.fixture @pytest.fixture
@ -19,10 +20,8 @@ def mock_agent():
tool2 = Mock() tool2 = Mock()
tool2.name = "Tool2" tool2.name = "Tool2"
handoff1 = Mock() handoff1 = Mock(spec=Handoff)
handoff1.name = "Handoff1" handoff1.agent_name = "Handoff1"
handoff1.tools = []
handoff1.handoffs = []
agent = Mock(spec=Agent) agent = Mock(spec=Agent)
agent.name = "Agent1" agent.name = "Agent1"
@ -34,12 +33,11 @@ def mock_agent():
def test_get_main_graph(mock_agent): def test_get_main_graph(mock_agent):
result = get_main_graph(mock_agent) result = get_main_graph(mock_agent)
print(result)
assert "digraph G" in result assert "digraph G" in result
assert "graph [splines=true];" in result assert "graph [splines=true];" in result
assert 'node [fontname="Arial"];' in result assert 'node [fontname="Arial"];' in result
assert "edge [penwidth=1.5];" in result assert "edge [penwidth=1.5];" in result
assert '"__start__" [shape=ellipse, style=filled, fillcolor=lightblue];' in result
assert '"__end__" [shape=ellipse, style=filled, fillcolor=lightblue];' in result
assert ( assert (
'"Agent1" [label="Agent1", shape=box, style=filled, ' '"Agent1" [label="Agent1", shape=box, style=filled, '
"fillcolor=lightyellow, width=1.5, height=0.8];" in result "fillcolor=lightyellow, width=1.5, height=0.8];" in result
@ -80,13 +78,11 @@ def test_get_all_nodes(mock_agent):
def test_get_all_edges(mock_agent): def test_get_all_edges(mock_agent):
result = get_all_edges(mock_agent) result = get_all_edges(mock_agent)
assert '"__start__" -> "Agent1";' in result
assert '"Agent1" -> "Tool1" [style=dotted, penwidth=1.5];' in result assert '"Agent1" -> "Tool1" [style=dotted, penwidth=1.5];' in result
assert '"Tool1" -> "Agent1" [style=dotted, penwidth=1.5];' in result assert '"Tool1" -> "Agent1" [style=dotted, penwidth=1.5];' in result
assert '"Agent1" -> "Tool2" [style=dotted, penwidth=1.5];' in result assert '"Agent1" -> "Tool2" [style=dotted, penwidth=1.5];' in result
assert '"Tool2" -> "Agent1" [style=dotted, penwidth=1.5];' in result assert '"Tool2" -> "Agent1" [style=dotted, penwidth=1.5];' in result
assert '"Agent1" -> "Handoff1";' in result assert '"Agent1" -> "Handoff1";' in result
assert '"Handoff1" -> "__end__";' in result
def test_draw_graph(mock_agent): def test_draw_graph(mock_agent):
@ -96,8 +92,6 @@ def test_draw_graph(mock_agent):
assert "graph [splines=true];" in graph.source assert "graph [splines=true];" in graph.source
assert 'node [fontname="Arial"];' in graph.source assert 'node [fontname="Arial"];' in graph.source
assert "edge [penwidth=1.5];" in graph.source assert "edge [penwidth=1.5];" in graph.source
assert '"__start__" [shape=ellipse, style=filled, fillcolor=lightblue];' in graph.source
assert '"__end__" [shape=ellipse, style=filled, fillcolor=lightblue];' in graph.source
assert ( assert (
'"Agent1" [label="Agent1", shape=box, style=filled, ' '"Agent1" [label="Agent1", shape=box, style=filled, '
"fillcolor=lightyellow, width=1.5, height=0.8];" in graph.source "fillcolor=lightyellow, width=1.5, height=0.8];" in graph.source