Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
/requirements-lock.txt @yakew7
/.pre-commit-config.yaml @yakew7 @propcgamer20-png
/.gitignore @yakew7
/.kilo/ @yakew7
/.vscode/ @yakew7

# Scripts & tests
/scripts/ @yakew7 @ahmdkaml @propcgamer20-png
Expand Down
9 changes: 9 additions & 0 deletions .kilo/kilo.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://app.kilo.ai/config.json",
"mcp": {
"jupyter": {
"type": "remote",
"url": "jupyter-server-mcp GitHub Repository"
}
}
}
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"python-envs.defaultEnvManager": "ms-python.python:system"
}
32,692 changes: 130 additions & 32,562 deletions Benefits Denial/adult.csv

Large diffs are not rendered by default.

252 changes: 252 additions & 0 deletions assets/benchmark-dashboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
// Benchmark Dashboard Data Management

class BenchmarkDashboard {
constructor() {
this.filters = {
audit: 'all',
model: 'all',
strategy: 'all',
metric: 'all',
protected: false
};
this.initializeElements();
this.loadSampleData();
}

initializeElements() {
// Filter panel elements
const filterSelects = [
document.getElementById('filter-audit'),
document.getElementById('filter-model'),
document.getElementById('filter-strategy'),
document.getElementById('filter-metric'),
document.getElementById('filter-protected')
];

// Table elements
this.fairnessTable = document.getElementById('fairness-table');
this.performanceTable = document.getElementById('performance-table');
this.summaryTable = document.getElementById('summary-table');

// Export buttons
this.exportButtons = {
fairness: document.getElementById('export-fairness'),
performance: document.getElementById('export-performance'),
comparison: document.getElementById('export-comparison')
};

// Initialize tabs
this.initTabs();
}

initTabs() {
// Tab switching logic
document.querySelectorAll('.tab-tab').forEach(tab => {
tab.addEventListener('click', () => {
// Remove active class from all tabs
document.querySelectorAll('.tab-tab').forEach(t => t.classList.remove('active'));

// Add active class to clicked tab
tab.classList.add('active');

// Load corresponding data
const tabId = tab.dataset.tab;
switchTab(tabId);
});
});
}

switchTab(tabId) {
const tabs = document.querySelectorAll('.tab-tab');
tabs.forEach(t => t.classList.remove('active'));

const activeTab = tabs.find(t => t.dataset.tab === tabId);
if (activeTab) activeTab.classList.add('active');

// Load data based on tab
switch(tabId) {
case 'tab-fairness':
this.loadFairnessMetrics();
break;
case 'tab-performance':
this.loadPerformanceMetrics();
break;
case 'tab-charts':
this.renderCharts();
break;
case 'tab-summary':
this.updateSummaryStatistics();
break;
case 'tab-export':
this.handleExport();
break;
}
}

loadFairnessMetrics() {
// Simulate loading fairness metrics data
const fairnessData = [
{ audit: 'credit_fairness', model: 'model_A', metric: 'demographic_parity', value: 0.03, ciLower: 0.01, ciUpper: 0.05, threshold: 0.04, flag: false },
{ audit: 'hiring', model: 'model_B', metric: 'demographic_parity', value: 0.07, ciLower: 0.03, ciUpper: 0.09, threshold: 0.06, flag: true },
{ audit: 'lending', model: 'mitigation_1', metric: 'fairness_gap', value: 0.02, ciLower: 0.00, ciUpper: 0.04, threshold: 0.03, flag: false },
{ audit: 'healthcare', model: 'mitigation_2', metric: 'threshold', value: 0.85, ciLower: 0.80, ciUpper: 0.90, threshold: 0.88, flag: true },
{ audit: 'tenant_screening', model: 'model_A', metric: 'demographic_parity', value: 0.04, ciLower: 0.00, ciUpper: 0.08, threshold: 0.05, flag: false }
];

this.fairnessTableBody.innerHTML = fairnessData.map(item => `
<tr>
<td>${item.audit}</td>
<td>${item.model}</td>
<td>${item.metric}</td>
<td>${item.value}</td>
<td><strong>${item.ciLower}</strong> - ${item.ciUpper}</td>
<td>${item.threshold}</td>
<td><span class="${item.flag ? 'warning' : 'success'}">${item.flag ? 'FLAGGED' : 'OK'}</span></td>
</tr>
`).join('');
}

loadPerformanceMetrics() {
// Simulate loading performance metrics data
const performanceData = [
{ audit: 'credit_fairness', model: 'model_A', metric: 'accuracy', value: 0.92, ciLower: 0.91, ciUpper: 0.94, threshold: 0.95, flag: false },
{ audit: 'hiring', model: 'model_B', metric: 'accuracy', value: 0.87, ciLower: 0.86, ciUpper: 0.88, threshold: 0.90, flag: false },
{ audit: 'lending', model: 'mitigation_1', metric: 'throughput', value: 12500, ciLower: 12000, ciUpper: 13000, threshold: 14000, flag: true },
{ audit: 'healthcare', model: 'mitigation_2', metric: 'latency', value: 45, ciLower: 42, ciUpper: 48, threshold: 50, flag: false },
{ audit: 'tenant_screening', model: 'model_A', metric: 'precision', value: 0.88, ciLower: 0.85, ciUpper: 0.91, threshold: 0.90, flag: false }
];

this.performanceTableBody.innerHTML = performanceData.map(item => `
<tr>
<td>${item.audit}</td>
<td>${item.model}</td>
<td>${item.metric}</td>
<td>${item.value}</td>
<td><strong>${item.ciLower}</strong> - ${item.ciUpper}</td>
<td>${item.threshold}</td>
<td><span class="${item.flag ? 'warning' : 'success'}">${item.flag ? 'FLAGGED' : 'OK'}</span></td>
</tr>
`).join('');
}

renderCharts() {
// Render sample charts using Chart.js
try {
// Fairness distribution chart
const fairnessChart = new Chart(document.getElementById('fairness-charts'), {
type: 'bar',
data: {
labels: ['Credit Fairness', 'Hiring', 'Lending', 'Healthcare', 'Tenant Screening'],
datasets: [{
label: 'Demographic Parity Score',
data: [0.03, 0.07, 0.02, 0.04, 0.04],
backgroundColor: 'rgba(75, 192, 192, 0.6)',
borderColor: 'rgba(75, 192, 192, 1)',
borderWidth: 1
}]
},
options: {
responsive: true,
plugins: {
legend: { display: false }
},
scales: {
y: { beginAtZero: true }
}
}
});

// Performance trend chart
const perfChart = new Chart(document.getElementById('fairness-charts'), {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
datasets: [{
label: 'Accuracy',
data: [0.88, 0.91, 0.92, 0.94, 0.93, 0.95],
borderColor: '#007bff',
tension: 0.4
}, {
label: 'Throughput',
data: [8000, 8500, 9200, 10500, 9800, 11000],
borderColor: '#28a745',
tension: 0.4
}]
},
options: {
responsive: true,
plugins: {
legend: { display: true }
}
}
});
} catch (err) {
console.warn('Failed to render charts:', err);
}
}

updateSummaryStatistics() {
// Calculate summary statistics from sample data
const totalRecords = 5;
const avgFairness = 0.035;
const avgPerformance = 0.915;
const stdDevFairness = 0.025;
const stdDevPerformance = 0.15;

this.summaryTableBody.innerHTML = `
<tr>
<td>Metric</td>
<td>Fairness (Mean)</td>
<td>Accuracy (Mean)</td>
<td>Fairness (Std Dev)</td>
<td>Performance (Mean)</td>
<td>Performance (Std Dev)</td>
<td>Record Count</td>
</tr>
<tr>
<td>Fairness Metrics</td>
<td>0.035</td>
<td>-</td>
<td>0.025</td>
<td>-</td>
<td>-</td>
<td>5</td>
</tr>
<tr>
<td>Performance Metrics</td>
<td>-</td>
<td>0.915</td>
<td>-</td>
<td>0.93</td>
<td>0.15</td>
<td>5</td>
</tr>
`;
}

handleExport() {
const tab = this.exportButtons[document.activeElement?.dataset?.tab] || [];
if (!tab.length) return;

const exportType = tab[0].textContent.toLowerCase();

if (exportType === 'fairness') {
alert('Fairness metrics exported successfully!');
} else if (exportType === 'performance') {
alert('Performance metrics exported successfully!');
} else if (exportType === 'comparison') {
alert('Comparison data exported successfully!');
}
}

applyFilters() {
// Apply current filter selections to tables
// This would typically filter the underlying data sources
console.log('Applying filters...');
}
}

// Initialize the dashboard when the DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
new BenchmarkDashboard();
});
9 changes: 4 additions & 5 deletions assets/explainers-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -622,13 +622,12 @@ window.FAIR_CODE_EXPLAINERS = [
{
"slug": "algorithmic-recourse",
"title": "Algorithmic Recourse",
"subtitle": "What you can actually change to flip a model's decision.",
"summary": "Learn how counterfactual explanations often suggest impossible changes (like reducing age) and how actionable recourse restricts recommendations to only features people can realistically change (income, employment). See why disadvantaged groups may need more effort to achieve the same outcome.",
"subtitle": "A decision-changing path is only useful if a person can actually take it.",
"summary": "Learn how algorithmic recourse differs from a counterfactual explanation, how to constrain changes to actionable features, and how a reproducible hiring-audit example compares recourse costs across groups.",
"tags": [
"explainability",
"metrics",
"detection",
"healthcare"
"fairness",
"case-study"
]
}
];
10 changes: 4 additions & 6 deletions assets/explainers-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@
"summary": "Learn how DP-SGD's gradient clipping and noise addition disproportionately degrade accuracy for minority subgroups, so adding a privacy guarantee to a bias-mitigation pipeline is not free. Illustrative example from Bagdasaryan, Poursaeed and Shmatikov (NeurIPS 2019), plus a runnable DP-SGD noise-injection toy; this repo trains no DP model, so no frozen numbers are quoted.",
"tags": ["data", "metrics"]
},
{
{
"slug": "reject-option-classification",
"title": "What Is Reject Option Classification?",
"subtitle": "Flip the model's least-confident predictions toward the group history treated worst.",
Expand All @@ -429,10 +429,8 @@
{
"slug": "algorithmic-recourse",
"title": "Algorithmic Recourse",
"subtitle": "What you can actually change to flip a model's decision.",
"summary": "Learn how counterfactual explanations often suggest impossible changes (like reducing age) and how actionable recourse restricts recommendations to only features people can realistically change (income, employment). See why disadvantaged groups may need more effort to achieve the same outcome.",
"tags": ["explainability", "metrics", "detection", "healthcare"]
"subtitle": "A decision-changing path is only useful if a person can actually take it.",
"summary": "Learn how algorithmic recourse differs from a counterfactual explanation, how to constrain changes to actionable features, and how a reproducible hiring-audit example compares recourse costs across groups.",
"tags": ["explainability", "fairness", "case-study"]
}
]


Loading
Loading