LPX
commited on
Commit
·
febce11
1
Parent(s):
679e047
feat: improve JSON handling and type safety in inference results and dataset logging
Browse files- app_mcp.py +32 -8
- utils/hf_logger.py +34 -21
app_mcp.py
CHANGED
|
@@ -27,6 +27,7 @@ from agents.smart_agents import ContextualIntelligenceAgent, ForensicAnomalyDete
|
|
| 27 |
from forensics.registry import register_model, MODEL_REGISTRY, ModelEntry
|
| 28 |
from agents.weight_management import ModelWeightManager
|
| 29 |
from dotenv import load_dotenv
|
|
|
|
| 30 |
|
| 31 |
# Configure logging
|
| 32 |
logging.basicConfig(level=logging.INFO)
|
|
@@ -236,8 +237,8 @@ def infer(image: Image.Image, model_id: str, confidence_threshold: float = 0.75)
|
|
| 236 |
"Model": entry.display_name,
|
| 237 |
"Contributor": entry.contributor,
|
| 238 |
"HF Model Path": entry.model_path,
|
| 239 |
-
"AI Score":
|
| 240 |
-
"Real Score":
|
| 241 |
"Label": f"Error: {str(e)}"
|
| 242 |
}
|
| 243 |
|
|
@@ -386,11 +387,15 @@ def predict_image_with_json(img, confidence_threshold, augment_methods, rotate_d
|
|
| 386 |
table_rows = [[
|
| 387 |
r.get("Model", ""),
|
| 388 |
r.get("Contributor", ""),
|
| 389 |
-
r.get("AI Score", ""),
|
| 390 |
-
r.get("Real Score", ""),
|
| 391 |
-
r.get("Label", "")
|
| 392 |
] for r in results]
|
| 393 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 394 |
# The get_consensus_label function is now replaced by final_prediction_label from weighted consensus
|
| 395 |
consensus_html = f"<b><span style='color:{'red' if final_prediction_label == 'AI' else ('green' if final_prediction_label == 'REAL' else 'orange')}'>{final_prediction_label}</span></b>"
|
| 396 |
|
|
@@ -441,7 +446,26 @@ def predict_image_with_json(img, confidence_threshold, augment_methods, rotate_d
|
|
| 441 |
human_feedback=None # This can be populated later with human review data
|
| 442 |
)
|
| 443 |
|
| 444 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 445 |
|
| 446 |
with gr.Blocks(css="#post-gallery { overflow: hidden !important;} .grid-wrap{ overflow-y: hidden !important;} .ms-gr-ant-welcome-icon{ height:unset !important;} .tabs{margin-top:10px;}") as demo:
|
| 447 |
with ms.Application() as app:
|
|
@@ -509,8 +533,8 @@ with gr.Blocks(css="#post-gallery { overflow: hidden !important;} .grid-wrap{ ov
|
|
| 509 |
gr.Markdown(QUICK_INTRO)
|
| 510 |
|
| 511 |
with gr.Tab("👑 Community Forensics Preview"):
|
| 512 |
-
temp_space = gr.load("aiwithoutborders-xyz/OpenSight-Community-Forensics-Preview", src="spaces")
|
| 513 |
-
|
| 514 |
with gr.Tab("🥇 Leaderboard"):
|
| 515 |
gr.Markdown("# AI Generated / Deepfake Detection Models Leaderboard: Soon™")
|
| 516 |
|
|
|
|
| 27 |
from forensics.registry import register_model, MODEL_REGISTRY, ModelEntry
|
| 28 |
from agents.weight_management import ModelWeightManager
|
| 29 |
from dotenv import load_dotenv
|
| 30 |
+
import json
|
| 31 |
|
| 32 |
# Configure logging
|
| 33 |
logging.basicConfig(level=logging.INFO)
|
|
|
|
| 237 |
"Model": entry.display_name,
|
| 238 |
"Contributor": entry.contributor,
|
| 239 |
"HF Model Path": entry.model_path,
|
| 240 |
+
"AI Score": 0.0, # Ensure it's a float even on error
|
| 241 |
+
"Real Score": 0.0, # Ensure it's a float even on error
|
| 242 |
"Label": f"Error: {str(e)}"
|
| 243 |
}
|
| 244 |
|
|
|
|
| 387 |
table_rows = [[
|
| 388 |
r.get("Model", ""),
|
| 389 |
r.get("Contributor", ""),
|
| 390 |
+
r.get("AI Score", 0.0) if r.get("AI Score") is not None else 0.0,
|
| 391 |
+
r.get("Real Score", 0.0) if r.get("Real Score") is not None else 0.0,
|
| 392 |
+
r.get("Label", "Error")
|
| 393 |
] for r in results]
|
| 394 |
|
| 395 |
+
logger.info(f"Type of table_rows: {type(table_rows)}")
|
| 396 |
+
for i, row in enumerate(table_rows):
|
| 397 |
+
logger.info(f"Row {i} types: {[type(item) for item in row]}")
|
| 398 |
+
|
| 399 |
# The get_consensus_label function is now replaced by final_prediction_label from weighted consensus
|
| 400 |
consensus_html = f"<b><span style='color:{'red' if final_prediction_label == 'AI' else ('green' if final_prediction_label == 'REAL' else 'orange')}'>{final_prediction_label}</span></b>"
|
| 401 |
|
|
|
|
| 446 |
human_feedback=None # This can be populated later with human review data
|
| 447 |
)
|
| 448 |
|
| 449 |
+
# Final type safety check for forensic_images before returning
|
| 450 |
+
cleaned_forensics_images = []
|
| 451 |
+
for f_img in forensics_images:
|
| 452 |
+
if isinstance(f_img, Image.Image):
|
| 453 |
+
cleaned_forensics_images.append(f_img)
|
| 454 |
+
elif isinstance(f_img, np.ndarray):
|
| 455 |
+
try:
|
| 456 |
+
cleaned_forensics_images.append(Image.fromarray(f_img))
|
| 457 |
+
except Exception as e:
|
| 458 |
+
logger.warning(f"Could not convert numpy array to PIL Image for gallery: {e}")
|
| 459 |
+
# Optionally, append a placeholder or skip
|
| 460 |
+
else:
|
| 461 |
+
logger.warning(f"Unexpected type in forensic_images: {type(f_img)}. Skipping.")
|
| 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 |
|
| 470 |
with gr.Blocks(css="#post-gallery { overflow: hidden !important;} .grid-wrap{ overflow-y: hidden !important;} .ms-gr-ant-welcome-icon{ height:unset !important;} .tabs{margin-top:10px;}") as demo:
|
| 471 |
with ms.Application() as app:
|
|
|
|
| 533 |
gr.Markdown(QUICK_INTRO)
|
| 534 |
|
| 535 |
with gr.Tab("👑 Community Forensics Preview"):
|
| 536 |
+
# temp_space = gr.load("aiwithoutborders-xyz/OpenSight-Community-Forensics-Preview", src="spaces")
|
| 537 |
+
gr.Markdown("Community Forensics Preview coming soon!") # Placeholder for now
|
| 538 |
with gr.Tab("🥇 Leaderboard"):
|
| 539 |
gr.Markdown("# AI Generated / Deepfake Detection Models Leaderboard: Soon™")
|
| 540 |
|
utils/hf_logger.py
CHANGED
|
@@ -5,7 +5,8 @@ import io
|
|
| 5 |
import datetime
|
| 6 |
from PIL import Image
|
| 7 |
import logging
|
| 8 |
-
from datasets import Dataset, load_dataset
|
|
|
|
| 9 |
|
| 10 |
logger = logging.getLogger(__name__)
|
| 11 |
|
|
@@ -33,16 +34,29 @@ def initialize_dataset():
|
|
| 33 |
except Exception:
|
| 34 |
# If dataset does not exist, create a new one with an empty structure
|
| 35 |
logger.info(f"Creating new Hugging Face dataset: {HF_DATASET_NAME}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
dataset = Dataset.from_dict({
|
| 37 |
"timestamp": [],
|
| 38 |
-
"image": [],
|
| 39 |
"inference_request": [],
|
| 40 |
"model_predictions": [],
|
| 41 |
"ensemble_output": [],
|
| 42 |
-
"forensic_outputs": [],
|
| 43 |
"agent_monitoring_data": [],
|
| 44 |
"human_feedback": []
|
| 45 |
-
})
|
| 46 |
return dataset
|
| 47 |
|
| 48 |
def log_inference_data(
|
|
@@ -77,26 +91,25 @@ def log_inference_data(
|
|
| 77 |
new_entry = {
|
| 78 |
"timestamp": datetime.datetime.now().isoformat(),
|
| 79 |
"image": original_image_b64,
|
| 80 |
-
"inference_request": inference_params,
|
| 81 |
-
"model_predictions": model_predictions,
|
| 82 |
-
"ensemble_output": ensemble_output,
|
| 83 |
-
"forensic_outputs": forensic_images_b64, #
|
| 84 |
-
"agent_monitoring_data": agent_monitoring_data,
|
| 85 |
-
"human_feedback": human_feedback if human_feedback is not None else {}
|
| 86 |
}
|
| 87 |
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
|
|
|
| 95 |
|
| 96 |
-
#
|
| 97 |
-
|
| 98 |
-
# For a production system, consider batched writes or more robust data pipelines.
|
| 99 |
-
updated_dataset = dataset.add_item(new_entry)
|
| 100 |
|
| 101 |
# This will push to the Hugging Face Hub if you are logged in and dataset is configured
|
| 102 |
# Or save locally if not.
|
|
|
|
| 5 |
import datetime
|
| 6 |
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 |
|
|
|
|
| 34 |
except Exception:
|
| 35 |
# If dataset does not exist, create a new one with an empty structure
|
| 36 |
logger.info(f"Creating new Hugging Face dataset: {HF_DATASET_NAME}")
|
| 37 |
+
|
| 38 |
+
# Define the features explicitly
|
| 39 |
+
features = Features({
|
| 40 |
+
"timestamp": Value('string'),
|
| 41 |
+
"image": Value('string'), # base64 string
|
| 42 |
+
"inference_request": Value('string'), # JSON string
|
| 43 |
+
"model_predictions": Value('string'), # JSON string
|
| 44 |
+
"ensemble_output": Value('string'), # JSON string
|
| 45 |
+
"forensic_outputs": Sequence(Value('string')), # List of base64 image strings
|
| 46 |
+
"agent_monitoring_data": Value('string'), # JSON string
|
| 47 |
+
"human_feedback": Value('string') # JSON string
|
| 48 |
+
})
|
| 49 |
+
|
| 50 |
dataset = Dataset.from_dict({
|
| 51 |
"timestamp": [],
|
| 52 |
+
"image": [],
|
| 53 |
"inference_request": [],
|
| 54 |
"model_predictions": [],
|
| 55 |
"ensemble_output": [],
|
| 56 |
+
"forensic_outputs": [],
|
| 57 |
"agent_monitoring_data": [],
|
| 58 |
"human_feedback": []
|
| 59 |
+
}, features=features) # Pass the features explicitly
|
| 60 |
return dataset
|
| 61 |
|
| 62 |
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
|
| 103 |
+
features = dataset.features
|
| 104 |
+
|
| 105 |
+
# Convert existing dataset to a list of dictionaries
|
| 106 |
+
dataset_list = dataset.to_list()
|
| 107 |
+
|
| 108 |
+
# Append the new entry to the list
|
| 109 |
+
dataset_list.append(new_entry)
|
| 110 |
|
| 111 |
+
# Create a new dataset from the updated list
|
| 112 |
+
updated_dataset = Dataset.from_list(dataset_list, features=features)
|
|
|
|
|
|
|
| 113 |
|
| 114 |
# This will push to the Hugging Face Hub if you are logged in and dataset is configured
|
| 115 |
# Or save locally if not.
|