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
| # ============================================================================= | |
| # ReVSI evaluation launcher — vLLM, data-parallel only. | |
| # | |
| # Usage: | |
| # bash eval/task/revsi/run_eval_vllm.sh [MODEL_PATH] | |
| # | |
| # Env overrides: | |
| # REVSI_ROOT root containing 16_frame/32_frame/64_frame/all_frame | |
| # FRAME_BUDGET 16, 32, 64, or all (default: all) | |
| # QA_FILE defaults to FRAME_BUDGET/test-00000-of-00001.parquet | |
| # OUTPUT_ROOT default: outputs/revsi | |
| # OUTPUT_DIR optional existing run dir; set this to resume an interrupted eval | |
| # TASK_FILTER comma-separated question_type list, optional | |
| # MAX_SAMPLES optional quick debug cap | |
| # TP_SIZE default 1 | |
| # MAX_MODEL_LEN default 32768 | |
| # MAX_NEW_TOKENS default 64 | |
| # BATCH_SIZE default 16 | |
| # GPU_MEM_UTIL default 0.90 | |
| # MEDIA_MODE image (default) or video | |
| # VIDEO_ROOT root for mp4s in video mode, e.g. VSI-590K root | |
| # MAX_FRAMES/FPS/VIDEO_TOTAL_PIXELS video sampling controls | |
| # ============================================================================= | |
| set -e | |
| SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | |
| PROJECT_DIR="$(cd "$SCRIPT_DIR/../../.." && pwd)" | |
| MODEL_PATH="${1:-${MODEL_PATH:-}}" | |
| REVSI_ROOT="${REVSI_ROOT:-}" | |
| FRAME_BUDGET="${FRAME_BUDGET:-all}" | |
| FRAME_DIR="${REVSI_ROOT:+${REVSI_ROOT}/${FRAME_BUDGET}_frame}" | |
| QA_FILE="${QA_FILE:-${FRAME_DIR:+${FRAME_DIR}/test-00000-of-00001.parquet}}" | |
| OUTPUT_ROOT="${OUTPUT_ROOT:-${PROJECT_DIR}/outputs/revsi}" | |
| TASK_FILTER="${TASK_FILTER:-}" | |
| MAX_SAMPLES="${MAX_SAMPLES:-0}" | |
| STRICT_NUMERIC_PROMPT="${STRICT_NUMERIC_PROMPT:-0}" | |
| ENABLE_THINKING="${ENABLE_THINKING:-false}" | |
| MEDIA_MODE="${MEDIA_MODE:-video}" | |
| VIDEO_ROOT="${VIDEO_ROOT:-${REVSI_ROOT}}" | |
| MAX_FRAMES="${MAX_FRAMES:-${FRAME_BUDGET/all/128}}" | |
| EXACT_NFRAMES="${EXACT_NFRAMES:-1}" | |
| FPS="${FPS:-2}" | |
| VIDEO_TOTAL_PIXELS="${VIDEO_TOTAL_PIXELS:-16777216}" | |
| VIDEO_MIN_PIXELS="${VIDEO_MIN_PIXELS:-65536}" | |
| VIDEO_MAX_PIXELS="${VIDEO_MAX_PIXELS:-}" | |
| TP_SIZE="${TP_SIZE:-1}" | |
| MAX_MODEL_LEN="${MAX_MODEL_LEN:-32768}" | |
| MAX_NEW_TOKENS="${MAX_NEW_TOKENS:-64}" | |
| BATCH_SIZE="${BATCH_SIZE:-16}" | |
| GPU_MEM_UTIL="${GPU_MEM_UTIL:-0.90}" | |
| SCORE_LOG_INTERVAL="${SCORE_LOG_INTERVAL:-200}" | |
| GLOBAL_SHARD_COUNT="${GLOBAL_SHARD_COUNT:-}" | |
| GLOBAL_SHARD_OFFSET="${GLOBAL_SHARD_OFFSET:-0}" | |
| MERGE_SHARDS="${MERGE_SHARDS:-1}" | |
| EXPECTED_SAMPLES="${EXPECTED_SAMPLES:-0}" | |
| VLLM_BASE_PORT="${VLLM_BASE_PORT:-}" | |
| LAUNCH_DELAY="${LAUNCH_DELAY:-2}" | |
| case "${FRAME_BUDGET}" in | |
| 16|32|64|all) ;; | |
| *) | |
| echo "ERROR: FRAME_BUDGET must be 16, 32, 64, or all." >&2 | |
| exit 2 | |
| ;; | |
| esac | |
| [[ -n "${MODEL_PATH}" ]] || { | |
| echo "ERROR: pass MODEL_PATH as the first argument or environment variable." >&2 | |
| exit 2 | |
| } | |
| [[ -n "${QA_FILE}" ]] || { | |
| echo "ERROR: set QA_FILE or REVSI_ROOT." >&2 | |
| exit 2 | |
| } | |
| for path in "${MODEL_PATH}/config.json" "${QA_FILE}"; do | |
| [[ -f "${path}" ]] || { | |
| echo "ERROR: required input is unavailable: ${path}" >&2 | |
| exit 1 | |
| } | |
| done | |
| if [[ "${QA_FILE}" == *.parquet ]]; then | |
| [[ -n "${FRAME_DIR}" ]] || { | |
| echo "ERROR: parquet input requires REVSI_ROOT to locate frame videos." >&2 | |
| exit 2 | |
| } | |
| compgen -G "${FRAME_DIR}/*.mp4" >/dev/null || { | |
| echo "ERROR: no ReVSI videos found under ${FRAME_DIR}; extract video.zip first." >&2 | |
| exit 1 | |
| } | |
| fi | |
| # Prefer the CUDA runtime libraries installed alongside PyTorch. In particular, | |
| # pip/conda CUDA 12.9 builds need their matching nvJitLink ahead of an older | |
| # system CUDA toolkit that may already be present in LD_LIBRARY_PATH. | |
| NVJITLINK_LIB="$( | |
| python - <<'PY' | |
| import site | |
| from pathlib import Path | |
| roots = [*site.getsitepackages(), site.getusersitepackages()] | |
| for root in roots: | |
| candidate = Path(root) / "nvidia" / "nvjitlink" / "lib" | |
| if candidate.is_dir(): | |
| print(candidate) | |
| break | |
| PY | |
| )" | |
| if [[ -n "${NVJITLINK_LIB}" ]]; then | |
| export LD_LIBRARY_PATH="${NVJITLINK_LIB}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}" | |
| fi | |
| if ! python -c "import torch; print(f'PyTorch preflight: {torch.__version__} CUDA {torch.version.cuda}')"; then | |
| echo "ERROR: PyTorch CUDA libraries cannot be loaded in the active environment." >&2 | |
| exit 1 | |
| fi | |
| IFS="," read -ra GPULIST <<< "${CUDA_VISIBLE_DEVICES:-$(seq -s, 0 $(($(nvidia-smi -L | wc -l)-1)))}" | |
| NUM_GPUS=${#GPULIST[@]} | |
| # Each vLLM subprocess must inherit only its worker-specific GPU mask. | |
| unset CUDA_VISIBLE_DEVICES | |
| if (( NUM_GPUS % TP_SIZE != 0 )); then | |
| echo "ERROR: NUM_GPUS=$NUM_GPUS must be divisible by TP_SIZE=$TP_SIZE" | |
| exit 1 | |
| fi | |
| DP_SIZE=$(( NUM_GPUS / TP_SIZE )) | |
| if [[ -z "${VLLM_BASE_PORT}" ]]; then | |
| VLLM_BASE_PORT="$( | |
| python - "$DP_SIZE" <<'PY' | |
| import socket | |
| import sys | |
| count = int(sys.argv[1]) | |
| spacing = 16 | |
| for base in range(48000, 64000 - spacing * count, 128): | |
| sockets = [] | |
| try: | |
| for index in range(count): | |
| sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
| sock.bind(("127.0.0.1", base + index * spacing)) | |
| sockets.append(sock) | |
| except OSError: | |
| for sock in sockets: | |
| sock.close() | |
| continue | |
| for sock in sockets: | |
| sock.close() | |
| print(base) | |
| break | |
| else: | |
| raise SystemExit("no free ReVSI vLLM port block found") | |
| PY | |
| )" | |
| fi | |
| MODEL_TAG=$(basename "${MODEL_PATH%/}") | |
| TIMESTAMP=$(date +%Y%m%d_%H%M%S) | |
| RUN_TAG="${RUN_TAG:-eval_revsi_${FRAME_BUDGET}frame_vllm-${MODEL_TAG}-${TIMESTAMP}}" | |
| # If OUTPUT_DIR points to an existing partial run, eval_revsi_vllm.py will skip | |
| # IDs already present in results_shard*.jsonl and continue the remaining samples. | |
| OUTPUT_DIR="${OUTPUT_DIR:-${OUTPUT_ROOT}/${RUN_TAG}}" | |
| mkdir -p "$OUTPUT_DIR" | |
| export MODEL_PATH QA_FILE VIDEO_ROOT FRAME_BUDGET MAX_FRAMES EXACT_NFRAMES FPS | |
| export VIDEO_TOTAL_PIXELS VIDEO_MIN_PIXELS VIDEO_MAX_PIXELS | |
| export MAX_MODEL_LEN MAX_NEW_TOKENS BATCH_SIZE TP_SIZE MAX_SAMPLES | |
| export EXPECTED_SAMPLES ENABLE_THINKING VLLM_BASE_PORT | |
| python - "$OUTPUT_DIR/run_config.json" <<'PY' | |
| import json | |
| import os | |
| import sys | |
| keys = ( | |
| "MODEL_PATH", | |
| "QA_FILE", | |
| "VIDEO_ROOT", | |
| "FRAME_BUDGET", | |
| "MAX_FRAMES", | |
| "EXACT_NFRAMES", | |
| "FPS", | |
| "VIDEO_TOTAL_PIXELS", | |
| "VIDEO_MIN_PIXELS", | |
| "VIDEO_MAX_PIXELS", | |
| "MAX_MODEL_LEN", | |
| "MAX_NEW_TOKENS", | |
| "BATCH_SIZE", | |
| "TP_SIZE", | |
| "MAX_SAMPLES", | |
| "EXPECTED_SAMPLES", | |
| "ENABLE_THINKING", | |
| "VLLM_BASE_PORT", | |
| ) | |
| payload = {key.lower(): os.environ.get(key, "") for key in keys} | |
| with open(sys.argv[1], "w", encoding="utf-8") as handle: | |
| json.dump(payload, handle, indent=2, sort_keys=True) | |
| handle.write("\n") | |
| PY | |
| cat <<EOF | |
| ============================================== | |
| ReVSI Evaluation (vLLM, data-parallel) | |
| ============================================== | |
| Model: $MODEL_PATH | |
| QA file: $QA_FILE | |
| Output: $OUTPUT_DIR | |
| GPUs: ${GPULIST[*]} (${NUM_GPUS} total, TP=${TP_SIZE}, DP=${DP_SIZE}) | |
| Max tokens: new=$MAX_NEW_TOKENS model_len=$MAX_MODEL_LEN | |
| Batch: $BATCH_SIZE | |
| Task filter: ${TASK_FILTER:-<none>} | |
| Max samples: ${MAX_SAMPLES} | |
| Strict num: ${STRICT_NUMERIC_PROMPT} | |
| Thinking: ${ENABLE_THINKING} | |
| Media mode: ${MEDIA_MODE} | |
| Video root: ${VIDEO_ROOT:-<none>} | |
| Base port: ${VLLM_BASE_PORT} | |
| Frame budget: ${FRAME_BUDGET} (exact_nframes=${EXACT_NFRAMES}) | |
| Video: max_frames=${MAX_FRAMES} fps=${FPS} total_pixels=${VIDEO_TOTAL_PIXELS} | |
| ============================================== | |
| EOF | |
| PIDS=() | |
| cleanup() { | |
| echo ""; echo "Caught interrupt, killing workers ..." | |
| for pid in "${PIDS[@]}"; do kill -TERM "$pid" 2>/dev/null || true; done | |
| wait 2>/dev/null || true | |
| exit 1 | |
| } | |
| trap cleanup INT TERM | |
| EFFECTIVE_SHARD_COUNT="${GLOBAL_SHARD_COUNT:-$DP_SIZE}" | |
| for IDX in $(seq 0 $((DP_SIZE - 1))); do | |
| START=$(( IDX * TP_SIZE )) | |
| GLOBAL_IDX=$((GLOBAL_SHARD_OFFSET + IDX)) | |
| SHARD_PORT=$((VLLM_BASE_PORT + IDX * 16)) | |
| SHARD_GPUS="" | |
| for j in $(seq 0 $((TP_SIZE - 1))); do | |
| g=${GPULIST[$((START + j))]} | |
| SHARD_GPUS="${SHARD_GPUS}${SHARD_GPUS:+,}${g}" | |
| done | |
| OUT_JSONL="${OUTPUT_DIR}/results_shard${GLOBAL_IDX}.jsonl" | |
| STRICT_FLAG="" | |
| if [ "$STRICT_NUMERIC_PROMPT" = "1" ] || [ "$STRICT_NUMERIC_PROMPT" = "true" ]; then | |
| STRICT_FLAG="--strict_numeric_prompt" | |
| fi | |
| VIDEO_MAX_PIXELS_ARGS=() | |
| if [ -n "$VIDEO_MAX_PIXELS" ]; then | |
| VIDEO_MAX_PIXELS_ARGS=(--video_max_pixels "$VIDEO_MAX_PIXELS") | |
| fi | |
| EXACT_NFRAMES_ARGS=() | |
| if [ "$EXACT_NFRAMES" = "1" ] || [ "$EXACT_NFRAMES" = "true" ]; then | |
| EXACT_NFRAMES_ARGS=(--exact_nframes) | |
| fi | |
| CUDA_VISIBLE_DEVICES="$SHARD_GPUS" \ | |
| VLLM_PORT="$SHARD_PORT" \ | |
| VLLM_HOST_IP=127.0.0.1 \ | |
| MASTER_PORT="$SHARD_PORT" \ | |
| MASTER_ADDR=127.0.0.1 \ | |
| PYTHONUNBUFFERED=1 \ | |
| python "${SCRIPT_DIR}/eval_revsi_vllm.py" \ | |
| --output_json_path "$OUT_JSONL" \ | |
| --model_path "$MODEL_PATH" \ | |
| --qa_file "$QA_FILE" \ | |
| --rank "$GLOBAL_IDX" \ | |
| --world_size "$EFFECTIVE_SHARD_COUNT" \ | |
| --tensor_parallel_size "$TP_SIZE" \ | |
| --max_model_len "$MAX_MODEL_LEN" \ | |
| --gpu_memory_utilization "$GPU_MEM_UTIL" \ | |
| --max_new_tokens "$MAX_NEW_TOKENS" \ | |
| --batch_size "$BATCH_SIZE" \ | |
| --score_log_interval "$SCORE_LOG_INTERVAL" \ | |
| --task_filter "$TASK_FILTER" \ | |
| --max_samples "$MAX_SAMPLES" \ | |
| --media_mode "$MEDIA_MODE" \ | |
| --video_root "$VIDEO_ROOT" \ | |
| --max_frames "$MAX_FRAMES" \ | |
| --fps "$FPS" \ | |
| --video_total_pixels "$VIDEO_TOTAL_PIXELS" \ | |
| --video_min_pixels "$VIDEO_MIN_PIXELS" \ | |
| "${VIDEO_MAX_PIXELS_ARGS[@]}" \ | |
| "${EXACT_NFRAMES_ARGS[@]}" \ | |
| --enable_thinking "$ENABLE_THINKING" \ | |
| $STRICT_FLAG \ | |
| > "$OUTPUT_DIR/worker_${GLOBAL_IDX}.log" 2>&1 & | |
| PIDS+=($!) | |
| echo "Launched shard $GLOBAL_IDX/$EFFECTIVE_SHARD_COUNT on GPU $SHARD_GPUS (PID ${PIDS[-1]})" | |
| if [ "$IDX" -lt $((DP_SIZE - 1)) ] && [ "$LAUNCH_DELAY" -gt 0 ]; then | |
| sleep "$LAUNCH_DELAY" | |
| fi | |
| done | |
| echo "Waiting for ${DP_SIZE} workers ..." | |
| FAILED=0 | |
| for i in "${!PIDS[@]}"; do | |
| RC=0 | |
| wait "${PIDS[$i]}" || RC=$? | |
| if [ $RC -ne 0 ]; then | |
| echo "[FAIL] shard $i (PID ${PIDS[$i]}) exit=$RC" | |
| FAILED=1 | |
| else | |
| echo "[DONE] shard $i (PID ${PIDS[$i]})" | |
| fi | |
| done | |
| if [ $FAILED -ne 0 ]; then | |
| echo "ERROR: some workers failed; not merging incomplete shards." >&2 | |
| echo "Logs: $OUTPUT_DIR/worker_*.log" >&2 | |
| exit 1 | |
| fi | |
| if [ "$MERGE_SHARDS" != "1" ]; then | |
| echo "Local ReVSI shard range completed; centralized merge deferred." | |
| exit 0 | |
| fi | |
| python "${SCRIPT_DIR}/merge_multinode_shards.py" \ | |
| --output-dir "$OUTPUT_DIR" \ | |
| --num-shards "$EFFECTIVE_SHARD_COUNT" \ | |
| --expected-samples "$EXPECTED_SAMPLES" | |
| echo "Done: $OUTPUT_DIR" | |
| exit $FAILED | |