Skip to content

Getting Started

Installation

Quickstart

pip install medvlm

Python version

medvlm requires Python >= 3.10. If your system default is older, create a dedicated virtualenv first:

python3.10 -m venv .venv && source .venv/bin/activate

PyTorch and your NVIDIA driver

pip install medvlm will pull the default PyPI PyTorch wheel, which currently tracks the newest CUDA build (torch 2.11 needs NVIDIA driver 555+). On older drivers this installs but fails at import with a CUDA error. To avoid that, install torch yourself first from the index URL matching your CUDA toolkit, then install medvlm:

pip install torch --index-url https://download.pytorch.org/whl/cu124
pip install medvlm

medvlm is tested against torch>=2.4,<2.12; pick the newest wheel your driver supports within that range.

InternVL extras

The InternVL loader depends on timm, which is not pulled in by the base install. If you plan to use internvl3_* models:

pip install 'medvlm[internvl]'

Flash Attention (optional)

For faster inference on CUDA GPUs:

pip install flash-attn --no-build-isolation --no-deps

Basic Usage

import medvlm

# Load data (auto-downloads from HuggingFace)
dataset = medvlm.load_dataset("vqa_rad", split="test", question_type="closed")

# Load model
model, processor, config = medvlm.load_model("qwen3vl_2b")

# Compute sampling-based confidence (N=20 samples per question)
results = medvlm.compute_confidence(
    model, processor, config, dataset,
    method="sampling", num_samples=20,
)

# Evaluate calibration
report = medvlm.evaluate_calibration(
    [r.is_correct for r in results],
    [r.confidence for r in results],
)
print(f"ECE: {report['ece']:.4f}")
print(f"Accuracy: {report['accuracy']:.4f}")
print(f"Mean Confidence: {report['mean_confidence']:.4f}")
print(f"Overconfidence: {report['overconfidence']:.4f}")

Confidence Methods

Sampling-based

Generates N independent answers per question and computes confidence as P(majority answer):

results = medvlm.compute_confidence(
    model, processor, config, dataset,
    method="sampling",
    num_samples=20,       # N samples per question
    temperature=0.7,      # sampling temperature
    prompt_mode="base",   # "base" (direct) or "cot" (chain-of-thought)
)

Each result has .confidence, .is_correct, .answer_counts, .raw_responses.

Verbalized

Prompts the model to self-report its confidence (0--100%):

results = medvlm.compute_confidence(
    model, processor, config, dataset,
    method="verbalized",
    variant="vanilla",    # see below for all variants
    batch_size=4,         # questions per forward pass
)

Each result has .confidence, .is_correct, .parse_success, .raw_response.

Variants:

Variant Description
vanilla "Provide your answer and confidence (0--100%)"
vanilla_cot Same with "think step by step" prefix
punish Adds punishment framing for overconfidence
top_k Top-3 guesses with probabilities
two_stage Answer first, then rate confidence separately
linguistic "almost certain", "likely", etc. mapped to numbers

Post-hoc Calibration

Fit a calibrator on a validation split, apply to test:

from medvlm import CalibrationPipeline, train_val_test_split
import numpy as np

# Split dataset
val_set, test_set = train_val_test_split(dataset, val_fraction=0.3, seed=42)

# Compute confidence on both splits
val_results = medvlm.compute_confidence(model, processor, config, val_set, ...)
test_results = medvlm.compute_confidence(model, processor, config, test_set, ...)

val_conf = np.array([r.confidence for r in val_results])
val_corr = np.array([r.is_correct for r in val_results])
test_conf = np.array([r.confidence for r in test_results])
test_corr = np.array([r.is_correct for r in test_results])

# Fit and transform
cal = CalibrationPipeline(method="platt")
cal.fit(val_conf, val_corr)
calibrated = cal.transform(test_conf)

# Evaluate
report = medvlm.evaluate_calibration(test_corr, calibrated)

HAC Calibration

HAC methods require hallucination scores (e.g., from HEDGE/VASE):

cal = CalibrationPipeline(method="hac_platt")
cal.fit(val_conf, val_corr, hallucination_scores=val_h)
calibrated = cal.transform(test_conf, hallucination_scores=test_h)

See Calibration API for all available methods.

Available Models

# List all registered models
print(medvlm.MODEL_REGISTRY)

# Load by short key
model, processor, config = medvlm.load_model("qwen3vl_8b")

# Load by full HuggingFace ID
model, processor, config = medvlm.load_model("Qwen/Qwen3-VL-8B-Instruct")

# With quantization
model, processor, config = medvlm.load_model("qwen3vl_8b", quantization="8bit")

Available Datasets

# Auto-download from HuggingFace
dataset = medvlm.load_dataset("vqa_rad", split="test")
dataset = medvlm.load_dataset("slake", split="test", question_type="open")

# Subsample for quick experiments
dataset = medvlm.load_dataset("vqa_rad", subsample_size=50, seed=42)