### Install qwen-vl-utils Source: https://github.com/cyuq1n/easyvideor1/blob/main/eval/code/qwen_vl_utils-0.0.8/README.md Install the qwen-vl-utils library using pip. ```bash pip install qwen-vl-utils ``` -------------------------------- ### Copy Example Configuration Source: https://github.com/cyuq1n/easyvideor1/blob/main/README.md Copies an example video RL configuration file to be customized for your training run. ```bash cp examples/video_rl/video_rl.yaml my_config.yaml ``` -------------------------------- ### Clone Repository and Install Package Source: https://github.com/cyuq1n/easyvideor1/blob/main/README.md Clones the EasyVideoR1 repository from GitHub and installs it in editable mode. ```bash git clone https://github.com/cyuQ1n/EasyVideoR1.git cd EasyVideoR1 pip install -e . ``` -------------------------------- ### Visual Token Calculation Example Source: https://github.com/cyuq1n/easyvideor1/blob/main/docs/token_calculation.md An example demonstrating the calculation of visual tokens for a video with specific pixel and frame count configurations. ```plaintext 每帧 tokens = (512 / 32) × (512 / 32) = 16 × 16 = 256 tokens/帧 视频 tokens = (128 / 2) × 256 = 64 × 256 = 16384 tokens ``` -------------------------------- ### Install Flash Attention Source: https://github.com/cyuq1n/easyvideor1/blob/main/README.md Installs Flash Attention version 2.8.3 without build isolation. This is a key dependency for performance. ```bash pip install flash-attn==2.8.3 --no-build-isolation ``` -------------------------------- ### Example Data Directory Structure Source: https://github.com/cyuq1n/easyvideor1/blob/main/eval/README.md Illustrates the recommended directory structure for evaluation data, including annotation files and dataset directories. ```text YOUR_EVAL_DATA_ROOT/ ├── valid_data/ │ ├── lvbench.json │ ├── mmvu.json │ └── ... ├── LVBench/ ├── MMVU/ ├── Video-MME/ └── ... ``` -------------------------------- ### Video Data Format Example Source: https://github.com/cyuq1n/easyvideor1/blob/main/README.md Example JSON structure for a single video entry in the training dataset. Supports open-ended questions. ```json { "problem": "What happens in this video?", "answer": "A cat jumps onto the table.", "videos": ["path/to/video.mp4"], "data_type": "video", "problem_type": "open-ended" } ``` -------------------------------- ### Run Unified RL Pipeline Source: https://github.com/cyuq1n/easyvideor1/blob/main/README.md Execute the modular pipeline for mixed image-video RL training. This script starts the training process for reinforcement learning tasks involving both images and videos. ```bash bash examples/unified_rl/run_unified_rl.sh ``` -------------------------------- ### Multiple Choice Video Data Format Example Source: https://github.com/cyuq1n/easyvideor1/blob/main/README.md Example JSON structure for a multiple-choice video entry. Includes 'options' for possible answers. ```json { "problem": "What color is the car?", "answer": "B", "videos": ["path/to/video.mp4"], "data_type": "video", "problem_type": "multiple choice", "options": ["A. Red", "B. Blue", "C. Green", "D. White"] } ``` -------------------------------- ### Example Cache Directory Name Source: https://github.com/cyuq1n/easyvideor1/blob/main/eval/README.md Cache directory names are automatically generated to encode dataset and sampling parameters. This example shows the typical structure. ```text lvbench_f256_fps2.0_mp256k_tp32768k ``` -------------------------------- ### Launch Training (Single-Node) Source: https://github.com/cyuq1n/easyvideor1/blob/main/README.md Launches the EasyVideoR1 training script on a single node, assuming 8 GPUs are available. ```bash bash examples/video_rl/run_video_rl.sh ``` -------------------------------- ### Launch Training (Multi-Node) Source: https://github.com/cyuq1n/easyvideor1/blob/main/README.md Launches the EasyVideoR1 training script across multiple nodes. Requires setting WORLD_SIZE, RANK, and MASTER_ADDR on each node. ```bash # Single-node (8 GPUs) bash examples/video_rl/run_video_rl.sh # Multi-node: set WORLD_SIZE, RANK, MASTER_ADDR on each node WORLD_SIZE=2 RANK=0 MASTER_ADDR= bash examples/video_rl/run_video_rl.sh # head WORLD_SIZE=2 RANK=1 MASTER_ADDR= bash examples/video_rl/run_video_rl.sh # worker ``` -------------------------------- ### Create Conda Environment Source: https://github.com/cyuq1n/easyvideor1/blob/main/eval/README.md Sets up a new Conda environment named 'easyvideorl' with Python 3.11 and activates it. ```bash conda create -n easyvideorl python=3.11 conda activate easyvideorl ``` -------------------------------- ### Process Vision Information with Qwen-VL Source: https://github.com/cyuq1n/easyvideor1/blob/main/eval/code/qwen_vl_utils-0.0.8/README.md Demonstrates how to prepare messages with various image and video formats for Qwen-VL models and process them using the library. This includes local file paths, URLs, base64 encoded images, PIL Images, and videos with specified frame rates and dimensions. ```python from transformers import Qwen2VLForConditionalGeneration, Qwen2VLProcessor from qwen_vl_utils import process_vision_info # You can directly insert a local file path, a URL, or a base64-encoded image into the position where you want in the text. messages = [ # Image ## Local file path [{"role": "user", "content": [{"type": "image", "image": "file:///path/to/your/image.jpg"}, {"type": "text", "text": "Describe this image."}]}], ## Image URL [{"role": "user", "content": [{"type": "image", "image": "http://path/to/your/image.jpg"}, {"type": "text", "text": "Describe this image."}]}], ## Base64 encoded image [{"role": "user", "content": [{"type": "image", "image": "data:image;base64,/9j/..."}, {"type": "text", "text": "Describe this image."}]}], ## PIL.Image.Image [{"role": "user", "content": [{"type": "image", "image": pil_image}, {"type": "text", "text": "Describe this image."}]}], ## Model dynamically adjusts image size, specify dimensions if required. [{"role": "user", "content": [{"type": "image", "image": "file:///path/to/your/image.jpg", "resized_height": 280, "resized_width": 420}, {"type": "text", "text": "Describe this image."}]}], # Video ## Local video path [{"role": "user", "content": [{"type": "video", "video": "file:///path/to/video1.mp4"}, {"type": "text", "text": "Describe this video."}]}], ## Local video frames [{"role": "user", "content": [{"type": "video", "video": ["file:///path/to/extracted_frame1.jpg", "file:///path/to/extracted_frame2.jpg", "file:///path/to/extracted_frame3.jpg"],}, {"type": "text", "text": "Describe this video."},],}], ## Model dynamically adjusts video nframes, video height and width. specify args if required. [{"role": "user", "content": [{"type": "video", "video": "file:///path/to/video1.mp4", "fps": 2.0, "resized_height": 280, "resized_width": 280}, {"type": "text", "text": "Describe this video."}]}], ] processor = Qwen2VLProcessor.from_pretrained(model_path) model = Qwen2VLForConditionalGeneration.from_pretrained(model_path, torch_dtype="auto", device_map="auto") text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) images, videos = process_vision_info(messages) inputs = processor(text=text, images=images, videos=videos, padding=True, return_tensors="pt") print(inputs) generated_ids = model.generate(**inputs) print(generated_ids) ``` -------------------------------- ### Preprocess ODV-Bench Videos Source: https://github.com/cyuq1n/easyvideor1/blob/main/eval/README.md Use this command to preprocess ODV-Bench videos by specifying input JSON, video root, output directory, and format. ```bash cd EasyVideoR1/eval/preprocess # ODV-Bench python cilp.py \ --input_json ../data/valid_data/odvbench.json \ --video_root /path/to/ODV-Bench \ --output_dir ../data/ODV-Bench/clips \ --format odvbench ``` -------------------------------- ### Preprocess LiveSports-3K Videos Source: https://github.com/cyuq1n/easyvideor1/blob/main/eval/README.md Use this command to preprocess LiveSports-3K videos, similar to ODV-Bench, by providing the necessary paths and format. ```bash # LiveSports-3K python cilp.py \ --input_json ../data/valid_data/livesports3k_qa.json \ --video_root /path/to/LiveSports-3K/videos \ --output_dir ../data/LiveSports-3K-QA/clips \ --format livesports ``` -------------------------------- ### Pixel Budget to Token Budget Conversion (Incorrect vs. Correct) Source: https://github.com/cyuq1n/easyvideor1/blob/main/docs/token_calculation.md Illustrates the correct Python code for converting token budget to pixel budget, highlighting the inclusion of temporal compression. ```python # 原来的配置(只考虑空间压缩,错误) max_pixels = token_budget * 32 * 32 # 正确的配置(同时考虑时间压缩) max_pixels = token_budget * 32 * 32 * 2 ``` -------------------------------- ### Pixel and Token Budget Conversion Formulas Source: https://github.com/cyuq1n/easyvideor1/blob/main/docs/token_calculation.md Provides Python formulas for converting between token budget and pixel budget, accounting for both spatial and temporal compression. ```python # 从 token 预算计算像素预算 max_pixels = max_visual_tokens * 32 * 32 * 2 # 从像素预算计算 token 数量 visual_tokens = (frames / 2) * (pixels / 32 / 32) ``` -------------------------------- ### Evaluate Using Existing Cache Source: https://github.com/cyuq1n/easyvideor1/blob/main/eval/README.md Runs evaluation using preprocessed video cache for specified datasets. This mode is faster as it skips the preprocessing step. ```bash python eval/code/AsyncLLMEngine_eval_videobench_qwen3vl_multi_task.py \ --mode eval \ --model_path /path/to/your/model \ --data_dir_path /path/to/EasyVideoR1/eval/data \ --datasets lvbench videomme \ --cache_dir ./eval/video_cache \ --output_dir ./eval/output-async \ --result_dir ./eval/result-async ``` -------------------------------- ### Full Load Configuration Visual Token Calculation Source: https://github.com/cyuq1n/easyvideor1/blob/main/docs/token_calculation.md Demonstrates the calculation of visual tokens for a full load configuration (128 frames, 512x512 pixels) and the resulting impact on remaining text prompt space. ```plaintext 视觉 tokens: 16384 max_prompt_length: 16384 剩余文本空间: ≈ 0 tokens ← 问题! ``` -------------------------------- ### Run Evaluation on a Single Dataset Source: https://github.com/cyuq1n/easyvideor1/blob/main/eval/README.md Executes the evaluation script for a single dataset using Qwen3VL model. Requires specifying model path, data directory, and various performance-related parameters. ```bash python eval/code/AsyncLLMEngine_eval_videobench_qwen3vl_multi_task.py \ --mode auto \ --model_path /path/to/your/model \ --model_family qwen3 \ --data_dir_path /path/to/EasyVideoR1/eval/data \ --datasets lvbench \ --cache_dir ./eval/video_cache \ --output_dir ./eval/output-async \ --result_dir ./eval/result-async \ --nframes 256 \ --fps 2.0 \ --max_pixels 262144 \ --total_pixels 33554432 \ --max_tokens 4096 \ --max_num_seqs 8 \ --max_concurrent 16 \ --queue_size 16 \ --thinking_mode ``` -------------------------------- ### Evaluate with Custom Dataset Configuration Source: https://github.com/cyuq1n/easyvideor1/blob/main/eval/README.md Run the evaluation script using a custom dataset configuration. Provide the model path, the path to your dataset configuration JSON, and the name of your custom dataset. ```bash python eval/code/AsyncLLMEngine_eval_videobench_qwen3vl_multi_task.py \ --model_path /path/to/your/model \ --dataset_config /path/to/dataset_config.json \ --datasets mybench ``` -------------------------------- ### Dataset Preprocessing in Python Source: https://github.com/cyuq1n/easyvideor1/blob/main/docs/qwen3_vl_multimodal_processing.md This snippet shows the video processing logic within the Dataset stage, calling `process_video` to handle video inputs and prepare them for tokenization. It highlights the parameters required and the output format. ```python # 位置: dataset.py, 约 332-342 行 for video in videos: # 必须传入 min_pixels, max_pixels, video_fps processed_video, video_fps = process_video( video, min_pixels=self.min_pixels if self.min_pixels else 4 * 32 * 32, max_pixels=self.max_pixels if self.max_pixels else 64 * 32 * 32, video_fps=self.video_fps, return_fps=True ) processed_videos.append(processed_video) ``` -------------------------------- ### Create Conda Environment Source: https://github.com/cyuq1n/easyvideor1/blob/main/README.md Creates and activates a new conda environment named 'easyvideor1' with Python 3.11. ```bash conda create -n easyvideor1 python=3.11 conda activate easyvideor1 ``` -------------------------------- ### Rollout Stage Video Processing (vLLM) in Python Source: https://github.com/cyuq1n/easyvideor1/blob/main/docs/qwen3_vl_multimodal_processing.md This Python code demonstrates video processing in the Rollout stage using vLLM. It re-processes videos using `process_video` and formats them as `(frames, metadata)` tuples for vLLM consumption, ensuring `do_resize` and `do_sample_frames` are set to False to avoid redundant operations. ```python # 位置: vllm_rollout_spmd.py, 约 74-98 行 if "videos" in multi_modal_data: for video in multi_modal_data["videos"]: processed, _ = process_video( video, min_pixels=min_pixels, # 从 meta_info 获取 max_pixels=max_pixels, # 从 meta_info 获取 video_fps=video_fps, # 从 meta_info 获取 return_fps=True ) if isinstance(processed, tuple) and len(processed) == 2: frames, metadata = processed videos.append((frames, metadata)) # vLLM 需要 (frames, metadata) 元组 if len(videos) > 0: mm_kwargs = {"do_sample_frames": False, "do_resize": False} ``` -------------------------------- ### Typical Configuration Visual Token Calculation Source: https://github.com/cyuq1n/easyvideor1/blob/main/docs/token_calculation.md Calculates visual tokens and remaining text prompt space for a typical configuration (60 frames, 480x320 pixels). ```plaintext 每帧 tokens = (480/32) × (320/32) = 15 × 10 = 150 tokens/帧 视频 tokens = (60/2) × 150 = 4500 tokens 剩余文本空间 = 16384 - 4500 ≈ 11884 tokens ``` -------------------------------- ### Training Stage Video Processing (FSDP) in Python Source: https://github.com/cyuq1n/easyvideor1/blob/main/docs/qwen3_vl_multimodal_processing.md This Python code shows the video processing within the FSDP Training stage. It calls `process_video` to extract frames and metadata, then prepares these for the video processor with specific arguments like `do_resize=False` and `do_sample_frames=False`. ```python # 位置: fsdp_workers.py, 约 484-532 行 if "videos" in multi_modal_data: video_metadatas = [] for video in multi_modal_data["videos"]: result = process_video( video, min_pixels=min_pixels, # 从 data.meta_info 获取 max_pixels=max_pixels, # 从 data.meta_info 获取 video_fps=video_fps, # 从 data.meta_info 获取 return_fps=True ) if isinstance(result, tuple) and len(result) == 2: video_data, _ = result if isinstance(video_data, tuple) and len(video_data) == 2: frames, metadata = video_data videos.append(frames) video_metadatas.append(metadata) # 调用 video_processor processor_kwargs = { "videos": videos, "return_tensors": "pt", "do_resize": False, # 已在 process_video 中 resize "do_sample_frames": False, # 已在 process_video 中采样 } if video_metadatas is not None: processor_kwargs["video_metadata"] = video_metadatas multi_modal_inputs = dict(self.processor.video_processor(**processor_kwargs)) ``` -------------------------------- ### Custom Dataset Configuration JSON Source: https://github.com/cyuq1n/easyvideor1/blob/main/eval/README.md Define custom dataset mappings using a JSON file. Specify the path to the JSON annotation file and the video root directory for your custom dataset. ```json { "mybench": { "json": "/path/to/mybench.json", "video": "/path/to/mybench_videos" } } ``` -------------------------------- ### Preprocess Video Cache Source: https://github.com/cyuq1n/easyvideor1/blob/main/eval/README.md Preprocesses video data for specified datasets and saves it to a cache directory. This is a prerequisite for cache-only evaluation. ```bash python eval/code/AsyncLLMEngine_eval_videobench_qwen3vl_multi_task.py \ --mode preprocess \ --model_path /path/to/your/model \ --data_dir_path /path/to/EasyVideoR1/eval/data \ --datasets lvbench videomme \ --cache_dir ./eval/video_cache ``` -------------------------------- ### BibTeX Citation for EasyVideoR1 Source: https://github.com/cyuq1n/easyvideor1/blob/main/README.md Use this BibTeX entry to cite the EasyVideoR1 project in academic publications. Ensure the URL and year are correct for your citation context. ```bibtex @misc{qin2026easyvideor1, title = {EasyVideoR1: Easier RL for Video Understanding}, author = {Chuanyu Qin, Chenxu Yang, Qingyi Si, Naibin Gu, Dingyu Yao, Zheng Lin, Peng Fu, Nan Duan, Jiaqi Wang}, howpublished = {\url{https://github.com/cyuQ1n/EasyVideoR1}}, year = {2026} } ``` -------------------------------- ### Calculate Total Visual Tokens for Video Source: https://github.com/cyuq1n/easyvideor1/blob/main/docs/token_calculation.md Calculates the total number of visual tokens for a video, considering frame rate and temporal compression. ```plaintext 视频 tokens = (帧数 / 2) × (H / 32) × (W / 32) ``` -------------------------------- ### vLLM Internal Video Processing Source: https://github.com/cyuq1n/easyvideor1/blob/main/docs/qwen3_vl_multimodal_processing.md This snippet illustrates how vLLM internally processes video data. It expects video items as tuples, creates `VideoMetadata`, and then calls the HuggingFace processor with specific `mm_kwargs`. ```python # 约 826-856 行 for item in mm_data["videos"]: video_array, metadata = item # 期望元组格式 # 创建 VideoMetadata metadata = VideoMetadata(**{ k: metadata[k] for k in metadata if k != "do_sample_frames" }) # 调用 HuggingFace processor video_outputs = super()._call_hf_processor( prompt="<|vision_start|><|video_pad|><|vision_end|>", mm_data={"videos": [[video_array]], "video_metadata": [[metadata]]}, mm_kwargs=video_mm_kwargs, # 包含 do_resize=False ... ) ``` -------------------------------- ### Essential Configuration Fields Source: https://github.com/cyuq1n/easyvideor1/blob/main/README.md Minimum required fields to update in the copied configuration file, including data paths and model path. ```yaml data: train_files: /path/to/your/train.jsonl val_files: /path/to/your/val.json worker: actor: model: model_path: Qwen/Qwen3-VL-8B-Instruct trainer: experiment_name: my_first_run save_checkpoint_path: ./checkpoints/my_first_run ``` -------------------------------- ### Validation and Saving Logic in RL Training Source: https://github.com/cyuq1n/easyvideor1/blob/main/docs/rl_training_deep_dive.md This snippet shows the conditional logic for performing validation and saving checkpoints during the RL training process. Validation occurs at specified frequencies based on global steps, and saving checkpoints includes actor weights, optimizer state, and DataLoader state for resuming training. ```python if self.global_step % self.config.trainer.val_freq == 0: val_metrics = self._validate() if self.global_step % self.config.trainer.save_freq == 0: self._save_checkpoint() ``` -------------------------------- ### Merge FSDP Checkpoints Source: https://github.com/cyuq1n/easyvideor1/blob/main/README.md Merges FSDP (Fully Sharded Data Parallel) checkpoints into Hugging Face format after training is complete. ```bash python3 scripts/model_merger.py --local_dir checkpoints/my_first_run/global_step_100/actor ``` -------------------------------- ### Video Feature and Token Count Validation in Python Source: https://github.com/cyuq1n/easyvideor1/blob/main/docs/qwen3_vl_multimodal_processing.md This Python snippet demonstrates a validation check during the verification phase to ensure the number of video features matches the number of video tokens. It raises a ValueError if there is a mismatch. ```python # 约 167-172 行 n_video_tokens = (input_ids == model.config.video_token_id).sum().item() n_video_features = video_embeds.shape[0] if n_video_tokens != n_video_features: raise ValueError( f"Video features and video tokens do not match: " f"tokens: {n_video_tokens}, features {n_video_features}" ) ``` -------------------------------- ### Run LLM Judge on Open-Ended Results Source: https://github.com/cyuq1n/easyvideor1/blob/main/eval/README.md Post-processes evaluation results using an LLM judge to score open-ended responses. Requires input JSON, judge model path, and output paths. ```bash python eval/code/llm_judge.py \ --input_json ./eval/output-async/videoreasonbench_f256_fps2.0_mp256k_tp32768k/YourModel_output.json \ --model_path /path/to/judge/model \ --output_json ./eval/output-async/videoreasonbench_f256_fps2.0_mp256k_tp32768k/YourModel_output_judged.json \ --result_file ./eval/result-async/YourModel.json \ --dataset_name videoreasonbench \ --num_gpus 1 \ --max_tokens 2048 \ --temperature 0.1 ``` -------------------------------- ### Calculate Visual Tokens Per Frame Source: https://github.com/cyuq1n/easyvideor1/blob/main/docs/token_calculation.md Calculates the number of visual tokens for a single frame based on image dimensions and spatial compression ratio. ```plaintext 每帧 tokens = (H / 32) × (W / 32) ``` -------------------------------- ### DataProto Class Definition for Data Transfer Source: https://github.com/cyuq1n/easyvideor1/blob/main/docs/rl_training_deep_dive.md Defines the DataProto class, a container used for passing data between different components in the system. It holds Tensor data, non-Tensor data, and metadata, facilitating structured data exchange. ```python class DataProto: batch: TensorDict # Tensor 数据 (input_ids, attention_mask, ...) non_tensor_batch: dict # 非 Tensor 数据 (multi_modal_data, uid, ...) meta_info: dict # 元信息 (temperature, image_max_pixels, ...) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.