Spaces:
Sleeping
Sleeping
| """ | |
| 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', '<br>') | |
| 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() | |