Source code for mllm_shap.viz.render
"""Public helpers for attribution visualization.
@domain viz
@see [[knowledge/architecture/viz]]
@tested-by [[tests/viz/test_render.py]]
"""
from typing import TYPE_CHECKING, Any, cast
from ..domain.conversation import ConversationSnapshot
from ..domain.players import PlayerSet
from ..pipeline.result import ExplainRunOutput
from ..plugins.builtin import default_registry
from ..plugins.context import PluginContext
from ..plugins.groups import PluginGroup
from ..plugins.registry import PluginRegistry
from ..protocols.renderer import AttributionRenderer
from .labels import token_labels
if TYPE_CHECKING:
from matplotlib.figure import Figure
[docs]
def render_attribution(
output: ExplainRunOutput,
snapshot: ConversationSnapshot,
player_set: PlayerSet,
*,
renderer: str = "token_text",
title: str | None = None,
registry: PluginRegistry | None = None,
) -> "Figure":
"""Render ``output`` attributions with a registered renderer plugin.
Pass ``registry=runner.registry`` to reuse the registry of the
:class:`~mllm_shap.pipeline.runner.ExplainRunner` that produced ``output``
(needed for custom renderers); otherwise the default registry is built.
"""
plugin_registry = registry or default_registry()
config = output.manifest.config
if config is None:
msg = "render_attribution needs an output whose manifest records its config"
raise ValueError(msg)
attribution_renderer = cast(
AttributionRenderer,
plugin_registry.resolve(
PluginGroup.RENDERERS,
renderer,
PluginContext(config=config, registry=plugin_registry),
),
)
labels = token_labels(snapshot, player_set)
values = output.result.values
return cast(
"Figure",
attribution_renderer.render(
labels,
values,
estimand=output.result.estimand,
title=title,
),
)
[docs]
def render_attribution_html(
output: ExplainRunOutput,
snapshot: ConversationSnapshot,
player_set: PlayerSet,
*,
title: str | None = None,
) -> str:
"""Return an HTML fragment for inline token coloring in Jupyter."""
from .token_text import TokenTextRenderer
renderer = TokenTextRenderer()
labels = token_labels(snapshot, player_set)
return renderer.to_html(
labels,
output.result.values,
estimand=output.result.estimand,
title=title,
)
[docs]
def display_attribution_html(
output: ExplainRunOutput,
snapshot: ConversationSnapshot,
player_set: PlayerSet,
*,
title: str | None = None,
) -> Any:
"""Display colored token HTML when IPython is available."""
html = render_attribution_html(output, snapshot, player_set, title=title)
display_cls = _import_ipython_display()
return display_cls(html)
def _import_ipython_display() -> Any:
try:
from IPython.display import HTML
except ImportError as exc:
msg = "IPython is required to display attribution HTML"
raise ImportError(msg) from exc
return HTML