email-assistant / app.py
devsu's picture
Add debugging statements to app.py and tools.py for enhanced output tracking
ffbefb9
Raw
History Blame Contribute Delete
8.57 kB
"""
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()