Explainability by default
Skill obielin/responsible-ai-skills/skills/explainability-by-default
Skills framework for coding agents that enforces responsible AI practices — bias assessment, fairness testing, explainability, governance documentation, and alignment review. Auto-activates when building AI systems.
npx -y skills add obielin/responsible-ai-skills --skill explainability-by-defaultAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when building any prediction, classification, recommendation, or scoring system. Explainability is not optional — it is a design requirement.
SKILL.md
7.6 KB, as published. Nobody here has run it
Explainability by Default
Every AI system you build must be able to explain its decisions. This is not an add-on — it is a design constraint. Build explanation capability first, then the model.
The Explainability Design Question
Before choosing a model architecture, answer this:
Who needs to understand this decision, and what do they need to know?
| Audience | What They Need | Approach |
|---|---|---|
| Affected citizen | "Why was I declined/flagged/scored?" | Plain-English local explanation |
| Frontline staff | "What drove this score for this person?" | Feature importance for this case |
| Auditor / regulator | "How does this system work systematically?" | Global model behaviour + documentation |
| Developer / data scientist | "Is the model behaving as expected?" | SHAP values, attention maps, partial dependence |
Design for all relevant audiences before writing model code.
Step 1: Choose an Interpretable-First Architecture
Prefer interpretable models unless you have a clear, documented reason not to:
Decision tree → Logistic regression → Linear SVM
↓ (only if accuracy genuinely requires it)
Random Forest + SHAP → Gradient Boosting + SHAP
↓ (only if task genuinely requires it)
Deep neural network + explanation layer
↓ (last resort — requires extra governance)
Black-box model (requires independent audit)
Rule: Use the simplest model that meets your accuracy requirements. Document why you didn't use a simpler one.
Step 2: Add Explanation Capability at Build Time
For Scikit-learn Models
import shap
# Train model
model.fit(X_train, y_train)
# Build explainer at training time — not as an afterthought
explainer = shap.TreeExplainer(model) # for tree-based models
# or
explainer = shap.LinearExplainer(model, X_train) # for linear models
# or
explainer = shap.KernelExplainer(model.predict, shap.sample(X_train, 100)) # for any model
# Save explainer alongside model
import joblib
joblib.dump({'model': model, 'explainer': explainer}, 'model_artifacts/model_with_explainer.pkl')
For Neural Networks
import shap
import torch
# Use DeepExplainer or GradientExplainer
explainer = shap.DeepExplainer(model, background_data)
# Or use integrated gradients via Captum (PyTorch)
from captum.attr import IntegratedGradients
ig = IntegratedGradients(model)
For LLMs / Generative Models
# Implement structured chain-of-thought that surfaces reasoning
SYSTEM_PROMPT = """
When making any classification or recommendation, you MUST:
1. State your conclusion
2. List the top 3 factors that led to it, in order of importance
3. State what would have changed your conclusion
4. Assign a confidence level: High / Medium / Low
Format:
CONCLUSION: <your decision>
FACTORS: 1. <most important> 2. <second> 3. <third>
COUNTERFACTUAL: <what would change the outcome>
CONFIDENCE: <High/Medium/Low> — <reason>
"""
Step 3: Implement the Explanation API
Every model must expose a standard explanation interface:
class ExplainableModel:
"""Wrapper that enforces explainability as a first-class concern."""
def __init__(self, model, explainer, feature_names: list[str]):
self.model = model
self.explainer = explainer
self.feature_names = feature_names
def predict(self, X):
"""Make prediction."""
return self.model.predict(X)
def explain(self, X_single, top_n: int = 5) -> dict:
"""
Explain a single prediction.
Returns:
{
'prediction': <value>,
'confidence': <float>,
'top_factors': [
{'feature': str, 'value': any, 'impact': float, 'direction': str},
...
],
'plain_english': str,
'counterfactual': str,
}
"""
prediction = self.model.predict(X_single)[0]
shap_values = self.explainer.shap_values(X_single)
# Get top N features by absolute SHAP value
importances = list(zip(
self.feature_names,
X_single[0],
shap_values[0] if isinstance(shap_values, list) else shap_values[0]
))
importances.sort(key=lambda x: abs(x[2]), reverse=True)
top_factors = [
{
'feature': feat,
'value': val,
'impact': float(shap),
'direction': 'increases' if shap > 0 else 'decreases',
}
for feat, val, shap in importances[:top_n]
]
plain_english = self._generate_plain_english(prediction, top_factors)
return {
'prediction': prediction,
'confidence': float(abs(shap_values).max()),
'top_factors': top_factors,
'plain_english': plain_english,
}
def _generate_plain_english(self, prediction, top_factors) -> str:
"""Generate a plain-English explanation a non-technical person can understand."""
factor_text = ', '.join(
f"{f['feature']} ({f['direction']} the score)"
for f in top_factors[:3]
)
return (
f"The system predicted '{prediction}'. "
f"The main factors were: {factor_text}."
)
def global_explanation(self) -> dict:
"""Return global feature importance for the entire model."""
raise NotImplementedError("Implement global explanation for audit purposes.")
Step 4: Test Your Explanations
Explanations can be wrong. Test them:
def test_explanation_is_consistent(model, test_df):
"""Explanation must be consistent with the prediction."""
for _, row in test_df.sample(20).iterrows():
result = model.explain(row.to_frame().T)
# Top positive factor should increase prediction
top_factor = result['top_factors'][0]
assert result['prediction'] is not None
assert len(result['top_factors']) > 0
assert result['plain_english'] != ""
def test_explanation_identifies_known_driver(model, test_data_with_known_driver):
"""When a feature is the dominant driver, explanation must surface it."""
# Create a test case where one feature clearly dominates
result = model.explain(test_data_with_known_driver)
assert result['top_factors'][0]['feature'] == 'known_dominant_feature', (
f"Expected known driver to be top factor, got: {result['top_factors'][0]['feature']}"
)
Step 5: Document for Stakeholders
For each deployed system, produce:
- Global explanation summary — which features matter most overall, and why
- Example explanations — 5 real examples covering different prediction outcomes
- Plain-English system description — what the system does, in language suitable for a citizen
- Limitations statement — when the explanation may be unreliable or incomplete
Add these to docs/explainability-<system-name>.md.
Completion Checklist
- Explanation approach chosen and documented before model training
- Explainer built and saved alongside model
-
explain()method implemented and tested - Plain-English explanation generated and reviewed by a non-technical person
- Global explanation documented
- Explanation limitations documented
- Tests written to verify explanation consistency
Proceed to governance-documentation before deployment.