๐ NEO Series: Native Vision-Language Models
May 27, 2026 ยท View on GitHub
Welcome to the NEO Training Framework - a comprehensive toolkit for training state-of-the-art vision-language models.
๐ Quick Start Guide
To use this framework, follow these two essential steps:
- ๐ Customize Your Dataset: Prepare your data and implement the configuration
- โ๏ธ Modify Training Scripts: Adjust parameters to match your training requirements
๐ Contents
๐ง Installation
Environment Setup
git clone https://github.com/EvolvingLMMs-Lab/NEO.git
cd NEO/VLMTrainKit
conda create -n neo python=3.12 -y
conda activate neo
pip install --upgrade pip
pip install .
Model Preparation
๐ Note: Download the required Qwen3 base models:
| Model | Link |
|---|---|
| Qwen3-1.7B-Base | ๐ค Hugging Face |
| Qwen3-8B-Base | ๐ค Hugging Face |
๐ Repository Structure
๐๏ธ neo/train/
Training-related modules:
trainer.py: Main trainer (extended from HuggingFace Trainer)argument.py: Dataclasses for model, data, and training arguments
๐ neo/data/
Data processing modules:
__init__.py: Dataset configuration registrydata_processor.py: Data processing pipeline for NEO models
๐ Custom Dataset Configuration
๐ JSON Data Structure
Your dataset should follow this structure:
Required Fields:
| Field | Description | Required |
|---|---|---|
image | Path to the media file | โ Yes |
conversations | List of question-answer pairs | โ Yes |
Media Tags:
- Use
<image>tag in prompts for image understanding tasks - Each tag must correspond to exactly one media file
๐ก Example Instances:
Single Image Example:
{
"image": "demo.jpg",
"width": 335,
"height": 500,
"conversations": [
{
"from": "human",
"value": "<image>\nSummarize the content of this picture."
},
{
"from": "gpt",
"value": "A wooden chair in the living room"
}
]
}
Packed Data Example:
[
{
"image": "images/001.jpg",
"conversations": [
{
"from": "human",
"value": "<image>\nWhat's the main object in this picture?"
},
{
"from": "gpt",
"value": "A red apple on a wooden table"
}
]
},
{
"image": "images/002.jpg",
"conversations": [
{
"from": "human",
"value": "<image>\nWhat's the main object in this picture?"
},
{
"from": "gpt",
"value": "A green orange on a plastic table"
}
]
}
]
โ๏ธ Dataset Configuration for Training
Step 1: Define Your Dataset
Create a dataset dictionary in neo/data/__init__.py:
DATASET_NAME = {
"annotation_path": "/path/to/annotations.json",
"data_path": "/path/to/image/data", # Can be empty if paths are in annotations
}
Step 2: Register Your Dataset
Add your dataset to the data_dict:
data_dict = {
"your_dataset_name": DATASET_NAME,
# ... other datasets
}
Step 3: Configure Sampling Rate (Optional)
Control the amount of data used by appending %X to the dataset name:
| Syntax | Effect |
|---|---|
"dataset_name%50" | Use 50% of the data |
"dataset_name%20" | Use 20% of the data |
"dataset_name" | Use 100% of the data (default) |
Usage Example:
dataset_names = ["my_dataset%50"] # Will use 50% of your dataset
configs = data_list(dataset_names)
๐ Important Notes
- โ Annotation Path: Must point to a JSON or JSONL file with dataset annotations
- โ Data Path: Can be empty if image paths in annotations are absolute
- โ Sampling Rates: Applied per-dataset when using multiple datasets
- โ
Format Compliance:
- Each
<image>tag must correspond to exactly one image file - Each
<video>tag must correspond to exactly one video file
- Each
๐ฏ Usage
๐พ Packed Data Training for Memory Efficiency
NEO adopts a packed data training strategy to maximize GPU memory utilization. This approach concatenates multiple samples into a single sequence, significantly improving training efficiency.
โก Key Considerations:
| Aspect | Description |
|---|---|
| Flexible Batch Size | Can be set to any value, but must align with dataset characteristics |
| Length Control | Total packed length must not exceed max_seq_length |
| Global Batch Size | Total samples processed across all GPUs in one optimizer step |
๐ Configuration Guidelines:
- Monitor your dataset's average sample length
- Calculate safe batch size:
batch_size ร average_sample_length โค max_seq_length - Adjust based on GPU memory capacity and model size
๐ก Example Calculation:
Given:
- max_seq_length = 18,432
- average_sample_length โ 3,000 tokens
Recommended:
- batch_size = 6 (safe: 6 ร 3,000 = 18,000 < 18,432)
โ ๏ธ If samples vary greatly in length, reduce batch_size to prevent overflow.
๐ง Training Script Configuration
#!/bin/bash
#==============================================================================
# ๐ Distributed Training Configuration
#==============================================================================
MASTER_ADDR=${MASTER_ADDR:-"127.0.0.1"}
MASTER_PORT=${MASTER_PORT:-$(shuf -i 20001-29999 -n 1)}
NNODES=${WORLD_SIZE:-1}
#==============================================================================
# โก DeepSpeed Configuration
#==============================================================================
deepspeed=./scripts/zero3.json
#==============================================================================
# ๐ค Model Configuration
# ๐ For detailed logic, refer to: neo/model/build.py build_model function
#==============================================================================
mllm="" # ๐ง Path to pre-trained NEO model for SFT (Supervised Fine-Tuning)
llm="" # ๐๏ธ Path to the base LLM model for training NEO from scratch
tokenizer="" # ๐ Path to the tokenizer
#==============================================================================
# ๐ฏ Training Hyperparameters
#==============================================================================
lr=2e-4
# ๐ฅ๐ฅ๐ฅ Global Batch Size Control
# Global Batch Size: The total number of samples processed across all GPUs in the entire
# training cluster during a single optimizer step (parameter update).
# Formula: Global batch size = batch_size ร grad_accum_steps ร num_gpus
# When data_flatten is enabled, batch_size also controls the length of flattened data
batch_size=1 # ๐ฆ Per-device batch size for controlling global batch size and flatten data length
grad_accum_steps=1 # ๐ Gradient accumulation steps for controlling global batch size
#==============================================================================
# ๐ Training Entry Point
#==============================================================================
entry_file=neo/train/train.py
#==============================================================================
# ๐ Dataset Configuration
#==============================================================================
datasets="" # ๐ Replace with your dataset names (e.g., "dataset1,dataset2%50")
#==============================================================================
# ๐พ Output Configuration
#==============================================================================
run_name="neo-baseline"
output_dir=./output
#==============================================================================
# โ๏ธ Training Arguments
#==============================================================================
args="
--deepspeed ${deepspeed} \
--model_name_or_path "${mllm}" \
--dataset_use ${datasets} \
--data_flatten True \
--dtype bfloat16 \
--output_dir ${output_dir} \
--extra_num_layers 12 \ # ๐งฑ Number of pre-buffer layers
--num_hidden_layers 28 \ # ๐๏ธ Total number of layers in the model
--train_buffer \ # ๐ Whether to train only the prebuffer layers
--num_train_epochs 1 \
--per_device_train_batch_size ${batch_size} \
--per_device_eval_batch_size $((batch_size*2)) \
--gradient_accumulation_steps ${grad_accum_steps} \
--max_pixels 262144 \ # ๐ผ๏ธ Maximum pixels for image processing
--min_pixels 12544 \ # ๐ผ๏ธ Minimum pixels for image processing
--eval_strategy "no" \
--save_strategy "steps" \
--save_steps 1000 \
--save_total_limit 1 \
--learning_rate ${lr} \
--weight_decay 0.0 \
--warmup_steps 1000 \ # ๐ฅ Learning rate warmup steps
--max_grad_norm 1 \
--logging_steps 1 \
--max_seq_length 18432 \ # โ๏ธ Maximum length after data flattening; sequences exceeding this will be truncated (see FlattenedDataCollatorForSupervisedDataset in data_processor.py)
--model_max_length 18432 \
--gradient_checkpointing True \
--dataloader_num_workers 4 \
--run_name ${run_name} \
--report_to tensorboard" # ๐ Logging to TensorBoard
#==============================================================================
# ๐ง Environment Setup
#==============================================================================
export PYTHONPATH="${PYTHONPATH}:$(pwd)"
#==============================================================================
# ๐ฌ Launch Training
#==============================================================================
torchrun --nproc_per_node=2 \
--master_addr=${MASTER_ADDR} \
--master_port=${MASTER_PORT} \
${entry_file} ${args}
๐ Key Training Parameters Explained
๐งฑ Model Architecture
extra_num_layers: Number of pre-buffer layers (default: 12)num_hidden_layers: Total layers in the model (default: 28)train_buffer: Whether to train only the pre-buffer layers
๐พ Batch Size & Memory
per_device_train_batch_size: Samples per GPU per forward passgradient_accumulation_steps: Accumulate gradients over N steps- Global Batch Size Formula:
batch_size ร grad_accum_steps ร num_gpus
๐ Sequence Length
max_seq_length: Maximum length after data packing (default: 18432)model_max_length: Model's maximum context length (should match above)
๐ผ๏ธ Image Processing
max_pixels: Maximum pixels for image processing (default: 262144)min_pixels: Minimum pixels for image processing (default: 12544)
๐ Learning Parameters
learning_rate: Optimizer learning rate (default: 2e-4)warmup_steps: Learning rate warmup steps (default: 1000)max_grad_norm: Gradient clipping threshold (default: 1)
๐ You're All Set!
Start your training journey with NEO and build powerful vision-language models!
For issues or questions, please visit our GitHub repository.