Spaces:
Sleeping
Sleeping
| import os | |
| import gradio as gr | |
| from crewai import Agent, Task, Crew, LLM | |
| from dotenv import load_dotenv | |
| # Make sure your tools.py file is in the same directory | |
| from tools import SendEmailTool | |
| load_dotenv() | |
| # --- 1. SET UP YOUR CREWAI AGENT AND TASKS WITH FORCED EXECUTION --- | |
| llm = LLM( | |
| model="gemini/gemini-1.5-flash", | |
| verbose=True, | |
| temperature=0.5, | |
| ) | |
| email_sender_tool = SendEmailTool() | |
| email_agent = Agent( | |
| role="Portfolio Contact Form Assistant", | |
| goal="Professionally format and send a visitor's message to the portfolio owner.", | |
| backstory=( | |
| "You are an expert assistant responsible for handling the 'Contact Me' form on a professional portfolio. " | |
| "Your job is to take a visitor's message, format it into a proper email, and send it to the portfolio owner. " | |
| "You MUST actually execute the SendEmailTool - do not simulate or fake the execution." | |
| ), | |
| verbose=True, | |
| tools=[email_sender_tool], | |
| llm=llm, | |
| # Force real execution settings | |
| allow_delegation=False, | |
| max_execution_time=300, # 5 minutes timeout | |
| ) | |
| write_and_send_mail_task = Task( | |
| description=( | |
| "A portfolio visitor has sent a message. Your task is to process it.\n" | |
| "1. Read the visitor's message from the '{topic}' input.\n" | |
| "2. The visitor's email address is provided in the '{sender_email}' input.\n" | |
| "3. Create a professional email body. **Crucially, the first line of the body must be 'Message from: {sender_email}'** followed by the rest of the formatted message.\n" | |
| "4. The email should be professional and well structured.\n" | |
| "5. Create a concise subject line, like 'New Message from Portfolio Visitor'.\n" | |
| "6. Use the SendEmailTool to send this email, passing the visitor's email, your generated subject, and the complete body.\n" | |
| "7. The portfolio belongs to Abdullah Tahir.\n" | |
| "CRITICAL: You MUST actually use the SendEmailTool. Do not simulate, mock, or fabricate the result." | |
| ), | |
| expected_output="The actual output from the SendEmailTool execution, including real confirmation details.", | |
| agent=email_agent, | |
| # Force real tool execution | |
| result_as_answer=True, | |
| tools=[email_sender_tool], | |
| ) | |
| crew = Crew( | |
| agents=[email_agent], | |
| tasks=[write_and_send_mail_task], | |
| verbose=True, | |
| process="sequential", | |
| full_output=True, | |
| ) | |
| # --- 2. ENHANCED WRAPPER FUNCTION WITH VALIDATION --- | |
| def validate_real_execution(result): | |
| """Check if the result indicates real or simulated execution""" | |
| result_str = str(result).lower() | |
| simulation_keywords = [ | |
| 'simulated', 'simulation', 'mock', 'fake', | |
| 'pretend', 'dummy', 'test-id', '12345-simulated' | |
| ] | |
| return not any(keyword in result_str for keyword in simulation_keywords) | |
| def run_crew_and_send_email(message, email_address): | |
| """ | |
| Enhanced function that ensures real tool execution | |
| """ | |
| if not message or not email_address: | |
| return "β Error: Please provide both a message and your email address." | |
| # Validate email format | |
| if '@' not in email_address: | |
| return "β Error: Please provide a valid email address." | |
| print(f"π Processing message from: {email_address}") | |
| inputs = { | |
| "topic": message, | |
| "sender_email": email_address | |
| } | |
| try: | |
| # Step 1: Try CrewAI execution | |
| print("π Attempting CrewAI execution...") | |
| result = crew.kickoff(inputs=inputs) | |
| print(f"π¨ CrewAI Result: {result}") | |
| # Step 2: Validate if execution was real | |
| if validate_real_execution(result): | |
| print("β Real tool execution detected") | |
| return f"β Message sent successfully!\n\nDetails: {result}" | |
| else: | |
| print("β οΈ Simulated execution detected - trying direct approach...") | |
| # Step 3: Fallback to direct tool execution | |
| professional_message = f"Message from: {email_address}\n\n{message}\n\nBest regards,\nPortfolio Visitor" | |
| direct_result = email_sender_tool._run( | |
| sender_email=email_address, | |
| subject="New Message from Portfolio Visitor", | |
| body=professional_message | |
| ) | |
| print(f"π§ Direct execution result: {direct_result}") | |
| if "β " in str(direct_result) or "successfully" in str(direct_result).lower(): | |
| return f"β Message sent successfully (direct execution)!\n\nDetails: {direct_result}" | |
| else: | |
| return f"β οΈ Email sending encountered an issue:\n\n{direct_result}" | |
| except Exception as e: | |
| print(f"β CrewAI execution failed: {str(e)}") | |
| # Emergency fallback: Direct tool execution | |
| try: | |
| print("π¨ Using emergency direct execution...") | |
| professional_message = f"Message from: {email_address}\n\n{message}\n\nBest regards,\nPortfolio Visitor" | |
| emergency_result = email_sender_tool._run( | |
| sender_email=email_address, | |
| subject="New Message from Portfolio Visitor", | |
| body=professional_message | |
| ) | |
| print(f"π Emergency result: {emergency_result}") | |
| if "β " in str(emergency_result) or "successfully" in str(emergency_result).lower(): | |
| return f"β Message sent successfully (emergency mode)!\n\nDetails: {emergency_result}" | |
| else: | |
| return f"β Failed to send message. Error details:\n\n{emergency_result}" | |
| except Exception as emergency_error: | |
| return f"β Critical error: Unable to send email. Please contact Abdullah directly.\n\nTechnical details: {str(emergency_error)}" | |
| # --- 3. ENHANCED GRADIO INTERFACE --- | |
| with gr.Blocks(theme=gr.themes.Soft(), title="AI Contact Assistant") as demo: | |
| gr.Markdown( | |
| """ | |
| # π€ AI Contact Assistant for Abdullah Tahir | |
| Welcome! Please leave your message and email address below. | |
| My AI assistant will format your message professionally and send it directly to Abdullah. | |
| **Status indicators:** | |
| - β = Message sent successfully | |
| - β οΈ = Warning or fallback used | |
| - β = Error occurred | |
| """ | |
| ) | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| # Input components with better validation | |
| message_input = gr.Textbox( | |
| lines=7, | |
| label="Your Message", | |
| placeholder="Hello Abdullah, I came across your portfolio and wanted to connect about...", | |
| info="Please write your message here" | |
| ) | |
| email_input = gr.Textbox( | |
| label="Your Email Address", | |
| placeholder="your.name@example.com", | |
| info="This will be used for Abdullah to reply to you" | |
| ) | |
| with gr.Row(): | |
| send_button = gr.Button("π§ Send Message", variant="primary", size="lg") | |
| clear_button = gr.Button("ποΈ Clear", variant="secondary") | |
| with gr.Column(scale=1): | |
| # Enhanced output component | |
| status_output = gr.Textbox( | |
| label="π Status & Results", | |
| interactive=False, | |
| lines=8, | |
| info="Real-time status updates will appear here" | |
| ) | |
| # Debug info (you can remove this in production) | |
| with gr.Accordion("π§ Debug Info (for testing)", open=False): | |
| debug_output = gr.Textbox( | |
| label="Environment Check", | |
| interactive=False, | |
| value=f"SendGrid API Key: {'β Found' if os.getenv('SENDGRID_API_KEY') else 'β Missing'}\n" | |
| f"Verified Sender: {os.getenv('VERIFIED_SENDER_EMAIL', 'β Missing')}\n" | |
| f"Receiver Email: {os.getenv('RECEIVER_EMAIL', 'β Missing')}" | |
| ) | |
| # Define actions | |
| def clear_form(): | |
| return "", "", "Form cleared. Ready for new message." | |
| send_button.click( | |
| fn=run_crew_and_send_email, | |
| inputs=[message_input, email_input], | |
| outputs=status_output | |
| ) | |
| clear_button.click( | |
| fn=clear_form, | |
| outputs=[message_input, email_input, status_output] | |
| ) | |
| # Add some examples | |
| gr.Markdown( | |
| """ | |
| ### π‘ Example Messages: | |
| - "Hi Abdullah, I'm interested in collaborating on an AI project..." | |
| - "Hello, I saw your portfolio and would like to discuss a job opportunity..." | |
| - "Hi there, I have a question about your CrewAI email assistant project..." | |
| """ | |
| ) | |
| # --- 4. LAUNCH THE APP WITH BETTER ERROR HANDLING --- | |
| if __name__ == "__main__": | |
| # Validate environment before launching | |
| required_vars = ['SENDGRID_API_KEY', 'VERIFIED_SENDER_EMAIL', 'RECEIVER_EMAIL'] | |
| missing_vars = [var for var in required_vars if not os.getenv(var)] | |
| if missing_vars: | |
| print(f"β οΈ WARNING: Missing environment variables: {missing_vars}") | |
| print("The app will launch but email sending may not work.") | |
| else: | |
| print("β All required environment variables found!") | |
| # Test the email tool on startup | |
| print("\nπ§ͺ Testing email tool...") | |
| test_tool = SendEmailTool() | |
| test_result = test_tool._run("test@example.com", "Startup Test", "Testing email tool on startup") | |
| print(f"Test result: {test_result}") | |
| print("\nπ Launching Gradio app...") | |
| demo.launch( | |
| share=False, # Set to True if you want a public link | |
| show_error=True, | |
| quiet=False | |
| ) |