improve logging
This commit is contained in:
parent
c20be407d5
commit
ea1519a208
@ -14,6 +14,9 @@ if __name__ == "__main__":
|
||||
messages = []
|
||||
print("Welcome to the multi-agent sysadmin assistant!")
|
||||
print("Type your sysadmin question below. Type 'exit' to quit.")
|
||||
print("\n💡 Note: When agents execute shell commands, you may see command output")
|
||||
print(" appear between the structured step logs. This is normal behavior.")
|
||||
print(" The output belongs to the agent that was most recently active.")
|
||||
while True:
|
||||
user_input = input("\n📝 User: ")
|
||||
if user_input.strip().lower() == 'exit':
|
||||
@ -22,27 +25,10 @@ if __name__ == "__main__":
|
||||
messages.append({"role": "user", "content": user_input})
|
||||
query = {"messages": messages}
|
||||
|
||||
print("\n=== Using invoke() method ===")
|
||||
result = supervisor.invoke(query)
|
||||
|
||||
print("\n📊 FINAL RESULT:")
|
||||
print("-" * 40)
|
||||
print(result["messages"][-1].content)
|
||||
print("-" * 40)
|
||||
print(f"\n📈 Total messages exchanged: {len(result['messages'])}")
|
||||
|
||||
# Add the assistant's reply to the conversation history
|
||||
messages.append({"role": "assistant", "content": result["messages"][-1].content})
|
||||
|
||||
# Ask if the user wants to continue
|
||||
cont = input("\nWould you like to continue the conversation? (y/n): ")
|
||||
if cont.strip().lower() not in ('y', 'yes'):
|
||||
print("Session ended.")
|
||||
break
|
||||
|
||||
print("\n=== Using stream() method for detailed step-by-step analysis ===")
|
||||
print("\n=== Processing with detailed step-by-step analysis ===")
|
||||
step_count = 0
|
||||
max_steps = 20 # Prevent infinite loops
|
||||
final_result = None
|
||||
|
||||
try:
|
||||
chunks_processed = []
|
||||
@ -51,21 +37,50 @@ if __name__ == "__main__":
|
||||
chunks_processed.append(chunk)
|
||||
print_step_info(step_count, chunk)
|
||||
|
||||
# Store the final result for conversation history
|
||||
if isinstance(chunk, dict):
|
||||
for agent_name, agent_data in chunk.items():
|
||||
if 'messages' in agent_data and agent_data['messages']:
|
||||
last_msg = agent_data['messages'][-1]
|
||||
if hasattr(last_msg, 'content') and last_msg.content:
|
||||
final_result = last_msg.content
|
||||
|
||||
# Safety check to prevent infinite loops
|
||||
if step_count >= max_steps:
|
||||
print(f"\n⚠️ Reached maximum steps ({max_steps}), stopping stream...")
|
||||
break
|
||||
|
||||
print(f"\n✅ Streaming completed successfully with {step_count} steps")
|
||||
print(f"📊 Total chunks processed: {len(chunks_processed)}")
|
||||
print(f"\n✅ Analysis completed with {step_count} steps")
|
||||
|
||||
# Check if the last chunk contains a complete final response
|
||||
if chunks_processed:
|
||||
last_chunk = chunks_processed[-1]
|
||||
print(f"🔍 Last chunk keys: {list(last_chunk.keys()) if isinstance(last_chunk, dict) else type(last_chunk)}")
|
||||
# Add the assistant's reply to the conversation history
|
||||
if final_result:
|
||||
messages.append({"role": "assistant", "content": final_result})
|
||||
|
||||
print(f"\n📊 FINAL SUMMARY:")
|
||||
print("-" * 60)
|
||||
if final_result:
|
||||
print(final_result)
|
||||
else:
|
||||
print("Analysis completed - check the detailed steps above for results")
|
||||
print("-" * 60)
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ Streaming error after {step_count} steps: {e}")
|
||||
print("💡 The invoke() method worked fine, so the supervisor itself is functional.")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
print("💡 Falling back to basic invoke method...")
|
||||
try:
|
||||
result = supervisor.invoke(query)
|
||||
final_result = result["messages"][-1].content
|
||||
messages.append({"role": "assistant", "content": final_result})
|
||||
print(f"\n📊 FINAL RESULT:")
|
||||
print("-" * 40)
|
||||
print(final_result)
|
||||
print("-" * 40)
|
||||
except Exception as fallback_error:
|
||||
print(f"❌ Fallback also failed: {fallback_error}")
|
||||
continue
|
||||
|
||||
# Ask if the user wants to continue
|
||||
cont = input("\nWould you like to continue the conversation? (y/n): ")
|
||||
if cont.strip().lower() not in ('y', 'yes'):
|
||||
print("Session ended.")
|
||||
break
|
||||
|
@ -26,12 +26,12 @@ def explain_supervisor_pattern():
|
||||
|
||||
|
||||
def print_step_info(step_count: int, chunk):
|
||||
"""Print formatted step information during streaming."""
|
||||
print(f"\n🔄 STEP {step_count}:")
|
||||
print("-" * 30)
|
||||
"""Print formatted step information during streaming with clear agent actions."""
|
||||
print(f"\n{'='*60}")
|
||||
print(f"STEP {step_count}")
|
||||
print(f"{'='*60}")
|
||||
|
||||
try:
|
||||
# Extract agent information from chunk
|
||||
if isinstance(chunk, dict):
|
||||
# Look for agent names in the chunk keys
|
||||
agent_names = [key for key in chunk.keys() if key in [
|
||||
@ -41,102 +41,115 @@ def print_step_info(step_count: int, chunk):
|
||||
]]
|
||||
|
||||
if agent_names:
|
||||
current_agent = agent_names[0]
|
||||
print(f"🤖 ACTIVE AGENT: {current_agent}")
|
||||
current_agent = agent_names[0].upper()
|
||||
agent_data = chunk[agent_names[0]]
|
||||
|
||||
# Show the messages from this agent
|
||||
agent_data = chunk[current_agent]
|
||||
if 'messages' in agent_data:
|
||||
messages = agent_data['messages']
|
||||
if messages:
|
||||
last_message = messages[-1]
|
||||
# Get message type from the class name
|
||||
if 'messages' in agent_data and agent_data['messages']:
|
||||
last_message = agent_data['messages'][-1]
|
||||
message_type = type(last_message).__name__
|
||||
print(f"💬 MESSAGE TYPE: {message_type}")
|
||||
|
||||
# Show content preview if available
|
||||
if hasattr(last_message, 'content') and last_message.content:
|
||||
content = last_message.content
|
||||
content_length = len(content)
|
||||
print(f"📏 CONTENT LENGTH: {content_length} characters")
|
||||
|
||||
# Show full content for final AI responses, abbreviated for others
|
||||
if message_type == 'AIMessage':
|
||||
print(f"📄 FULL CONTENT:")
|
||||
print(content)
|
||||
print() # Extra line for readability
|
||||
# Handle different message types with clear formatting
|
||||
if message_type == 'HumanMessage':
|
||||
# This is typically the user query or supervisor instruction
|
||||
content = getattr(last_message, 'content', '')
|
||||
if current_agent == 'SUPERVISOR':
|
||||
print(f"[ SUPERVISOR ] received user query: {content[:100]}{'...' if len(content) > 100 else ''}")
|
||||
else:
|
||||
# Truncate other message types for brevity
|
||||
preview = content[:200] + "..." if len(content) > 200 else content
|
||||
print(f"📄 CONTENT PREVIEW:")
|
||||
print(preview)
|
||||
print() # Extra line for readability
|
||||
print(f"[ {current_agent} ] received prompt from supervisor: {content[:100]}{'...' if len(content) > 100 else ''}")
|
||||
|
||||
# Show tool calls if any
|
||||
if hasattr(last_message, 'tool_calls') and last_message.tool_calls:
|
||||
tool_calls = last_message.tool_calls
|
||||
print(f"🔧 TOOL CALLS: {len(tool_calls)} tool(s)")
|
||||
for i, tool_call in enumerate(tool_calls):
|
||||
tool_name = getattr(tool_call, 'name', 'unknown')
|
||||
print(f" {i+1}. {tool_name}")
|
||||
# Show transfer details for supervisor delegation
|
||||
elif message_type == 'ToolMessage':
|
||||
# Result of tool execution
|
||||
tool_name = getattr(last_message, 'name', 'unknown')
|
||||
content = getattr(last_message, 'content', '')
|
||||
|
||||
if "Successfully transferred" in content:
|
||||
if tool_name.startswith('transfer_to_'):
|
||||
target_agent = tool_name.replace('transfer_to_', '')
|
||||
print(f" 🎯 DELEGATING to: {target_agent}")
|
||||
# Show the arguments/context being passed
|
||||
if hasattr(tool_call, 'args') and tool_call.args:
|
||||
print(f" 📋 Context/Args: {tool_call.args}")
|
||||
|
||||
# Show additional info for ToolMessage
|
||||
if message_type == 'ToolMessage':
|
||||
if hasattr(last_message, 'name'):
|
||||
tool_name = last_message.name
|
||||
print(f"🔧 TOOL NAME: {tool_name}")
|
||||
|
||||
# Explain what "Successfully transferred" means
|
||||
if "transfer" in tool_name and "Successfully transferred" in content:
|
||||
if tool_name.startswith('transfer_to_'):
|
||||
target_agent = tool_name.replace('transfer_to_', '')
|
||||
print(f" ℹ️ EXPLANATION: Supervisor delegated control to {target_agent}")
|
||||
print(f" ℹ️ The {target_agent} will now execute its specialized tasks")
|
||||
target_agent = tool_name.replace('transfer_to_', '').upper()
|
||||
print(f"[ SUPERVISOR ] successfully transferred control to {target_agent}")
|
||||
print(f"[ SUPERVISOR ] {target_agent} will now analyze the situation and execute necessary commands")
|
||||
print(f"[ SUPERVISOR ] (Any shell command output below belongs to {target_agent})")
|
||||
elif tool_name == 'transfer_back_to_supervisor':
|
||||
print(f" ℹ️ EXPLANATION: Agent completed its task and returned control to supervisor")
|
||||
print(f" ℹ️ Supervisor will decide the next step based on results")
|
||||
print(f"[ {current_agent} ] completed analysis and transferred control back to supervisor")
|
||||
print(f"[ {current_agent} ] (Any shell command output above was from {current_agent})")
|
||||
|
||||
if hasattr(last_message, 'tool_call_id'):
|
||||
print(f"🔧 TOOL CALL ID: {last_message.tool_call_id}")
|
||||
|
||||
# Show conversation context for better understanding
|
||||
agent_data = chunk[current_agent]
|
||||
# Show the result being sent back to supervisor
|
||||
# Look for the last AIMessage before this transfer to get the result
|
||||
if 'messages' in agent_data and len(agent_data['messages']) > 1:
|
||||
print(f"\n📚 CONVERSATION CONTEXT ({len(agent_data['messages'])} messages):")
|
||||
for i, msg in enumerate(agent_data['messages'][-3:], start=max(0, len(agent_data['messages'])-3)):
|
||||
msg_type = type(msg).__name__
|
||||
if hasattr(msg, 'content') and msg.content:
|
||||
preview = msg.content[:100].replace('\n', ' ')
|
||||
if len(msg.content) > 100:
|
||||
preview += "..."
|
||||
print(f" {i+1}. {msg_type}: {preview}")
|
||||
elif hasattr(msg, 'tool_calls') and msg.tool_calls:
|
||||
tool_names = [getattr(tc, 'name', 'unknown') for tc in msg.tool_calls]
|
||||
print(f" {i+1}. {msg_type}: Tool calls: {tool_names}")
|
||||
# Look for the most recent AIMessage with content
|
||||
for msg in reversed(agent_data['messages'][:-1]): # Exclude current ToolMessage
|
||||
if type(msg).__name__ == 'AIMessage' and hasattr(msg, 'content') and msg.content:
|
||||
result_content = msg.content
|
||||
if len(result_content) > 300:
|
||||
preview = result_content[:300] + "..."
|
||||
print(f"[ {current_agent} ] sending result to supervisor (preview): {preview}")
|
||||
print(f"[ {current_agent} ] (full result length: {len(result_content)} characters)")
|
||||
else:
|
||||
print(f" {i+1}. {msg_type}: (no content)")
|
||||
print(f"[ {current_agent} ] sending result to supervisor: {result_content}")
|
||||
break
|
||||
else:
|
||||
print(f"[ {current_agent} ] sending analysis results to supervisor")
|
||||
else:
|
||||
print(f"[ {current_agent} ] sending analysis results to supervisor")
|
||||
else:
|
||||
# Other tool execution result
|
||||
if len(content) > 200:
|
||||
preview = content[:200] + "..."
|
||||
print(f"[ {current_agent} ] tool result preview: {preview}")
|
||||
print(f"[ {current_agent} ] (full result length: {len(content)} characters)")
|
||||
else:
|
||||
print(f"[ {current_agent} ] tool result: {content}")
|
||||
|
||||
elif message_type == 'AIMessage':
|
||||
# Agent is responding or making tool calls
|
||||
content = getattr(last_message, 'content', '')
|
||||
tool_calls = getattr(last_message, 'tool_calls', [])
|
||||
|
||||
if tool_calls:
|
||||
for tool_call in tool_calls:
|
||||
tool_name = getattr(tool_call, 'name', 'unknown')
|
||||
|
||||
if tool_name.startswith('transfer_to_'):
|
||||
target_agent = tool_name.replace('transfer_to_', '').upper()
|
||||
args = getattr(tool_call, 'args', {})
|
||||
context = str(args)[:150] + "..." if len(str(args)) > 150 else str(args)
|
||||
print(f"[ SUPERVISOR ] calling {target_agent} with context: {context}")
|
||||
|
||||
elif tool_name == 'transfer_back_to_supervisor':
|
||||
print(f"[ {current_agent} ] completed task, transferring back to supervisor")
|
||||
|
||||
print() # Extra spacing for readability
|
||||
else:
|
||||
print("📋 CHUNK DATA:")
|
||||
# Show first few keys for debugging
|
||||
chunk_keys = list(chunk.keys())[:3]
|
||||
print(f" Keys: {chunk_keys}")
|
||||
print(f"[ {current_agent} ] using tool: {tool_name}")
|
||||
args = getattr(tool_call, 'args', {})
|
||||
if args:
|
||||
args_preview = str(args)[:100] + "..." if len(str(args)) > 100 else str(args)
|
||||
print(f"[ {current_agent} ] tool arguments: {args_preview}")
|
||||
|
||||
elif content:
|
||||
# Final response from agent
|
||||
if len(content) > 200:
|
||||
preview = content[:200] + "..."
|
||||
print(f"[ {current_agent} ] response preview: {preview}")
|
||||
print(f"[ {current_agent} ] (full response length: {len(content)} characters)")
|
||||
else:
|
||||
print(f"📦 CHUNK TYPE: {type(chunk)}")
|
||||
print(f"📄 CONTENT: {str(chunk)[:100]}...")
|
||||
print(f"[ {current_agent} ] response: {content}")
|
||||
|
||||
else:
|
||||
print(f"[ {current_agent} ] {message_type}: {getattr(last_message, 'content', 'No content')[:100]}")
|
||||
|
||||
else:
|
||||
print(f"[ {current_agent} ] no message data available")
|
||||
|
||||
else:
|
||||
print("[ SYSTEM ] processing chunk with keys:", list(chunk.keys())[:3])
|
||||
|
||||
else:
|
||||
print(f"[ SYSTEM ] received {type(chunk).__name__}: {str(chunk)[:100]}{'...' if len(str(chunk)) > 100 else ''}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error processing chunk: {e}")
|
||||
print(f"📦 CHUNK TYPE: {type(chunk)}")
|
||||
print(f"[ ERROR ] processing step {step_count}: {e}")
|
||||
print(f"[ DEBUG ] chunk type: {type(chunk)}")
|
||||
if hasattr(chunk, '__dict__'):
|
||||
print(f"📄 CHUNK ATTRIBUTES: {list(chunk.__dict__.keys())}")
|
||||
print(f"[ DEBUG ] chunk attributes: {list(chunk.__dict__.keys())}")
|
||||
|
||||
print("-" * 30)
|
||||
print(f"{'='*60}")
|
||||
print(f"NOTE: Shell command output may appear below before the next step")
|
||||
|
Loading…
x
Reference in New Issue
Block a user