Seth0330 commited on
Commit
e47273e
·
verified ·
1 Parent(s): a1fcd1d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +62 -10
app.py CHANGED
@@ -16,7 +16,6 @@ OPENROUTER_URL = "https://openrouter.ai/api/v1/chat/completions"
16
  GEMMA_MODEL = "google/gemma-3-4b-it:free"
17
 
18
  st.set_page_config(page_title="EZOFIS Document Validation Agent", layout="wide")
19
-
20
  st.markdown("""
21
  <style>
22
  .block-card {
@@ -39,7 +38,7 @@ st.markdown(
39
  unsafe_allow_html=True
40
  )
41
  st.markdown(
42
- "<div style='font-size:20px; margin-bottom:28px; color:#24345C;'>AI-driven checklist-based document acceptance for mortgage applications.</div>",
43
  unsafe_allow_html=True
44
  )
45
 
@@ -174,6 +173,44 @@ def query_gemma_llm(doc_text, checklist, status_box=None):
174
  status_box.write(result)
175
  return None, result, prompt
176
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  def fuzzy_match_type(detected_type, checklist_types):
178
  best_type = None
179
  best_score = 0
@@ -219,6 +256,10 @@ uploaded_files = st.file_uploader(
219
  accept_multiple_files=True
220
  )
221
 
 
 
 
 
222
  # ========== PROCESSING ==========
223
  if st.button("Run Document Validation", type="primary") and uploaded_files:
224
  results = []
@@ -254,17 +295,17 @@ if st.button("Run Document Validation", type="primary") and uploaded_files:
254
  detected_type = llm_json.get("document_type", "")
255
  matched_type, match_score = fuzzy_match_type(detected_type, required_types)
256
 
257
- # Accept only if LLM states checklist_matched, looks genuine, and not expired
258
  checklist_matched = llm_json.get("checklist_matched", False)
259
- if checklist_matched:
260
- # Double check: If match_score < 65, override to not matched
261
- if match_score < 65:
262
- checklist_matched = False
263
 
 
264
  accepted = (
265
  checklist_matched and
266
  llm_json.get("looks_genuine", False) and
267
- not llm_json.get("is_expired", False)
 
268
  )
269
 
270
  reason = []
@@ -279,9 +320,20 @@ if st.button("Run Document Validation", type="primary") and uploaded_files:
279
  if llm_json.get("is_expired", False):
280
  reason.append("Document is expired.")
281
 
282
- reason.append(f"Genuineness confidence: {llm_json.get('confidence', 0)}.")
283
  reason.append(llm_json.get("verdict", ""))
284
 
 
 
 
 
 
 
 
 
 
 
 
285
  results.append({
286
  "File": uploaded_file.name,
287
  "Detected Type": detected_type,
@@ -290,7 +342,7 @@ if st.button("Run Document Validation", type="primary") and uploaded_files:
290
  "Expiry Date": llm_json.get("expiry_date", "-"),
291
  "Expired": "Yes" if llm_json.get("is_expired", False) else "No",
292
  "Genuine": "Yes" if llm_json.get("looks_genuine", False) else "No",
293
- "Confidence": llm_json.get("confidence", "-"),
294
  "Accepted": "Yes" if accepted else "No",
295
  "Reason": " ".join(reason)
296
  })
 
16
  GEMMA_MODEL = "google/gemma-3-4b-it:free"
17
 
18
  st.set_page_config(page_title="EZOFIS Document Validation Agent", layout="wide")
 
19
  st.markdown("""
20
  <style>
21
  .block-card {
 
38
  unsafe_allow_html=True
39
  )
40
  st.markdown(
41
+ "<div style='font-size:20px; margin-bottom:28px; color:#24345C;'>AI-driven, agentic document acceptance for mortgage applications.</div>",
42
  unsafe_allow_html=True
43
  )
44
 
 
173
  status_box.write(result)
174
  return None, result, prompt
175
 
176
+ def advanced_llm_verdict(llm_json, min_confidence, status_box=None):
177
+ # Only trigger if confidence is in gray zone: [min_confidence, min_confidence+15)
178
+ conf = llm_json.get("confidence", 0)
179
+ if conf < min_confidence or conf >= min_confidence + 15:
180
+ return None, None, None
181
+ verdict_prompt = f"""
182
+ Here is the extracted document information and prior validation result:
183
+ {json.dumps(llm_json)}
184
+
185
+ The minimum required confidence is {min_confidence}. Should this document be accepted or rejected for a mortgage application, based on all available information?
186
+ Respond ONLY as: {{ "accepted": true/false, "reason": "..." }}
187
+ """
188
+ headers = {
189
+ "Authorization": f"Bearer {OPENROUTER_API_KEY}",
190
+ "HTTP-Referer": "https://chat.openai.com",
191
+ "X-Title": "EZOFIS-Doc-Validator",
192
+ "Content-Type": "application/json",
193
+ }
194
+ data = {
195
+ "model": GEMMA_MODEL,
196
+ "messages": [{"role": "user", "content": verdict_prompt}],
197
+ "temperature": 0.1,
198
+ "max_tokens": 256
199
+ }
200
+ if status_box:
201
+ status_box.info("Step 3: LLM self-verdict (gray zone confidence)...")
202
+ resp = requests.post(OPENROUTER_URL, headers=headers, json=data, timeout=60)
203
+ if resp.status_code == 200:
204
+ try:
205
+ content = resp.json()["choices"][0]["message"]["content"]
206
+ vstart = content.find("{")
207
+ vend = content.rfind("}") + 1
208
+ verdict_json = json.loads(content[vstart:vend])
209
+ return verdict_json, content, verdict_prompt
210
+ except Exception:
211
+ return None, content, verdict_prompt
212
+ return None, None, verdict_prompt
213
+
214
  def fuzzy_match_type(detected_type, checklist_types):
215
  best_type = None
216
  best_score = 0
 
256
  accept_multiple_files=True
257
  )
258
 
259
+ st.markdown("<span class='step-num'>3</span> <b>Configure Acceptance Thresholds</b>", unsafe_allow_html=True)
260
+ min_match_score = st.slider("Minimum Type Match Score (0-100)", 50, 100, 70, 1)
261
+ min_confidence = st.slider("Minimum LLM Confidence (0-100)", 50, 100, 70, 1)
262
+
263
  # ========== PROCESSING ==========
264
  if st.button("Run Document Validation", type="primary") and uploaded_files:
265
  results = []
 
295
  detected_type = llm_json.get("document_type", "")
296
  matched_type, match_score = fuzzy_match_type(detected_type, required_types)
297
 
298
+ # Accept only if LLM states checklist_matched, looks genuine, and not expired, and confidence high enough
299
  checklist_matched = llm_json.get("checklist_matched", False)
300
+ if checklist_matched and match_score < min_match_score:
301
+ checklist_matched = False
 
 
302
 
303
+ llm_conf = llm_json.get("confidence", 0)
304
  accepted = (
305
  checklist_matched and
306
  llm_json.get("looks_genuine", False) and
307
+ not llm_json.get("is_expired", False) and
308
+ (llm_conf >= min_confidence)
309
  )
310
 
311
  reason = []
 
320
  if llm_json.get("is_expired", False):
321
  reason.append("Document is expired.")
322
 
323
+ reason.append(f"Genuineness confidence: {llm_conf}.")
324
  reason.append(llm_json.get("verdict", ""))
325
 
326
+ # Advanced agent: If confidence is in a "gray zone", ask the LLM for a final self-verdict
327
+ verdict_json, verdict_raw, verdict_prompt = advanced_llm_verdict(llm_json, min_confidence, status_box)
328
+ debug['LLM_self_verdict_prompt'] = verdict_prompt
329
+ debug['LLM_self_verdict_raw'] = verdict_raw
330
+ debug['LLM_self_verdict_json'] = verdict_json
331
+
332
+ if verdict_json:
333
+ accepted = verdict_json.get("accepted", False)
334
+ reason.append(f"LLM Self-verdict: {verdict_json.get('reason','')}")
335
+ status_box.info("Final decision (gray zone) taken by LLM self-verdict.")
336
+
337
  results.append({
338
  "File": uploaded_file.name,
339
  "Detected Type": detected_type,
 
342
  "Expiry Date": llm_json.get("expiry_date", "-"),
343
  "Expired": "Yes" if llm_json.get("is_expired", False) else "No",
344
  "Genuine": "Yes" if llm_json.get("looks_genuine", False) else "No",
345
+ "Confidence": llm_conf,
346
  "Accepted": "Yes" if accepted else "No",
347
  "Reason": " ".join(reason)
348
  })