AI-Powered Email Processing and Invoice Tracking: Streamlining Financial Management
In a previous blog post, we explored how generative AI can enhance customer support email management. In this guide, we’ll walk you through how to evolve that tool into an AI-powered solution specifically designed for efficient invoice status tracking and financial management.
The New Use Case: Invoice Status Tracking
Invoice management can be daunting for businesses, often involving manually tracking emails, payment statuses, and disputes. This guide will help you build an AI-powered tool that automates the extraction and summarization of invoice information directly from your email threads. By the end, you’ll have a streamlined process for assessing the status of multiple invoices, tracking payments, and identifying any issues—saving you time and reducing errors.
Key Features of the Invoice Status Tracker
- Email Thread Analysis: Automatically scans and analyzes email threads related to invoices, ensuring all pertinent information is captured.
- Invoice Status Categorization: Sorts invoices into clear statuses: Paid, Promise, or Dispute, allowing you to see where your money is at a glance.
- Comprehensive Invoice Summary: This function extracts and displays critical details like Invoice Number, Amount, Due Date, Status, Next Action, and Summary for each invoice.
- Thread Deduplication: Ensures only the latest email from each thread is processed, avoiding duplication and maintaining accuracy.
Step-by-Step Guide
Let’s explain how you can implement this AI-powered invoice tracker, complete with code snippets and explanations.
1. Setting Up the Environment
Start by setting up the development environment. Here’s the basic setup using Streamlit for the user interface:
import streamlit as st
import requests
import json
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from PIL import Image
import os
import pandas as pd
from datetime import datetime
import email.utils
import dotenv
dotenv.load_dotenv()
def load_css(file_name):
with open(file_name) as css:
st.markdown(f'<style>{css.read()}</style>', unsafe_allow_html=True)
# Load your CSS
load_css('style.css')
# Load your image
image = Image.open('logo.png')
st.image(image, width=40)
This code initializes your environment, loading custom CSS for styling and a logo for branding. It uses Streamlit to create an intuitive user interface, making it easy to interact with the tool.
2. Retrieving Emails
Next, let’s create a function to retrieve relevant emails using Zapier’s AI Actions:
def get_emails(search_prompt):
url = "https://actions.zapier.com/api/v2/ai-actions/01J06T8Q6TM4EVE9F3NYW1Z292/execute/"
payload = {
"instructions": search_prompt,
"params_constraints": {},
"preview_only": False
}
headers = {
"X-API-Key": os.getenv('ZAPIER_NLA_API_KEY'),
"Content-Type": "application/json"
}
response = requests.request("POST", url, json=payload, headers=headers)
response_json = json.loads(response.text)
return response_json["full_results"]
This function sends a POST request to Zapier’s API, searching for emails that match a specific prompt. The retrieved emails will be analyzed to extract invoice details.
3. Summarizing Invoices
With the emails in hand, the next step is to summarize the invoice information:
def summarize_invoices(email_body):
documents = SimpleDirectoryReader("pdf").load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
response = query_engine.query(f"""
Summarize the invoice information from the following email chain:
{email_body}
Extract and provide the following information in a structured format:
| Invoice Number | Invoice Amount | Due Date | Current Status (Paid, Promise, or Dispute) | Next Action | Summary |
|----------------|----------------|------------|--------------------------------------------|---------------------------------------|-------------------|
| | | | | | |
Email status is paid if the invoice is already paid. Status is promise if the invoice is expected to be paid soon by the client. Status is dispute if there is some discrepancy or dispute related to the invoice that is yet to be resolved.
Provide the information in a markdown table format.
""")
return response
This function uses LlamaIndex to parse and summarize the relevant information from the email body. The extracted details are formatted into a clear, structured table.
4. Deduplicating Email Threads
To avoid processing redundant information, we deduplicate email threads:
def get_latest_emails(emails):
thread_dict = {}
for email_data in emails:
if email_data['_zap_search_was_found_status']:
thread_id = email_data.get('thread_id', email_data['id']) # Use thread_id if available, else use email id
# Parse the date string using email.utils.parsedate_to_datetime
date = email.utils.parsedate_to_datetime(email_data['date'])
if thread_id not in thread_dict or date > thread_dict[thread_id]['date']:
thread_dict[thread_id] = {
'date': date,
'subject': email_data['subject'],
'body_plain': email_data['body_plain'],
'from_email': email_data['from']['email']
}
return [{'Subject': v['subject'], 'Body': v['body_plain'], 'FromEmail': v['from_email']}
for v in thread_dict.values()]
This function ensures that only the latest email from each thread is considered, minimizing duplicate entries and ensuring the most current information is processed.
5. Streamlit User Interface
Finally, here’s how you can build the user interface with Streamlit:
st.title("Invoice Status Tracker")
search_prompt = st.text_input("Enter search prompt:", value="Get all emails in inbox with 'Invoices' in the subject")
if st.button("Search Emails"):
with st.spinner("Searching emails based on the search prompt"):
if search_prompt:
emails = get_emails(search_prompt)
if emails:
# Get only the latest email from each thread
email_data = get_latest_emails(emails)
if email_data:
# Store email data in session state
st.session_state.email_data = email_data
else:
st.markdown('No emails match the search criteria')
# Display the email data if it exists in session state
if 'email_data' in st.session_state:
st.subheader("Found Emails (Latest from each thread)")
for email in st.session_state.email_data:
st.markdown(f"**Subject:** {email['Subject']}")
st.markdown(f"**From:** {email['FromEmail']}")
with st.expander("View Email Body"):
st.text(email['Body'])
st.markdown("---")
# Button to summarize invoices
if st.button("Summarize Invoice Statuses"):
with st.spinner('Analyzing emails and summarizing invoice statuses'):
all_invoice_data = []
for email in st.session_state.email_data:
response = summarize_invoices(email['Body'])
st.markdown(response.response)
This interface allows users to enter a search prompt, retrieve relevant emails, and display summaries of invoice statuses. The UI is designed to be user-friendly and interactive, making it accessible to users with varying technical expertise.
How It All Works Together
- User Input: The user enters a search prompt in the text box and clicks "Search Emails".
- Email Retrieval: The
get_emails()
function retrieves relevant emails based on the search prompt. - Deduplication: The
get_latest_emails()
function processes these emails to ensure only the latest email from each thread is used. - Display: The found emails are displayed in the Streamlit UI.
- Invoice Summarization: When the user clicks "Summarize Invoice Statuses", the
summarize_invoices()
function is called to extract and summarize the invoice details.
Benefits for Users
- Time Savings: Quickly assess invoice statuses without manually searching through email threads.
- Improved Accuracy: Automated extraction and categorization reduce the risk of human error.
- Better Cash Flow Management: Enhanced visibility into invoice statuses allows for more effective cash flow management.
- Dispute Resolution: Identifies disputed invoices early, facilitating prompt resolution.
- Audit Trail: Maintains a structured record of invoice-related communications, aiding in audits.
Check out our Github page for more code snippets and a complete app implementation. Share comments and thoughts with us at hello@cohorte.co.
Conclusion
This blog provides the main blocks to build a simple app that significantly simplifies invoice management by integrating AI. It reduces the time and effort required to track invoices, automates repetitive tasks, improves accuracy, and ultimately enhances your ability to manage cash flow and maintain healthy client relationships.
Whether managing a small business or a large enterprise, this AI-powered invoice tracker can be a game-changer, freeing your team to focus on more strategic tasks. As AI technology evolves, this tool will become increasingly indispensable in modern financial management, seamlessly bridging the gap between communication and accounting systems.