Configuration

mllm-shap uses one ExplainConfig schema with three top-level sections: backend (which model), generation (how it generates) and explanation (what is explained and how). Every section rejects unknown keys, so a typo fails validation instead of being ignored.

YAML skeleton

A complete configuration. Only backend.kind and backend.model_id are required; every omitted key takes the default listed in the key reference below. The prefix cache (kv_cache) only affects the transformers backend and is off by default; max_players refuses, before any model call, runs whose budget plans more than \(2^{\text{max\_players}}\) coalitions (budget.fraction times \(2^n\) for \(n\) players, so every full-table run on more than max_players players). budget.evaluations replaces budget.fraction with an absolute number of coalition evaluations; set one of the two, never both:

backend:
  kind: lmstudio
  model_id: qwen2-500m-instruct

generation:
  max_new_tokens: 128
  temperature: 0.0
  top_k: 1

explanation:
  estimand: shapley
  estimator: neyman_cc
  value_fn: tfidf_cosine
  normalizer: identity
  players: tokens
  absence_policy: delete
  budget:
    fraction: 0.3
  include_minimal_masks: false
  neyman:
    use_standard_method: false
    initial_fraction: null
    initial_num_samples: null
  max_inflight: 2
  max_players: 24
  archive:
    path: ./runs/{run_id}
    flush_every: 50
    on_exists: error
  dedup:
    enabled: auto
  kv_cache:
    enabled: false
    max_entries: 8
  embedding_mode: static
  seed: 42
  plugin_options: {}

Load and save

explain_config_from_yaml() validates YAML text and explain_config_to_yaml() writes every key back, defaults included:

from pathlib import Path

from mllm_shap import ExplainConfig, explain_config_from_yaml, explain_config_to_yaml

Path("config.yaml").write_text(
    "backend:\n"
    "  kind: mock\n"
    "  model_id: stub\n"
    "explanation:\n"
    "  estimator: exact\n",
    encoding="utf-8",
)
config = explain_config_from_yaml(Path("config.yaml").read_text(encoding="utf-8"))
assert isinstance(config, ExplainConfig)

text = explain_config_to_yaml(config)
Path("config.roundtrip.yaml").write_text(text, encoding="utf-8")
print("\n".join(text.splitlines()[:8]))

Output

backend:
  kind: mock
  model_id: stub
  api_host: null
  timeout_s: 120.0
  max_retries: 3
  options: {}
generation:

In Python, build the same object with ExplainConfig.model_validate({...}); configs are frozen, so derive variants with model_copy(update=...).

Key reference

Generated from the pydantic models, so it always matches the installed version.

backend

Key

Type

Default

Meaning

backend.kind

str

required

Registered backend plugin identifier.

backend.model_id

str

required

Model name or repository id passed to the backend.

backend.api_host

str | null

null

API host for HTTP-compatible backends. Required for the api backend (there is no environment or localhost fallback); optional for lmstudio, which otherwise asks LM Studio for its local server. The api backend sends MLLM_SHAP_API_KEY as the bearer key to any host; OPENAI_API_KEY is used only when that is unset and the host is api.openai.com.

backend.timeout_s

float

120.0

Per-request timeout in seconds for remote backends.

backend.max_retries

int

3

Retries after a transient backend failure (0 disables retrying).

backend.options

dict[str, object]

{}

Backend-specific settings validated by the selected backend.

generation

Key

Type

Default

Meaning

generation.max_new_tokens

int

128

Maximum tokens generated per coalition evaluation.

generation.temperature

float

0.0

Sampling temperature for model generation.

generation.top_k

int

1

Top-k sampling cutoff for model generation.

generation.compute_embeddings

bool

false

Ask backends that can (transformers) to attach model embeddings to records. The pipeline turns it on when the value function declares needs_embeddings; it costs extra forward passes per coalition.

explanation

Key

Type

Default

Meaning

explanation.estimand

"shapley" | "banzhaf"

"shapley"

Cooperative-game value targeted by aggregation.

explanation.estimator

str

"neyman_cc"

Registered estimator plugin used to sample coalitions.

explanation.value_fn

str

"tfidf_cosine"

Registered value-function plugin used to score outputs.

explanation.normalizer

str

"identity"

Registered normalizer applied after estimand aggregation.

explanation.players

str

"tokens"

Registered partition plugin that defines explainability players.

explanation.absence_policy

str

"delete"

Registered absence policy used to render masked snapshots.

explanation.budget

section

Estimator budget controls.

explanation.budget.fraction

float | null

null

Share of the 2^n coalitions evaluated; 1.0 when evaluations is unset.

explanation.budget.evaluations

int | null

null

Coalition evaluations in total, empty and grand included, instead of fraction; raised to the estimator’s floor (2 for mc, 2n + 2 for complementary and neyman_cc, which also round down to whole pairs) and capped at 2^n.

explanation.include_minimal_masks

bool

false

Whether minimal coalitions are included in estimator sampling.

explanation.neyman

section

Neyman-CC controls applied when the Neyman estimator is selected.

explanation.neyman.use_standard_method

bool

false

Whether phase-one sampling uses unstructured random coalitions.

explanation.neyman.initial_fraction

float | null

null

Fraction of the total budget used during phase-one initialization, in (0, 1].

explanation.neyman.initial_num_samples

int | null

null

Explicit phase-one pair budget overriding initial_fraction; at least 1.

explanation.max_inflight

int

2

Maximum concurrent coalition evaluations.

explanation.max_players

int

24

Runs planning more than 2^max_players coalitions (fraction * 2^n, or evaluations) are refused. The ceiling of 62 keeps 2^n inside a signed 64-bit integer, which the samplers’ NumPy mask arithmetic needs.

explanation.archive

section

Run archive persistence settings.

explanation.archive.path

str

"./runs/{run_id}"

Filesystem path template for persisted run archives.

explanation.archive.flush_every

int

50

Number of coalition records between archive flushes.

explanation.archive.on_exists

"error" | "overwrite"

"error"

What to do when the archive directory already holds a run.

explanation.dedup

section

Coalition deduplication settings.

explanation.dedup.enabled

"auto" | "on" | "off"

"auto"

Deduplication mode for repeated coalition evaluations.

explanation.kv_cache

section

Prefix cache settings for supported backends.

explanation.kv_cache.enabled

bool

false

Whether prefix/KV cache reuse is enabled when supported.

explanation.kv_cache.max_entries

int

8

Maximum prefix KV states a backend keeps; the oldest is evicted first.

explanation.embedding_mode

"static" | "contextual"

"static"

Embedding mode used by embedding-based value functions.

explanation.seed

int

42

Random seed for reproducible coalition sampling.

explanation.plugin_options

dict[str, dict[str, object]]

{}

Per-plugin options keyed by plugin name, passed as PluginContext.options.

Plugin options

explanation.plugin_options passes settings to one plugin of the run. Key them by <group>/<name> (groups: estimators, estimands, value_fns, normalizers, backends, partitions, absence_policies, renderers) or by the bare plugin name when no other plugin of the run shares it. The registry hands them to the plugin as PluginContext.options; see Extending mllm-shap for a plugin that reads them. Built-in plugins with options are absence_policies/pad (placeholder), absence_policies/neutral (fill_char) and normalizers/power_shift (power); the others accept none. Before a run starts, a key naming no plugin of the run, an unknown option or a value of the wrong type raises ConfigError naming the group, plugin and key.

explanation:
  value_fn: my_metric
  plugin_options:
    value_fns/my_metric:
      threshold: 0.5

Archive path and re-runs

explanation.archive.path is a template; {run_id} expands to the first 16 characters of the snapshot id plus a 12-character digest of the configuration (archive settings excluded) and the backend model id. Changing the estimator, policy, value function, seed or model therefore writes to a new directory.

Re-running the same configuration on the same snapshot targets the same directory. With on_exists: error (the default) the run raises ArchiveExistsError instead of appending to the old archive; on_exists: overwrite replaces it. Set path: "" to skip archiving entirely.

Example configurations

The repository ships one configuration per local backend in config/ (dev_api.yaml, dev_lmstudio.yaml, dev_transformers.yaml); Generative backends explains each backend’s keys.

Further reading