LPX commited on
Commit
0f427f3
·
1 Parent(s): febce11

feat: implement custom JSON encoder for numpy types and ensure type consistency in inference results

Browse files
Files changed (2) hide show
  1. app_mcp.py +18 -3
  2. utils/hf_logger.py +13 -5
app_mcp.py CHANGED
@@ -38,6 +38,13 @@ os.environ['HF_HUB_CACHE'] = './models'
38
  load_dotenv()
39
  # print(os.getenv("HF_HUB_CACHE"))
40
 
 
 
 
 
 
 
 
41
  # Ensure using GPU if available
42
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
43
 
@@ -221,8 +228,8 @@ def infer(image: Image.Image, model_id: str, confidence_threshold: float = 0.75)
221
  result = entry.model(img)
222
  scores = entry.postprocess(result, entry.class_names)
223
  # Flatten output for Dataframe: include metadata and both class scores
224
- ai_score = scores.get(entry.class_names[0], 0.0)
225
- real_score = scores.get(entry.class_names[1], 0.0)
226
  label = "AI" if ai_score >= confidence_threshold else ("REAL" if real_score >= confidence_threshold else "UNCERTAIN")
227
  return {
228
  "Model": entry.display_name,
@@ -462,8 +469,16 @@ def predict_image_with_json(img, confidence_threshold, augment_methods, rotate_d
462
 
463
  logger.info(f"Cleaned forensic images types: {[type(img) for img in cleaned_forensics_images]}")
464
 
 
 
 
 
 
 
 
 
465
  # Return raw model results as JSON string for debug_json component
466
- json_results = json.dumps(results)
467
 
468
  return img_pil, cleaned_forensics_images, table_rows, json_results, consensus_html
469
 
 
38
  load_dotenv()
39
  # print(os.getenv("HF_HUB_CACHE"))
40
 
41
+ # Custom JSON Encoder to handle numpy types
42
+ class NumpyEncoder(json.JSONEncoder):
43
+ def default(self, obj):
44
+ if isinstance(obj, np.float32):
45
+ return float(obj)
46
+ return json.JSONEncoder.default(self, obj)
47
+
48
  # Ensure using GPU if available
49
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
50
 
 
228
  result = entry.model(img)
229
  scores = entry.postprocess(result, entry.class_names)
230
  # Flatten output for Dataframe: include metadata and both class scores
231
+ ai_score = float(scores.get(entry.class_names[0], 0.0))
232
+ real_score = float(scores.get(entry.class_names[1], 0.0))
233
  label = "AI" if ai_score >= confidence_threshold else ("REAL" if real_score >= confidence_threshold else "UNCERTAIN")
234
  return {
235
  "Model": entry.display_name,
 
469
 
470
  logger.info(f"Cleaned forensic images types: {[type(img) for img in cleaned_forensics_images]}")
471
 
472
+ # Ensure numerical values in results are standard Python floats before JSON serialization
473
+ for i, res_dict in enumerate(results):
474
+ for key in ["AI Score", "Real Score"]:
475
+ value = res_dict.get(key)
476
+ if isinstance(value, np.float32):
477
+ res_dict[key] = float(value)
478
+ logger.info(f"Converted {key} for result {i} from numpy.float32 to float.")
479
+
480
  # Return raw model results as JSON string for debug_json component
481
+ json_results = json.dumps(results, cls=NumpyEncoder)
482
 
483
  return img_pil, cleaned_forensics_images, table_rows, json_results, consensus_html
484
 
utils/hf_logger.py CHANGED
@@ -7,11 +7,19 @@ from PIL import Image
7
  import logging
8
  from datasets import Dataset, load_dataset, Features, Value, Sequence
9
  import copy
 
10
 
11
  logger = logging.getLogger(__name__)
12
 
13
  HF_DATASET_NAME = "aiwithoutborders-xyz/degentic_rd0" # TODO: Replace with your actual HF username and dataset name
14
 
 
 
 
 
 
 
 
15
  def _pil_to_base64(image: Image.Image) -> str:
16
  """Converts a PIL Image to a base64 string."""
17
  # Explicitly check if the input is a PIL Image
@@ -91,12 +99,12 @@ def log_inference_data(
91
  new_entry = {
92
  "timestamp": datetime.datetime.now().isoformat(),
93
  "image": original_image_b64,
94
- "inference_request": json.dumps(inference_params),
95
- "model_predictions": json.dumps(model_predictions),
96
- "ensemble_output": json.dumps(ensemble_output),
97
  "forensic_outputs": forensic_images_b64, # This is already a list of strings
98
- "agent_monitoring_data": json.dumps(agent_monitoring_data),
99
- "human_feedback": json.dumps(human_feedback if human_feedback is not None else {})
100
  }
101
 
102
  # Get current dataset features
 
7
  import logging
8
  from datasets import Dataset, load_dataset, Features, Value, Sequence
9
  import copy
10
+ import numpy as np
11
 
12
  logger = logging.getLogger(__name__)
13
 
14
  HF_DATASET_NAME = "aiwithoutborders-xyz/degentic_rd0" # TODO: Replace with your actual HF username and dataset name
15
 
16
+ # Custom JSON Encoder to handle numpy types (copy from app_mcp.py if it's identical)
17
+ class NumpyEncoder(json.JSONEncoder):
18
+ def default(self, obj):
19
+ if isinstance(obj, np.float32):
20
+ return float(obj)
21
+ return json.JSONEncoder.default(self, obj)
22
+
23
  def _pil_to_base64(image: Image.Image) -> str:
24
  """Converts a PIL Image to a base64 string."""
25
  # Explicitly check if the input is a PIL Image
 
99
  new_entry = {
100
  "timestamp": datetime.datetime.now().isoformat(),
101
  "image": original_image_b64,
102
+ "inference_request": json.dumps(inference_params, cls=NumpyEncoder),
103
+ "model_predictions": json.dumps(model_predictions, cls=NumpyEncoder),
104
+ "ensemble_output": json.dumps(ensemble_output, cls=NumpyEncoder),
105
  "forensic_outputs": forensic_images_b64, # This is already a list of strings
106
+ "agent_monitoring_data": json.dumps(agent_monitoring_data, cls=NumpyEncoder),
107
+ "human_feedback": json.dumps(human_feedback if human_feedback is not None else {}, cls=NumpyEncoder)
108
  }
109
 
110
  # Get current dataset features