dpv007 commited on
Commit
015f48e
·
verified ·
1 Parent(s): d5eb738

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +30 -2
app.py CHANGED
@@ -13,7 +13,7 @@ Notes:
13
  - This version includes a robust regex-based extractor that finds the outermost {...} block
14
  in the LLM output, extracts numeric values for the required keys, and always returns
15
  numeric defaults (no NaN) so frontends will not receive null/None for numeric fields.
16
- - This variant logs raw LLM output and the parsed JSON using Python logging.
17
  """
18
 
19
  import io
@@ -276,7 +276,8 @@ def run_vlm_and_get_features(face_path: str, eye_path: str, prompt: Optional[str
276
  (parsed_features_dict_or_None, raw_text_response_str)
277
 
278
  We attempt to parse JSON as before, but always return the original raw text so it can be
279
- forwarded verbatim to the LLM if desired.
 
280
  """
281
  prompt = prompt or DEFAULT_VLM_PROMPT
282
  if not os.path.exists(face_path) or not os.path.exists(eye_path):
@@ -312,6 +313,12 @@ def run_vlm_and_get_features(face_path: str, eye_path: str, prompt: Optional[str
312
  if not text_out:
313
  text_out = json.dumps(out)
314
 
 
 
 
 
 
 
315
  # Try to parse JSON but remember raw text always
316
  parsed_features = None
317
  try:
@@ -333,6 +340,15 @@ def run_vlm_and_get_features(face_path: str, eye_path: str, prompt: Optional[str
333
  except Exception:
334
  parsed_features = None
335
 
 
 
 
 
 
 
 
 
 
336
  return parsed_features, text_out
337
 
338
  # -----------------------
@@ -735,6 +751,10 @@ async def get_vitals_from_upload(
735
  # Run VLM (off the event loop)
736
  vlm_features, vlm_raw = await asyncio.to_thread(run_vlm_and_get_features, face_path, eye_path)
737
 
 
 
 
 
738
  # Prefer sending raw vlm text to LLM (same behavior as process_screening)
739
  llm_input = vlm_raw if vlm_raw else (vlm_features if vlm_features else "{}")
740
 
@@ -770,6 +790,10 @@ async def get_vitals_for_screening(screening_id: str):
770
  # Run VLM off the event loop
771
  vlm_features, vlm_raw = await asyncio.to_thread(run_vlm_and_get_features, face_path, eye_path)
772
 
 
 
 
 
773
  llm_input = vlm_raw if vlm_raw else (vlm_features if vlm_features else "{}")
774
  structured_risk = await asyncio.to_thread(run_llm_on_vlm, llm_input)
775
 
@@ -901,6 +925,10 @@ async def process_screening(screening_id: str):
901
  vlm_features = None
902
  vlm_raw = None
903
 
 
 
 
 
904
  # --------------------------
905
  # RUN LLM on vlm_raw (preferred) or vlm_features -> structured risk JSON
906
  # --------------------------
 
13
  - This version includes a robust regex-based extractor that finds the outermost {...} block
14
  in the LLM output, extracts numeric values for the required keys, and always returns
15
  numeric defaults (no NaN) so frontends will not receive null/None for numeric fields.
16
+ - This variant logs raw VLM & LLM outputs and the parsed JSON using Python logging.
17
  """
18
 
19
  import io
 
276
  (parsed_features_dict_or_None, raw_text_response_str)
277
 
278
  We attempt to parse JSON as before, but always return the original raw text so it can be
279
+ forwarded verbatim to the LLM if desired. This function now logs the raw VLM output and
280
+ the parsed features for debugging.
281
  """
282
  prompt = prompt or DEFAULT_VLM_PROMPT
283
  if not os.path.exists(face_path) or not os.path.exists(eye_path):
 
313
  if not text_out:
314
  text_out = json.dumps(out)
315
 
316
+ # Log raw VLM output for debugging/auditing
317
+ try:
318
+ logger.info("VLM raw output:\n%s", text_out)
319
+ except Exception:
320
+ logger.info("VLM raw output (could not pretty print)")
321
+
322
  # Try to parse JSON but remember raw text always
323
  parsed_features = None
324
  try:
 
340
  except Exception:
341
  parsed_features = None
342
 
343
+ # Log parsed features if available
344
+ if parsed_features is not None:
345
+ try:
346
+ logger.info("VLM parsed features:\n%s", json.dumps(parsed_features, indent=2, ensure_ascii=False))
347
+ except Exception:
348
+ logger.info("VLM parsed features (raw): %s", str(parsed_features))
349
+ else:
350
+ logger.info("VLM parsed features: None (raw output kept)")
351
+
352
  return parsed_features, text_out
353
 
354
  # -----------------------
 
751
  # Run VLM (off the event loop)
752
  vlm_features, vlm_raw = await asyncio.to_thread(run_vlm_and_get_features, face_path, eye_path)
753
 
754
+ # Log VLM outputs (already logged inside run_vlm..., but log again with context)
755
+ logger.info("get_vitals_from_upload - VLM raw (snippet): %s", (vlm_raw[:100] + "...") if vlm_raw else "None")
756
+ logger.info("get_vitals_from_upload - VLM parsed features: %s", vlm_features if vlm_features is not None else "None")
757
+
758
  # Prefer sending raw vlm text to LLM (same behavior as process_screening)
759
  llm_input = vlm_raw if vlm_raw else (vlm_features if vlm_features else "{}")
760
 
 
790
  # Run VLM off the event loop
791
  vlm_features, vlm_raw = await asyncio.to_thread(run_vlm_and_get_features, face_path, eye_path)
792
 
793
+ # Log VLM outputs
794
+ logger.info("get_vitals_for_screening(%s) - VLM raw (snippet): %s", screening_id, (vlm_raw[:100] + "...") if vlm_raw else "None")
795
+ logger.info("get_vitals_for_screening(%s) - VLM parsed features: %s", screening_id, vlm_features if vlm_features is not None else "None")
796
+
797
  llm_input = vlm_raw if vlm_raw else (vlm_features if vlm_features else "{}")
798
  structured_risk = await asyncio.to_thread(run_llm_on_vlm, llm_input)
799
 
 
925
  vlm_features = None
926
  vlm_raw = None
927
 
928
+ # Log VLM outputs in pipeline context
929
+ logger.info("process_screening(%s) - VLM raw (snippet): %s", screening_id, (vlm_raw[:100] + "...") if vlm_raw else "None")
930
+ logger.info("process_screening(%s) - VLM parsed features: %s", screening_id, vlm_features if vlm_features is not None else "None")
931
+
932
  # --------------------------
933
  # RUN LLM on vlm_raw (preferred) or vlm_features -> structured risk JSON
934
  # --------------------------