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 ID 2610.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 给视频检索 / 摘要 / 交互式编辑。

解决什么问题

  1. 生成式模型的歧义性:传统 VQA 用 LLM 生成 "the woman in green eats pasta",出现 "A." / "Pasta." / "pasta." 等格式漂移;VideoJev 直接返回 answer_index=0,稳定可解析。
  2. 时序定位的离散性:把 grounding 当成"在 N 个候选窗口上做 N 次二分类",而不是回归一个连续区间,避免坐标对齐误差;阈值化即可切换 recall/precision。
  3. 统一一个模型覆盖两个任务:不需要两个独立 head / 模型,简化部署,适合做视频检索系统的统一打分模块。
  4. 小模型可负担: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 攻略规范工程三段式)

  1. Qwen3.5-4B / Qwen3.6-35B-A3B 版本号未独立核实 - 现象:README 的 base 模型名是 Qwen3.5-4B / Qwen3.6-35B-A3B,Qwen 官方仓库是否真用这套命名,本攻略 fetch 范围未覆盖(W41 P0 三轮核实要求)。 - 影响:若版本号实为笔误或私有名,AutoModel.from_pretrained(...) 会找不到权重。 - 修复:跑 demo 前先到 HF Qwen/Qwen3.5-4B / Qwen/Qwen3.6-35B-A3B 校验;找不到就改 models/Qwen3.5-4B 为本地实有 checkpoint 路径。

  2. 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 扩展要求。

  3. QA 用 256K 固定 context - 现象:--manifest 评估时 QA 上下文固定 256K,远超 4B 训练典型长度。 - 影响:长 video QA 时显存吃紧,单帧切片损失增加。 - 修复:对长视频做 chunking,分片评估再聚合。

  4. 默认 grounding 阈值 0.25 - 现象:低于 0.25 视为无匹配。 - 影响:低质量 query / 长视频可能漏召回。 - 修复:传 threshold=... 调到 0.1~0.15,或用 predict_features 拿概率自己定。

  5. 生成式不可用 - 现象:不输出自然语言,只输出概率与索引。 - 影响:需要可解释答案的下游场景不适配。 - 修复:搭配一个 LLM 把概率 + 候选重写成自然语言。

  6. 训练强依赖 XTuner 特定 commit + 编译扩展 - 现象:XTuner 用 76e705134521eff867b409f3b3451df1c4d8dd36;35B 还需要 grouped-GEMM/token-permutation 编译产物。 - 影响:换 XTuner 版本可能直接挂。 - 修复:锁 commit;编译扩展前确认 CUDA 12.8 + Triton 3.4。

  7. HF Demo 数据集 eating_spaghetti.mp4 锁定 revision - 现象:revision 7e2b9685bca592c3b929268f6fcf82c4ad74b267,不锁会拉到 main 头版。 - 影响:若数据集文件被替换,示例可能跑不通。 - 修复:保持 revision 不变。

  8. 评估脚本与训练脚本目录分叉 - 现象:35B 训练要走 scripts/train_qwen36.py + scripts/env_qwen36.sh,与 4B 的 scripts/train.py 不同。 - 影响:复用 config 时易踩坑。 - 修复:训练前先 data preparation 生成两份 configs,不要混用。

  9. 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 三轮核实待办)。