mirror of
https://github.com/run-llama/workflows-py.git
synced 2026-08-24 20:01:34 -04:00
Adds workflow name to workflow graph (#278)
* feat: add workflow class name to WorkflowGraph representation Add a required `name` field to the WorkflowGraph model that contains the workflow class name. This provides better identification of workflows when viewing their graph representation or JSON output.
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"llama-index-workflows": patch
|
||||
"llama-index-utils-workflow": patch
|
||||
---
|
||||
|
||||
add workflow class name to WorkflowGraph representation
|
||||
@@ -339,7 +339,7 @@ def _extract_single_agent_structure(agent: BaseWorkflowAgent) -> WorkflowGraph:
|
||||
# Add edge from agent to tool
|
||||
edges.append(WorkflowGraphEdge(source="agent", target=tool_id))
|
||||
|
||||
return WorkflowGraph(nodes=nodes, edges=edges)
|
||||
return WorkflowGraph(name=agent.name, nodes=nodes, edges=edges)
|
||||
|
||||
|
||||
def _process_tools_and_handoffs(
|
||||
@@ -428,7 +428,7 @@ def _extract_agent_workflow_structure(
|
||||
agent_nodes = [n for n in nodes if n.node_type == "workflow_agent"]
|
||||
edges.append(WorkflowGraphEdge(source=agent_nodes[-1].id, target="output"))
|
||||
|
||||
return WorkflowGraph(nodes=nodes, edges=edges)
|
||||
return WorkflowGraph(name=type(agent_workflow).__name__, nodes=nodes, edges=edges)
|
||||
|
||||
|
||||
def _extract_execution_graph(
|
||||
|
||||
@@ -248,8 +248,11 @@ def get_workflow_representation(workflow: Workflow) -> WorkflowGraph:
|
||||
)
|
||||
)
|
||||
|
||||
workflow_name = type(workflow).__name__
|
||||
workflow_description = inspect.getdoc(workflow)
|
||||
return WorkflowGraph(nodes=nodes, edges=edges, description=workflow_description)
|
||||
return WorkflowGraph(
|
||||
name=workflow_name, nodes=nodes, edges=edges, description=workflow_description
|
||||
)
|
||||
|
||||
|
||||
__all__ = ["get_workflow_representation"]
|
||||
|
||||
@@ -139,6 +139,7 @@ class WorkflowGraphEdge(BaseModel):
|
||||
class WorkflowGraph(BaseModel):
|
||||
"""Complete workflow graph structure containing all nodes and edges."""
|
||||
|
||||
name: str = Field(description="Name of the workflow class")
|
||||
nodes: list[WorkflowGraphNode] = Field(
|
||||
description="All nodes in the workflow graph"
|
||||
)
|
||||
@@ -233,6 +234,7 @@ class WorkflowGraph(BaseModel):
|
||||
)
|
||||
|
||||
return WorkflowGraph(
|
||||
name=self.name,
|
||||
nodes=remaining_nodes,
|
||||
edges=new_edges,
|
||||
description=self.description,
|
||||
|
||||
@@ -21,6 +21,7 @@ from .conftest import DummyWorkflow # type: ignore[import]
|
||||
@pytest.fixture()
|
||||
def ground_truth_repr() -> WorkflowGraph:
|
||||
return WorkflowGraph(
|
||||
name="DummyWorkflow",
|
||||
nodes=[
|
||||
WorkflowStepNode(
|
||||
id="end_step",
|
||||
@@ -96,6 +97,7 @@ def test_truncated_label() -> None:
|
||||
def test_graph_serialization() -> None:
|
||||
"""Test that WorkflowGraphNodeEdges serializes correctly to JSON."""
|
||||
graph = WorkflowGraph(
|
||||
name="TestWorkflow",
|
||||
nodes=[
|
||||
WorkflowStepNode(id="test", label="test"),
|
||||
WorkflowEventNode(
|
||||
@@ -451,6 +453,7 @@ def test_resource_node_serialization_roundtrip() -> None:
|
||||
def test_graph_with_all_node_types_serialization() -> None:
|
||||
"""Test full graph serialization/deserialization with all node types."""
|
||||
graph = WorkflowGraph(
|
||||
name="TestWorkflow",
|
||||
nodes=[
|
||||
WorkflowStepNode(id="step1", label="Step 1"),
|
||||
WorkflowEventNode(
|
||||
@@ -509,6 +512,7 @@ def test_graph_with_all_node_types_serialization() -> None:
|
||||
def test_graph_deserialization_from_raw_json() -> None:
|
||||
"""Test that graph can be deserialized from raw JSON dict."""
|
||||
raw_data = {
|
||||
"name": "TestWorkflow",
|
||||
"nodes": [
|
||||
{"id": "step1", "label": "Step 1", "node_type": "step"},
|
||||
{
|
||||
@@ -544,6 +548,7 @@ def test_graph_deserialization_from_raw_json() -> None:
|
||||
def test_filter_by_node_type_removes_nodes() -> None:
|
||||
"""Test that filter_by_node_type removes specified node types."""
|
||||
graph = WorkflowGraph(
|
||||
name="TestWorkflow",
|
||||
nodes=[
|
||||
WorkflowStepNode(id="step1", label="Step 1"),
|
||||
WorkflowEventNode(
|
||||
@@ -572,6 +577,7 @@ def test_filter_by_node_type_removes_nodes() -> None:
|
||||
def test_filter_by_node_type_resolves_edges() -> None:
|
||||
"""Test that edges through filtered nodes are resolved."""
|
||||
graph = WorkflowGraph(
|
||||
name="TestWorkflow",
|
||||
nodes=[
|
||||
WorkflowStepNode(id="step1", label="Step 1"),
|
||||
WorkflowEventNode(
|
||||
@@ -599,6 +605,7 @@ def test_filter_by_node_type_resolves_edges() -> None:
|
||||
def test_filter_by_node_type_chain_of_filtered_nodes() -> None:
|
||||
"""Test filtering handles chains of filtered nodes."""
|
||||
graph = WorkflowGraph(
|
||||
name="TestWorkflow",
|
||||
nodes=[
|
||||
WorkflowStepNode(id="step1", label="Step 1"),
|
||||
WorkflowEventNode(
|
||||
@@ -635,6 +642,7 @@ def test_filter_by_node_type_chain_of_filtered_nodes() -> None:
|
||||
def test_filter_by_node_type_multiple_types() -> None:
|
||||
"""Test filtering multiple node types at once."""
|
||||
graph = WorkflowGraph(
|
||||
name="TestWorkflow",
|
||||
nodes=[
|
||||
WorkflowStepNode(id="step1", label="Step 1"),
|
||||
WorkflowEventNode(
|
||||
@@ -667,6 +675,7 @@ def test_filter_by_node_type_multiple_types() -> None:
|
||||
def test_filter_by_node_type_preserves_direct_edges() -> None:
|
||||
"""Test that direct edges between remaining nodes are preserved."""
|
||||
graph = WorkflowGraph(
|
||||
name="TestWorkflow",
|
||||
nodes=[
|
||||
WorkflowStepNode(id="step1", label="Step 1"),
|
||||
WorkflowStepNode(id="step2", label="Step 2"),
|
||||
@@ -694,6 +703,7 @@ def test_filter_by_node_type_preserves_direct_edges() -> None:
|
||||
def test_filter_by_node_type_uses_filtered_node_label() -> None:
|
||||
"""Test that the first filtered node's label becomes the new edge label."""
|
||||
graph = WorkflowGraph(
|
||||
name="TestWorkflow",
|
||||
nodes=[
|
||||
WorkflowStepNode(id="step1", label="Step 1"),
|
||||
WorkflowEventNode(
|
||||
@@ -720,6 +730,7 @@ def test_filter_by_node_type_uses_filtered_node_label() -> None:
|
||||
def test_filter_by_node_type_preserves_direct_edge_labels() -> None:
|
||||
"""Test that labels on direct edges are preserved."""
|
||||
graph = WorkflowGraph(
|
||||
name="TestWorkflow",
|
||||
nodes=[
|
||||
WorkflowStepNode(id="step1", label="Step 1"),
|
||||
WorkflowResourceNode(id="resource1", label="Resource"),
|
||||
@@ -746,6 +757,7 @@ def test_filter_by_node_type_preserves_direct_edge_labels() -> None:
|
||||
def test_filter_by_node_type_no_matching_types() -> None:
|
||||
"""Test filtering with types that don't exist in graph."""
|
||||
graph = WorkflowGraph(
|
||||
name="TestWorkflow",
|
||||
nodes=[
|
||||
WorkflowStepNode(id="step1", label="Step 1"),
|
||||
WorkflowStepNode(id="step2", label="Step 2"),
|
||||
@@ -763,6 +775,7 @@ def test_filter_by_node_type_no_matching_types() -> None:
|
||||
def test_filter_by_node_type_preserves_description() -> None:
|
||||
"""Test that the workflow description is preserved."""
|
||||
graph = WorkflowGraph(
|
||||
name="TestWorkflow",
|
||||
nodes=[WorkflowStepNode(id="step1", label="Step 1")],
|
||||
edges=[],
|
||||
description="My workflow description",
|
||||
@@ -776,6 +789,7 @@ def test_filter_by_node_type_preserves_description() -> None:
|
||||
def test_filter_by_node_type_deduplicates_edges() -> None:
|
||||
"""Test that duplicate edges are not created."""
|
||||
graph = WorkflowGraph(
|
||||
name="TestWorkflow",
|
||||
nodes=[
|
||||
WorkflowStepNode(id="step1", label="Step 1"),
|
||||
WorkflowEventNode(
|
||||
|
||||
@@ -1644,7 +1644,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "llama-index-utils-workflow"
|
||||
version = "0.6.0"
|
||||
version = "0.7.0"
|
||||
source = { editable = "packages/llama-index-utils-workflow" }
|
||||
dependencies = [
|
||||
{ name = "llama-index-core" },
|
||||
@@ -1677,7 +1677,7 @@ dev = [
|
||||
|
||||
[[package]]
|
||||
name = "llama-index-workflows"
|
||||
version = "2.11.7"
|
||||
version = "2.12.0"
|
||||
source = { editable = "packages/llama-index-workflows" }
|
||||
dependencies = [
|
||||
{ name = "eval-type-backport", marker = "python_full_version < '3.10'" },
|
||||
|
||||
Reference in New Issue
Block a user