ngupta2026 commited on
Commit
04107b1
Β·
verified Β·
1 Parent(s): f5ff3d2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -23
app.py CHANGED
@@ -41,11 +41,18 @@ def normalize(box, width, height):
41
  ]
42
 
43
  # =====================================================
44
- # EXTRACT DATA
 
 
 
 
 
 
 
 
45
  # =====================================================
46
  def extract_receipt(image):
47
  try:
48
- # πŸ”₯ Speed optimization
49
  image = image.convert("RGB")
50
  image.thumbnail((1200, 1200))
51
 
@@ -54,8 +61,7 @@ def extract_receipt(image):
54
  output_type=pytesseract.Output.DICT
55
  )
56
 
57
- words = []
58
- boxes = []
59
 
60
  for i in range(len(data["text"])):
61
  text = data["text"][i].strip()
@@ -90,7 +96,10 @@ def extract_receipt(image):
90
  with torch.no_grad():
91
  outputs = model(**encoding)
92
 
93
- predictions = torch.argmax(outputs.logits, dim=2)[0][:len(words)]
 
 
 
94
 
95
  result = {
96
  "company": [],
@@ -98,39 +107,70 @@ def extract_receipt(image):
98
  "total": []
99
  }
100
 
101
- for word, pred in zip(words, predictions):
 
 
 
 
 
 
102
  label = id2label[pred.item()]
 
103
 
104
  if label == "COMPANY":
105
  result["company"].append(word)
 
106
 
107
  if re.search(r"\d{2}[/-]\d{2}[/-]\d{2,4}", word):
108
  result["date"].append(word)
 
109
 
110
  if re.search(r"\d+(\.\d{2})?", word):
111
  try:
112
  value = float(word.replace(",", ""))
113
  if value > 50:
114
  result["total"].append(word)
 
115
  except:
116
  pass
117
 
 
118
  result["company"] = " ".join(result["company"]) if result["company"] else "Not Found"
119
  result["date"] = result["date"][0] if result["date"] else "Not Found"
120
  result["total"] = result["total"][-1] if result["total"] else "Not Found"
121
 
 
 
 
 
 
 
 
 
 
122
  return result
123
 
124
  except Exception as e:
125
  return {"error": str(e)}
126
 
127
  # =====================================================
128
- # SEND EMAIL (RESEND API - WORKING)
 
 
 
 
 
 
 
 
 
 
 
129
  # =====================================================
130
  def send_claim_email(to_email, extracted):
131
 
132
  if not RESEND_API_KEY:
133
- return "❌ RESEND_API_KEY missing in HuggingFace Secrets"
134
 
135
  subject = "Insurance Claim Request"
136
 
@@ -139,7 +179,6 @@ def send_claim_email(to_email, extracted):
139
  <p><b>Provider:</b> {extracted['company']}</p>
140
  <p><b>Date:</b> {extracted['date']}</p>
141
  <p><b>Amount:</b> β‚Ή{extracted['total']}</p>
142
- <p>Please process this claim.</p>
143
  """
144
 
145
  try:
@@ -150,7 +189,7 @@ def send_claim_email(to_email, extracted):
150
  "Content-Type": "application/json",
151
  },
152
  json={
153
- "from": "onboarding@resend.dev",
154
  "to": [to_email],
155
  "subject": subject,
156
  "html": html_body,
@@ -158,10 +197,8 @@ def send_claim_email(to_email, extracted):
158
  timeout=10
159
  )
160
 
161
- print("EMAIL RESPONSE:", response.status_code, response.text)
162
-
163
  if response.status_code in [200, 201]:
164
- return f"βœ… Email sent successfully to {to_email}"
165
  else:
166
  return f"❌ Email failed: {response.text}"
167
 
@@ -169,23 +206,29 @@ def send_claim_email(to_email, extracted):
169
  return f"❌ Email error: {str(e)}"
170
 
171
  # =====================================================
172
- # MAIN FUNCTION
173
  # =====================================================
174
  def process_and_send(image, email_id):
175
 
176
- print("Processing started...")
177
-
178
  extracted = extract_receipt(image)
179
- print("Extracted:", extracted)
180
 
181
  if "error" in extracted:
182
  return extracted, extracted["error"]
183
 
184
- print("Sending email to:", email_id)
 
 
 
 
 
 
 
 
185
 
186
- email_status = send_claim_email(email_id, extracted)
 
187
 
188
- print("Email status:", email_status)
189
 
190
  return extracted, email_status
191
 
@@ -199,11 +242,11 @@ demo = gr.Interface(
199
  gr.Textbox(label="Enter Email ID")
200
  ],
201
  outputs=[
202
- gr.JSON(label="Extracted Data"),
203
  gr.Textbox(label="Email Status")
204
  ],
205
- title="πŸ“„ AI Insurance Claim Generator",
206
- description="Upload receipt β†’ Extract details β†’ Auto send claim email"
207
  )
208
 
209
  demo.launch()
 
41
  ]
42
 
43
  # =====================================================
44
+ # CONFIDENCE HELPER
45
+ # =====================================================
46
+ def avg_conf(lst):
47
+ if len(lst) == 0:
48
+ return 0
49
+ return sum(lst) / len(lst)
50
+
51
+ # =====================================================
52
+ # EXTRACT DATA + CONFIDENCE
53
  # =====================================================
54
  def extract_receipt(image):
55
  try:
 
56
  image = image.convert("RGB")
57
  image.thumbnail((1200, 1200))
58
 
 
61
  output_type=pytesseract.Output.DICT
62
  )
63
 
64
+ words, boxes = [], []
 
65
 
66
  for i in range(len(data["text"])):
67
  text = data["text"][i].strip()
 
96
  with torch.no_grad():
97
  outputs = model(**encoding)
98
 
99
+ # πŸ”₯ CONFIDENCE LOGIC
100
+ probs = torch.softmax(outputs.logits, dim=2)
101
+ preds = torch.argmax(probs, dim=2)[0][:len(words)]
102
+ confs = torch.max(probs, dim=2)[0][0][:len(words)]
103
 
104
  result = {
105
  "company": [],
 
107
  "total": []
108
  }
109
 
110
+ conf_store = {
111
+ "company": [],
112
+ "date": [],
113
+ "total": []
114
+ }
115
+
116
+ for word, pred, conf in zip(words, preds, confs):
117
  label = id2label[pred.item()]
118
+ confidence = conf.item()
119
 
120
  if label == "COMPANY":
121
  result["company"].append(word)
122
+ conf_store["company"].append(confidence)
123
 
124
  if re.search(r"\d{2}[/-]\d{2}[/-]\d{2,4}", word):
125
  result["date"].append(word)
126
+ conf_store["date"].append(confidence)
127
 
128
  if re.search(r"\d+(\.\d{2})?", word):
129
  try:
130
  value = float(word.replace(",", ""))
131
  if value > 50:
132
  result["total"].append(word)
133
+ conf_store["total"].append(confidence)
134
  except:
135
  pass
136
 
137
+ # FINAL VALUES
138
  result["company"] = " ".join(result["company"]) if result["company"] else "Not Found"
139
  result["date"] = result["date"][0] if result["date"] else "Not Found"
140
  result["total"] = result["total"][-1] if result["total"] else "Not Found"
141
 
142
+ # πŸ”₯ FINAL CONFIDENCE
143
+ company_conf = avg_conf(conf_store["company"])
144
+ date_conf = avg_conf(conf_store["date"])
145
+ total_conf = avg_conf(conf_store["total"])
146
+
147
+ overall_conf = (company_conf + date_conf + total_conf) / 3
148
+
149
+ result["confidence"] = round(overall_conf, 3)
150
+
151
  return result
152
 
153
  except Exception as e:
154
  return {"error": str(e)}
155
 
156
  # =====================================================
157
+ # DECISION ENGINE
158
+ # =====================================================
159
+ def decision_layer(confidence):
160
+ if confidence > 0.9:
161
+ return "AUTO_SEND"
162
+ elif confidence > 0.7:
163
+ return "REVIEW"
164
+ else:
165
+ return "REJECT"
166
+
167
+ # =====================================================
168
+ # SEND EMAIL (RESEND)
169
  # =====================================================
170
  def send_claim_email(to_email, extracted):
171
 
172
  if not RESEND_API_KEY:
173
+ return "❌ RESEND_API_KEY missing"
174
 
175
  subject = "Insurance Claim Request"
176
 
 
179
  <p><b>Provider:</b> {extracted['company']}</p>
180
  <p><b>Date:</b> {extracted['date']}</p>
181
  <p><b>Amount:</b> β‚Ή{extracted['total']}</p>
 
182
  """
183
 
184
  try:
 
189
  "Content-Type": "application/json",
190
  },
191
  json={
192
+ "from": "onboarding@resend.dev", # change after domain verify
193
  "to": [to_email],
194
  "subject": subject,
195
  "html": html_body,
 
197
  timeout=10
198
  )
199
 
 
 
200
  if response.status_code in [200, 201]:
201
+ return f"βœ… Email sent to {to_email}"
202
  else:
203
  return f"❌ Email failed: {response.text}"
204
 
 
206
  return f"❌ Email error: {str(e)}"
207
 
208
  # =====================================================
209
+ # MAIN PIPELINE
210
  # =====================================================
211
  def process_and_send(image, email_id):
212
 
 
 
213
  extracted = extract_receipt(image)
 
214
 
215
  if "error" in extracted:
216
  return extracted, extracted["error"]
217
 
218
+ confidence = extracted.get("confidence", 0)
219
+ decision = decision_layer(confidence)
220
+
221
+ # πŸ”₯ DECISION CONTROL
222
+ if decision == "AUTO_SEND":
223
+ email_status = send_claim_email(email_id, extracted)
224
+
225
+ elif decision == "REVIEW":
226
+ email_status = f"⚠️ Needs human review (confidence={confidence})"
227
 
228
+ else:
229
+ email_status = f"❌ Rejected due to low confidence ({confidence})"
230
 
231
+ extracted["decision"] = decision
232
 
233
  return extracted, email_status
234
 
 
242
  gr.Textbox(label="Enter Email ID")
243
  ],
244
  outputs=[
245
+ gr.JSON(label="Extracted Data + Confidence + Decision"),
246
  gr.Textbox(label="Email Status")
247
  ],
248
+ title="πŸ“„ AI Insurance Claim Generator (Enterprise Version)",
249
+ description="Upload receipt β†’ AI extracts β†’ Confidence check β†’ Safe decision β†’ Email"
250
  )
251
 
252
  demo.launch()