Evaluate with VLMEvalKit#
VLMEvalKit can score the
OpenAI-compatible server on any of its image, video, and text benchmarks. In
API mode it downloads each dataset, sends every sample to
/v1/chat/completions, and scores the answers. No conversion scripts are
needed.
Serve the Model#
Use the recommended sequence length. The image-token flags are the recommended image budget for this model. Raise a limit when a prompt or image does not fit:
edgellm serve Qwen/Qwen3.5-4B \
--max-input-len 32768 \
--max-kv-cache-capacity 40960 \
--max-image-tokens 3920 \
--max-image-tokens-per-image 3920 \
--served-model-name qwen35-local \
--port 8000
Install VLMEvalKit#
API mode needs VLMEvalKit main from April 2026 or later
(open-compass/VLMEvalKit#1499).
This guide was tested at commit
54a063c.
git clone https://github.com/open-compass/VLMEvalKit.git
cd VLMEvalKit
pip install -r requirements.txt rouge-score
pip install --no-deps -e .
Run Benchmarks#
Pass one or more dataset names to --data:
python run.py --api-mode \
--base-url http://127.0.0.1:8000/v1 \
--model qwen35-local \
--key local \
--data MMStar HallusionBench OCRBench \
--judge qwen35-local \
--judge-base-url http://127.0.0.1:8000/v1 \
--judge-key local \
--api-nproc 4 \
--max-tokens 1024 \
--temperature 0 \
--work-dir outputs
--modelmust match--served-model-name.--keyis sent as the bearer token. Any value works unless the server sets--api-key.The
--judge*options reuse the same server to read the chosen option out of free-form answers. Any OpenAI-compatible model works as the judge.Keep
--max-tokensbelow the server’s KV-cache capacity. VLMEvalKit’s default is 32768.Keep
--api-nprocat or below the number of requests the server can handle at once.Do not pass
presence_penaltyorfrequency_penaltythrough--extra-body. The server accepts only0.
Each dataset is downloaded on first use to $LMUData (default ~/LMUData),
with an MD5 check. Video datasets are downloaded to the Hugging Face cache.
Scores are written to outputs/qwen35-local/<run id>/. Rerun with --reuse
to resume an interrupted run, or with --mode eval --reuse to rescore
existing predictions.
Choose Datasets#
List every registered dataset name with:
vlmutil dlist all
The dataset type sets how answers are scored:
Type |
Examples |
Scoring |
|---|---|---|
Multiple choice |
|
Rule match first, then the judge |
Yes/no |
|
Rule match first, then the judge |
Rule-scored VQA |
|
Built-in rules; no judge |
Judge-scored |
|
LLM judge |
Without --judge, multiple-choice and yes/no datasets use gpt-4o-mini. If
that is unreachable, they fall back to rule matching only, which is the same
as --judge exact_matching. Rule matching counts an answer as wrong when it
cannot find a single option in the reply. This undercounts models that
answer in prose.
Video datasets use frame-count or frame-rate variants, such as
Video-MME_16frame and MVBench_1fps. VLMEvalKit sends the sampled frames as
images, so size --max-image-tokens for all frames in one request.
To run your own data, save it as ~/LMUData/<name>.tsv with index,
question, and image (base64) columns, then pass --data <name>. Files with
A, B, … and answer columns are scored as multiple choice. Other files
produce predictions only.
Score MMMU Offline#
Without a server, VLMEvalKit can rescore MMMU predictions from llm_inference.
Run the dataset commands from examples/accuracy.
Qwen3-VL’s VLMEvalKit setup uses 980–3920 tokens per image and up to 5 images
per MMMU input, so build with maxImageTokens = 3920 × 5 = 19600:
python3 scripts/prepare_dataset.py \
--dataset MMMU_VLMEvalkit \
--output_dir /path/to/datasets/mmmu_vlmevalkit \
--top_p 0.8 --top_k 20 --temperature 0.7
./build/bin/visual_build \
--onnxDir /path/to/visual/onnx/model/ \
--engineDir /path/to/visual/engine/ \
--minImageTokens 980 \
--maxImageTokens 19600 \
--maxImageTokensPerImage 3920
./build/bin/llm_build \
--onnxDir /path/to/text/onnx/model/ \
--engineDir /path/to/text/engine/ \
--maxInputLen 21000 \
--maxKVCacheCapacity 30000 \
--maxBatchSize 1 \
--vlm \
--minImageTokens 980 \
--maxImageTokens 19600
./build/bin/llm_inference \
--engineDir /path/to/text/engine/ \
--multimodalEngineDir /path/to/visual/engine/ \
--inputFile /path/to/datasets/mmmu_vlmevalkit/mmmu_dataset.json \
--outputFile /path/to/outputs/mmmu_predictions.json \
--batchSize 1 \
--maxGenerateLength 8192
Convert the predictions to VLMEvalKit’s format and score them:
wget https://opencompass.openxlab.space/utils/VLMEval/MMMU_DEV_VAL.tsv
python3 scripts/prepare_mmmu_vlmevalkit.py \
--tsv_file MMMU_DEV_VAL.tsv \
--json_file /path/to/outputs/mmmu_predictions.json \
--output_file /path/to/outputs/${Model}_MMMU_DEV_VAL.xlsx
cd /path/to/VLMEvalKit
python3 run.py --data MMMU_DEV_VAL --model ${Model} \
--work-dir /path/to/outputs --mode eval --reuse