Instructions to use nvidia/Flora-TempSeg with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use nvidia/Flora-TempSeg with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3.5-9B") model = PeftModel.from_pretrained(base_model, "nvidia/Flora-TempSeg") - Notebooks
- Google Colab
- Kaggle
File size: 11,436 Bytes
a4ba82a | 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 | from collections import Counter
from pathlib import Path
import gc
import hashlib
import json
import os
import threading
import time
from datetime import datetime, timezone
from .config import MODELS, VENDOR, MODEL_CACHE
_LOCK = threading.Lock()
_MANIFEST_LOCK = threading.Lock()
_VERIFIED_MANIFESTS = {}
class NotReady(RuntimeError):
pass
def verify_cuda_residency(model):
devices = Counter((str(p.device) for p in model.parameters()))
if not devices or any((not d.startswith('cuda:') for d in devices)):
raise NotReady('GPU memory is insufficient for this native Captioner configuration.')
return dict(devices)
def runtime_event(event, **values):
print('FLORA_RUNTIME ' + json.dumps(dict(event=event, utc=datetime.now(timezone.utc).isoformat(), **values), sort_keys=True), flush=True)
def ready():
if os.environ.get('FLORA_ENABLE_INFERENCE', '0') != '1':
return (False, 'Preview ready 路 live annotation is paused.')
import torch
if not torch.cuda.is_available():
return (False, 'Preview ready 路 GPU hardware is needed for annotation.')
if sum((torch.cuda.get_device_properties(i).total_memory for i in range(torch.cuda.device_count()))) < 75 * 1024 ** 3:
return (False, 'Annotation needs an 80 GB GPU or a validated multi-GPU configuration.')
if not os.environ.get('HF_TOKEN'):
return (False, 'Annotation is waiting for access to the private weights.')
return (True, 'Ready to annotate 路 one video at a time.')
def snapshot(kind):
from huggingface_hub import snapshot_download
spec = dict(MODELS[kind])
spec['repo'] = os.environ.get(spec.get('repo_env', ''), spec['repo'])
if not spec['repo']:
raise ValueError('Set ' + spec['repo_env'] + ' to the released checkpoint repository.')
patterns = ['adapter_config.json', 'adapter_model.safetensors', 'config.json', 'generation_config.json', 'model.safetensors.index.json', 'model-*.safetensors', 'processor_config.json', 'tokenizer.json', 'tokenizer_config.json', 'chat_template.jinja', 'README.md', 'MODEL_PROVENANCE.json', 'SOURCE_MANIFEST.sha256']
return Path(snapshot_download(spec['repo'], revision=spec['revision'], token=os.environ.get('HF_TOKEN'), allow_patterns=patterns, local_dir=MODEL_CACHE / kind))
def processor(kind, path):
from transformers import AutoProcessor
from transformers.models.qwen3_vl.video_processing_qwen3_vl import Qwen3VLVideoProcessor
proc = AutoProcessor.from_pretrained(path, local_files_only=True, use_fast=True, min_pixels=1024, max_pixels=589824, video_processor=Qwen3VLVideoProcessor.from_pretrained(path, local_files_only=True, fps=4 if kind == 'tempseg' else 8, max_frames=128 if kind == 'tempseg' else 40))
proc.chat_template = (path / 'chat_template.jinja').read_text()
return proc
def validate_manifest(path):
with _MANIFEST_LOCK:
_validate_manifest(path)
def _validate_manifest(path):
started = time.monotonic()
allowed_root = path.parent.parent if path.parent.name == 'snapshots' else path
manifest = (path / 'SOURCE_MANIFEST.sha256').read_bytes()
key = str(path.resolve())
manifest_sha = hashlib.sha256(manifest).hexdigest()
files = []
def fingerprint(source):
resolved = source.resolve()
if not resolved.is_relative_to(allowed_root.resolve()):
raise RuntimeError('Invalid model manifest')
stat = resolved.stat()
return (str(resolved), stat.st_dev, stat.st_ino, stat.st_size, stat.st_mtime_ns, stat.st_ctime_ns)
for line in manifest.decode().splitlines():
if not line.strip():
continue
expected, filename = line.split(maxsplit=1)
relative = Path(filename.lstrip('*'))
if relative.is_absolute() or '..' in relative.parts:
raise RuntimeError('Invalid model manifest')
source = path / relative
if not source.resolve().is_relative_to(allowed_root.resolve()):
runtime_event('manifest_path_rejected', file=filename, snapshot=str(path), target=str(source.resolve()), allowed_root=str(allowed_root.resolve()))
raise RuntimeError('Invalid model manifest')
files.append((source, expected, fingerprint(source)))
before = tuple(((str(source), expected, stamp) for source, expected, stamp in files))
if _VERIFIED_MANIFESTS.get(key) == (manifest_sha, before):
runtime_event('manifest_verified_reuse', kind=path.name, files=len(files), payload_bytes_read=0, elapsed_s=round(time.monotonic() - started, 3))
return
_VERIFIED_MANIFESTS.pop(key, None)
for source, expected, _ in files:
with source.open('rb') as f:
if hashlib.file_digest(f, 'sha256').hexdigest() != expected:
raise RuntimeError('A model asset failed its integrity check')
after = tuple(((str(source), expected, fingerprint(source)) for source, expected, _ in files))
if before != after or manifest != (path / 'SOURCE_MANIFEST.sha256').read_bytes():
raise RuntimeError('A model asset changed during its integrity check')
_VERIFIED_MANIFESTS[key] = (manifest_sha, after)
runtime_event('manifest_full_verification', kind=path.name, files=len(files), payload_bytes_read=sum((stamp[3] for _, _, stamp in files)), elapsed_s=round(time.monotonic() - started, 3))
def preflight_adapter_download():
path = snapshot('tempseg')
validate_manifest(path)
runtime_event('adapter_download_preflight_pass', revision=MODELS['tempseg']['revision'], adapter_sha256=MODELS['tempseg']['sha256'], directory=str(path))
class Session:
def __init__(self):
self.model = self.proc = None
self.audit = {}
def load(self, kind):
import torch
previous_threads = torch.get_num_threads()
torch.set_num_threads(4)
load_started = time.monotonic()
from transformers import AutoModelForImageTextToText
from transformers.models.qwen3_5.modeling_qwen3_5 import Qwen3_5PreTrainedModel
from production_gdn_fix import _keep_native_gdn_fp32
from verify_gdn import verify
self.close()
runtime_event('model_load_start', kind=kind, cpu_threads=torch.get_num_threads(), previous_cpu_threads=previous_threads)
_keep_native_gdn_fp32(Qwen3_5PreTrainedModel)
path = snapshot(kind)
runtime_event('model_assets_ready', kind=kind, elapsed_s=round(time.monotonic() - load_started, 3))
validate_manifest(path)
runtime_event('model_assets_verified', kind=kind, elapsed_s=round(time.monotonic() - load_started, 3))
if kind == 'tempseg':
base_spec = MODELS['tempseg_base']
from huggingface_hub import snapshot_download
base = snapshot_download(base_spec['repo'], revision=base_spec['revision'], token=os.environ.get('HF_TOKEN'), allow_patterns=['*.safetensors', '*.json', '*.jinja'])
from tempseg_fp32_loader import load
records = {}
self.model = load({'base': base, 'export': str(path), 'adapter_sha256': MODELS[kind]['sha256']}, lambda name, value: records.__setitem__(name, value))
self.audit[kind] = records
else:
index = json.loads((path / 'model.safetensors.index.json').read_text())
extra = {k for k in index['weight_map'] if '_extra_state' in k}
memory = {i: f'{max(1, int(torch.cuda.get_device_properties(i).total_memory / 1024 ** 3) - 12)}GiB' for i in range(torch.cuda.device_count())}
self.model, info = AutoModelForImageTextToText.from_pretrained(path, local_files_only=True, dtype=torch.bfloat16, attn_implementation={'text_config': 'sdpa', 'vision_config': 'sdpa'}, device_map='balanced', max_memory=memory, output_loading_info=True)
if any((info.get(k) for k in ['missing_keys', 'mismatched_keys', 'error_msgs'])) or not set(info.get('unexpected_keys', [])) <= extra:
raise RuntimeError('The released Captioner did not load completely')
devices = verify_cuda_residency(self.model)
self.model.eval()
self.audit[kind] = {'gdn': verify(self.model, path), 'loading_info': info, 'parameter_devices': devices, 'parameter_dtypes': dict(Counter((str(p.dtype) for p in self.model.parameters())))}
runtime_event('model_parameters_verified', kind=kind, elapsed_s=round(time.monotonic() - load_started, 3))
self.proc = processor(kind, path)
if kind == 'tempseg':
adapter = self.audit[kind]['ADAPTER_VALUE_VERIFICATION.json']
gdn = self.audit[kind]['GDN_VALUE_VERIFICATION.json']
verification = dict(adapter_tensors=adapter['tensors'], adapter_values_exact=adapter['all_saved_values_exact_before_and_after_placement'], adapter_fp32=adapter['holders_fp32_before_assignment'], gdn_values_exact=gdn['all_values_equal_saved_checkpoint'], gdn_fp32=gdn['all_runtime_fp32'])
else:
gdn = self.audit[kind]['gdn']
verification = dict(gdn_values_exact=gdn['all_values_equal_saved_checkpoint'], gdn_fp32=gdn['all_runtime_fp32'], parameter_dtypes=self.audit[kind]['parameter_dtypes'])
runtime_event('model_ready', kind=kind, revision=MODELS[kind]['revision'], torch_version=torch.__version__, gpu=torch.cuda.get_device_name(0), allocated_gib=round(torch.cuda.memory_allocated() / 1024 ** 3, 3), **verification)
return (self.model, self.proc)
def close(self):
self.model = self.proc = None
gc.collect()
import torch
if torch.cuda.is_available():
torch.cuda.empty_cache()
def generate(model, proc, inputs, budget):
import torch
inputs = dict(inputs)
inputs.pop('video_metadata', None)
n = inputs['input_ids'].shape[1]
if n + budget > 32768:
raise InputErrorForModel('The selected video exceeds the native model context budget.')
input_tensors = {k: {'dtype': str(v.dtype), 'shape': list(v.shape), 'sha256': hashlib.sha256(v.detach().cpu().contiguous().view(torch.uint8).numpy().tobytes()).hexdigest()} for k, v in inputs.items() if torch.is_tensor(v)}
input_tensor_digest = hashlib.sha256(json.dumps(input_tensors, sort_keys=True, separators=(',', ':')).encode()).hexdigest()
device = next(model.parameters()).device
args = {k: v.to(device) if torch.is_tensor(v) else v for k, v in inputs.items()}
eos = proc.tokenizer.eos_token_id
started = time.monotonic()
runtime_event('generation_start', input_tokens=n, output_limit=budget, input_tensor_digest=input_tensor_digest, input_tensors=input_tensors)
with torch.inference_mode():
output = model.generate(**args, do_sample=False, num_beams=1, max_new_tokens=budget, eos_token_id=eos, pad_token_id=proc.tokenizer.pad_token_id, use_cache=True, max_time=300)
ids = output[0, n:].cpu().tolist()
stop = bool(ids) and ids[-1] in ([eos] if isinstance(eos, int) else eos)
text = proc.tokenizer.decode(ids, skip_special_tokens=True).strip()
runtime_event('generation_end', input_tokens=n, output_limit=budget, generated_tokens=len(ids), complete=stop and bool(text), elapsed_s=round(time.monotonic() - started, 3), peak_allocated_gib=round(torch.cuda.max_memory_allocated() / 1024 ** 3, 3))
if not stop or not text:
raise InputErrorForModel('The model did not return a complete output for this input.')
return text
class InputErrorForModel(RuntimeError):
pass
|