Sparkonix's picture
refactored the code
edc8356
import os
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Dict, Any, List, Tuple
import uvicorn
from dotenv import load_dotenv
from utils import PIIMasker
from models import EmailClassifier
# Load environment variables from .env file if available
try:
load_dotenv()
except ImportError:
pass # dotenv might not be installed in production
# Set database path for Hugging Face, using persistent storage
if os.path.exists('/data'):
db_path = "/data/emails.db"
else:
db_path = "emails.db" # Fallback to local directory
# Initialize the FastAPI application
app = FastAPI(title="Email Classification API",
description="API for classifying support emails and masking PII",
version="1.0.0")
# Initialize the PII masker and email classifier
pii_masker = PIIMasker(db_path=db_path)
email_classifier = EmailClassifier()
class EmailInput(BaseModel):
"""Input model for the email classification endpoint"""
input_email_body: str
class EntityInfo(BaseModel):
"""Model for entity information"""
position: Tuple[int, int]
classification: str
entity: str
class EmailOutput(BaseModel):
"""Output model for the email classification endpoint"""
input_email_body: str
list_of_masked_entities: List[EntityInfo]
masked_email: str
category_of_the_email: str
class MaskedEmailInput(BaseModel):
"""Input model for retrieving original email by masked email content"""
masked_email: str
access_key: str
@app.post("/classify", response_model=EmailOutput)
async def classify_email(email_input: EmailInput) -> Dict[str, Any]:
"""
Classify an email into a support category while masking PII
Args:
email_input: The input email data
Returns:
The classified email data with masked PII
"""
try:
# Process the email to mask PII and store original in database
processed_data = pii_masker.process_email(email_input.input_email_body)
# Classify the masked email
classified_data = email_classifier.process_email(processed_data)
# Make sure we return only the fields expected in the response model
return {
"input_email_body": email_input.input_email_body,
"list_of_masked_entities": classified_data["list_of_masked_entities"],
"masked_email": classified_data["masked_email"],
"category_of_the_email": classified_data["category_of_the_email"]
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error processing email: {str(e)}")
@app.post("/api/v1/unmask-email", response_model=Dict[str, Any])
async def unmask_email(masked_email_input: MaskedEmailInput) -> Dict[str, Any]:
"""
Retrieve the original unmasked email.
Args:
masked_email_input: Contains the masked email and access key
Returns:
The original email data with PII information
"""
try:
# Verify access key matches the global access key
if masked_email_input.access_key != os.environ.get(
"EMAIL_ACCESS_KEY", "default_secure_access_key"):
raise HTTPException(status_code=401, detail="Invalid access key")
# Retrieve the original email using the masked content
email_data = pii_masker.get_original_by_masked_email(
masked_email_input.masked_email
)
if not email_data:
raise HTTPException(
status_code=404,
detail="Original email not found for the provided masked email"
)
return {
"status": "success",
"data": {
"id": email_data["id"],
"original_email": email_data["original_email"],
"masked_email": email_data["masked_email"],
"masked_entities": email_data["masked_entities"],
"category": email_data.get("category", ""),
"created_at": email_data.get("created_at", "")
},
"message": "Original email retrieved successfully"
}
except Exception as e:
if isinstance(e, HTTPException):
raise e
raise HTTPException(
status_code=500,
detail=f"Error retrieving original email: {str(e)}"
)
@app.get("/health")
async def health_check():
"""
Health check endpoint
Returns:
Status message indicating the API is running
"""
return {"status": "healthy", "message": "Email classification API is running"}
# For local development and testing
if __name__ == "__main__":
port = int(os.environ.get("PORT", 8000))
uvicorn.run("main:app", host="0.0.0.0", port=port, reload=True)