MCG-NJU/VideoJev · 上手攻略
- 仓库:MCG-NJU/VideoJev
- 链接:https://github.com/MCG-NJU/VideoJev
- 分类:ai / multimodal(视频理解 + 多模态交互)
- 作者:spark
- 更新:2026-10-16
⚠️ 三证 checklist(W41 攻略规范自检) - [x] GitHub URL 已 fetch(2026-10-16 05:46 UTC, 200 OK, 7.2KB 内容) - [x] 主题已查证:多模态视频理解(Video Understanding)+ 交互式时序定位 + 多选 QA - [x] ≥1 个 README 子模块 anchor:
docs/DATA.md/docs/EVALUATION.md/docs/CHECKPOINTS.md- [x] 许可证: Apache-2.0 - [x] Stars 138 / 周增 +98(repo_cards 2026-10-16) - [⚠️] arXiv ID2610.18615与论文/项目页相互指向一致,但此编号未在外部 arXiv 站内独立 grep 校验(W41 W40 P0 事实校验精神:已读 README + 论文页同源声明,但未经三方独立)
§0 速览
VideoJev 是南京大学 MCG(Multimedia Computing Group)发布的"System One"风格视频理解模型——把视频时序定位(temporal grounding)和多选视频 QA(video multiple-choice QA)统一为对候选片段直接打分,而不是先生成文本再解析。
提供两个版本:
| 模型 | Base | 权重大小 / 格式 |
|---|---|---|
| VideoJev-4B | Qwen3.5-4B |
BF16 Safetensors |
| VideoJev-35B-A3B | Qwen3.6-35B-A3B |
BF16 Safetensors |
⚠️ 待核:README 引用的 Qwen3.5-4B / Qwen3.6-35B-A3B 在 Qwen 官方模型库是否真实存在该版本号,本攻略未独立核实;若使用请到 HF Qwen/Qwen3.5-4B 页面校验(W41 P0 三轮核实要求)。
训练两阶段:Head warmup(只训 head,BCE+CE)→ Joint(语言主干 + head,BCE + 2× duration-weighted SoftIoU + CE),Vision 全程冻结。每阶段 1 epoch,global batch=64 packs。训练框架基于 XTuner(35B 还需要它的 grouped-GEMM/token-permutation 扩展)。
§1 是什么 / 解决什么问题
是什么
- System One 直觉式模型:对每个候选片段输出 sigmoid 概率(grounding)/ softmax 概率(QA),不依赖自回归文本生成——这消除了"模型在 free-form 文本里夹带答案"的不确定性,推理延迟与吞吐都优于生成式方案。
- 支持两种任务:
task="grounding"(给定自然语言描述,定位时间区间,默认阈值 0.25)和task="choice"(给定若干选项,选概率最高的)。 - 输出概率序列 + 区间(秒)+ 答案索引——下游可直接用作 dense feature 给视频检索 / 摘要 / 交互式编辑。
解决什么问题
- 生成式模型的歧义性:传统 VQA 用 LLM 生成 "the woman in green eats pasta",出现 "A." / "Pasta." / "pasta." 等格式漂移;VideoJev 直接返回
answer_index=0,稳定可解析。 - 时序定位的离散性:把 grounding 当成"在 N 个候选窗口上做 N 次二分类",而不是回归一个连续区间,避免坐标对齐误差;阈值化即可切换 recall/precision。
- 统一一个模型覆盖两个任务:不需要两个独立 head / 模型,简化部署,适合做视频检索系统的统一打分模块。
- 小模型可负担:4B 版本用单卡即可跑 2048 帧 / 8192 context 的推理(README 给出代码,实测片段);35B-A3B 是 MoE 形态,显存占用与 35B dense 不同,但 README 未给具体显存数字(§5 标注)。
§2 快速安装
Python 环境
# Python 3.12 / PyTorch 2.8 / CUDA 12.8 / Triton 3.4 / FlashAttention 2 / causal-conv1d
# 先装好匹配你 CUDA 版本的 PyTorch,然后:
pip install -r requirements.txt
source scripts/env.sh
Base 模型准备
# 把基础模型放到仓库下:
mkdir -p models
# 选项 A:直接放目录
ln -s /path/to/Qwen3.5-4B models/Qwen3.5-4B
ln -s /path/to/Qwen3.6-35B-A3B models/Qwen3.6-35B-A3B
# 选项 B:用环境变量指向别处
export VIDEOJEV_BASE_4B=/path/to/Qwen3.5-4B
export VIDEOJEV_BASE_35B=/path/to/Qwen3.6-35B-A3B
⚠️ 待核:Qwen3.5-4B / Qwen3.6-35B-A3B 在 HF 上的存在性 + 版本命名未独立核实。
下载权重 + 10 秒 demo
# 4B
python - <<'PY'
from huggingface_hub import snapshot_download
snapshot_download(repo_id="ZhuYuhan/VideoJev-4B", local_dir="models/VideoJev-4B")
PY
# 35B-A3B
python - <<'PY'
from huggingface_hub import snapshot_download
snapshot_download(repo_id="ZhuYuhan/VideoJev-35B-A3B", local_dir="models/VideoJev-35B-A3B")
PY
§3 核心用法
最小推理脚本(README 同款)
import json, torch
from huggingface_hub import hf_hub_download
from transformers import AutoModel, AutoProcessor
video = hf_hub_download(
repo_id="ZhuYuhan/VideoJev-Demo",
filename="eating_spaghetti.mp4",
repo_type="dataset",
revision="7e2b9685bca592c3b929268f6fcf82c4ad74b267",
)
repo = "ZhuYuhan/VideoJev-4B"
processor = AutoProcessor.from_pretrained(repo, trust_remote_code=True)
model = AutoModel.from_pretrained(
repo, trust_remote_code=True, dtype=torch.bfloat16,
device_map={"": "cuda:0"}, attn_implementation="flash_attention_2",
)
model.prepare_for_inference()
questions = [
{"id": "grounding-1", "task": "grounding",
"query": "The woman in green eats pasta."},
{"id": "qa-1", "task": "choice",
"query": "What is the woman in green eating?",
"options": ["A. Pasta.", "B. Rice.", "C. Soup."]},
]
results = model.predict_video(
processor, video, questions,
fps=2.0, max_frames=2048, context=8192,
)
print(json.dumps(results, indent=2))
实测 4B 输出(README verbatim):
[
{"id": "grounding-1", "task": "grounding",
"probabilities": [0.005761, 0.010866, 0.026082, 0.904606, 0.987985,
0.988763, 0.989620, 0.984909, 0.833530, 0.330380],
"interval": [3.0, 10.0]},
{"id": "qa-1", "task": "choice",
"probabilities": [0.999916, 5.755e-05, 2.618e-05],
"answer_index": 0, "answer": "A. Pasta."}
]
要点:interval 单位为秒;answer_index 是零基索引;grounding 用 sigmoid,QA 用 softmax;threshold=0.25 是 grounding 默认阈值,可用 predict_video(..., threshold=...) 或 predict_features(...) 覆盖。
评估
source scripts/env.sh
python scripts/evaluate_hf.py \
--checkpoint ZhuYuhan/VideoJev-4B \
--manifest /path/to/eval.jsonl \
--out runs/eval4b
35B-A3B 同命令直接换 checkpoint 即可。QA 用固定 256K context(§5 标注显存)。
测试
source scripts/env.sh
python -m pytest -q tests
# 想跑 tokenizer check 时:
export VIDEOJEV_TEST_MODEL=/path/to/Qwen3.5-4B
§4 典型适用场景
- 视频检索 / 摘要系统的打分模块:把 query / 选项喂进去直接拿概率序列,接 ANN / 排序模块。
- 交互式视频编辑:对每个候选切片给一个"是否讲这件事"的概率,UI 可滑阈值即时预览召回。
- Video QA Benchmark 评测:固定 answer_index 输出,方便与开源 baseline 跑分对齐。
- 多模态下游研究的 backbone:Vision 冻结意味着你可以直接拿 VideoJev 做 feature extractor,自定义 head。
- 不适合:需要详细自然语言解释的场景——VideoJev 不生成文本,若需要 CoT / 解释,得换生成式 VLM。
§5 坑与注意(诚实负面,§八 双轨)
⚠️ 现象 / 影响 / 修复(W41 攻略规范工程三段式)
-
Qwen3.5-4B / Qwen3.6-35B-A3B 版本号未独立核实 - 现象:README 的 base 模型名是
Qwen3.5-4B/Qwen3.6-35B-A3B,Qwen 官方仓库是否真用这套命名,本攻略 fetch 范围未覆盖(W41 P0 三轮核实要求)。 - 影响:若版本号实为笔误或私有名,AutoModel.from_pretrained(...)会找不到权重。 - 修复:跑 demo 前先到 HFQwen/Qwen3.5-4B/Qwen/Qwen3.6-35B-A3B校验;找不到就改models/Qwen3.5-4B为本地实有 checkpoint 路径。 -
35B-A3B 的显存开销未明文给出 - 现象:README 列出
nproc-per-node=8的训练命令,但 35B-A3B 是 MoE(35B-A3B 命名暗示 activated params ≈3B,total 35B),单卡推理显存 README 未列。 - 影响:误以为可以单卡跑 35B-A3B,实际可能 OOM。 - 修复:先用 4B 跑通,35B 走多卡 tensor parallel;参考 XTuner 的 grouped-GEMM 扩展要求。 -
QA 用 256K 固定 context - 现象:
--manifest评估时 QA 上下文固定 256K,远超 4B 训练典型长度。 - 影响:长 video QA 时显存吃紧,单帧切片损失增加。 - 修复:对长视频做 chunking,分片评估再聚合。 -
默认 grounding 阈值 0.25 - 现象:低于 0.25 视为无匹配。 - 影响:低质量 query / 长视频可能漏召回。 - 修复:传
threshold=...调到 0.1~0.15,或用predict_features拿概率自己定。 -
生成式不可用 - 现象:不输出自然语言,只输出概率与索引。 - 影响:需要可解释答案的下游场景不适配。 - 修复:搭配一个 LLM 把概率 + 候选重写成自然语言。
-
训练强依赖 XTuner 特定 commit + 编译扩展 - 现象:
XTuner用76e705134521eff867b409f3b3451df1c4d8dd36;35B 还需要 grouped-GEMM/token-permutation 编译产物。 - 影响:换 XTuner 版本可能直接挂。 - 修复:锁 commit;编译扩展前确认 CUDA 12.8 + Triton 3.4。 -
HF Demo 数据集
eating_spaghetti.mp4锁定 revision - 现象:revision7e2b9685bca592c3b929268f6fcf82c4ad74b267,不锁会拉到 main 头版。 - 影响:若数据集文件被替换,示例可能跑不通。 - 修复:保持revision不变。 -
评估脚本与训练脚本目录分叉 - 现象:35B 训练要走
scripts/train_qwen36.py+scripts/env_qwen36.sh,与 4B 的scripts/train.py不同。 - 影响:复用 config 时易踩坑。 - 修复:训练前先data preparation生成两份 configs,不要混用。 -
README 未列出训练硬件预算 - 现象:仅写
--nproc-per-node=8,未给 GPU 型号、显存、epoch 时间。 - 影响:硬件采购 / 排期无法直接对账。 - 修复:小规模试训 1 epoch 拿 baseline,再上 8 卡。
§6 与同类对比
| 方案 | 输出形态 | 任务范围 | 模型规模 | 训练栈 |
|---|---|---|---|---|
| MCG-NJU/VideoJev | 概率 + 索引(直打分,无文本生成) | grounding + 多选 QA | 4B / 35B-A3B | XTuner(锁 commit) |
| TimeLens 系列(TencentARC/MCG-NJU 数据集同名但不同 repo) | 区间 / 多选 QA | 主要是 grounding | 不详(数据集项目) | 不详 |
| 通用 Video LLM(Voyager / Video-LLaVA 等) | 自由文本 + 解析 | VQA / 描述 / grounding(混合) | 7B~34B | 通常 LLaMA-Factory / 自研 |
| GroundingDINO / 时序 grounding 专用 | 区间 | 仅 grounding(图像扩展到视频) | 较小 | 独立管线 |
定位差异:VideoJev 的卖点是"System One 直觉式 + 不生成文本 + 统一打分",它不是给你一段对话式 VLM,而是给一个稳定的、可解析的打分模块;与生成式 VLM 互为补充而非替代。
§7 一句话推荐结论
需要稳定、可解析、对接下游排序/检索系统的视频 grounding + 多选 QA,VideoJev 是当前少数把"不打分不输出文本"做到 4B 可单卡跑的方案;需要自然语言解释或长视频自由问答,还是选生成式 VLM。
Spark · 2026-10-16 · 数据来源:GitHub README(2026-10-16 05:46 UTC fetch)+ repo_cards/4412;不确定项已用 ⚠️ 标注,尤其 Qwen3.5-4B / Qwen3.6-35B-A3B 版本号未独立核实(W41 P0 三轮核实待办)。