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-4B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use OraRL/Video-ORA-4B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="OraRL/Video-ORA-4B") 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-4B") model = AutoModelForMultimodalLM.from_pretrained("OraRL/Video-ORA-4B", 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-4B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "OraRL/Video-ORA-4B" # 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-4B", "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-4B
- SGLang
How to use OraRL/Video-ORA-4B 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-4B" \ --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-4B", "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-4B" \ --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-4B", "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-4B with Docker Model Runner:
docker model run hf.co/OraRL/Video-ORA-4B
| # Copyright 2024 Bytedance Ltd. and/or its affiliates | |
| # | |
| # 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. | |
| import inspect | |
| import re | |
| from typing import Iterable, Union | |
| import torch | |
| import torch.distributed as dist | |
| from torch.distributed._tensor import DTensor | |
| from torch.distributed.checkpoint.state_dict import get_model_state_dict | |
| from torch.distributed.device_mesh import DeviceMesh | |
| from torch.distributed.fsdp.fully_sharded_data_parallel import FullyShardedDataParallel as FSDP | |
| from transformers import PreTrainedModel | |
| from vllm import LLM | |
| from vllm.distributed import parallel_state as vllm_ps | |
| from ...protocol import DataProto, all_gather_data_proto | |
| from ...utils.fsdp_utils import load_fsdp_model, offload_fsdp_model | |
| from ...utils.model_utils import print_gpu_memory_usage | |
| from .base import BaseShardingManager | |
| class FSDPVLLMShardingManager(BaseShardingManager): | |
| def __init__( | |
| self, | |
| module: FSDP, | |
| inference_engine: LLM, | |
| device_mesh: DeviceMesh, | |
| use_param_offload: bool, | |
| rollout_seed: int = 1, | |
| ): | |
| self.module = module | |
| self.inference_engine = inference_engine | |
| self.device_mesh = device_mesh | |
| self.use_param_offload = use_param_offload | |
| self.loaded = False | |
| self.world_size = dist.get_world_size() | |
| self.tp_size = vllm_ps.get_tensor_model_parallel_world_size() | |
| self.tp_rank = vllm_ps.get_tensor_model_parallel_rank() | |
| try: | |
| self.tp_group = vllm_ps.get_tensor_model_parallel_group().device_group | |
| except AttributeError: | |
| # vLLM >= 0.17.0 renamed to get_tp_group() | |
| self.tp_group = vllm_ps.get_tp_group().device_group | |
| # Record freed bytes to estimate memory usage correctly | |
| # https://github.com/vllm-project/vllm/pull/11743#issuecomment-2754338119 | |
| self.freed_bytes = 0 | |
| # Note that torch_random_states may be different on each dp rank | |
| self.torch_random_states = torch.cuda.get_rng_state() | |
| # Match Accelerate's ``set_seed(seed, device_specific=True)`` convention | |
| # used by the reference trainer: each data-parallel generation worker | |
| # starts from base_seed + rank, while all TP ranks agree. | |
| gen_dp_rank = self.device_mesh["dp"].get_local_rank() | |
| torch.cuda.manual_seed(int(rollout_seed) + gen_dp_rank) | |
| self.gen_random_states = torch.cuda.get_rng_state() | |
| torch.cuda.set_rng_state(self.torch_random_states) | |
| def _rename_weight_keys(self, actor_weights: dict[str, Union[torch.Tensor, DTensor]], model: PreTrainedModel): | |
| # convert state dict keys: https://github.com/huggingface/transformers/pull/38385 | |
| if not hasattr(model, "_checkpoint_conversion_mapping"): | |
| return actor_weights | |
| reverse_key_mapping = {v: k for k, v in model._checkpoint_conversion_mapping.items()} | |
| original_weights = {} | |
| for key, value in actor_weights.items(): | |
| for pattern, replacement in reverse_key_mapping.items(): | |
| replacement = replacement.lstrip("^") # strip off un-needed chars and patterns | |
| replacement = re.sub(r"\(.*\)", "", replacement) | |
| key, n_replace = re.subn(pattern, replacement, key) | |
| # Early exit of the loop | |
| if n_replace > 0: | |
| break | |
| original_weights[key] = value | |
| return original_weights | |
| def _make_weight_iterator( | |
| self, actor_weights: dict[str, Union[torch.Tensor, DTensor]] | |
| ) -> Iterable[tuple[str, torch.Tensor]]: | |
| for name, tensor in actor_weights.items(): | |
| yield name, tensor.full_tensor() if self.world_size != 1 else tensor | |
| def _sync_weight_to_vllm(self): | |
| if self.use_param_offload: | |
| load_fsdp_model(self.module) | |
| actor_weights = get_model_state_dict(self.module) | |
| actor_weights = self._rename_weight_keys(actor_weights, self.module._fsdp_wrapped_module) | |
| print_gpu_memory_usage("After gather model weights in sharding manager") | |
| model = self.inference_engine.llm_engine.model_executor.driver_worker.worker.model_runner.model | |
| model.load_weights(self._make_weight_iterator(actor_weights)) | |
| del actor_weights | |
| if self.use_param_offload: | |
| offload_fsdp_model(self.module) | |
| torch.cuda.empty_cache() | |
| print_gpu_memory_usage("After sync model weights in sharding manager") | |
| def load_vllm_and_sync_weights(self): | |
| """Load vllm engine and sync model weights to vllm model.""" | |
| # NOTE: Basically, we only need `torch.cuda.empty_cache()` before vllm wake_up and | |
| # after vllm sleep, since vllm has its own caching memory allocator CuMemAllocator. | |
| # Out of vllm scope, we should avoid empty cache to let pytorch using caching memory | |
| # to speed up memory allocations. | |
| # | |
| # pytorch: https://pytorch.org/docs/stable/notes/cuda.html#memory-management | |
| # vllm: https://github.com/vllm-project/vllm/blob/v0.7.3/vllm/device_allocator/cumem.py#L103 | |
| torch.cuda.empty_cache() | |
| assert self.loaded is False, "vllm engine has already been loaded" | |
| self.loaded = True | |
| print_gpu_memory_usage("Before vllm wake up in sharding manager") | |
| if "tags" in inspect.signature(self.inference_engine.wake_up).parameters: | |
| self.inference_engine.wake_up(tags=["weights"]) | |
| else: | |
| self.inference_engine.wake_up() | |
| self._sync_weight_to_vllm() | |
| if "tags" in inspect.signature(self.inference_engine.wake_up).parameters: | |
| self.inference_engine.wake_up(tags=["kv_cache"]) | |
| print_gpu_memory_usage("After vllm wake up in sharding manager") | |
| # important: need to manually set the random states of each tp to be identical. | |
| if self.device_mesh is not None: | |
| self.torch_random_states = torch.cuda.get_rng_state() | |
| torch.cuda.set_rng_state(self.gen_random_states) | |
| def offload_vllm(self): | |
| """Offload vllm engine.""" | |
| assert self.loaded is True, "vllm engine has not been loaded" | |
| self.loaded = False | |
| print_gpu_memory_usage("Before vllm offload in sharding manager") | |
| free_bytes_before_sleep = torch.cuda.mem_get_info()[0] | |
| self.inference_engine.sleep(level=1) | |
| free_bytes_after_sleep = torch.cuda.mem_get_info()[0] | |
| self.freed_bytes = free_bytes_after_sleep - free_bytes_before_sleep | |
| print_gpu_memory_usage("After vllm offload in sharding manager") | |
| self.module.train() | |
| torch.cuda.empty_cache() # add empty cache after each compute | |
| # restore random states | |
| if self.device_mesh is not None: | |
| self.gen_random_states = torch.cuda.get_rng_state() | |
| torch.cuda.set_rng_state(self.torch_random_states) | |
| def preprocess_data(self, data: DataProto) -> DataProto: | |
| """All gather across tp group to make each rank has identical input.""" | |
| all_gather_data_proto(data, size=self.tp_size, group=self.tp_group) | |
| return data | |
| def postprocess_data(self, data: DataProto) -> DataProto: | |
| """Get chunk data of this tp rank since we do all gather in preprocess.""" | |
| if self.tp_size > 1: | |
| data = data.chunk(chunks=self.tp_size)[self.tp_rank] | |
| return data | |