Views
No views yet
(start, end) time spans in the video.NemoStation/Marlin-2B packaged for internal use. Weights are unmodified. Licensed under the Business Source License 1.1 — see LICENSE and NOTICE for terms and attribution. The internal Python module name (modeling_marlin.py) and class name (MarlinForConditionalGeneration) are preserved verbatim so that trust_remote_code=True loading via auto_map continues to work without modification.Scene: <paragraph> followed by Events: <X.X - Y.Y> <description> lines.From X.X to Y.Y..<think>-style chunked-video reasoning with chunk-time to source-time arithmetic. Not exposed through the .caption() / .find() helpers — use a raw prompt to access it.modeling_marlin.py exposes two convenience methods (.caption() and .find()) that wrap a single canonical training prompt per mode and parse the structured output into typed Python dicts. Raw .generate() is also available for custom prompts.| Component | Value |
|---|---|
| Base model | Qwen/Qwen3.5-2B |
| Parameters | 2.21B (text + vision combined) |
| Precision | bfloat16 |
| Storage on disk | ~5.5 GB |
| Architecture string | MarlinForConditionalGeneration |
model_type | qwen3_5 |
| Context length | 262144 tokens |
1import torch
2from transformers import AutoModelForCausalLM
3
4model = AutoModelForCausalLM.from_pretrained(
5 "cudabenchmarktest/video-scan",
6 trust_remote_code=True,
7 dtype=torch.bfloat16,
8 device_map={"": "cuda"},
9)
10model.compile() # optional — wraps torch.compile, faster after first call1result = model.caption("video.mp4")
2
3print(result["caption"]) # full raw caption text (Scene: ... Events: ...)
4print(result["scene"]) # parsed Scene paragraph
5for ev in result["events"]:
6 print(f"<{ev['start']:.1f} - {ev['end']:.1f}> {ev['description']}")max_new_tokens=2048 — generation token cap (default).prompt=None — override the canonical training prompt. Almost always leave as None.do_sample=False, temperature=1.0, top_p=1.0 — sampling controls.1result = model.find("video.mp4", event="a person enters the room")
2
3print(result["raw"]) # "From 14.3 to 18.2." raw model output
4print(result["span"]) # (14.3, 18.2) tuple in seconds, or None on parse failure
5print(result["format_ok"]) # True if output matched the trained formatgenerate() directly:1import torch
2from transformers import AutoModelForCausalLM, AutoProcessor
3
4model = AutoModelForCausalLM.from_pretrained(
5 "cudabenchmarktest/video-scan",
6 trust_remote_code=True,
7 dtype=torch.bfloat16,
8 device_map={"": "cuda"},
9)
10processor = AutoProcessor.from_pretrained(
11 "cudabenchmarktest/video-scan", trust_remote_code=True
12)
13
14messages = [{"role": "user", "content": [
15 {"type": "video", "video": "video.mp4"},
16 {"type": "text", "text": "Your custom prompt here"},
17]}]
18inputs = processor.apply_chat_template(
19 messages, tokenize=True, add_generation_prompt=True,
20 return_tensors="pt", return_dict=True,
21).to(model.device)
22
23with torch.inference_mode():
24 out = model.generate(**inputs, max_new_tokens=512, do_sample=False)
25out = out[:, inputs["input_ids"].shape[1]:]
26text = processor.batch_decode(out, skip_special_tokens=True)[0]
27print(text)<think> token at the start of every response (an artifact of training with add_non_thinking_prefix=True). The .caption() and .find() helpers strip this automatically. When calling generate() directly, strip any leading <think>...</think> block (with or without closing tag) from the output before parsing.transformers >= 5.7.0 (for native qwen3_5 architecture)torch >= 2.11.0torchcodec (video decoding)qwen-vl-utils >= 0.0.14av (torchcodec system dependency)pillowpip install "transformers>=5.7.0" "torch>=2.11.0" torchcodec "qwen-vl-utils>=0.0.14" av pillow| Env var | Default | Purpose |
|---|---|---|
FORCE_QWENVL_VIDEO_READER | torchcodec | Video decoder backend |
VIDEO_MAX_PIXELS | 200704 | Max pixels per frame (~448x448) |
FPS | 2.0 | Frame sampling rate |
FPS_MAX_FRAMES | 240 | Cap on total frames (~2 min at 2 FPS) |
FPS_MIN_FRAMES | 4 | Floor for very short videos |
LICENSE. The Qwen3.5-2B base weights remain under Apache License 2.0 — see LICENSE-QWEN-BASE and NOTICE.MarlinForConditionalGeneration and the module name modeling_marlin.py are preserved only because auto_map requires them for trust_remote_code loading; they do not imply trademark use beyond technical interoperability.