capradeepgujaran commited on
Commit
d9b720f
·
verified ·
1 Parent(s): 09a15da

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +193 -0
app.py ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ from dotenv import load_dotenv
4
+ import pandas as pd
5
+ from groq import Groq
6
+ from PIL import Image
7
+ import base64
8
+ import io
9
+ import openpyxl
10
+ from datetime import datetime
11
+
12
+ # Load environment variables from .env file
13
+ load_dotenv()
14
+
15
+ # Initialize Groq client
16
+ client = Groq(
17
+ api_key=os.environ.get("GROQ_API_KEY")
18
+ )
19
+
20
+ def encode_image_to_base64(image_path):
21
+ """Convert image to base64 string"""
22
+ with open(image_path, "rb") as image_file:
23
+ return base64.b64encode(image_file.read()).decode('utf-8')
24
+
25
+ def extract_invoice_details(image):
26
+ """Extract invoice details using Groq's vision model"""
27
+ # Save the uploaded image temporarily
28
+ temp_path = "temp_invoice.png"
29
+ image.save(temp_path)
30
+
31
+ # Convert image to base64
32
+ base64_image = encode_image_to_base64(temp_path)
33
+
34
+ # Remove temporary file
35
+ os.remove(temp_path)
36
+
37
+ # Prepare the prompt
38
+ prompt = """Analyze this invoice image and provide ONLY ONE dictionary with the following format, including all line items. Remove any special characters (*, #, $) and format numbers as plain decimal values:
39
+
40
+ {
41
+ "Invoice Number": "inv-00", # Remove special chars, keep alphanumeric only
42
+ "Invoice Date": "07/07/2025", # Use MM/DD/YYYY format
43
+ "Items": [
44
+ {
45
+ "Item Name": "Product 1", # Clean text only
46
+ "Price/Rate": "40.00", # Numeric only
47
+ "Quantity": "2", # Numeric only
48
+ "Amount": "80.00" # Numeric only
49
+ },
50
+ {
51
+ "Item Name": "Product 2",
52
+ "Price/Rate": "19.00",
53
+ "Quantity": "6",
54
+ "Amount": "114.00"
55
+ }
56
+ ],
57
+ "Total Invoice Value": "2555.00" # Numeric only, total amount
58
+ }
59
+
60
+ Provide ONLY the dictionary, no additional text or formatting."""
61
+
62
+ # Make API call to Groq
63
+ response = client.chat.completions.create(
64
+ model="llama-3.2-90b-vision-preview",
65
+ messages=[
66
+ {
67
+ "role": "user",
68
+ "content": [
69
+ {
70
+ "type": "image_url",
71
+ "image_url": {
72
+ "url": f"data:image/png;base64,{base64_image}"
73
+ }
74
+ },
75
+ {
76
+ "type": "text",
77
+ "text": prompt
78
+ }
79
+ ]
80
+ }
81
+ ]
82
+ )
83
+
84
+ return response.choices[0].message.content
85
+
86
+ def parse_response(response_text):
87
+ """Parse the model's response into structured data"""
88
+ try:
89
+ # Find the dictionary part of the response
90
+ start_idx = response_text.find('{')
91
+ end_idx = response_text.rfind('}') + 1
92
+ if start_idx != -1 and end_idx != -1:
93
+ dict_str = response_text[start_idx:end_idx]
94
+ # Safely evaluate the dictionary string
95
+ data = eval(dict_str)
96
+
97
+ # Create rows for each item in the items list
98
+ rows = []
99
+ for item in data.get('Items', []):
100
+ row = {
101
+ 'Invoice Number': data.get('Invoice Number', ''),
102
+ 'Invoice Date': data.get('Invoice Date', ''),
103
+ 'Item Name': item.get('Item Name', ''),
104
+ 'Price/Rate': item.get('Price/Rate', ''),
105
+ 'Quantity': item.get('Quantity', ''),
106
+ 'Amount': item.get('Amount', ''),
107
+ 'Total Invoice Value': data.get('Total Invoice Value', '')
108
+ }
109
+ rows.append(row)
110
+
111
+ return rows
112
+ except Exception as e:
113
+ print(f"Error parsing response: {e}")
114
+ return [{
115
+ 'Invoice Number': '',
116
+ 'Invoice Date': '',
117
+ 'Item Name': '',
118
+ 'Price/Rate': '',
119
+ 'Quantity': '',
120
+ 'Amount': '',
121
+ 'Total Invoice Value': ''
122
+ }]
123
+
124
+ def save_to_excel(data_rows):
125
+ """Save cleaned extracted data to Excel file"""
126
+ excel_file = "invoice_data.xlsx"
127
+
128
+ # Create new DataFrame with the current data only
129
+ df = pd.DataFrame(data_rows, columns=[
130
+ 'Invoice Number', 'Invoice Date', 'Item Name',
131
+ 'Price/Rate', 'Quantity', 'Amount', 'Total Invoice Value'
132
+ ])
133
+
134
+ # Apply number formatting for currency columns
135
+ currency_columns = ['Price/Rate', 'Amount', 'Total Invoice Value']
136
+ for col in currency_columns:
137
+ df[col] = pd.to_numeric(df[col], errors='ignore')
138
+
139
+ # Save to Excel with formatting
140
+ with pd.ExcelWriter(excel_file, engine='openpyxl') as writer:
141
+ df.to_excel(writer, index=False, sheet_name='Invoice Data')
142
+
143
+ # Get the workbook and worksheet
144
+ workbook = writer.book
145
+ worksheet = writer.sheets['Invoice Data']
146
+
147
+ # Apply currency formatting to relevant columns
148
+ for col_idx, col_name in enumerate(df.columns):
149
+ if col_name in currency_columns:
150
+ for row in range(2, len(df) + 2): # Start from row 2 to skip header
151
+ cell = worksheet.cell(row=row, column=col_idx + 1)
152
+ cell.number_format = '$#,##0.00'
153
+
154
+ return excel_file
155
+
156
+ def process_invoice(image):
157
+ """Main function to process invoice image"""
158
+ try:
159
+ # Extract text from image
160
+ extracted_text = extract_invoice_details(image)
161
+
162
+ # Parse the response
163
+ data = parse_response(extracted_text)
164
+
165
+ # Save to Excel
166
+ excel_path = save_to_excel(data)
167
+
168
+ return (
169
+ f"Successfully processed invoice!\n\n"
170
+ f"Extracted Information:\n{extracted_text}",
171
+ excel_path
172
+ )
173
+
174
+ except Exception as e:
175
+ return f"Error processing invoice: {str(e)}", None
176
+
177
+ # Create Gradio interface
178
+ iface = gr.Interface(
179
+ fn=process_invoice,
180
+ inputs=gr.Image(type="pil", label="Upload Handwritten Invoice"),
181
+ outputs=[
182
+ gr.Textbox(label="Processing Result"),
183
+ gr.File(label="Download Excel File")
184
+ ],
185
+ title="Handwritten Invoice Processor",
186
+ description="Upload a handwritten invoice to extract key information and save it to Excel.",
187
+ examples=[],
188
+ theme=gr.themes.Base()
189
+ )
190
+
191
+ # Launch the application
192
+ if __name__ == "__main__":
193
+ iface.launch()