""" Email Assistant Agent - Gradio Interface This is the main application file that provides a Gradio web interface for the AI-powered Email Assistant using OpenAI Agents SDK. """ import gradio as gr import os from agent import process_email def load_email_examples() -> list: """ Loads email examples from the external text file. Returns: list: List of email examples for the Gradio interface """ examples_file = os.path.join(os.path.dirname(__file__), "email_examples.txt") try: with open(examples_file, 'r', encoding='utf-8') as f: content = f.read() # Split examples by the separator "---" examples = [example.strip() for example in content.split('---') if example.strip()] return examples except FileNotFoundError: print(f"Warning: Examples file not found at {examples_file}") return [] except Exception as e: print(f"Error loading examples: {e}") return [] def flag_inappropriate_content(output_text: str) -> str: """ Flags inappropriate content and saves it for review. Args: output_text (str): The output content to flag Returns: str: Confirmation message """ import datetime # Create flagged content directory if it doesn't exist import os flagged_dir = "flagged_content" if not os.path.exists(flagged_dir): os.makedirs(flagged_dir) # Save flagged content with timestamp timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"{flagged_dir}/flagged_{timestamp}.txt" try: with open(filename, 'w', encoding='utf-8') as f: f.write(f"Flagged at: {datetime.datetime.now()}\n") f.write("=" * 50 + "\n") f.write(output_text) return f"✅ Content flagged and saved to {filename}" except Exception as e: return f"❌ Error saving flagged content: {str(e)}" def process_email_interface(api_key: str, email_text: str) -> str: """ Gradio interface function to process emails through the AI agent. Args: api_key (str): OpenAI API key email_text (str): Email content to process Returns: str: Formatted response with category, summary, and suggested reply """ print("Starting email processing...") # Validate inputs first if not api_key or not api_key.strip(): return "**Error:** OpenAI API key is required. Please enter your API key." if not email_text or not email_text.strip(): return "**Error:** Email content is required. Please enter the email text to process." print("Inputs validated, calling process_email...") # Process the email through the agent result = process_email(email_text, api_key) print(f"Process email result: {result}") if not result['success']: return f"**Error:** {result['error']}" # Format the reply text for HTML display formatted_reply = result['reply'] print("=" * 80) print("DEBUG: HTML FORMATTING IN APP.PY") print("=" * 80) print(f"Original reply from result: '{result['reply']}'") print(f"Reply length: {len(result['reply'])} characters") if formatted_reply: # Convert \n to HTML line breaks for proper rendering in Gradio formatted_reply = formatted_reply.replace('\n', '
') print(f"After HTML formatting: '{formatted_reply}'") print(f"Formatted reply length: {len(formatted_reply)} characters") else: print("WARNING: Reply is empty or None!") print("=" * 80) # Format the successful response response = f""" ## Email Analysis Results ### **Detected Category:** {result['category']} ### **Summary:** {result['summary']} ### **Suggested Reply:** {formatted_reply} --- *Generated by Email Assistant Agent using OpenAI Agents SDK* """ print("DEBUG: FINAL RESPONSE FOR GRADIO") print("=" * 80) print(f"Final response length: {len(response)} characters") print(f"Final response content:\n{response}") print("=" * 80) return response def create_gradio_interface() -> gr.Blocks: """ Creates and configures the Gradio interface for the Email Assistant. Returns: gr.Blocks: Configured Gradio interface with separate API key field """ # Load email examples from external file email_examples = load_email_examples() with gr.Blocks( title="Email Assistant Agent", theme=gr.themes.Soft(), css=""" .gradio-container { max-width: 1000px !important; } .main-header { text-align: center; margin-bottom: 2rem; } """ ) as interface: gr.Markdown(""" # Email Assistant Agent **Automatically classify, summarize, and respond to business emails using OpenAI Agents SDK.** This AI agent will: - **Classify** your email into categories (Inquiry, Complaint, Feedback, Other) - **Summarize** the content in two concise sentences - **Generate** a professional reply suggestion **Note:** You need a valid OpenAI API key to use this service. The key is not stored and is only used for processing your request. **Flag Button:** Use the flag button to report inappropriate, offensive, or incorrect responses. This helps improve the AI's performance and ensures a better experience for all users. """) # Two-column layout with gr.Row(): # Left column: API Key, Email input and controls with gr.Column(scale=1): api_key_input = gr.Textbox( label="OpenAI API Key", placeholder="Enter your OpenAI API key here...", type="password", info="Your API key is not stored and is only used for this session" ) email_input = gr.Textbox( label="Email Content", placeholder="Paste your business email here...", lines=10, max_lines=20, info="Enter the full email content you want to analyze" ) # Examples for email content only gr.Examples( examples=email_examples, inputs=email_input, label="Email Examples (click to load)" ) with gr.Row(): submit_btn = gr.Button("Submit", variant="primary") clear_btn = gr.Button("Clear", variant="secondary") # Right column: Output results with gr.Column(scale=1): output = gr.Markdown( label="Analysis Results", show_copy_button=True ) # Manual flag button for inappropriate content with gr.Row(): flag_btn = gr.Button("🚩 Flag Inappropriate Content", variant="stop", size="sm") flag_status = gr.Textbox(label="Flag Status", visible=False) # Connect the function with flagging submit_btn.click( fn=process_email_interface, inputs=[api_key_input, email_input], outputs=output, api_name="process_email" ) clear_btn.click( fn=lambda: ("", ""), outputs=[api_key_input, email_input] ) # Connect flag button flag_btn.click( fn=flag_inappropriate_content, inputs=output, outputs=flag_status ) return interface def main(): """ Main function to launch the Gradio interface. """ # Create and launch the interface interface = create_gradio_interface() # Launch the interface interface.launch( server_name="0.0.0.0", # Allow external connections for Hugging Face Spaces server_port=7860, # Default Gradio port share=False, # Don't create public link (for Hugging Face Spaces) show_error=True, # Show errors in the interface quiet=False # Show startup messages ) if __name__ == "__main__": main()