GenAiEmailClassification / backend /app /services /retrieve_email_process.py
Vivek0912's picture
updated code for files issue
122ab6b
Raw
History Blame Contribute Delete
7.26 kB
import json
import os
from pathlib import Path
import re
from typing import List, Optional
from app.services.duplicate_checker import check_duplicate
from app.services.email_reader import parse_email_bytes
from app.services.gemeni_classification import classify_email_gemeni, extract_key_number_with_llm, extract_text_from_attachment
from config import settings
async def process_single_email(file_content: bytes, filename: str) -> Optional[dict]:
"""Processes a single email content."""
# Load customizable priority rules
rules = load_priority_rules() # Expected to return a dict with "priority_rules" key
priority_config = rules.get("priority_rules", {})
use_priority = priority_config.get("is_prioritization_extraction", False)
all_extracted_numbers = [] # This will hold the combined results from all attachments
# Parse the email into its components
email_data = parse_email_bytes(file_content, filename)
if email_data:
# attachment_text = ""
# for attachment in email_data["attachments"]:
# attachment_text += extract_text_from_attachment(attachment["content"], attachment["filename"])
email_chain_text = email_data["email_chain_text"]
email_body_text = email_data["body"]
# Process attachments: extract text and numerical fields
attachment_text = ""
extracted_numbers = []
for attachment in email_data.get("attachments", []):
text = extract_text_from_attachment(attachment["content"], attachment["filename"])
attachment_text += text + "\n"
# extracted_numbers.extend(extract_key_number_with_llm(text,rules))
extracted_numbers_json = extract_key_number_with_llm(text, rules)
if extracted_numbers_json:
try:
parsed_result = json.loads(extracted_numbers_json) # Convert JSON string to Python object
# Check if the parsed result is a list; if so, merge it into our overall list.
if isinstance(parsed_result, list):
all_extracted_numbers.extend(parsed_result)
else:
all_extracted_numbers.append(parsed_result)
except Exception as e:
print("Error parsing JSON result from LLM:", e)
# Choose classification logic based on priority configuration
if use_priority:
# -- Priority Based Extraction Logic --
identification_order = priority_config.get("request_type_identification", {}).get("order", [])
classification_source = ""
if "email_content" in identification_order and email_body_text.strip():
classification_source = email_body_text
elif "document_content" in identification_order and attachment_text.strip():
classification_source = attachment_text
else:
classification_source = email_body_text # default fallback
primary_result = classify_email_gemeni(email_data["subject"], classification_source, rules)
# special condition to check if priority is email content and email has multi thread then we
# have to compare confidence score with primary confidence score
if "email_content" in identification_order:
email_chain_result = classify_email_gemeni(email_data["subject"], email_chain_text, rules) if email_chain_text else ("Unknown", "Unknown", "0")
email_chain_confidence = float(email_chain_result[2])
primary_email_confidence = float(primary_result[2])
if email_chain_confidence > primary_email_confidence and email_chain_confidence:
primary_result = email_chain_result
else:
# 1. Separate Classification:
document_result = classify_email_gemeni(email_data["subject"], attachment_text, rules) if attachment_text else ("Unknown", "Unknown", "0")
email_chain_result = classify_email_gemeni(email_data["subject"], email_chain_text, rules) if email_chain_text else ("Unknown", "Unknown", "0")
primary_email_result = classify_email_gemeni(email_data["subject"], email_body_text, rules)
# 2. Confidence Score Comparison:
document_confidence = float(document_result[2])
email_chain_confidence = float(email_chain_result[2])
primary_email_confidence = float(primary_email_result[2])
primary_result = primary_email_result # Default to email body
if document_confidence > primary_email_confidence and document_confidence > email_chain_confidence:
primary_result = document_result
elif email_chain_confidence > primary_email_confidence and email_chain_confidence > document_confidence:
primary_result = email_chain_result
# Extract classification results
request_type = primary_result[0]
sub_request_type = primary_result[1]
confidence_score = primary_result[2]
duplicate_flag, duplicate_reason = check_duplicate(email_data["body"])
email_obj = {
"sender": email_data["sender"],
"subject": email_data["subject"],
"request_type": request_type,
"sub_request_type": sub_request_type,
"confidence_score": confidence_score,
"duplicate_flag": duplicate_flag,
"extracted_numbers_list": all_extracted_numbers
}
return email_obj
else:
print(f"Parsing failed for file: {filename}")
return None
def load_priority_rules() -> dict:
"""
Loads the priority rules from a JSON file.
The JSON file should be located at 'config/rules.json'.
If the file does not exist, a default rules dictionary is returned.
Expected JSON structure example:
{
"priority_rules": {
"is_prioritization_extraction": true,
"request_type_identification": {
"order": ["email_content", "document_content"],
"fallback": "document_content"
},
"numerical_field_extraction": {
"preferred_source": ["attachments"],
"fallback": "email_body"
}
}
}
"""
# Get the rules directory and filename from environment variables
RULES_FILENAME = settings.settings.ALLOWED_PRIORITY_RULES_FILENAME
RULES_DIR = Path(settings.settings.DATA_DIRECTORY_ATTACHMENTS_PATH)
# Build the full file path using pathlib
RULES_FILE_PATH = Path(RULES_DIR) / RULES_FILENAME
if os.path.exists(RULES_FILE_PATH):
with open(RULES_FILE_PATH, "r") as file:
return json.load(file)
# Return default rules if file doesn't exist
return {
"priority_rules": {
"is_prioritization_extraction": False,
"request_type_identification": {
"order": ["email_content", "document_content"],
"fallback": "document_content"
},
"numerical_field_extraction": {
"preferred_source": ["attachments"],
"fallback": "email_body"
}
}
}