Video-Text-to-Text
Transformers
Safetensors
qwen3_5
image-text-to-text
robotics
reward-model
vlm
gr00t
system-2
Instructions to use nvidia/Flora-Rewarder with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use nvidia/Flora-Rewarder with Transformers:
# pip install -U transformers accelerate # Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("nvidia/Flora-Rewarder") model = AutoModelForMultimodalLM.from_pretrained("nvidia/Flora-Rewarder", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Download batch_utils/terminal_reward.py from nvidia/Flora-Rewarder: direct link, hf CLI and curl.
- Browser
- Download file 4.62 kB
-
https://huggingface.co/nvidia/Flora-Rewarder/resolve/main/batch_utils/terminal_reward.py
- Command line
-
hf download hf://nvidia/Flora-Rewarder/batch_utils/terminal_reward.py
-
curl -L -o terminal_reward.py https://huggingface.co/nvidia/Flora-Rewarder/resolve/main/batch_utils/terminal_reward.py
4.62 kB
| """Terminal reward: one 1-5 success score for each whole episode. | |
| python -m batch_utils.terminal_reward --jobs jobs.jsonl --output terminal.jsonl | |
| python -m batch_utils.terminal_reward --video top.mp4 wrist.mp4 --task "Put the cup on the tray." --output terminal.jsonl | |
| Each job is ``{"id": ..., "task": ..., "videos": [camera videos, in collage order]}``. | |
| """ | |
| from __future__ import annotations | |
| from . import core | |
| from .engine import ( | |
| COLLAGE_VIDEO_SIZE, | |
| base_parser, | |
| load_llm, | |
| load_processor, | |
| log, | |
| open_output, | |
| read_jobs, | |
| render, | |
| resolve_model, | |
| write_record, | |
| ) | |
| def main(argv=None) -> int: | |
| p = base_parser("FLORA rewarder: terminal (episode success) score, 1-5.") | |
| p.add_argument("--with-rationale", action="store_true", help="Ask for a one-line rationale before the score.") | |
| p.add_argument("--max-model-len", type=int, default=16384) | |
| args = p.parse_args(argv) | |
| jobs = read_jobs(args) | |
| model_path = resolve_model(args.model, args.revision, weights=not args.dry_run) | |
| processor = load_processor(model_path) | |
| prepared = [] | |
| for job in jobs: | |
| collage = core.Collage(job["videos"]) | |
| indices = core.terminal_frame_indices(collage.num_frames, collage.fps) | |
| messages = core.terminal_messages(job["task"], args.with_rationale) | |
| prepared.append((job, collage, indices, render(processor, messages, thinking=False))) | |
| if args.dry_run: | |
| job, collage, indices, prompt = prepared[0] | |
| log(f"{job['id']}: {collage.num_frames} frames at {collage.fps:g} FPS, " | |
| f"collage {collage.width}x{collage.height}, {len(indices)} sampled frames\n{prompt}") | |
| return 0 | |
| from vllm import SamplingParams | |
| from vllm.sampling_params import StructuredOutputsParams | |
| llm = load_llm(model_path, args, max_model_len=args.max_model_len, | |
| mm_processor_kwargs={"do_sample_frames": False, "size": COLLAGE_VIDEO_SIZE}, | |
| max_logprobs=core.TERMINAL_TOP_LOGPROBS) | |
| tokenizer = llm.get_tokenizer() | |
| params = SamplingParams( | |
| temperature=0.0, | |
| max_tokens=core.terminal_max_tokens(args.with_rationale), | |
| logprobs=core.TERMINAL_TOP_LOGPROBS, | |
| structured_outputs=StructuredOutputsParams(regex=core.terminal_regex(args.with_rationale)), | |
| ) | |
| with open_output(args) as stream: | |
| for start in range(0, len(prepared), args.max_num_seqs): | |
| batch = prepared[start : start + args.max_num_seqs] | |
| requests = [ | |
| { | |
| "prompt": prompt, | |
| "multi_modal_data": { | |
| "video": (collage.frames(indices), core.video_metadata(indices, collage.fps, collage.num_frames)) | |
| }, | |
| "mm_processor_kwargs": {"do_sample_frames": False}, | |
| } | |
| for _, collage, indices, prompt in batch | |
| ] | |
| outputs = llm.generate(requests, params, use_tqdm=False) | |
| for _, collage, _, _ in batch: | |
| collage.release() | |
| for (job, collage, indices, _), output in zip(batch, outputs): | |
| completion = output.outputs[0] | |
| score, rationale = core.parse_terminal(completion.text, args.with_rationale) | |
| positions = [ | |
| ( | |
| tokenizer.decode([token]), | |
| float(candidates[token].logprob), | |
| [(tokenizer.decode([i]), float(c.logprob)) for i, c in candidates.items()], | |
| ) | |
| for token, candidates in zip(completion.token_ids, completion.logprobs) | |
| ] | |
| probabilities, expected = core.score_probabilities(positions, score) | |
| write_record(stream, { | |
| "id": job["id"], | |
| "task": job["task"], | |
| "score": score, | |
| "expected_score": round(expected, 4), | |
| # Expected score rescaled to [0, 1]: a progress value, not a success probability. | |
| "progress": round((expected - 1.0) / 4.0, 4), | |
| "probabilities": {k: round(v, 4) for k, v in probabilities.items()}, | |
| "rationale": rationale, | |
| "duration_s": round(collage.duration_s, 3), | |
| "sampled_frames": len(indices), | |
| "output": completion.text, | |
| }) | |
| log(f"terminal: {min(start + len(batch), len(prepared))}/{len(prepared)} episodes") | |
| return 0 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |