Getting Started with vfairness
A full-pipeline Python library for measuring, mitigating, and monitoring fairness in machine learning systems.
vfairness covers the entire ML fairness lifecycle: from pre-training bias auditing and fairness-aware model training, through group-specific calibration and post-processing, to production monitoring, stakeholder reporting, and controlled experimentation. Every stage produces auditable artifacts — SVG visualizations, structured reports, and machine-readable metrics — designed for regulatory environments including the EU AI Act.
Full-pipeline coverage from data audit to production monitoring
Installation
# Core (numpy, pandas, scipy, scikit-learn, requests)
pip install vfairness
# With visualization support (matplotlib, seaborn)
pip install "vfairness[viz]"
# With interactive dashboards (Plotly + Dash)
pip install "vfairness[interactive]"
# Plotly charts only
pip install "vfairness[dashboard]"
# Experiment tracking (MLflow, Weights & Biases)
pip install "vfairness[mlops]"
# Full installation (all optional dependencies)
pip install "vfairness[all]"
vfairness is in beta: 0.1.0 is the release that is cut and ready, with its first PyPI publish as the pending release step, and the API is not frozen until 1.0.0. See the Release Pipeline for how versions ship.
import vfairness
print(f"vfairness {vfairness.__version__}")
Library Structure
vfairness is organized into 15 top-level sub-packages: a 6-stage fairness pipeline (preprocessing, in_processing, post_processing, evaluation, operations, rendering), 8 specialized analysis surfaces (llm, agents, multi_agent, xai, vision, legal, mcp, validity) and 1 cross-cutting infrastructure package (net, the egress guard). The areas below walk that pipeline from data to production.
vfairness.preprocessingvfairness.in_processingvfairness.post_processingvfairness.evaluationvfairness.operations.monitoringvfairness.operations.reportingvfairness.operations.experimentationvfairness.operations.cicdvfairness.llmvfairness.agentsvfairness.multi_agentQuick Start
Measure fairness in a loan approval model in under 30 lines.
import numpy as np
from vfairness import FairnessAnalyzer, demographic_parity_difference
# Sample data
y_true = np.array([1, 0, 1, 0, 1, 0, 1, 0, 1, 1] * 100)
y_pred = np.array([1, 0, 1, 1, 1, 0, 0, 0, 1, 1] * 100)
gender = np.array(['M','M','M','M','M','F','F','F','F','F'] * 100)
# Single metric
dp = demographic_parity_difference(y_true, y_pred, gender)
print(f"Demographic Parity Difference: {dp:.3f}")
# Full analyzer with confidence intervals
analyzer = FairnessAnalyzer(y_true, y_pred, gender, min_group_size=30)
result = analyzer.demographic_parity_difference(
include_ci=True, n_bootstrap=5000, confidence_level=0.95
)
lo, hi = result.confidence_interval
print(f"DP Diff: {result.value:.3f} 95% CI: [{lo:.3f}, {hi:.3f}]")
# All metrics at once
for name, value in analyzer.compute_all_metrics().items():
print(f" {name}: {value:.3f}")
Fairness metrics are mathematically incompatible — you cannot satisfy demographic parity, equalized odds, and calibration simultaneously (Kleinberg et al., 2016). Decide which definition matches your use case before running analysis. See The Impossibility Theorem.
Production Features
Every test result includes audit trail metadata for EU AI Act compliance:
from vfairness.llm import OutputAnalyzer
analyzer = OutputAnalyzer(alpha=0.05)
result = analyzer.analyze_sentiment(texts_a, texts_b)
# Every result has audit metadata
print(result.metadata.timestamp) # ISO 8601 UTC
print(result.metadata.library_version) # current vfairness.__version__
print(result.metadata.parameters) # {"alpha": 0.05, "metric": "sentiment", ...}
# Serialize for database storage
data = result.to_dict() # Plain dict
json_str = result.to_json() # JSON string
# Structured logging (configure once)
import logging
logging.basicConfig(level=logging.INFO)
# All vfairness operations now emit structured logs:
# INFO:vfairness.llm.output_analysis:Starting analyze_all with 4 metrics, 50 samples per group
# WARNING:vfairness.llm.output_analysis:Sample size (18) below recommended minimum of 25
Production Scorers
Install production-quality scorers with pip install "vfairness[llm]":
| Metric | Scorer | Quality | Details |
|---|---|---|---|
| Sentiment | VADER | Production | 7,500+ word lexicon, negation, intensity, emojis |
| Toxicity | alt-profanity-check | Production | SVM trained on 200K samples, 95% accuracy |
| Refusal | Pattern-based | Production | 50+ patterns, 5 categories, weighted scoring |
| Helpfulness | Multi-signal heuristic | Good | 6 quality signals: length, vocabulary, structure, specificity, engagement, deflection |
| Stereotype | Curated word lists | Good | 61 terms + 14 phrase patterns (gender, racial, age, religious) |
Progress Callbacks
Long-running batch operations support progress callbacks for UI integration:
from tqdm import tqdm
# With tqdm progress bar
pbar = tqdm(total=100)
proxy.send_batch(
prompts=my_prompts,
n_runs=25,
progress_callback=lambda current, total: pbar.update(1)
)
pbar.close()
Bias Detection
Audit training data for representation bias, proxy variables, and historical discrimination patterns before any model is trained.
import pandas as pd
from vfairness import BiasDetector, detect_historical_patterns, identify_proxy_variables
# Full audit
detector = BiasDetector(
df,
protected_attributes=['gender', 'age'],
outcome_column='approved',
benchmarks={'gender': {'M': 0.49, 'F': 0.51}}
)
report = detector.full_audit()
print(report.summary())
# Historical discrimination patterns (scans all column names)
for r in detect_historical_patterns(df):
print(f" {r.feature}: {r.risk_level.value} - {r.pattern_type}")
# Proxy variable detection
for p in identify_proxy_variables(df, protected_attributes=['gender'], correlation_threshold=0.3):
print(f" {p.feature} -> {p.protected_attribute} (r={p.correlation:.3f})")
Calibration
Ensure that a predicted probability of 70% means the same risk for every demographic group. Detect and correct calibration disparities.
from vfairness.post_processing.calibration import CalibrationAnalyzer
analyzer = CalibrationAnalyzer(
y_true=labels, y_prob=model_probabilities,
protected_attr=gender, attribute_name='gender'
)
report = analyzer.full_analysis(context='lending')
print(f"Well Calibrated: {report.is_well_calibrated}")
print(f"Significant Disparity: {report.has_significant_disparity}")
print(f"Overall ECE: {report.overall_metrics['ece']:.4f}")
# Apply group-specific recalibration
analyzer.fit_calibrator(method='isotonic')
calibrated_probs = analyzer.transform(y_prob_test, gender_test)
Explanations
Generate context-aware, stakeholder-ready explanations for every metric and audit result.
from vfairness import FairnessAnalyzer
# FairExplAIner mode for per-metric explanations
analyzer = FairnessAnalyzer(y_true, y_pred, gender, fair_explainer=True)
report = analyzer.get_report(include_ci=True)
for name, expl in report['explanations']['metrics'].items():
print(f"{name}: {expl['severity']} - {expl['evaluation']}")
# FairnessExplainer for cross-module explanations
from vfairness.explainer import FairnessExplainer
explanation = FairnessExplainer.explain(audit_report) # Takes a vfairness report object (BiasAuditReport, CalibrationReport, GateDecision, ...)
print(explanation.severity) # 'info' | 'low' | 'medium' | 'high' | 'critical'
print(explanation.recommendations) # Actionable next steps
Visualization
A library of SVG templates for card-based dashboards, plus Matplotlib and Plotly outputs. SVG rendering needs the [rendering] extra (Jinja2); the output SVG is self-contained. Call vfairness.rendering.list_templates() for the current set (44 renderable chart templates, plus the internal _shared_defs partial).
from vfairness import classification_fairness_report, plot_fairness_metrics, create_fairness_dashboard
from vfairness.rendering import radar_chart_to_svg, fairness_detailed_report_to_svg
report = classification_fairness_report(y_true, y_pred, gender, include_ci=True)
# Matplotlib (static): returns a Matplotlib Axes
ax = plot_fairness_metrics(report, style='academic', show_thresholds=True)
ax.figure.savefig('fairness_metrics.png', dpi=300, bbox_inches='tight')
# Plotly (interactive)
dashboard = create_fairness_dashboard(report, style='modern')
dashboard.write_html('fairness_dashboard.html')
# SVG templates (needs the [rendering] extra: Jinja2)
svg = radar_chart_to_svg(metrics_data, save_path='radar.svg')
plot_fairness_metrics needs the [viz] extra (Matplotlib); create_fairness_dashboard needs the [dashboard] extra (Plotly); the SVG templates need the [rendering] extra (Jinja2). Unlike the Matplotlib and Plotly charts, the SVG templates render to self-contained SVG with no runtime, browser, or JavaScript dependency.
See the SVG Gallery for every template with live previews.
Monitoring
Track fairness in production with real-time metrics, multi-scale drift detection, and adaptive alerting.
import pandas as pd
from vfairness.operations.monitoring import FairnessMonitor, FairnessDriftDetector
# Real-time monitoring: each batch is a DataFrame with
# 'prediction', 'label', and one 'group_<attr>' column per protected attribute
batch_df = pd.DataFrame({
'prediction': predictions,
'label': labels,
'group_gender': gender,
})
monitor = FairnessMonitor(window_size=1000)
window = monitor.update_and_check(batch_df)
if window.any_alert:
print(f"Alert! Flagged metrics: {[k for k, v in window.alerts.items() if v]}")
# Multi-scale drift detection: set a known-good baseline once,
# then compare each new stretch of metric history against it
detector = FairnessDriftDetector()
detector.set_baseline(pd.Series(reference_metrics))
drift = detector.check_drift(pd.Series(current_metrics), metric="demographic_parity")
print(f"Drift detected: {drift.drift_detected} (score: {drift.overall_drift_score:.3f})")
Reporting
Transform metrics into stakeholder-ready intelligence with multi-tier reports and interactive dashboards.
from vfairness.operations.reporting import MetricsStore, FairnessDashboard, ReportGenerator
store = MetricsStore()
store.ingest_from_monitor(monitor)
# Interactive Plotly dashboard
dashboard = FairnessDashboard(store)
fig = dashboard.create_executive_view()
fig.write_html("dashboard.html")
# Automated multi-format report (HTML, PDF, JSON)
gen = ReportGenerator(store, dashboard)
report = gen.generate_executive_report()
report.save("executive_report.html")
create_executive_view needs Plotly (the [dashboard] extra); MetricsStore and ReportGenerator run on the core install.
Experimentation
Run fairness-aware A/B tests with intersectional analysis and automated deployment recommendations.
from vfairness.operations.experimentation import (
FairnessExperiment, FairnessPowerAnalyzer, ExperimentAnalysis
)
exp = FairnessExperiment(
control_data=df_ctrl, treatment_data=df_treat,
protected_attributes=['gender', 'race'], outcome_column='approved',
)
result = exp.run_full_analysis()
# Per-intersection power analysis
power = FairnessPowerAnalyzer(exp)
print(power.get_power_summary())
# Multi-objective analysis and deployment decision
analysis = ExperimentAnalysis(result, experiment=exp)
rec = analysis.decision_recommendation()
print(f"Decision: {rec.decision}") # DEPLOY | HOLD | REVERT
Workflow Integration
Embed fairness checks into every stage of the development lifecycle — from experiment tracking and version control to CI/CD gates and collaborative review.
from vfairness.operations.cicd import (
ModelFairnessGate, HierarchicalGateConfig, FairnessReportCard
)
# Hierarchical gate: overall → single-attribute → intersectional
gate = ModelFairnessGate(
metrics=['demographic_parity_difference', 'equal_opportunity_difference'],
thresholds={'demographic_parity_difference': 0.1, 'equal_opportunity_difference': 0.1}
)
config = HierarchicalGateConfig(
check_intersections=True, intersection_depth=2
)
decision = gate.evaluate_hierarchical(
y_true, y_pred,
protected_attrs={'gender': gender, 'race': race}, # arrays, keyed by attribute
hierarchical_config=config
)
# Generate PR-ready report card
card = FairnessReportCard(decision, model_name='loan-approval-v2.1')
print(card.to_markdown()) # Paste into PR comment
from vfairness import log_fairness_to_wandb, auto_log_fairness
# W&B experiment tracking
log_fairness_to_wandb(analyzer, prefix='fairness')
# Auto-log decorator: the wrapped function returns (y_pred, y_true, sensitive_attr)
@auto_log_fairness(backend='mlflow')
def evaluate_model(X, y, sensitive):
model = LogisticRegression().fit(X, y)
return model.predict(X), y, sensitive # fairness metrics logged automatically
Experiment tracking needs the [mlops] extra (pip install "vfairness[mlops]" for MLflow and Weights & Biases). Without it, log_fairness_to_wandb raises an ImportError, and the auto_log_fairness decorator warns and skips logging.
See the Workflow Integration Guide for CI/CD YAML templates, pre-commit hooks, pytest plugin setup, and end-to-end examples.
Next Steps
API Reference
Complete documentation of all classes, functions, parameters, and return types.
Business Guide
Regulatory context, decision frameworks, and EU AI Act compliance guidance.
Concepts
Fairness definitions, the impossibility theorem, causal fairness, and statistical methodology.
SVG Gallery
Browse the full set of visualization templates with live previews and code examples.
Workflow Integration
CI/CD gates, pytest plugin, pre-commit hooks, MLOps logging, and PR report cards.