Generative backends¶
mllm-shap sends the base prompt and every coalition prompt to a generative
backend. Each backend implements
GenerativeBackend and is selected with
backend.kind in ExplainConfig. The rest of the pipeline is
the same for every backend.
Built-in backends¶
|
Extra |
Use when |
|---|---|---|
|
(core) |
Tests, CI and offline demos; no model involved |
|
(core) |
Audio runs in tests and demos (Audio input) |
|
|
Remote or local OpenAI-compatible HTTP servers (OpenAI, vLLM, LM Studio’s server mode, proxies) |
|
|
Local models through the LM Studio SDK, with automatic download |
|
|
Hugging Face language models in-process, with prefix-cache reuse; audio language models hear audio parts (Audio input) |
Settings shared by all backends are the top-level backend keys (see the
reference in Configuration); settings that only one backend understands go under
backend.options and are validated by that backend.
Speakers and token logprobs¶
Chat templates have no speaker slot, so every backend sends a message with a
speaker as "<speaker>: <text>" content under its role (user,
assistant or system). A message emptied by the delete policy is sent
empty, without the name.
The logprob value function (Using value functions) needs the log probability
of each generated token:
|
Token logprobs |
|---|---|
|
Always: log-softmax of the raw logits at each generated token, the end-of-sequence token included, with or without the KV cache |
|
Requests |
|
None: the SDK’s prediction result carries no logprobs; use |
|
None |
Mock¶
MockBackend returns a hash of the rendered prompt
and the model id as its “generation”. It is deterministic and fast, so every guide
and the test suite use it. The text has no meaning: attributions computed with it
test the plumbing, not a model.
backend:
kind: mock
model_id: stub
mock_audio hears audio parts; see Audio input.
HTTP API¶
ApiBackend posts chat-completions requests to
{api_host}/chat/completions. At temperature: 0.0 it caches responses keyed
by the request body, so identical coalition prompts cost one HTTP call.
backend:
kind: api
model_id: gpt-4o-mini
api_host: https://api.openai.com/v1
timeout_s: 120
max_retries: 3
generation:
temperature: 0.0
timeout_s bounds each request. Timeouts, refused connections and HTTP 408,
429, 500, 502, 503 and 504 responses are retried up to max_retries times with
exponential backoff (0.5 s doubling, at most 8 s, or the server’s
Retry-After). Any other error status, a response that is not JSON, or running
out of retries raises BackendUnavailableError. The
backend keeps at most 1024 cached responses and opens at most
explanation.max_inflight connections. Contract tests in CI mock the HTTP
transport; point api_host at a live server only for manual runs.
LM Studio¶
LmStudioBackend talks to a running
LM Studio through its Python SDK. It looks for a
downloaded model whose key matches model_id and, when none is found and
auto_download is on, searches the LM Studio hub (hub_search or
model_id) and downloads the quantization variant. LM Studio’s MLX runtime
does not accept concurrent requests on one model, so serialize_generate
(default on) runs one generate at a time whatever max_inflight says.
model_id is matched against downloaded models exactly (after normalization)
first, then as the prefix of the last / segment, then as a substring; more
than one match at a stage raises BackendUnavailableError
listing the candidates. Only connection failures (OSError and the SDK’s
websocket or connection errors) are retried, once; ValueError and
TypeError propagate unchanged.
backend:
kind: lmstudio
model_id: qwen2-500m-instruct
options:
quantization: Q4_K_M
auto_download: true
serialize_generate: true
Key |
Type |
Default |
Meaning |
|---|---|---|---|
|
|
|
Repository search term used to download the model; defaults to |
|
|
|
GGUF quantization to download when the model is not already local. |
|
|
|
Download missing models through the LM Studio repository API. |
|
|
|
Serialize |
|
|
|
What to do with audio parts, which the LM Studio SDK cannot send. |
Integration tests that need a running LM Studio with qwen2-500m-instruct are
marked lms and excluded from make check:
uv run pytest -m lms tests/
Hugging Face transformers¶
TransformersTextBackend loads
model_id on the first call (AutoModelForCausalLM, or a processor and the
checkpoint’s class for audio models, Audio input), on CUDA or Apple MPS
when available, otherwise on CPU. backend.options.dtype picks the weight
dtype: auto (default) uses bfloat16 on accelerators that support it,
float16 on other accelerators and float32 on CPU; float32,
float16 and bfloat16 force one. backend.options.revision pins the Hub
revision (a commit hash makes runs reproducible). It needs transformers>=4.56.
With explanation.kv_cache.enabled (off by default) it caches the key/value
states of up to kv_cache.max_entries prompt prefixes (all prompt tokens but the
last) and reuses the longest match for each coalition prompt. The reuse is counted
in metrics.kv_cache_hits and metrics.kv_cache_reused_tokens. A hit copies
the cached state, crops it to the shared prefix (Hugging Face
DynamicCache.crop), computes the missing prefix tokens and caches the completed
prefix, so coalitions reuse a shared prefix in any order. In float32 greedy outputs
are the same with the cache on and off. In float16 and bfloat16 the cached
prefix runs in separate forward passes that round differently, so a near-tied
greedy token can flip and values can move slightly; the backend logs one warning,
and dtype: float32 gives identical results. Static and
contextual embeddings of the output are computed only for value functions that
need them (embedding_cosine, embedding_euclidean). The tiny random model below loads in seconds and is what the
gpu-marked tests use:
backend:
kind: transformers
model_id: hf-internal-testing/tiny-random-gpt2
options:
dtype: auto
generation:
max_new_tokens: 8
explanation:
max_inflight: 1
kv_cache:
enabled: true
uv run pytest -m gpu tests/
Environment variables¶
Variable |
Effect |
|---|---|
|
Bearer token the |
|
Fallback bearer token, sent by the |
|
Path to a TOML file whose |
Example configurations¶
The repository keeps one runnable configuration per backend in config/:
dev_api.yaml,
dev_lmstudio.yaml and
dev_transformers.yaml.
Each file starts with a comment saying what it needs and how to run it.
Install the extra of the backend you use:
pip install "mllm-shap[api]"
pip install "mllm-shap[lmstudio]"
pip install "mllm-shap[transformers]"
To add a backend of your own, see Extending mllm-shap.
Further reading¶
Configuration schema: Configuration
What a run does with the backend: How a run works
API module reference: Backends
examples/text_explain_e2e.ipynb(embedded on Examples) — one prompt on the LM Studio, transformers and HTTP API backends