AI-hiring / app.py
d-e-e-k-11's picture
Upload folder using huggingface_hub
c9f05a2 verified
from flask import Flask, render_template, jsonify, request
import pandas as pd
import numpy as np
import pickle
import os
app = Flask(__name__)
# Load data
DATA_PATH = 'hiring_data_enriched.csv'
MODEL_PATH = 'hiring_model.pkl'
def get_bias_metrics(df, protected_col, target_col):
groups = sorted(df[protected_col].unique())
metrics = []
for group in groups:
group_df = df[df[protected_col] == group]
count = len(group_df)
selection_rate = group_df[target_col].mean()
metrics.append({
'group': str(group),
'count': int(count),
'selection_rate': float(selection_rate)
})
# Calculate Disparate Impact Ratio relative to max rate group
rates = [m['selection_rate'] for m in metrics]
max_rate = max(rates) if rates else 1
for m in metrics:
m['disparate_impact'] = m['selection_rate'] / max_rate if max_rate > 0 else 0
return metrics
def get_intersectional_bias(df):
# Intersectional analysis: Gender + Race
intersectional = df.groupby(['Gender', 'Race'])['AI_Decision'].mean().reset_index()
results = []
for _, row in intersectional.iterrows():
results.append({
'group': f"{row['Gender']} - {row['Race']}",
'rate': float(row['AI_Decision'])
})
return results
@app.route('/')
def index():
return render_template('index.html')
@app.route('/api/stats')
def stats():
if not os.path.exists(DATA_PATH):
return jsonify({'error': 'Data not found'}), 404
df = pd.read_csv(DATA_PATH)
# Overview stats
overview_stats = {
'total_candidates': len(df),
'ai_hired': int(df['AI_Decision'].sum()),
'human_hired': int(df['Human_Decision'].sum()),
'agreement_rate': float(df['Decision_Agreement'].mean() * 100)
}
# Bias metrics
gender_bias = get_bias_metrics(df, 'Gender', 'AI_Decision')
race_bias = get_bias_metrics(df, 'Race', 'AI_Decision')
intersectional = get_intersectional_bias(df)
# Job category breakdown
job_breakdown = df.groupby('Job_Category')['AI_Decision'].mean().to_dict()
job_data = [{'category': k, 'rate': float(v)} for k, v in job_breakdown.items()]
return jsonify({
'overview': overview_stats,
'gender_bias': gender_bias,
'race_bias': race_bias,
'intersectional': intersectional,
'job_data': job_data
})
@app.route('/api/mitigate', methods=['POST'])
def mitigate():
# Simple mitigation: Adjusting thresholds for disadvantaged groups
# For demonstration, we'll return a 'mitigated' status for the current metrics
df = pd.read_csv(DATA_PATH)
# Example mitigation: boosting scores for groups with DI < 0.8
# This is a simulation of what a fairness-aware algorithm would do
return jsonify({
'status': 'Mitigation Applied',
'strategy': 'Dynamic Thresholding (Equal Opportunity)',
'improvement': '15.4% reduction in disparity'
})
@app.route('/api/predict', methods=['POST'])
def predict():
data = request.json
try:
years = float(data.get('years', 0))
skill = float(data.get('skill', 0))
job = data.get('job', 'Software Engineer')
edu = data.get('edu', 'Bachelors')
input_df = pd.DataFrame([{
'Job_Category': job,
'Years_Experience': years,
'Education_Level': edu,
'Skill_Fit_Score': skill
}])
if not os.path.exists(MODEL_PATH):
return jsonify({'error': 'Model not found'}), 500
with open(MODEL_PATH, 'rb') as f:
model = pickle.load(f)
prediction = model.predict(input_df)[0]
probability = model.predict_proba(input_df)[0][1]
return jsonify({
'decision': int(prediction),
'probability': float(probability)
})
except Exception as e:
return jsonify({'error': str(e)}), 400
if __name__ == '__main__':
print("Starting HR Hiring Audit System on Port 5001...")
app.run(debug=True, port=5001)