Download examples/tutorials/lens_embed.py from gexinh/vlm-probe: direct link, hf CLI and curl.
- Browser
- Download file 3.36 kB
-
https://huggingface.co/spaces/gexinh/vlm-probe/resolve/main/examples/tutorials/lens_embed.py
- Command line
-
hf download hf://spaces/gexinh/vlm-probe/examples/tutorials/lens_embed.py
-
curl -L -o lens_embed.py https://huggingface.co/spaces/gexinh/vlm-probe/resolve/main/examples/tutorials/lens_embed.py
3.36 kB
| """Live projected visual-token nearest-neighbor tutorial. No result cache.""" | |
| import hashlib | |
| import os | |
| from pathlib import Path | |
| from urllib.request import urlretrieve | |
| import matplotlib.pyplot as plt | |
| import torch | |
| from PIL import Image | |
| from transformers import AutoModelForImageTextToText, AutoProcessor | |
| from vlmprobe import Prober | |
| from vlmprobe.visualization import plot_input, plot_lens_heatmap | |
| MODEL_ID = os.environ.get("VLM_PROBING_MODEL", "HuggingFaceTB/SmolVLM-500M-Instruct") | |
| DEVICE = os.environ.get("VLM_PROBING_DEVICE", "cuda:0" if torch.cuda.is_available() else "cpu") | |
| OUT = Path(os.environ.get("VLM_PROBING_OUTPUT", "outputs/embed_tutorial")) | |
| OUT.mkdir(parents=True, exist_ok=True) | |
| custom_image = os.environ.get("VLM_PROBING_IMAGE") | |
| image_path = Path(custom_image) if custom_image else OUT / "2341576.jpg" | |
| if custom_image and not image_path.is_file(): | |
| raise FileNotFoundError(image_path) | |
| if not image_path.is_file(): | |
| urlretrieve("https://raw.githubusercontent.com/gexinh/vlm-probing/main/demos/assets/images/2341576.jpg", image_path) | |
| if not custom_image: | |
| assert hashlib.sha256(image_path.read_bytes()).hexdigest() == "f2f5880022dce631fd23240b2d690a56dd1fa551205c48b16db210b147d2f968" | |
| image = Image.open(image_path).convert("RGB") | |
| question = "Is the shirt black or yellow?" | |
| model = AutoModelForImageTextToText.from_pretrained( | |
| MODEL_ID, dtype=torch.float32, attn_implementation="eager", | |
| ).to(DEVICE).eval() | |
| processor = AutoProcessor.from_pretrained(MODEL_ID) | |
| probe = Prober(model, processor) | |
| print(probe.describe()) | |
| messages = [{"role": "user", "content": [ | |
| {"type": "image"}, {"type": "text", "text": question}, | |
| ]}] | |
| prompt = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) | |
| inputs = probe.prepare(prompt=prompt, image=image, device=DEVICE) | |
| result = probe.lens.embed(tokens="visual").run(inputs, top_k=5, vocabulary_chunk_size=4096) | |
| print("neighbors / cosine:", result.tensors["token_ids"].shape, result.tensors["similarities"].shape) | |
| print("coordinates:", result.tensors["positions"].shape) | |
| for position, ids, cosine in zip(result.tensors["positions"][:8], | |
| result.tensors["token_ids"][0, :8], | |
| result.tensors["similarities"][0, :8]): | |
| print(position.tolist(), [(processor.tokenizer.decode([int(i)]), round(float(s), 3)) | |
| for i, s in zip(ids, cosine)]) | |
| # Geometry is not guessed: crops/tiles are model-specific. Display exact token | |
| # coordinates rather than stretching a multi-crop sequence over the raw image. | |
| count = min(32, result.tensors["positions"].shape[0]) | |
| fig, axes = plt.subplots(2, 1, figsize=(12, 6), height_ratios=[4, 1], constrained_layout=True) | |
| plot_input(image, prompt=question, answer="yellow" if not custom_image else None, ax=axes[0]) | |
| plot_lens_heatmap(result.tensors["similarities"][0, :count, 0][None], | |
| value_kind="logit", log_scale=False, vmin=-1, vmax=1, | |
| layer_labels=["Decoder input"], | |
| token_labels=result.tensors["positions"][:count, 1].tolist(), | |
| ax=axes[1], value_label="Nearest vocabulary cosine similarity", | |
| title="First 32 visual-token positions (not image pixel coordinates)") | |
| fig.savefig(OUT / "embed.png", dpi=160, bbox_inches="tight") | |
| plt.show() | |
| result.save(OUT / "embed-result") | |