vlm-probe / examples /prober_quickstart.py
gexinh's picture
Publish vlmprobe library, demos, technical report and project page
196d16f verified
Raw History Blame Contribute Delete
3.61 kB
"""Exercise model-bound methods on a synthetic tiny decoder, without downloads.
PYTHONPATH=src python examples/prober_quickstart.py
"""
import tempfile
import torch
from tiny_model import TinyModel
from vlmprobe import Prober, TokenMargin
def main():
torch.manual_seed(7)
torch.set_num_threads(1)
model = TinyModel().eval()
probe = Prober(model)
clean = {"input_ids": torch.tensor([[1, 2, 3], [3, 4, 5]]),
"image_tokens": torch.randn(2, 2, 6)}
corrupt = {**clean, "image_tokens": torch.zeros_like(clean["image_tokens"])}
metric = TokenMargin(positive=4, negative=5)
print("Available:", sum(v["available"] for v in probe.describe()["methods"].values()))
result = probe.lens.logit(layers=[0, 1]).run(clean)
print("Logit Lens [layer, selected position, vocabulary]:", result.tensors["logits"].shape)
print("Positions [batch, expanded token]:", result.tensors["positions"].tolist())
probe.lens.embed().run(clean, top_k=3)
binding = {"model_id": "tiny-seed7", "tokenizer_id": "integer-demo",
"calibration_id": "two-demo-prompts", "readout_id": "tiny.norm+head"}
tuned = probe.lens.tuned(layers=[0], binding=binding).fit(clean, steps=20, lr=0.01)
print("Tuned calibration KL:", tuned.losses[0][0], "->", tuned.losses[0][-1])
with tempfile.TemporaryDirectory() as path:
tuned.save(path)
probe.lens.tuned(layers=[0], binding=binding).load(path).run(clean)
probe.lens.attention(layers=[0]).fit(clean, steps=5).run(clean)
probe.lens.jacobian(layers=[0]).fit(clean, skip_first=0, exclude_last=False).run(clean)
probe.lens.patchscope(layers=[0], source_position=0, target_layer=0, target_position=2).run(
clean, target_inputs={**clean, "input_ids": torch.tensor([[6, 7, 8], [6, 7, 8]])})
patched = probe.causal.patch(layers=[0, 1], tokens="visual").run(corrupt, source=clean, metric=metric)
print("Patch effects [independent layer, batch]:", patched.tensors["effect"])
path = probe.causal.path(senders=[(0, 0)], receivers=[(1, 0, "v")],
sender_tokens="visual", receiver_tokens="visual")
print("Path effects [batch]:", path.run(corrupt, donor=clean, metric=metric).tensors["effect"])
probe.causal.attribute(layers=[0]).run(corrupt, source=clean, metric=metric)
probe.causal.knockout(layers=[0]).run(clean, metric=metric)
probe.causal.steer(layers=[0], strength=0.1).run(clean, direction=torch.ones(6), metric=metric)
probe.causal.eap_ig(steps=4).run(corrupt, source=clean, metric=metric)
probe.attention.profile(layers=[0, 1]).run(clean)
probe.attention.rollout().run(clean)
probe.attention.relevance().run(clean, metric=metric)
probe.attention.head_logits(layers=[1]).run(clean)
probe.attention.reweight(layers=[0], weight=2.).run(clean, metric=metric)
probe.attention.temperature(layers=[0], temperature=0.7).run(clean, metric=metric)
probe.attention.grad_cam(layers=[1], keys="visual").run(clean, metric=metric)
probe.attention.attribution(layers=[1], steps=4).run(clean, metric=metric)
# This synthetic model receives image embeddings, rather than raw pixels.
# The integration path is explicitly an embedding-space method transfer.
probe.attention.tam(steps=4, input_key="image_tokens").run(clean, metric=metric)
probe.attention.beyond_intuition(variant="head", steps=4, input_key="image_tokens").run(
clean, metric=metric)
print("Core methods and attention-map calls completed; DTD uses the separate ViT backend.")
if __name__ == "__main__":
main()