R1-V Framework

repository·main·Indexed 26 days ago

https://github.com/starsfieldai/r1-v

A framework for reinforcing super generalization ability in Vision Language Models (VLMs) using Reinforcement Learning from Verifiable Feedback (RLVR). It focuses on improving reasoning and perception in models such as Qwen2-VL. The repository provides tools for GRPO training, Supervised Fine-Tuning (SFT), evaluation on SuperCLEVR and GEOQA, and a pipeline for distilling R1 responses into training datasets including reasoning path filtering and Hugging Face dataset creation.

Tokens
8.1K
Snippets
15
Records
40
Agent score
88%

What's inside R1-V

  1. Evaluate on SuperCLEVR

    main

    To evaluate OOD counting performance on SuperCLEVR, download the required images, unzip them, and run the evaluation script. You can modify the script to test on your own datasets.

    cd ./src/eval
    wget https://www.cs.jhu.edu/~zhuowan/zhuowan/SuperCLEVR/to_be_released/images.zip
    unzip images.zip
    
    # change the model path in the script
    python test_qwen2vl_counting_superclevr.py 
  2. Train with SFT

    main

    Perform Supervised Fine-Tuning (SFT) using accelerate launch. You must provide a configuration file and a specific SFT task config file.

    accelerate launch --config_file src/r1-v/configs/zero2.yaml src/r1-v/src/open_r1/sft.py --config src/r1-v/configs/qwen2vl_sft_config.yaml 
  3. Generate R1 responses using query_r1.py

    main

    Use query_r1.py to obtain predictions and reasoning traces from R1 by querying SiliconFlow.

    Note on Output Formats:

    • v1: Does not constrain output format, making answers difficult to parse.
    • v2: Uses explicit prompting to ensure the model generates the answer using the marker **The answer is: ** for easier parsing.
    <think>
    Okay, let's see. The user is asking how many items are there in the described scene... [reasoning trace]
    </think>
    
    There are 7 items in the described scene. Each entry corresponds to one distinct object, listed by their properties, coordinates, and rotations.
  4. Evaluate on GEOQA

    main

    To evaluate on the GEOQA test set (direct answer form), you must first clone the Geo170K dataset from Hugging Face and unzip the images before running the evaluation script. For faster inference using multiple GPUs, use the multi-GPU script provided in the repository.

    # prepare images for testing
    cd ./src/eval
    git lfs install
    git clone https://huggingface.co/datasets/Luckyjhg/Geo170K
    cd Geo170K
    unzip images.zip
    
    # Evaluation Script
    python test_qwen2vl_geoqa.py
    
    # For multi-GPU inference:
    bash src/scripts/test_grpo_geoqa_multigpu.sh
  5. Train with GRPO

    main

    Use torchrun to execute the GRPO training script located at src/open_r1/grpo.py.

    Key Configuration Notes:

    • Debug Mode: Set export DEBUG_MODE="true" to see model rollouts during RL.
    • Batch Size: It is currently recommended to keep --per_device_train_batch_size 1 to avoid known bugs with batched training.
    • Memory Management: If you encounter Out-of-Memory (OOM) errors, reduce the --num_generations value.
    • Acceleration: To use vLLM for faster training, refer to the script at src/scripts/run_grpo_vllm.sh and ensure vllm==0.7.2 is installed.
    cd src/r1-v
    
    export DEBUG_MODE="true" # Enable Debug if you want to see the rollout of model during RL
    export LOG_PATH="./debug_log_2b.txt"
    
    torchrun --nproc_per_node="8" \ 
        --nnodes="1" \ 
        --node_rank="0" \ 
        --master_addr="127.0.0.1" \ 
        --master_port="12345" \ 
        src/open_r1/grpo.py \ 
        --output_dir <OUTPUT_DIR> \ 
        --model_name_or_path <PATH-TO-Qwen2-VL-2B-Instruct> \  
        --dataset_name leonardPKU/clevr_cogen_a_train \  
        --deepspeed local_scripts/zero3.json \ 
        --max_prompt_length 512 \ 
        --max_completion_length 512 \ 
        --per_device_train_batch_size 1 \ 
        --gradient_accumulation_steps 2 \ 
        --logging_steps 1 \ 
        --bf16 \ 
        --report_to wandb \ 
        --gradient_checkpointing false \ 
        --attn_implementation flash_attention_2 \ 
        --max_pixels 401408 \ 
        --num_train_epochs 2 \ 
        --run_name Qwen2-VL-2B-GRPO-CLEVR-70k \ 
        --save_steps 100 \ 
        --save_only_model true \ 
        --num_generations 8
  6. Setup the R1-V environment

    main

    To set up the R1-V environment, create a new Conda environment with Python 3.11 and run the provided setup script. If you encounter issues, ensure your environment matches the specifications in ./src/requirements.txt.

    conda create -n r1-v python=3.11 
    conda activate r1-v
    
    bash setup.sh
  7. Generate QA pairs for reasoning datasets

    main

    To generate reasoning datasets, create scene description strings by combining object metadata (location, depth, etc.) using a template. For each scene, generate counting-relevant questions and include a mandatory question: How many items are there in the described scene? to ensure all objects are counted.

    Refer to generate_scene_qa_pairs.ipynb for the implementation details.

  8. Format QA pairs for R1 Model Queries

    main

    To use generated QA pairs with a Large Language Model (like DeepSeek-R1), you must format the query to include the scene description followed by the specific question. This provides the model with the necessary context to answer based on the text description rather than just the image.

    def format_query(qa_dict):
        query = "Answer the question according to scene description.\n\n"
        query += qa_dict['description']
        query += f"\nQuestion:\n{qa_dict['q']}"
        return query
  9. Convert raw reasoning data to HuggingFace format

    main

    Use the prepare_hf_data.py script to transform raw datasets containing GPT-4o reasoning responses into a structured HuggingFace Dataset format. The script parses responses into <think> and <answer> blocks, extracts images, and filters out invalid entries.

    Data Transformation Logic:

    • Problem Extraction: Extracts text before the <think> tag, removing Question: prefixes and Answer: suffixes.
    • Solution Construction: Combines reasoning steps into a single <think>...</think> block and appends the final answer within <answer>...</answer> tags.
    • Filtering: Automatically removes entries that contain:
      • Empty tags (e.g., <tag></tag>).
      • The string Answer: within the problem text.
      • Images with dimensions smaller than 28x28 pixels.
      • Missing images or null data.

    Output Schema: The resulting dataset contains the following fields:

    • image: datasets.Image()
    • problem: string (The extracted question)
    • solution: string (The formatted <think> and <answer> blocks)
    • original_question: string
    • original_answer: string
    # Example workflow logic used in the script
    raw_data_list = [
        "/path/to/reasoning_data_with_response_90k_verified",
    ]
    
    # 1. Load and process
    raw_data = concatenate_datasets([load_from_disk(path) for path in raw_data_list])
    processed_data = raw_data.map(process_raw_data, num_proc=128).shuffle(seed=42)
    
    # 2. Create Dataset with specific features
    features = datasets.Features({
        "image": datasets.Image(),
        "problem": datasets.Value("string"),
        "solution": datasets.Value("string"),
        "original_question": datasets.Value("string"),
        "original_answer": datasets.Value("string"),
    })
    
    # 3. Filter and Push
    ds = datasets.Dataset.from_dict(hf_dict, features=features)
    ds = ds.filter(
        lambda x: not has_empty_tags(x["solution"])
        and not has_answer_pattern(x["problem"])
        and has_valid_image_size(x)
        and x["image"] is not None,
        num_proc=128,
    )
    ds.push_to_hub("path/to/your/dataset")
  10. Run Supervised Fine-Tuning (SFT) via CLI

    main

    You can perform supervised fine-tuning for decoder language models using the src/open_r1/sft.py script via accelerate launch. This script supports vision-language models and requires specific arguments for the model path, dataset, and training hyperparameters.

    Example command for a single node with 8 x H100 GPUs:

    accelerate launch --config_file=configs/zero3.yaml src/open_r1/sft.py \
        --model_name_or_path Qwen/Qwen2.5-1.5B-Instruct \
        --dataset_name HuggingFaceH4/Bespoke-Stratos-17k \
        --learning_rate 2.0e-5 \
        --num_train_epochs 1 \
        --packing \
        --max_seq_length 4096 \
        --per_device_train_batch_size 4 \
        --gradient_accumulation_steps 4 \
        --gradient_checkpointing \
        --bf16 \
        --logging_steps 5 \
        --eval_strategy steps \
        --eval_steps 100 \
        --output_dir data/Qwen2.5-1.5B-Open-R1-Distill
    accelerate launch --config_file=configs/zero3.yaml src/open_r1/sft.py \
        --model_name_or_path Qwen/Qwen2.5-1.5B-Instruct \
        --dataset_name HuggingFaceH4/Bespoke-Stratos-17k \
        --learning_rate 2.0e-5 \
        --num_train_epochs 1 \
        --packing \
        --max_seq_length 4096 \
        --per_device_train_batch_size 4 \
        --gradient_accumulation_steps 4 \
        --gradient_checkpointing \
        --bf16 \
        --logging_steps 5 \
        --eval_strategy steps \
        --eval_steps 100 \
        --output_dir data/Qwen2.5-1.5B-Open-R1-Distill