Spaces:
Sleeping
Sleeping
Update app.py
Browse filesUpdated with MIA Analysis
app.py
CHANGED
|
@@ -20,7 +20,7 @@ from PIL import Image
|
|
| 20 |
import torch
|
| 21 |
import torch.nn as nn
|
| 22 |
|
| 23 |
-
# Dynamic import from enhanced IBOM backend
|
| 24 |
from IBOM import DetailedIBOMGenerator, get_paths_with_smart_fallback
|
| 25 |
|
| 26 |
# Page configuration
|
|
@@ -118,17 +118,17 @@ def load_tbom_data(file_path="TBOM.json"):
|
|
| 118 |
with open(tbom_path, 'r') as f:
|
| 119 |
return json.load(f)
|
| 120 |
except Exception:
|
| 121 |
-
st.error("
|
| 122 |
return None
|
| 123 |
except Exception as e:
|
| 124 |
-
st.error(f"Error loading
|
| 125 |
return None
|
| 126 |
|
| 127 |
#Enhanced IBOM Interface
|
| 128 |
|
| 129 |
def create_enhanced_ibom_interface(tbom_data):
|
| 130 |
"""Complete enhanced IBOM interface with all advanced features"""
|
| 131 |
-
st.markdown('<h2 class="sub-header">π Interactive
|
| 132 |
|
| 133 |
# Feature overview
|
| 134 |
with st.expander("Enhanced Features Overview", expanded=False):
|
|
@@ -148,7 +148,7 @@ def create_enhanced_ibom_interface(tbom_data):
|
|
| 148 |
with col2:
|
| 149 |
st.markdown("""
|
| 150 |
**π₯ Export Functionality:**
|
| 151 |
-
- Download
|
| 152 |
- CSV exports for spreadsheet analysis
|
| 153 |
- Detailed analysis reports
|
| 154 |
|
|
@@ -164,12 +164,8 @@ def create_enhanced_ibom_interface(tbom_data):
|
|
| 164 |
"Upload a mushroom image for comprehensive analysis",
|
| 165 |
type=['jpg', 'jpeg', 'png', 'bmp'],
|
| 166 |
help="Upload a clear image showing cap, gills, and stalk for detailed AI analysis"
|
| 167 |
-
|
| 168 |
|
| 169 |
-
# Display the disclaimer and caption AFTER the file uploader
|
| 170 |
-
st.info("Disclaimer: **π¨ NEVER consume any mushroom based solely on AI analysis.**")
|
| 171 |
-
st.caption("This tool is for educational and research purposes only.")
|
| 172 |
-
|
| 173 |
# Main layout: Image on the left, results on the right
|
| 174 |
img_col, results_col = st.columns([1, 2.5])
|
| 175 |
|
|
@@ -195,7 +191,7 @@ def create_enhanced_ibom_interface(tbom_data):
|
|
| 195 |
st.warning("β οΈ Low resolution - results may be less accurate")
|
| 196 |
|
| 197 |
# Enhanced analysis trigger
|
| 198 |
-
if st.button(" Analyze
|
| 199 |
perform_enhanced_ibom_analysis(uploaded_image)
|
| 200 |
else:
|
| 201 |
st.info("Upload an image to begin analysis")
|
|
@@ -208,13 +204,22 @@ def create_enhanced_ibom_interface(tbom_data):
|
|
| 208 |
- Show any bruising or discoloration
|
| 209 |
- Minimal background distractions
|
| 210 |
""")
|
| 211 |
-
|
| 212 |
with results_col:
|
| 213 |
-
# Display results if available
|
| 214 |
if 'enhanced_ibom_data' in st.session_state:
|
| 215 |
display_comprehensive_ibom_results()
|
| 216 |
-
create_concept_score_modification_interface()
|
| 217 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 218 |
|
| 219 |
|
| 220 |
def perform_enhanced_ibom_analysis(uploaded_file):
|
|
@@ -286,7 +291,7 @@ def display_comprehensive_ibom_results():
|
|
| 286 |
# --- Add download button for Original IBOM ---
|
| 287 |
original_json_data = json.dumps(original_result, indent=2)
|
| 288 |
st.download_button(
|
| 289 |
-
label="π Download Original
|
| 290 |
data=original_json_data,
|
| 291 |
file_name=f"IBOM_{data['analysis_timestamp'].strftime('%Y%m%d_%H%M%S')}.json",
|
| 292 |
mime="application/json"
|
|
@@ -577,7 +582,7 @@ def display_enhanced_export_options():
|
|
| 577 |
|
| 578 |
with col1:
|
| 579 |
st.download_button(
|
| 580 |
-
label="π Original
|
| 581 |
data=json.dumps(data['original_result'], indent=2),
|
| 582 |
file_name=f"original_IBOM_{timestamp}.json",
|
| 583 |
mime="application/json"
|
|
@@ -585,7 +590,7 @@ def display_enhanced_export_options():
|
|
| 585 |
with col2:
|
| 586 |
if 'modified_result' in data:
|
| 587 |
st.download_button(
|
| 588 |
-
label="π Modified
|
| 589 |
data=json.dumps(data['modified_result'], indent=2),
|
| 590 |
file_name=f"modified_IBOM_{timestamp}.json",
|
| 591 |
mime="application/json"
|
|
@@ -612,7 +617,7 @@ def create_performance_overview(tbom_data):
|
|
| 612 |
test_results = perf_metrics.get('final_test_results', {})
|
| 613 |
cv_results = perf_metrics.get('cross_validation_results', {})
|
| 614 |
|
| 615 |
-
col1, col2, col3 = st.columns(
|
| 616 |
|
| 617 |
with col1:
|
| 618 |
test_acc = test_results.get('accuracy', 0) * 100
|
|
@@ -638,6 +643,14 @@ def create_performance_overview(tbom_data):
|
|
| 638 |
delta=f"CV: {cv_results.get('mean_pr_auc', 0)*100:.2f}%"
|
| 639 |
)
|
| 640 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 641 |
def create_confusion_matrix_viz(tbom_data):
|
| 642 |
"""Create interactive confusion matrix visualization (UNCHANGED)"""
|
| 643 |
test_results = tbom_data.get('performance_metrics', {}).get('final_test_results', {})
|
|
@@ -1068,7 +1081,7 @@ def create_technical_details(tbom_data):
|
|
| 1068 |
|
| 1069 |
st.markdown(f"""
|
| 1070 |
<div class="metric-card">
|
| 1071 |
-
<h4>π
|
| 1072 |
<p><strong>Version:</strong> {tbom_version}</p>
|
| 1073 |
<p><strong>Generated:</strong> {timestamp}</p>
|
| 1074 |
<p><strong>Training Time:</strong> {training_time/3600:.2f} hours</p>
|
|
@@ -1097,19 +1110,126 @@ def create_technical_details(tbom_data):
|
|
| 1097 |
|
| 1098 |
st.markdown("---")
|
| 1099 |
# --- Add download button for TBOM.json ---
|
| 1100 |
-
st.subheader("Download Full
|
| 1101 |
tbom_json_data = json.dumps(tbom_data, indent=2)
|
| 1102 |
st.download_button(
|
| 1103 |
-
label="π₯ Download
|
| 1104 |
data=tbom_json_data,
|
| 1105 |
file_name="TBOM.json",
|
| 1106 |
mime="application/json"
|
| 1107 |
)
|
| 1108 |
|
| 1109 |
# Expander for raw data
|
| 1110 |
-
with st.expander("π View Raw
|
| 1111 |
st.json(tbom_data)
|
| 1112 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1113 |
|
| 1114 |
#Main function to run the Streamlit app
|
| 1115 |
|
|
@@ -1117,13 +1237,13 @@ def main():
|
|
| 1117 |
"""Main Streamlit application with enhanced IBOM integration"""
|
| 1118 |
# Header (keeping your original style)
|
| 1119 |
st.markdown('<h1 class="main-header">π Dependable FungAI</h1>', unsafe_allow_html=True)
|
| 1120 |
-
st.markdown('<h2 class="sub-header">
|
| 1121 |
|
| 1122 |
# Load TBOM data
|
| 1123 |
tbom_data = load_tbom_data()
|
| 1124 |
|
| 1125 |
if tbom_data is None:
|
| 1126 |
-
st.error("Could not load
|
| 1127 |
st.stop()
|
| 1128 |
|
| 1129 |
# Sidebar information (keeping your original sidebar)
|
|
@@ -1145,7 +1265,7 @@ def main():
|
|
| 1145 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 1146 |
|
| 1147 |
# File info
|
| 1148 |
-
st.markdown("### π
|
| 1149 |
tbom_version = tbom_data.get('tbom_version', 'Unknown')
|
| 1150 |
timestamp = tbom_data.get('generation_details', {}).get('timestamp_utc', 'Unknown')
|
| 1151 |
st.markdown(f"**Version:** {tbom_version}")
|
|
@@ -1153,16 +1273,17 @@ def main():
|
|
| 1153 |
|
| 1154 |
# Main content tabs
|
| 1155 |
tabs = st.tabs([
|
| 1156 |
-
"π
|
| 1157 |
-
"
|
| 1158 |
-
"
|
| 1159 |
-
"
|
| 1160 |
-
"
|
| 1161 |
-
"
|
| 1162 |
-
"
|
|
|
|
| 1163 |
])
|
| 1164 |
|
| 1165 |
-
# NEW ENHANCED IBOM TAB
|
| 1166 |
with tabs[0]:
|
| 1167 |
create_enhanced_ibom_interface(tbom_data)
|
| 1168 |
|
|
@@ -1194,6 +1315,8 @@ def main():
|
|
| 1194 |
|
| 1195 |
with tabs[6]:
|
| 1196 |
create_technical_details(tbom_data)
|
|
|
|
|
|
|
| 1197 |
|
| 1198 |
if __name__ == "__main__":
|
| 1199 |
main()
|
|
|
|
| 20 |
import torch
|
| 21 |
import torch.nn as nn
|
| 22 |
|
| 23 |
+
# Dynamic import from enhanced IBOM backend (no hardcoded paths)
|
| 24 |
from IBOM import DetailedIBOMGenerator, get_paths_with_smart_fallback
|
| 25 |
|
| 26 |
# Page configuration
|
|
|
|
| 118 |
with open(tbom_path, 'r') as f:
|
| 119 |
return json.load(f)
|
| 120 |
except Exception:
|
| 121 |
+
st.error("TBOM file not found. Please ensure TBOM.json is available.")
|
| 122 |
return None
|
| 123 |
except Exception as e:
|
| 124 |
+
st.error(f"Error loading TBOM data: {str(e)}")
|
| 125 |
return None
|
| 126 |
|
| 127 |
#Enhanced IBOM Interface
|
| 128 |
|
| 129 |
def create_enhanced_ibom_interface(tbom_data):
|
| 130 |
"""Complete enhanced IBOM interface with all advanced features"""
|
| 131 |
+
st.markdown('<h2 class="sub-header">π Enhanced Interactive Inference Bill of Materials (IBOM)</h2>', unsafe_allow_html=True)
|
| 132 |
|
| 133 |
# Feature overview
|
| 134 |
with st.expander("Enhanced Features Overview", expanded=False):
|
|
|
|
| 148 |
with col2:
|
| 149 |
st.markdown("""
|
| 150 |
**π₯ Export Functionality:**
|
| 151 |
+
- Download IBOM JSON files
|
| 152 |
- CSV exports for spreadsheet analysis
|
| 153 |
- Detailed analysis reports
|
| 154 |
|
|
|
|
| 164 |
"Upload a mushroom image for comprehensive analysis",
|
| 165 |
type=['jpg', 'jpeg', 'png', 'bmp'],
|
| 166 |
help="Upload a clear image showing cap, gills, and stalk for detailed AI analysis"
|
| 167 |
+
)
|
| 168 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
# Main layout: Image on the left, results on the right
|
| 170 |
img_col, results_col = st.columns([1, 2.5])
|
| 171 |
|
|
|
|
| 191 |
st.warning("β οΈ Low resolution - results may be less accurate")
|
| 192 |
|
| 193 |
# Enhanced analysis trigger
|
| 194 |
+
if st.button(" Analyze with Enhanced IBOM", type="primary"):
|
| 195 |
perform_enhanced_ibom_analysis(uploaded_image)
|
| 196 |
else:
|
| 197 |
st.info("Upload an image to begin analysis")
|
|
|
|
| 204 |
- Show any bruising or discoloration
|
| 205 |
- Minimal background distractions
|
| 206 |
""")
|
| 207 |
+
# Results Section
|
| 208 |
with results_col:
|
|
|
|
| 209 |
if 'enhanced_ibom_data' in st.session_state:
|
| 210 |
display_comprehensive_ibom_results()
|
|
|
|
| 211 |
|
| 212 |
+
# Add MIA analysis section
|
| 213 |
+
st.markdown("---")
|
| 214 |
+
st.markdown("### π Membership Inference Attack (MIA) Analysis")
|
| 215 |
+
st.markdown("**Description:** Analysis to distinguish members from non-members using Loss and Confidence metrics.")
|
| 216 |
+
|
| 217 |
+
# Display MIA results for uploaded image
|
| 218 |
+
if uploaded_image is not None:
|
| 219 |
+
display_mia_analysis_for_image(st.session_state.enhanced_ibom_data['ibom_generator'],
|
| 220 |
+
Image.open(uploaded_image))
|
| 221 |
+
|
| 222 |
+
create_concept_score_modification_interface()
|
| 223 |
|
| 224 |
|
| 225 |
def perform_enhanced_ibom_analysis(uploaded_file):
|
|
|
|
| 291 |
# --- Add download button for Original IBOM ---
|
| 292 |
original_json_data = json.dumps(original_result, indent=2)
|
| 293 |
st.download_button(
|
| 294 |
+
label="π Download Original IBOM.json",
|
| 295 |
data=original_json_data,
|
| 296 |
file_name=f"IBOM_{data['analysis_timestamp'].strftime('%Y%m%d_%H%M%S')}.json",
|
| 297 |
mime="application/json"
|
|
|
|
| 582 |
|
| 583 |
with col1:
|
| 584 |
st.download_button(
|
| 585 |
+
label="π Original IBOM JSON",
|
| 586 |
data=json.dumps(data['original_result'], indent=2),
|
| 587 |
file_name=f"original_IBOM_{timestamp}.json",
|
| 588 |
mime="application/json"
|
|
|
|
| 590 |
with col2:
|
| 591 |
if 'modified_result' in data:
|
| 592 |
st.download_button(
|
| 593 |
+
label="π Modified IBOM JSON",
|
| 594 |
data=json.dumps(data['modified_result'], indent=2),
|
| 595 |
file_name=f"modified_IBOM_{timestamp}.json",
|
| 596 |
mime="application/json"
|
|
|
|
| 617 |
test_results = perf_metrics.get('final_test_results', {})
|
| 618 |
cv_results = perf_metrics.get('cross_validation_results', {})
|
| 619 |
|
| 620 |
+
col1, col2, col3, col4 = st.columns(4)
|
| 621 |
|
| 622 |
with col1:
|
| 623 |
test_acc = test_results.get('accuracy', 0) * 100
|
|
|
|
| 643 |
delta=f"CV: {cv_results.get('mean_pr_auc', 0)*100:.2f}%"
|
| 644 |
)
|
| 645 |
|
| 646 |
+
with col4:
|
| 647 |
+
training_time = tbom_data.get('generation_details', {}).get('training_time_seconds', 0)
|
| 648 |
+
st.metric(
|
| 649 |
+
label="β±οΈ Training Time",
|
| 650 |
+
value=f"{training_time/60:.1f} min",
|
| 651 |
+
delta=f"{training_time:.0f}s total"
|
| 652 |
+
)
|
| 653 |
+
|
| 654 |
def create_confusion_matrix_viz(tbom_data):
|
| 655 |
"""Create interactive confusion matrix visualization (UNCHANGED)"""
|
| 656 |
test_results = tbom_data.get('performance_metrics', {}).get('final_test_results', {})
|
|
|
|
| 1081 |
|
| 1082 |
st.markdown(f"""
|
| 1083 |
<div class="metric-card">
|
| 1084 |
+
<h4>π TBOM Information</h4>
|
| 1085 |
<p><strong>Version:</strong> {tbom_version}</p>
|
| 1086 |
<p><strong>Generated:</strong> {timestamp}</p>
|
| 1087 |
<p><strong>Training Time:</strong> {training_time/3600:.2f} hours</p>
|
|
|
|
| 1110 |
|
| 1111 |
st.markdown("---")
|
| 1112 |
# --- Add download button for TBOM.json ---
|
| 1113 |
+
st.subheader("Download Full TBOM")
|
| 1114 |
tbom_json_data = json.dumps(tbom_data, indent=2)
|
| 1115 |
st.download_button(
|
| 1116 |
+
label="π₯ Download TBOM.json",
|
| 1117 |
data=tbom_json_data,
|
| 1118 |
file_name="TBOM.json",
|
| 1119 |
mime="application/json"
|
| 1120 |
)
|
| 1121 |
|
| 1122 |
# Expander for raw data
|
| 1123 |
+
with st.expander("π View Raw TBOM Data"):
|
| 1124 |
st.json(tbom_data)
|
| 1125 |
+
|
| 1126 |
+
# Membership Inference Attack Analysis tab
|
| 1127 |
+
def create_mia_analysis(tbom_data):
|
| 1128 |
+
"""Display Membership Inference Attack analysis results"""
|
| 1129 |
+
st.markdown("### π Membership Inference Attack (MIA) Analysis")
|
| 1130 |
+
|
| 1131 |
+
mia_data = tbom_data.get('membership_inference_analysis', {})
|
| 1132 |
+
if not mia_data:
|
| 1133 |
+
st.warning("No MIA analysis data available")
|
| 1134 |
+
return
|
| 1135 |
+
|
| 1136 |
+
# Display description and method
|
| 1137 |
+
st.markdown(f"**Description:** {mia_data.get('description', 'N/A')}")
|
| 1138 |
+
|
| 1139 |
+
# Create metrics display
|
| 1140 |
+
col1, col2 = st.columns(2)
|
| 1141 |
+
with col1:
|
| 1142 |
+
threshold = mia_data.get('threshold_finding_summary', {}).get('decision_threshold', 0)
|
| 1143 |
+
st.metric(
|
| 1144 |
+
"Decision Threshold",
|
| 1145 |
+
f"{threshold:.4f}",
|
| 1146 |
+
help="Confidence score threshold for member/non-member classification"
|
| 1147 |
+
)
|
| 1148 |
+
|
| 1149 |
+
with col2:
|
| 1150 |
+
auc_score = mia_data.get('threshold_finding_summary', {}).get('attack_auc_score_on_confidence', 0)
|
| 1151 |
+
st.metric(
|
| 1152 |
+
"Attack AUC Score",
|
| 1153 |
+
f"{auc_score:.4f}",
|
| 1154 |
+
help="Area Under Curve score for the membership inference attack"
|
| 1155 |
+
)
|
| 1156 |
+
|
| 1157 |
+
# Display visualization if available
|
| 1158 |
+
viz_path = mia_data.get('visualization_artifact')
|
| 1159 |
+
if viz_path and os.path.exists(viz_path):
|
| 1160 |
+
st.markdown("### Confidence Score Distribution")
|
| 1161 |
+
st.image(viz_path, caption="Member vs Non-member Confidence Distributions")
|
| 1162 |
+
|
| 1163 |
+
# Display detailed statistics
|
| 1164 |
+
st.markdown("### Detailed Statistics")
|
| 1165 |
+
|
| 1166 |
+
stats_tabs = st.tabs(["Member Statistics", "Non-member Statistics"])
|
| 1167 |
+
|
| 1168 |
+
with stats_tabs[0]:
|
| 1169 |
+
member_stats = mia_data.get('metric_statistics', {}).get('members', {})
|
| 1170 |
+
if member_stats:
|
| 1171 |
+
st.dataframe(pd.DataFrame(member_stats))
|
| 1172 |
+
else:
|
| 1173 |
+
st.info("No member statistics available")
|
| 1174 |
+
|
| 1175 |
+
with stats_tabs[1]:
|
| 1176 |
+
non_member_stats = mia_data.get('metric_statistics', {}).get('non_members', {})
|
| 1177 |
+
if non_member_stats:
|
| 1178 |
+
st.dataframe(pd.DataFrame(non_member_stats))
|
| 1179 |
+
else:
|
| 1180 |
+
st.info("No non-member statistics available")
|
| 1181 |
+
|
| 1182 |
+
# Display MIA analysis for uploaded image
|
| 1183 |
+
def display_mia_analysis_for_image(model_wrapper, image):
|
| 1184 |
+
"""Display MIA analysis results for an uploaded image"""
|
| 1185 |
+
st.markdown("### π MIA Analysis for Uploaded Image")
|
| 1186 |
+
|
| 1187 |
+
# Get MIA metrics for single image
|
| 1188 |
+
transform = model_wrapper.preprocess
|
| 1189 |
+
img_tensor = transform(image).unsqueeze(0).to(model_wrapper.device)
|
| 1190 |
+
|
| 1191 |
+
with torch.no_grad():
|
| 1192 |
+
# Feature extraction
|
| 1193 |
+
img_features = model_wrapper.clip_model.encode_image(img_tensor).float()
|
| 1194 |
+
img_features_norm = img_features / img_features.norm(dim=1, keepdim=True)
|
| 1195 |
+
concept_scores = img_features_norm @ model_wrapper.text_embeddings.T
|
| 1196 |
+
hybrid_features = torch.cat([img_features, concept_scores], dim=1)
|
| 1197 |
+
|
| 1198 |
+
# Get predictions
|
| 1199 |
+
logits = model_wrapper.model(hybrid_features)
|
| 1200 |
+
probabilities = torch.sigmoid(logits)
|
| 1201 |
+
confidence = torch.max(probabilities, 1 - probabilities).item()
|
| 1202 |
+
|
| 1203 |
+
# Load threshold from TBOM
|
| 1204 |
+
tbom_path = "TBOM.json"
|
| 1205 |
+
with open(tbom_path, 'r') as f:
|
| 1206 |
+
tbom_data = json.load(f)
|
| 1207 |
+
|
| 1208 |
+
mia_data = tbom_data.get('membership_inference_analysis', {})
|
| 1209 |
+
threshold = mia_data.get('threshold_finding_summary', {}).get('decision_threshold', 0.92)
|
| 1210 |
+
|
| 1211 |
+
# Display results
|
| 1212 |
+
col1, col2 = st.columns(2)
|
| 1213 |
+
with col1:
|
| 1214 |
+
st.metric(
|
| 1215 |
+
"Confidence Score",
|
| 1216 |
+
f"{confidence:.4f}",
|
| 1217 |
+
help="Model's confidence in its prediction"
|
| 1218 |
+
)
|
| 1219 |
+
|
| 1220 |
+
with col2:
|
| 1221 |
+
is_member = confidence > threshold
|
| 1222 |
+
st.metric(
|
| 1223 |
+
"MIA Classification",
|
| 1224 |
+
"Training Set Member" if is_member else "Non-Member",
|
| 1225 |
+
help=f"Threshold: {threshold:.4f}"
|
| 1226 |
+
)
|
| 1227 |
+
|
| 1228 |
+
# Add interpretation
|
| 1229 |
+
if is_member:
|
| 1230 |
+
st.success("β
This image is likely a member of the training data")
|
| 1231 |
+
else:
|
| 1232 |
+
st.warning("β οΈ This image is likely NOT a member of the training data")
|
| 1233 |
|
| 1234 |
#Main function to run the Streamlit app
|
| 1235 |
|
|
|
|
| 1237 |
"""Main Streamlit application with enhanced IBOM integration"""
|
| 1238 |
# Header (keeping your original style)
|
| 1239 |
st.markdown('<h1 class="main-header">π Dependable FungAI</h1>', unsafe_allow_html=True)
|
| 1240 |
+
st.markdown('<h2 class="sub-header">Training Bill of Materials (TBOM) & Enhanced Inference Analysis</h2>', unsafe_allow_html=True)
|
| 1241 |
|
| 1242 |
# Load TBOM data
|
| 1243 |
tbom_data = load_tbom_data()
|
| 1244 |
|
| 1245 |
if tbom_data is None:
|
| 1246 |
+
st.error("Could not load TBOM data. Please ensure the TBOM.json file is available.")
|
| 1247 |
st.stop()
|
| 1248 |
|
| 1249 |
# Sidebar information (keeping your original sidebar)
|
|
|
|
| 1265 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 1266 |
|
| 1267 |
# File info
|
| 1268 |
+
st.markdown("### π TBOM Info")
|
| 1269 |
tbom_version = tbom_data.get('tbom_version', 'Unknown')
|
| 1270 |
timestamp = tbom_data.get('generation_details', {}).get('timestamp_utc', 'Unknown')
|
| 1271 |
st.markdown(f"**Version:** {tbom_version}")
|
|
|
|
| 1273 |
|
| 1274 |
# Main content tabs
|
| 1275 |
tabs = st.tabs([
|
| 1276 |
+
"π Enhanced IBOM",
|
| 1277 |
+
"Overview",
|
| 1278 |
+
"Performance",
|
| 1279 |
+
"Architecture",
|
| 1280 |
+
"Concepts",
|
| 1281 |
+
"Data Summary",
|
| 1282 |
+
"Technical",
|
| 1283 |
+
"MIA Analysis"
|
| 1284 |
])
|
| 1285 |
|
| 1286 |
+
# NEW ENHANCED IBOM TAB WITH ALL REQUESTED FEATURES
|
| 1287 |
with tabs[0]:
|
| 1288 |
create_enhanced_ibom_interface(tbom_data)
|
| 1289 |
|
|
|
|
| 1315 |
|
| 1316 |
with tabs[6]:
|
| 1317 |
create_technical_details(tbom_data)
|
| 1318 |
+
with tabs[7]:
|
| 1319 |
+
create_mia_analysis(tbom_data)
|
| 1320 |
|
| 1321 |
if __name__ == "__main__":
|
| 1322 |
main()
|