Image-Text-to-Text
Transformers
Safetensors
premonition_diffusion_gemma
vllm
diffusion-gemma
multimodal
audio
video
custom_code
conversational
Instructions to use prem-research/Premonition-Exp with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use prem-research/Premonition-Exp with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="prem-research/Premonition-Exp", trust_remote_code=True) messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] pipe(text=messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoModelForImageTextToText model = AutoModelForImageTextToText.from_pretrained("prem-research/Premonition-Exp", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use prem-research/Premonition-Exp with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "prem-research/Premonition-Exp" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "prem-research/Premonition-Exp", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker
docker model run hf.co/prem-research/Premonition-Exp
- SGLang
How to use prem-research/Premonition-Exp with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "prem-research/Premonition-Exp" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "prem-research/Premonition-Exp", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "prem-research/Premonition-Exp" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "prem-research/Premonition-Exp", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }' - Docker Model Runner
How to use prem-research/Premonition-Exp with Docker Model Runner:
docker model run hf.co/prem-research/Premonition-Exp
File size: 8,516 Bytes
b965204 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | # Copyright 2026 Prem Research. Licensed under the Apache License, Version 2.0.
"""Gemma 4 audio/video prefill for the unchanged DiffusionGemma decoder and sampler."""
import torch
from torch import nn
from transformers import AutoModel
from transformers.modeling_outputs import BaseModelOutputWithPast
from transformers.models.diffusion_gemma.modeling_diffusion_gemma import (
DiffusionGemmaDecoderModel,
DiffusionGemmaEncoderModel,
DiffusionGemmaForBlockDiffusion,
DiffusionGemmaModel,
DiffusionGemmaPreTrainedModel,
)
from transformers.models.gemma4.modeling_gemma4 import Gemma4Model, Gemma4MultimodalEmbedder
from .configuration_premonition import PremonitionConfig
class PremonitionEncoderModel(DiffusionGemmaEncoderModel):
config_class = PremonitionConfig
input_modalities = ("text", "image", "video", "audio")
def __init__(self, config):
super().__init__(config)
self.audio_tower = (
AutoModel.from_config(config.audio_config) if config.audio_config is not None else None
)
self.embed_audio = (
Gemma4MultimodalEmbedder(config.audio_config, config.text_config)
if config.audio_config is not None
else None
)
self.post_init()
get_audio_features = Gemma4Model.get_audio_features
get_video_features = Gemma4Model.get_video_features
def forward(
self,
input_ids=None,
pixel_values=None,
attention_mask=None,
position_ids=None,
past_key_values=None,
mm_token_type_ids=None,
inputs_embeds=None,
image_position_ids=None,
input_features=None,
input_features_mask=None,
pixel_values_videos=None,
video_position_ids=None,
**kwargs,
):
if (input_features is None) != (input_features_mask is None):
raise ValueError("Audio requires both input_features and input_features_mask.")
if input_features is None and pixel_values_videos is None:
return super().forward(
input_ids=input_ids,
pixel_values=pixel_values,
attention_mask=attention_mask,
position_ids=position_ids,
past_key_values=past_key_values,
mm_token_type_ids=mm_token_type_ids,
inputs_embeds=inputs_embeds,
image_position_ids=image_position_ids,
**kwargs,
)
if input_ids is None or inputs_embeds is not None:
raise ValueError("Audio/video prefill requires input_ids, without inputs_embeds.")
if pixel_values_videos is not None and video_position_ids is None:
raise ValueError("Video requires video_position_ids.")
masks = {
"image": input_ids == self.config.image_token_id,
"video": input_ids == self.config.video_token_id,
"audio": input_ids == self.config.audio_token_id,
}
multimodal_mask = masks["image"] | masks["video"] | masks["audio"]
safe_ids = input_ids.masked_fill(multimodal_mask, self.config.text_config.pad_token_id)
inputs_embeds = self.get_input_embeddings()(safe_ids)
def merge(modality, features):
mask = masks[modality].unsqueeze(-1).expand_as(inputs_embeds)
if int(masks[modality].sum()) != features.numel() // inputs_embeds.shape[-1]:
raise ValueError(
f"{modality} placeholder count ({int(masks[modality].sum())}) "
f"does not match valid feature count ({features.shape[0]})."
)
return inputs_embeds.masked_scatter(mask, features.to(inputs_embeds))
if pixel_values is not None:
features = self.get_image_features(
pixel_values, image_position_ids, return_dict=True
).pooler_output
inputs_embeds = merge("image", features)
if pixel_values_videos is not None:
features = self.get_video_features(
pixel_values_videos, video_position_ids, return_dict=True
).pooler_output
inputs_embeds = merge("video", torch.cat(features, dim=0))
if input_features is not None:
audio_outputs = self.get_audio_features(
input_features, input_features_mask, return_dict=True
)
features = audio_outputs.pooler_output
features = features[audio_outputs.attention_mask.to(features.device)]
inputs_embeds = merge("audio", features)
if position_ids is None:
past_seen = past_key_values.get_seq_length() if past_key_values is not None else 0
position_ids = (
torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device) + past_seen
).unsqueeze(0)
if not isinstance(attention_mask, dict):
attention_mask = self.create_masks_for_generate(
config=self.config.get_text_config(),
inputs_embeds=inputs_embeds,
attention_mask=attention_mask,
past_key_values=past_key_values,
position_ids=position_ids,
mm_token_type_ids=mm_token_type_ids,
)
return_dict = kwargs.pop("return_dict", True)
outputs = self.language_model(
attention_mask=attention_mask,
position_ids=position_ids,
past_key_values=past_key_values,
inputs_embeds=inputs_embeds,
return_dict=True,
**kwargs,
)
result = BaseModelOutputWithPast(
last_hidden_state=outputs.last_hidden_state,
past_key_values=outputs.past_key_values,
hidden_states=outputs.hidden_states,
attentions=outputs.attentions,
)
return result if return_dict else result.to_tuple()
class PremonitionModel(DiffusionGemmaModel):
config_class = PremonitionConfig
input_modalities = ("text", "image", "video", "audio")
def __init__(self, config):
DiffusionGemmaPreTrainedModel.__init__(self, config)
self.encoder = PremonitionEncoderModel(config)
self.decoder = DiffusionGemmaDecoderModel(config)
self.post_init()
class PremonitionForBlockDiffusion(DiffusionGemmaForBlockDiffusion):
config_class = PremonitionConfig
input_modalities = ("text", "image", "video", "audio")
def __init__(self, config):
DiffusionGemmaPreTrainedModel.__init__(self, config)
self.model = PremonitionModel(config)
self.lm_head = nn.Linear(
config.text_config.hidden_size, config.text_config.vocab_size, bias=False
)
self.final_logit_softcapping = config.text_config.final_logit_softcapping
self.post_init()
if config.freeze_backbone:
self.freeze_for_projector_training()
def freeze_for_projector_training(self):
self.requires_grad_(False)
projector = self.model.encoder.embed_audio
if projector is not None:
projector.requires_grad_(True)
return [name for name, param in self.named_parameters() if param.requires_grad]
@classmethod
def from_pretrained(cls, *args, **kwargs):
loaded = super().from_pretrained(*args, **kwargs)
model = loaded[0] if isinstance(loaded, tuple) else loaded
# HF's meta-device loader replaces Parameters and can reset requires_grad.
if model.config.freeze_backbone:
model.freeze_for_projector_training()
return loaded
def _prepare_denoiser_inputs(
self,
decoder_attention_mask,
past_key_values,
sampler,
diffusion_stopping_criteria,
batch_size,
device,
model_kwargs,
):
# Consume modalities once, during prefill. Never re-encode on subsequent canvases.
for key in (
"input_features",
"input_features_mask",
"pixel_values_videos",
"video_position_ids",
):
model_kwargs.pop(key, None)
return super()._prepare_denoiser_inputs(
decoder_attention_mask,
past_key_values,
sampler,
diffusion_stopping_criteria,
batch_size,
device,
model_kwargs,
)
PremonitionModel.register_for_auto_class("AutoModel")
PremonitionForBlockDiffusion.register_for_auto_class("AutoModelForImageTextToText")
|