Getting started¶
This page gets you from zero to a first token attribution in a few minutes, and shows the two numbers every Shapley explanation is checked against.
Installation¶
Install from PyPI (Python 3.12 or newer):
pip install mllm-shap
From a local clone (development uses uv):
git clone https://github.com/Pawlo77/MLLM-SHAP
cd MLLM-SHAP
make install
Your first aggregation¶
The estimand aggregators take boolean coalition masks and aligned payoffs \(v(S)\). On a three-player majority game, Shapley and Banzhaf disagree:
from itertools import product
from mllm_shap import BanzhafAggregator, ShapleyAggregator
num_players = 3
masks = [tuple(bits) for bits in product([False, True], repeat=num_players)]
def majority_payoff(mask: tuple[bool, ...]) -> float:
return 1.0 if sum(mask) >= 2 else 0.0
payoffs = [majority_payoff(mask) for mask in masks]
shapley = ShapleyAggregator().aggregate(masks, payoffs)
banzhaf = BanzhafAggregator().aggregate(masks, payoffs)
print("Shapley:", shapley)
print("Banzhaf:", banzhaf)
Output
Shapley: [0.3333333333333333, 0.3333333333333333, 0.3333333333333333]
Banzhaf: [0.5, 0.5, 0.5]
See Using estimand aggregators for why the two differ.
Explain a short prompt¶
For end-to-end token attributions, build a
ConversationSnapshot, validate an
ExplainConfig, and call ExplainRunner.
The mock backend needs no model, GPU or optional extra:
import math
from mllm_shap import (
ConversationSnapshot,
ExplainConfig,
ExplainRunner,
Message,
Role,
Turn,
)
snapshot = ConversationSnapshot.from_turns((
Turn(messages=(Message(role=Role.USER, text="refund my order"),)),
))
config = ExplainConfig.model_validate({
"backend": {"kind": "mock", "model_id": "stub"},
"explanation": {
"estimator": "exact",
"value_fn": "tfidf_cosine",
"absence_policy": "pad",
"archive": {"path": ""}, # keep this demo off disk
},
})
output = ExplainRunner(config).explain_sync(snapshot)
result = output.result
print("values:", tuple(round(value, 4) for value in result.values))
print("base_value v(empty):", round(result.base_value, 4))
print("grand_value v(N):", round(result.grand_value, 4))
# Efficiency: Shapley values sum to v(N) - v(empty).
print(
"efficient:",
math.isclose(sum(result.values), result.grand_value - result.base_value),
)
Output
values: (0.3333, 0.3333, 0.3333)
base_value v(empty): 0.0
grand_value v(N): 1.0
efficient: True
Each token of "refund my order" is a player. base_value is the payoff of
the fully masked prompt and grand_value the payoff of the full prompt; Shapley
values distribute the difference. With the default identity normalizer the
check above holds for every exact run and is the first thing to verify when an
attribution looks wrong.
Without archive.path: "" the run is archived under ./runs/{run_id}, and
re-running the same configuration on the same snapshot raises
ArchiveExistsError unless
explanation.archive.on_exists is overwrite. See Configuration.
Which estimator?¶
exact scores all \(2^n\) coalitions and is only practical for short
prompts. For longer inputs pick mc, complementary or neyman_cc and a
budget.fraction below 1; Choosing an estimator has the decision table
and Using approximate estimators the code.
Label results for archives¶
Every run carries a RunManifest that records the estimand,
estimator, value function and players. It round-trips through JSON:
from mllm_shap import parse_manifest
restored = parse_manifest(output.manifest.to_dict())
print("schema_version:", restored.schema_version)
print("estimand:", restored.estimand.value)
print("estimator:", restored.estimator)
print("players:", restored.player_ids)
Output
schema_version: 4
estimand: shapley
estimator: exact
players: ('f5986ca22ea8567e:0:0:0', 'f5986ca22ea8567e:0:0:1', 'f5986ca22ea8567e:0:0:2')
Logging¶
Importing mllm_shap leaves your logging configuration alone. Call
mllm_shap.configure_logging(level="INFO") to see the pipeline’s stage events
(run start, base generation, scheduled coalitions and run duration) on stderr,
mllm_shap.configure_logging() to apply the [tool.logging] section of the
nearest pyproject.toml (or pass a path), or set MLLM_SHAP_LOGGING_CONFIG.
Runtime core lists the events.
Next steps¶
How a run works — what happens inside a run, metrics and archives
Command line — the same run from the command line, with JSON input and output
Configuration — every configuration key
Choosing an estimator — exact, Monte Carlo, complementary or Neyman
Generative backends — run against LM Studio, Hugging Face or an HTTP API
Examples — runnable notebooks