Source code for nlp_shap.pipeline.config
"""Explain pipeline configuration schema."""
from __future__ import annotations
from typing import Literal
import yaml
from pydantic import BaseModel, ConfigDict, Field
from ..domain.enums import EmbeddingMode
from ..domain.estimands import Estimand
[docs]
class BackendConfig(BaseModel):
"""Backend selection and connection parameters."""
model_config = ConfigDict(extra="forbid", frozen=True)
kind: str
"""Registered backend plugin identifier."""
model_id: str
"""Model name or repository id passed to the backend."""
api_host: str | None = None
"""Optional API host for HTTP-compatible backends."""
[docs]
class GenerationConfig(BaseModel):
"""Generation parameters for the base and coalition evaluations."""
model_config = ConfigDict(extra="forbid", frozen=True)
max_new_tokens: int = 128
"""Maximum tokens generated per coalition evaluation."""
temperature: float = 0.0
"""Sampling temperature for model generation."""
top_k: int = 1
"""Top-k sampling cutoff for model generation."""
precompute_base: bool = True
"""Whether to generate the grand-coalition reference before explaining."""
[docs]
class BudgetConfig(BaseModel):
"""Estimator budget controls replacing standard/limited split configs."""
model_config = ConfigDict(extra="forbid", frozen=True)
fraction: float = Field(default=1.0, gt=0.0, le=1.0)
"""Fraction of the full coalition budget used by the estimator."""
[docs]
class ArchiveConfig(BaseModel):
"""Run archive persistence options."""
model_config = ConfigDict(extra="forbid", frozen=True)
path: str = "./runs/{run_id}"
"""Filesystem path template for persisted run archives."""
flush_every: int = Field(default=50, ge=1)
"""Number of coalition records between archive flushes."""
[docs]
class DedupConfig(BaseModel):
"""Coalition deduplication options."""
model_config = ConfigDict(extra="forbid", frozen=True)
enabled: Literal["auto", "on", "off"] = "auto"
"""Deduplication mode for repeated coalition evaluations."""
[docs]
class KvCacheConfig(BaseModel):
"""Prefix cache options for supported backends."""
model_config = ConfigDict(extra="forbid", frozen=True)
enabled: bool = True
"""Whether prefix/KV cache reuse is enabled when supported."""
[docs]
class ExplanationConfig(BaseModel):
"""Explanation algorithm and runtime controls."""
model_config = ConfigDict(extra="forbid", frozen=True)
use_v2: bool = True
"""Whether the v2 explain pipeline is active."""
estimand: Estimand = Estimand.SHAPLEY
"""Cooperative-game value targeted by aggregation."""
estimator: str = "neyman_cc"
"""Registered estimator plugin used to sample coalitions."""
value_fn: str = "tfidf_cosine"
"""Registered value-function plugin used to score outputs."""
normalizer: str = "identity"
"""Registered normalizer applied after estimand aggregation."""
players: str = "tokens"
"""Registered partition plugin that defines explainability players."""
absence_policy: str = "delete"
"""Registered absence policy used to render masked snapshots."""
budget: BudgetConfig = BudgetConfig()
"""Estimator budget controls."""
include_minimal_masks: bool = False
"""Whether minimal coalitions are included in estimator sampling."""
max_inflight: int = Field(default=2, ge=1)
"""Maximum concurrent coalition evaluations."""
archive: ArchiveConfig = ArchiveConfig()
"""Run archive persistence settings."""
dedup: DedupConfig = DedupConfig()
"""Coalition deduplication settings."""
kv_cache: KvCacheConfig = KvCacheConfig()
"""Prefix cache settings for supported backends."""
embedding_mode: EmbeddingMode = EmbeddingMode.STATIC
"""Embedding mode used by embedding-based value functions."""
seed: int = 42
"""Random seed for reproducible coalition sampling."""
[docs]
class ExplainConfig(BaseModel):
"""Top-level explain pipeline configuration."""
model_config = ConfigDict(extra="forbid", frozen=True)
backend: BackendConfig
"""Backend selection and connection parameters."""
generation: GenerationConfig = GenerationConfig()
"""Generation parameters for base and coalition evaluations."""
explanation: ExplanationConfig = ExplanationConfig()
"""Explanation algorithm and runtime controls."""
[docs]
def explain_config_from_yaml(text: str) -> ExplainConfig:
"""Parse YAML text into a validated :class:`ExplainConfig`."""
data = yaml.safe_load(text)
if not isinstance(data, dict):
msg = "explain config root must be a mapping"
raise TypeError(msg)
return ExplainConfig.model_validate(data)
[docs]
def explain_config_to_yaml(config: ExplainConfig) -> str:
"""Serialize a config to YAML with stable key ordering within sections."""
payload = config.model_dump(mode="json")
dumped: str = yaml.safe_dump(payload, sort_keys=False)
return dumped