Image-Text-to-Text
Transformers
Safetensors
qwen3_5
vllm
video
multimodal
reinforcement-learning
temporal-grounding
object-tracking
video-segmentation
visual-question-answering
spatial-reasoning
qwen3.5
conversational
Instructions to use OraRL/Video-ORA-9B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use OraRL/Video-ORA-9B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="OraRL/Video-ORA-9B") 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)# Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("OraRL/Video-ORA-9B") model = AutoModelForMultimodalLM.from_pretrained("OraRL/Video-ORA-9B", device_map="auto") 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?"} ] }, ] inputs = processor.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=40) print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use OraRL/Video-ORA-9B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "OraRL/Video-ORA-9B" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "OraRL/Video-ORA-9B", "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/OraRL/Video-ORA-9B
- SGLang
How to use OraRL/Video-ORA-9B 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 "OraRL/Video-ORA-9B" \ --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": "OraRL/Video-ORA-9B", "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 "OraRL/Video-ORA-9B" \ --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": "OraRL/Video-ORA-9B", "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 OraRL/Video-ORA-9B with Docker Model Runner:
docker model run hf.co/OraRL/Video-ORA-9B
| # Copyright 2024 Bytedance Ltd. and/or its affiliates | |
| # Copyright 2026 OraRL contributors | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| """Validation and serialization for the GRPO/OraRL algorithm surface. | |
| The trainer accepts exactly two recipes. Every OraRL option is checked here, | |
| before any worker is created, so an inconsistent batch layout or a missing | |
| oracle builder fails immediately instead of half-way through the first step. | |
| """ | |
| from __future__ import annotations | |
| import math | |
| from dataclasses import asdict | |
| from typing import Any | |
| SUPPORTED_ALGORITHMS = frozenset({"grpo", "orarl"}) | |
| _ORACLE_CONFIG_PREFIXES = ( | |
| "oracle_", | |
| "directional_gain", | |
| "detached_oracle_", | |
| "selection_", | |
| "post_selection_", | |
| ) | |
| def algorithm_name(config: Any) -> str: | |
| """Return the normalized algorithm name.""" | |
| return str(getattr(config.algorithm, "name", "grpo")).strip().lower() | |
| def is_orarl(config: Any) -> bool: | |
| return algorithm_name(config) == "orarl" | |
| def validate_algorithm(config: Any) -> None: | |
| """Validate GRPO/OraRL options before workers are initialized.""" | |
| name = algorithm_name(config) | |
| if name not in SUPPORTED_ALGORITHMS: | |
| choices = ", ".join(sorted(SUPPORTED_ALGORITHMS)) | |
| raise ValueError(f"algorithm.name must be one of {{{choices}}}, got {name!r}.") | |
| if name == "grpo": | |
| return | |
| algo = config.algorithm | |
| estimator = getattr(algo.adv_estimator, "value", algo.adv_estimator) | |
| if estimator != "grpo": | |
| raise ValueError("OraRL requires algorithm.adv_estimator=grpo.") | |
| if bool(getattr(algo, "scale_rewards", True)): | |
| raise ValueError("OraRL requires raw advantages: algorithm.scale_rewards=false.") | |
| if not bool(algo.oracle_injection): | |
| raise ValueError("OraRL requires algorithm.oracle_injection=true.") | |
| if str(algo.oracle_injection_mode) != "append": | |
| raise ValueError("OraRL requires algorithm.oracle_injection_mode=append.") | |
| if not str(algo.oracle_builder or "").strip(): | |
| raise ValueError("OraRL requires algorithm.oracle_builder.") | |
| if int(config.worker.rollout.n) <= 1: | |
| raise ValueError("OraRL requires worker.rollout.n > 1.") | |
| if bool(getattr(config.worker.rollout, "calculate_log_probs", False)): | |
| raise ValueError( | |
| "OraRL oracle rows require worker.rollout.calculate_log_probs=false so " | |
| "old log probabilities are recomputed for their actual tokens." | |
| ) | |
| prune_ratio = float(algo.selection_prune_ratio) | |
| if not math.isfinite(prune_ratio) or not 0.0 < prune_ratio < 1.0: | |
| raise ValueError("OraRL selection_prune_ratio must be in (0, 1).") | |
| n_rollouts = int(config.worker.rollout.n) | |
| keep_rows = max(1, int(n_rollouts * (1.0 - prune_ratio))) | |
| if not bool(algo.selection_keep_oracle): | |
| raise ValueError("OraRL requires the oracle rollout to be retained.") | |
| oracle_slot = 1 | |
| positive = int(algo.selection_positive_quota) | |
| negative = int(algo.selection_negative_quota) | |
| if positive < 0 or negative < 0: | |
| raise ValueError("OraRL selection quotas must be non-negative.") | |
| if positive + negative + oracle_slot != keep_rows: | |
| raise ValueError( | |
| "OraRL selection quotas must fill the keep budget: " | |
| f"positive({positive}) + negative({negative}) + " | |
| f"oracle({oracle_slot}) != keep_rows({keep_rows})." | |
| ) | |
| if not bool(algo.selection_strict_sign_balance): | |
| raise ValueError("OraRL requires strict sign-balanced selection.") | |
| nodes = int(config.trainer.nnodes) | |
| gpus_per_node = int(config.trainer.n_gpus_per_node) | |
| rollout_batch_size = int(config.data.rollout_batch_size) | |
| if nodes <= 0 or gpus_per_node <= 0 or rollout_batch_size <= 0: | |
| raise ValueError( | |
| "OraRL requires positive trainer node/GPU counts and rollout_batch_size." | |
| ) | |
| world_size = nodes * gpus_per_node | |
| selected_batch = rollout_batch_size * keep_rows | |
| if selected_batch % world_size != 0: | |
| raise ValueError( | |
| "OraRL selected batch must divide the actor world size: " | |
| f"{selected_batch} rows for world_size={world_size}." | |
| ) | |
| # The oracle is appended as an extra row, so the pre-selection batch is | |
| # rollout_batch_size*(n+1) and seqlen-balanced partitioning needs it to | |
| # shard evenly. | |
| preselection_batch = rollout_batch_size * (n_rollouts + 1) | |
| if preselection_batch % world_size != 0: | |
| raise ValueError( | |
| "OraRL append-oracle batch must divide the actor world size: " | |
| f"{preselection_batch} rows for world_size={world_size}." | |
| ) | |
| if not bool(algo.directional_gain): | |
| raise ValueError("OraRL requires algorithm.directional_gain=true.") | |
| if not bool(algo.directional_gain_positive_only): | |
| raise ValueError("OraRL requires positive-only directional gain.") | |
| if not bool(algo.directional_gain_recenter): | |
| raise ValueError("OraRL requires post-gain policy re-centering.") | |
| gain_gamma = float(algo.directional_gain_gamma) | |
| if not math.isfinite(gain_gamma) or gain_gamma <= 0.0: | |
| raise ValueError("OraRL directional_gain_gamma must be finite and positive.") | |
| if not bool(algo.detached_oracle_advantage): | |
| raise ValueError("OraRL requires a detached oracle advantage.") | |
| detached_scale = float(algo.detached_oracle_advantage_scale) | |
| if not math.isfinite(detached_scale) or detached_scale <= 0.0: | |
| raise ValueError( | |
| "OraRL detached_oracle_advantage_scale must be finite and positive." | |
| ) | |
| gap_beta = float(algo.oracle_reward_gate_beta) | |
| if not math.isfinite(gap_beta) or gap_beta <= 0.0: | |
| raise ValueError("OraRL oracle_reward_gate_beta must be finite and positive.") | |
| if bool(algo.detached_oracle_use_directional_gain): | |
| raise ValueError( | |
| "The released OraRL recipe keeps directional gain policy-only; " | |
| "set detached_oracle_use_directional_gain=false." | |
| ) | |
| match_ratio = float(algo.detached_oracle_match_best_ratio) | |
| match_min = float(algo.detached_oracle_match_best_min) | |
| match_max = float(algo.detached_oracle_match_best_max) | |
| if ( | |
| not all(math.isfinite(value) for value in (match_ratio, match_min, match_max)) | |
| or match_ratio <= 0.0 | |
| or match_min < 0.0 | |
| or match_max < match_min | |
| ): | |
| raise ValueError( | |
| "OraRL oracle cap requires a finite positive ratio and " | |
| "finite 0 <= min <= max." | |
| ) | |
| if not bool(algo.post_selection_recenter): | |
| raise ValueError("OraRL requires post-selection re-centering.") | |
| if not bool(algo.post_selection_rms_match): | |
| raise ValueError("OraRL requires post-selection RMS matching.") | |
| rms_min = float(algo.post_selection_rms_min_scale) | |
| if not 0.0 <= rms_min <= 1.0: | |
| raise ValueError("OraRL post_selection_rms_min_scale must be in [0, 1].") | |
| def public_config_dict(config: Any) -> dict[str, Any]: | |
| """Serialize the config, dropping options the selected recipe never reads.""" | |
| value = asdict(config) | |
| if algorithm_name(config) != "grpo": | |
| return value | |
| algorithm = value.get("algorithm", {}) | |
| for key in tuple(algorithm): | |
| if key.startswith(_ORACLE_CONFIG_PREFIXES): | |
| algorithm.pop(key, None) | |
| value.get("worker", {}).get("actor", {}).pop("selection_prune_ratio", None) | |
| return value | |