ca_invoice / app.py
jayanth-2005's picture
Update app.py
e85d379 verified
Raw History Blame Contribute Delete
4.82 kB
import streamlit as st
import pdfplumber
import pytesseract
import pandas as pd
from PIL import Image
import cv2
import numpy as np
import os
import json
from groq import Groq
st.set_page_config(page_title="AI Invoice Intelligence Engine", layout="wide")
st.title("πŸ€– AI Financial Document Intelligence")
st.write("Upload ANY invoice / receipt / subscription / purchase document")
uploaded_file = st.file_uploader(
"Upload File",
type=["pdf", "jpg", "jpeg", "png"]
)
# ---------------------------------------------------------
# TEXT EXTRACTION
# ---------------------------------------------------------
def extract_text(uploaded_file):
text = ""
if uploaded_file.type == "application/pdf":
with pdfplumber.open(uploaded_file) as pdf:
for page in pdf.pages:
page_text = page.extract_text()
if page_text:
text += page_text + "\n"
else:
image = Image.open(uploaded_file)
img_np = np.array(image)
gray = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
text = pytesseract.image_to_string(gray)
return text
# ---------------------------------------------------------
# SAFE JSON LOADER
# ---------------------------------------------------------
def safe_json_load(text):
text = text.strip()
text = text.replace("```json", "")
text = text.replace("```", "")
try:
return json.loads(text)
except:
return None
# ---------------------------------------------------------
# SPLIT LARGE DOCUMENT INTO CHUNKS
# ---------------------------------------------------------
def split_into_chunks(text, max_chars=4000):
chunks = []
current = ""
for line in text.split("\n"):
if len(current) + len(line) > max_chars:
chunks.append(current)
current = ""
current += line + "\n"
if current:
chunks.append(current)
return chunks
# ---------------------------------------------------------
# AI EXTRACTION (GROQ)
# ---------------------------------------------------------
def ai_extract_invoice(text):
client = Groq(api_key=os.getenv("GROQ_API_KEY"))
chunks = split_into_chunks(text)
invoices = []
for chunk in chunks:
prompt = f"""
You are a financial document extraction engine.
If this text contains:
- invoice
- receipt
- subscription
- payment confirmation
- order
- tax invoice
Extract structured JSON array.
Format:
[
{{
"document_type": "",
"invoice_or_order_number": "",
"invoice_date": "",
"vendor_name": "",
"vendor_gstin": null,
"taxable_amount": null,
"cgst": null,
"sgst": null,
"igst": null,
"total_amount": null
}}
]
If no financial transaction, return [].
TEXT:
{chunk}
"""
try:
completion = client.chat.completions.create(
model="llama-3.1-8b-instant",
messages=[{"role": "user", "content": prompt}],
temperature=0
)
response_text = completion.choices[0].message.content
parsed = safe_json_load(response_text)
if parsed and isinstance(parsed, list):
invoices.extend(parsed)
except Exception as e:
print("Chunk error:", e)
continue
return invoices
# ---------------------------------------------------------
# CONFIDENCE SCORE
# ---------------------------------------------------------
def calculate_confidence(row):
total_fields = len(row)
filled_fields = sum(
1 for v in row.values
if v not in [None, "", "null"]
)
return round((filled_fields / total_fields) * 100, 2)
# ---------------------------------------------------------
# MAIN EXECUTION
# ---------------------------------------------------------
if uploaded_file:
raw_text = extract_text(uploaded_file)
st.subheader("πŸ“„ Raw Text Preview")
st.text_area("Preview", raw_text[:3000], height=250)
with st.spinner("πŸ€– AI Analyzing Document..."):
invoices = ai_extract_invoice(raw_text)
if invoices:
df = pd.DataFrame(invoices).drop_duplicates()
df["confidence_%"] = df.apply(calculate_confidence, axis=1)
st.success(f"βœ… {len(df)} document(s) detected")
st.dataframe(df, use_container_width=True)
st.download_button(
"⬇ Download CSV",
df.to_csv(index=False),
"invoice_output.csv",
"text/csv"
)
else:
st.warning("⚠ No financial transaction detected.")