Refactor EventListener logging and visualization with improved tool usage tracking

This commit is contained in:
Lorenze Jay
2025-03-11 11:37:05 -07:00
parent 51599cc36e
commit e077ffcbbe

View File

@@ -61,6 +61,7 @@ class EventListener(BaseEventListener):
current_tool_branch = None current_tool_branch = None
current_flow_tree = None current_flow_tree = None
current_method_branch = None current_method_branch = None
tool_usage_counts = {}
def __new__(cls): def __new__(cls):
if cls._instance is None: if cls._instance is None:
@@ -76,6 +77,7 @@ class EventListener(BaseEventListener):
self.execution_spans = {} self.execution_spans = {}
self._initialized = True self._initialized = True
self.console = Console(width=None) self.console = Console(width=None)
self.tool_usage_counts = {}
def _format_timestamp(self, timestamp: float) -> str: def _format_timestamp(self, timestamp: float) -> str:
return datetime.fromtimestamp(timestamp).strftime("%H:%M:%S") return datetime.fromtimestamp(timestamp).strftime("%H:%M:%S")
@@ -258,11 +260,9 @@ class EventListener(BaseEventListener):
if self.verbose: if self.verbose:
task_content = Text() task_content = Text()
task_content.append("📋 Task: ", style="yellow bold") task_content.append(f"📋 Task: {source.id}", style="yellow bold")
task_content.append("\n Assigned to: ", style="white")
task_content.append(source.agent.role, style="green")
task_content.append("\n Status: ", style="white") task_content.append("\n Status: ", style="white")
task_content.append("Waiting for agent...", style="yellow dim") task_content.append("Executing Task...", style="yellow dim")
# Add task to the crew tree # Add task to the crew tree
if self.current_crew_tree: if self.current_crew_tree:
@@ -283,26 +283,26 @@ class EventListener(BaseEventListener):
self.execution_spans[source] = None self.execution_spans[source] = None
if self.verbose: if self.verbose:
completion_content = Text()
completion_content.append("✅ Task Completed\n", style="green bold")
completion_content.append(f"Task: {str(source.id)}", style="white")
completion_content.append("\nAgent: ", style="white")
completion_content.append(source.agent.role, style="green")
# Update the tree if it exists
if self.current_crew_tree: if self.current_crew_tree:
for branch in self.current_crew_tree.children: for branch in self.current_crew_tree.children:
if source.description in branch.label: if str(source.id) in str(branch.label):
branch.label = ( task_content = Text()
Text(" ", style="green bold") + branch.label task_content.append("📋 Task: ", style="green bold")
) task_content.append("\n Assigned to: ", style="white")
task_content.append(source.agent.role, style="green")
task_content.append("\n Status: ", style="white")
task_content.append("✅ Completed", style="green bold")
branch.label = task_content
self.console.print(self.current_crew_tree) self.console.print(self.current_crew_tree)
break break
completion_content = self._create_status_content(
"Task Completed", str(source.id), "green", Agent=source.agent.role
)
panel = self._create_panel( panel = self._create_panel(
completion_content, "Task Completion", "green" completion_content, "Task Completion", "green"
) )
self.console.print(panel) self.console.print(panel)
self.console.print() self.console.print()
@@ -377,168 +377,172 @@ class EventListener(BaseEventListener):
def on_flow_created(source, event: FlowCreatedEvent): def on_flow_created(source, event: FlowCreatedEvent):
self._telemetry.flow_creation_span(event.flow_name) self._telemetry.flow_creation_span(event.flow_name)
if self.verbose: content = self._create_status_content(
content = self._create_status_content( "Starting Flow Execution", event.flow_name, "blue"
"Starting Flow Execution", event.flow_name, "blue" )
)
panel = self._create_panel(content, "Flow Execution", "blue") panel = self._create_panel(content, "Flow Execution", "blue")
self.console.print() self.console.print()
self.console.print(panel) self.console.print(panel)
self.console.print() self.console.print()
# Create and display the initial tree # Create and display the initial tree
flow_label = Text() flow_label = Text()
flow_label.append("🌊 Flow: ", style="blue bold") flow_label.append("🌊 Flow: ", style="blue bold")
flow_label.append(event.flow_name, style="blue") flow_label.append(event.flow_name, style="blue")
self.current_flow_tree = Tree(flow_label) self.current_flow_tree = Tree(flow_label)
# Add both creation steps to show progression # Add both creation steps to show progression
self.current_flow_tree.add(Text("✨ Created", style="blue")) self.current_flow_tree.add(Text("✨ Created", style="blue"))
self.current_flow_tree.add( self.current_flow_tree.add(
Text("✅ Initialization Complete", style="green") Text("✅ Initialization Complete", style="green")
) )
self.console.print(self.current_flow_tree) self.console.print(self.current_flow_tree)
self.console.print() self.console.print()
@crewai_event_bus.on(FlowStartedEvent) @crewai_event_bus.on(FlowStartedEvent)
def on_flow_started(source, event: FlowStartedEvent): def on_flow_started(source, event: FlowStartedEvent):
self._telemetry.flow_execution_span( self._telemetry.flow_execution_span(
event.flow_name, list(source._methods.keys()) event.flow_name, list(source._methods.keys())
) )
self.current_flow_tree = Tree("")
self._update_tree_label(
self.current_flow_tree,
"🌊 Flow:",
event.flow_name,
"blue",
"In Progress",
)
if self.verbose: # Add initial thinking state
self.current_flow_tree = Tree("") self.current_flow_tree.add(Text("🧠 Initializing...", style="yellow"))
self._update_tree_label(
self.current_flow_tree,
"🌊 Flow:",
event.flow_name,
"blue",
"In Progress",
)
# Add initial thinking state self.console.print()
self.current_flow_tree.add(Text("🧠 Initializing...", style="yellow")) self.console.print(self.current_flow_tree)
self.console.print()
self.console.print()
self.console.print(self.current_flow_tree)
self.console.print()
@crewai_event_bus.on(FlowFinishedEvent) @crewai_event_bus.on(FlowFinishedEvent)
def on_flow_finished(source, event: FlowFinishedEvent): def on_flow_finished(source, event: FlowFinishedEvent):
if self.verbose: if self.current_flow_tree:
if self.current_flow_tree: self._update_tree_label(
self._update_tree_label( self.current_flow_tree,
self.current_flow_tree, "✅ Flow Finished:",
"✅ Flow Finished:", event.flow_name,
event.flow_name, "green",
"green", )
)
content = self._create_status_content( content = self._create_status_content(
"Flow Execution Completed", "Flow Execution Completed",
event.flow_name, event.flow_name,
"green", "green",
ID=source.flow_id, ID=source.flow_id,
) )
panel = self._create_panel(content, "Flow Completion", "green") panel = self._create_panel(content, "Flow Completion", "green")
self.console.print(panel) self.console.print(panel)
self.console.print() self.console.print()
@crewai_event_bus.on(MethodExecutionStartedEvent) @crewai_event_bus.on(MethodExecutionStartedEvent)
def on_method_execution_started(source, event: MethodExecutionStartedEvent): def on_method_execution_started(source, event: MethodExecutionStartedEvent):
if self.verbose: if self.current_flow_tree:
if self.current_flow_tree: # Find and update the method branch
# Find and update the method branch for branch in self.current_flow_tree.children:
for branch in self.current_flow_tree.children: if event.method_name in branch.label:
if event.method_name in branch.label: self.current_method_branch = branch
self.current_method_branch = branch branch.label = Text("🔄 Running: ", style="yellow bold") + Text(
branch.label = Text( event.method_name, style="yellow"
"🔄 Running: ", style="yellow bold" )
) + Text(event.method_name, style="yellow") break
break
self.console.print(self.current_flow_tree) self.console.print(self.current_flow_tree)
self.console.print() self.console.print()
@crewai_event_bus.on(MethodExecutionFinishedEvent) @crewai_event_bus.on(MethodExecutionFinishedEvent)
def on_method_execution_finished(source, event: MethodExecutionFinishedEvent): def on_method_execution_finished(source, event: MethodExecutionFinishedEvent):
if self.verbose: if self.current_method_branch:
if self.current_method_branch: # Update method status
# Update method status self.current_method_branch.label = Text(
self.current_method_branch.label = Text( "✅ Completed: ", style="green bold"
"✅ Completed: ", style="green bold" ) + Text(event.method_name, style="green")
) + Text(event.method_name, style="green") self.console.print(self.current_flow_tree)
self.console.print(self.current_flow_tree) self.console.print()
self.console.print()
@crewai_event_bus.on(MethodExecutionFailedEvent) @crewai_event_bus.on(MethodExecutionFailedEvent)
def on_method_execution_failed(source, event: MethodExecutionFailedEvent): def on_method_execution_failed(source, event: MethodExecutionFailedEvent):
if self.verbose: if self.current_method_branch:
if self.current_method_branch: self.current_method_branch.label = Text(
self.current_method_branch.label = Text( "❌ Failed: ", style="red bold"
"❌ Failed: ", style="red bold" ) + Text(event.method_name, style="red")
) + Text(event.method_name, style="red") self.console.print(self.current_flow_tree)
self.console.print(self.current_flow_tree) self.console.print()
self.console.print()
# ----------- TOOL USAGE EVENTS ----------- # ----------- TOOL USAGE EVENTS -----------
@crewai_event_bus.on(ToolUsageStartedEvent) @crewai_event_bus.on(ToolUsageStartedEvent)
def on_tool_usage_started(source, event: ToolUsageStartedEvent): def on_tool_usage_started(source, event: ToolUsageStartedEvent):
if self.verbose: if self.verbose and self.current_agent_branch:
# Create tool usage content # Update tool usage count
tool_content = Text() self.tool_usage_counts[event.tool_name] = (
tool_content.append("🔧 Using ", style="yellow bold") self.tool_usage_counts.get(event.tool_name, 0) + 1
tool_content.append(event.tool_name, style="yellow") )
# Add to tree under the agent branch # Find existing tool node or create new one
if self.current_agent_branch: tool_node = None
self.current_tool_branch = self.current_agent_branch.add( for child in self.current_agent_branch.children:
tool_content if event.tool_name in child.label.plain:
) tool_node = child
self.console.print(self.current_crew_tree) break
self.console.print()
if not tool_node:
# Create new tool node
self.current_tool_branch = self.current_agent_branch.add("")
else:
self.current_tool_branch = tool_node
# Update label with current count
self._update_tree_label(
self.current_tool_branch,
"🔧",
f"Using {event.tool_name} ({self.tool_usage_counts[event.tool_name]})",
"yellow",
)
self.console.print(self.current_crew_tree)
self.console.print()
@crewai_event_bus.on(ToolUsageFinishedEvent) @crewai_event_bus.on(ToolUsageFinishedEvent)
def on_tool_usage_finished(source, event: ToolUsageFinishedEvent): def on_tool_usage_finished(source, event: ToolUsageFinishedEvent):
if self.verbose: if self.verbose and self.current_tool_branch:
completion_content = Text() self._update_tree_label(
completion_content.append("🔧 Used ", style="green bold") self.current_tool_branch,
completion_content.append(event.tool_name, style="green") "🔧",
f"Used {event.tool_name} ({self.tool_usage_counts[event.tool_name]})",
# Update under the agent branch "green",
if self.current_tool_branch: )
self.current_tool_branch.label = completion_content self.console.print(self.current_crew_tree)
self.console.print(self.current_crew_tree) self.console.print()
self.console.print()
@crewai_event_bus.on(ToolUsageErrorEvent) @crewai_event_bus.on(ToolUsageErrorEvent)
def on_tool_usage_error(source, event: ToolUsageErrorEvent): def on_tool_usage_error(source, event: ToolUsageErrorEvent):
if self.verbose: if self.verbose:
error_content = Text()
error_content.append("🔧 Tool Failed: ", style="red bold")
error_content.append(event.tool_name, style="red")
# Update under the agent branch
if self.current_tool_branch: if self.current_tool_branch:
self.current_tool_branch.label = error_content self._update_tree_label(
self.current_tool_branch,
"🔧 Failed",
f"{event.tool_name} ({self.tool_usage_counts[event.tool_name]})",
"red",
)
self.console.print(self.current_crew_tree) self.console.print(self.current_crew_tree)
self.console.print() self.console.print()
# Show error panel # Show error panel
panel = self._create_panel( error_content = self._create_status_content(
Text( "Tool Usage Failed", event.tool_name, "red", Error=event.error
f"Tool usage failed: {event.tool_name}: {event.error}",
style="red",
),
"Tool Error",
"red",
) )
panel = self._create_panel(error_content, "Tool Error", "red")
self.console.print(panel) self.console.print(panel)
self.console.print() self.console.print()
@@ -546,27 +550,25 @@ class EventListener(BaseEventListener):
@crewai_event_bus.on(LLMCallStartedEvent) @crewai_event_bus.on(LLMCallStartedEvent)
def on_llm_call_started(source, event: LLMCallStartedEvent): def on_llm_call_started(source, event: LLMCallStartedEvent):
if self.verbose: if self.verbose and self.current_agent_branch:
llm_content = Text() # Only show thinking state if no previous LLM calls are shown
llm_content.append("🧠 Thinking...", style="blue bold") if not any(
"Thinking" in str(child.label)
# Add to tree under the agent branch for child in self.current_agent_branch.children
if self.current_agent_branch: ):
self.current_tool_branch = self.current_agent_branch.add( self.current_tool_branch = self.current_agent_branch.add("")
llm_content self._update_tree_label(
self.current_tool_branch, "🧠", "Thinking...", "blue"
) )
self.console.print(self.current_crew_tree) self.console.print(self.current_crew_tree)
self.console.print() self.console.print()
@crewai_event_bus.on(LLMCallCompletedEvent) @crewai_event_bus.on(LLMCallCompletedEvent)
def on_llm_call_completed(source, event: LLMCallCompletedEvent): def on_llm_call_completed(source, event: LLMCallCompletedEvent):
if self.verbose: if self.verbose and self.current_tool_branch:
completion_content = Text() # Remove the thinking status node when complete
completion_content.append("✨ Done", style="green bold") if "Thinking" in str(self.current_tool_branch.label):
self.current_agent_branch.children.remove(self.current_tool_branch)
# Update under the agent branch
if self.current_tool_branch:
self.current_tool_branch.label = completion_content
self.console.print(self.current_crew_tree) self.console.print(self.current_crew_tree)
self.console.print() self.console.print()