CoolFace
Modelpublic

shi-labs/slowfast-video-mllm-qwen2-7b-convnext-576-frame64-s1t4

sourceHugging Facecc-by-nc-4.0updated 1y agoView on Hugging Face
0likes28downloads
Model Card
markdown
# Slow-Fast Architecture for Video Multi-Modal Large Language Models (Qwen2-7B, 64 Frames)

This repository contains the **Slow-Fast Video MLLM (Qwen2-7B, ConvNeXt-576, 64 frames, stride 1/4)** model, presented in the paper [Slow-Fast Architecture for Video Multi-Modal Large Language Models](https://huggingface.co/papers/2504.01328).

[Code Repository](https://github.com/SHI-Labs/Slow-Fast-Video-Multimodal-LLM) | [HuggingFace Collection](https://huggingface.co/collections/shi-labs/slow-fast-video-mllm-67ef347a28772734c15a78b5)

## Model Description

This model introduces a novel slow-fast architecture to address the challenge of balancing temporal resolution and spatial detail in video-based multi-modal large language models (MLLMs) under limited compute budgets. Existing methods often compress video representations irreversibly, losing detail.

Inspired by how humans first skim a video before focusing on relevant parts, the slow-fast design employs a dual-token strategy:
1.  **"Fast" visual tokens:** A compact set of compressed video features fed into the LLM (Qwen2-7B-Instruct) alongside text embeddings for a quick overview.
2.  **"Slow" visual tokens:** Uncompressed video features cross-attended by text embeddings via specially designed hybrid decoder layers, enabling instruction-aware extraction of relevant visual details with linear complexity.

This approach allows processing more input frames (e.g., 64 frames for this checkpoint) while preserving spatial details, leading to significant performance improvements on video understanding benchmarks compared to self-attention-only baselines. This checkpoint uses a Qwen2-7B-Instruct base LLM and a ConvNeXt-576 vision tower.

<div align="center">
<img src="https://huggingface.co/shi-labs/slowfast-video-mllm-qwen2-7b-convnext-576-frame64-s1t4/resolve/main/assets/images/fig-teaser.png" width="45%">
</div>

## Usage

**Note:** This model relies on custom code integrated within the `transformers` library (`LlavaQwenSlowFastForCausalLM`). Ensure you have the necessary packages installed from the [official repository](https://github.com/SHI-Labs/Slow-Fast-Video-Multimodal-LLM) or use `trust_remote_code=True` when loading the model.

First, clone the repository and install requirements if running locally:

git clone https://github.com/SHI-Labs/Slow-Fast-Video-Multimodal-LLM.git cd Slow-Fast-Video-Multimodal-LLM pip install --upgrade pip pip install -r requirements.txt

Add the cloned repo path to your PYTHONPATH or install it


Then, use the following Python script:

import torch import os import numpy as np from decord import VideoReader, cpu import requests # Required to download video

Make sure the necessary llava modules are importable

If not installed from the repo, trustremotecode=True handles this

from llava.constants import IMAGETOKENINDEX, DEFAULTIMAGETOKEN, DEFAULTIMSTARTTOKEN, DEFAULTIMENDTOKEN from llava.conversation import convtemplates from llava.model.builder import loadpretrainedmodel from llava.mmutils import tokenizerimagetoken, getmodelnamefrompath from llava.utils import disabletorchinit

def loadvideo(videopath, maxframesnum): """Helper function to load video frames.""" vr = VideoReader(videopath, numthreads=4) total_frames = len(vr)

# Ensure sparse sampling doesn't lead to fewer frames than requested if totalframes >= maxframesnum: # Uniformly sample frames across the video uniformsampledframes = np.linspace(0, totalframes - 1, maxframesnum, dtype=int) frameidx = uniformsampledframes.tolist() else: # If video is shorter than maxframesnum, sample all frames and repeat the last frameidx = list(range(totalframes)) frameidx.extend([totalframes - 1] * (maxframesnum - totalframes))

try: spareframes = vr.getbatch(frameidx).asnumpy() except Exception as e: print(f"Error loading video frames: {e}") # Fallback or error handling: return None or raise exception # Example: return a black frame tensor of the expected shape # This part depends on how imageprocessor handles None or errors # For now, re-raising the exception might be best raise e

return spare_frames

Model configuration

modelpath = "shi-labs/slowfast-video-mllm-qwen2-7b-convnext-576-frame64-s1t4" videourl = "https://huggingface.co/shi-labs/slowfast-video-mllm-qwen2-7b-convnext-576-frame64-s1t4/resolve/main/assets/catinterrupt.mp4" videolocalpath = "catinterrupt.mp4" question = "Please describe this video in detail." max_frames = 64 # This checkpoint was trained with 64 frames

Download the video if it doesn't exist

if not os.path.exists(videolocalpath): print(f"Downloading video from {videourl}...") response = requests.get(videourl, stream=True) response.raiseforstatus() # Raise an exception for bad status codes with open(videolocalpath, "wb") as f: for chunk in response.itercontent(chunksize=8192): f.write(chunk) print("Download complete.")

Load the model and processor

disabletorchinit() modelname = getmodelnamefrompath(modelpath)

Use trustremotecode=True to load the custom architecture

tokenizer, model, imageprocessor, contextlen = loadpretrainedmodel( modelpath, None, modelname, useflashattn=True, # Use Flash Attention if available devicemap="auto", # Automatically distribute model across GPUs/CPU torchdtype=torch.bfloat16, # Use bfloat16 for efficiency trustremotecode=True )

Prepare the prompt

if model.config.mmuseimstartend: prompt = DEFAULTIMSTARTTOKEN + DEFAULTIMAGETOKEN + DEFAULTIMENDTOKEN + " " + question else: prompt = DEFAULTIMAGETOKEN + " " + question

conv = convtemplates["qwen15"].copy() # Use the appropriate conversation template conv.appendmessage(conv.roles[0], prompt) conv.appendmessage(conv.roles[1], None) promptfinal = conv.get_prompt()

Load and process video frames

print("Loading video...") videoframes = loadvideo(videolocalpath, maxframesnum=maxframes) print(f"Video loaded, shape: {videoframes.shape}")

Preprocess video frames

print("Preprocessing video...")

Ensure video has shape (T, H, W, C) before preprocessing

videotensor = imageprocessor.preprocess(videoframes, returntensors="pt")["pixelvalues"] videotensor = videotensor.to(model.device, dtype=torch.bfloat16) videos = [videotensor] # The model expects a list of video tensors print(f"Video tensor processed, shape: {videos[0].shape}")

Tokenize the prompt

inputids = tokenizerimagetoken(promptfinal, tokenizer, IMAGETOKENINDEX, returntensors='pt') inputids = inputids.to(device=model.device, nonblocking=True)

Add batch dimension if necessary (tokenizerimagetoken might already return batched)

if inputids.ndim == 1: inputids = inputids.unsqueeze(0) print(f"Input IDs processed, shape: {inputids.shape}")

Generate response

print("Generating response...") with torch.inferencemode(): outputids = model.generate( inputids, images=videos, # Pass the processed video tensor list dosample=True, temperature=0.2, topp=1.0, numbeams=1, maxnewtokens=1024, use_cache=True )

Decode and print the output

outputs = tokenizer.batchdecode(outputids, skipspecialtokens=True)[0].strip() print(f" User input: {question} ") print(f"Model output: {outputs}")


## License

The model weights are released under the [CC-BY-NC-4.0 license](LICENSE).
The code is released under the Apache 2.0 license.
Users must comply with all terms and conditions of the original licenses, including the specific licenses for the base language model ([Qwen2 License](https://huggingface.co/Qwen/Qwen2-7B-Instruct/blob/main/LICENSE)).

## Citation

If you find this work useful, please consider citing the paper:

@misc{zhou2025slowfast, title={Slow-Fast Architecture for Video Multi-Modal Large Language Models}, author={Yifei Zhou and Jiaming Zuo and Chen Change Loy and Chongyang Zhong and Xin Wang and Qi Wu and Weidong Cai and Xiaodong He and Qingzhong Wang and Lei Zhang and Marcelo H. Ang Jr and Boyang Li and Yanfeng Wang and Qinghai He and Fengbei Liu and Liangchen Luo and Jingdong Wang and Conghui He and Wenhai Wang}, year={2025}, eprint={2504.01328}, archivePrefix={arXiv}, primaryClass={cs.CV} }

*(Note: Author list based on potential updates to the arXiv paper; please verify with the final published version if available.)*