EVA: Efficient Reinforcement Learning for End-to-End Video Agent

Paper: arXiv:2603.22918 Code: wangruohui/EfficientVideoAgent Code reference: main @ 758ad8d3 (2026-04-03)

1. Motivation (研究动机)

长视频理解的核心矛盾不是“模型是否能看视频”,而是“模型应不应该、何时、以多大粒度去看视频”。当前 MLLM 往往把视频当作被动输入:要么均匀采样固定帧数,要么把长视频压成大量视觉 token 后交给模型推理。这种 perception-first 路线在短视频上可行,但面对数千秒视频时会同时遇到三个问题:关键帧可能被均匀采样错过;大量无关帧占满上下文;噪声帧会把推理锚定到错误线索上。

已有 video-agent 方法虽然引入了 frame selection 等外部工具,但通常仍然先给模型一批均匀采样帧,再让 agent 调工具补充信息;这会把大量上下文预算花在初始视觉输入上,并且 tool workflow 多由人工规则固定。EVA 试图解决的是更具体的问题:训练一个 end-to-end video agent,让它在没有初始视觉帧的情况下,仅根据问题与视频长度先规划观察策略,然后通过多轮 tool call 自主决定看哪个时间段、采多少帧、用多高分辨率。

这个问题值得研究,因为长视频 QA、事件追踪、因果推理和幻觉检测都不一定需要“看完整视频”,但需要模型知道如何主动获取证据。若 agent 能学会 planning-before-perception,它就可以用较少视觉 token 覆盖关键证据,并把计算预算从无差别 dense sampling 转向 query-driven active perception。

2. Idea (核心思想)

EVA 的核心 insight 是:长视频 agent 不应先被动接收一批帧再推理,而应先形成文本计划,再把视觉观察当作可控动作来执行;动作空间同时包含时间窗口和空间/帧数粒度。论文的主要创新不是单个新 reward,而是把 SFT cold start → KTO 纠错 → GRPO 在线优化 串成一个可训练的 agentic video-understanding curriculum,让模型逐步从“会按格式调工具”变成“会主动规划视觉 token”。

与 FrameThinker、VideoAgent 等 adaptive agent 相比,EVA 更强调 end-to-end policy learning:传统 agent 往往依赖固定 workflow 或只选择时间段;EVA 的 policy 直接输出 start_time/end_time/nframes/resize,并通过多轮 summary-plan-action-reflection 循环决定是否继续观察或提交答案。

Figure 1 解读:图中对比了三类长视频理解路径。Uniform sampling 把长视频压成固定帧,容易错过关键片段;traditional agentic method 先消耗一批均匀帧,再用工具补救;EVA 则从 query 出发先计划,再按需调用 frame-select tool,因此能在 6600 秒以上的视频中把视觉 token 集中到与问题相关的片段。

3. Method (方法)

3.1 Overall framework:把主动视频理解建模成 MDP

EVA 将 active video understanding 建模为 MDP。第 轮的 belief state 为: 其中 是用户问题, 是文本与帧交织的历史, 是工具调用已经返回的视觉证据。策略写作 。初始状态 中模型只看到 query 和 video length,不直接看到视频帧;这样做是为了强迫模型先规划,而不是被初始均匀采样帧误导。

EVA 的核心 action 是 frame-selection tool call,包含四个参数:

参数含义为什么重要
start_timetemporal window 起点决定从哪段视频开始找证据
end_timetemporal window 终点控制观察范围,避免无关片段
nframes该窗口内采样帧数高帧数更适合动作/事件变化
resize空间下采样比例高分辨率更适合文字、物体细节

直觉上,EVA 的动作空间比“选一个时间段”更大:它不仅选择看哪里,还选择“看多密”和“看多清”。如果没有 nframesresize,agent 很难学到不同轮次的预算分配;如果一开始就给全局均匀帧,模型又容易把推理建立在噪声帧上。

3.2 Training pipeline:SFT cold start → KTO → Data-Enhanced GRPO

Figure 2 解读:EVA 的训练分三步。第一步用 synthetic SFT 数据教会模型 summary、planning、action、reflection 的工具调用模式;第二步用 KTO 让模型偏好成功轨迹、拒绝典型失败策略;第三步用 GRPO 在线采样 rollouts,并把当前 policy 的失败案例反馈给 teacher MLLM 生成新的 open-ended QA,形成 data-enhanced multi-stage GRPO。

SFT cold start data

SFT 数据由 Qwen2.5-VL-72B 作为 teacher MLLM 生成,源视频 QA 来自 LLaVA-Video(短视频)和 CG-Bench(长视频)。为了提高策略多样性,teacher prompt 包括三类信息:Past Success Experiences、Diverse Workflow Hints、Reflective Thinking Prompts。每条 SFT 轨迹遵循 Summary + Planning + Action + Reflection:Summary 描述返回帧内容;Planning 估计候选动作的成本与收益;Action 产生 tool call;Reflection 判断当前证据是否足够回答,不足则继续调用工具。

KTO preference correction

SFT 能学到格式和基本推理,但容易出现三类失败:没有足够视觉证据就猜答案;短时间窗口内采太多帧;长时间窗口内采太少帧。EVA 用 KTO 而非 DPO,是因为 DPO 需要 pairwise preference 且假设对话轮次对齐,这会截断 multi-turn 策略;KTO 只需要单样本 chosen/rejected 标签,更适合多轮 agent 轨迹。Rejected 来自 SFT data construction pipeline 中的错误轨迹,尤其是 LLM-as-judge 判定为“视觉证据不足却提交答案”的 guessing case;chosen 则是重新采样的高质量成功轨迹。

Data-Enhanced GRPO

普通 GRPO 在固定 query-video 数据上做 self-play,失败多样性受限。EVA 的改动是:先从 KTO-trained model 收集失败案例;若若干 GRPO steps 后仍出现新失败,则把这些失败作为 in-context examples 交给 teacher MLLM,让它在 HD-VILA 未见视频上生成新的 open-ended QA,再用增强后的数据继续训练。作者强调 open-ended 形式比直接生成 MCQ 更不容易被选项线索 reward hacking,也更容易由 teacher 高效生成。

Figure 3 解读:该图展示 EVA-SFT、EVA-KTO、EVA-RL 的数据构成。论文正文报告 EVA-SFT 约 10k samples,EVA-KTO 约 11k chosen/rejected trajectories,EVA-RL 包含 9.6k open-ended video QA 和 1.1k multiple-choice questions;这些数据分别支撑格式冷启动、偏好纠错和在线 RL。

3.3 Cold-start 数据生成中的 multi-agent loop

Figure 8 解读:appendix 中的 cold-start pipeline 进一步说明了 SFT 数据如何生成。Executor agent 读取 query 和当前上下文,提出候选 tool call 并判断是否已有足够信息;Reflective Thinker 检查参数是否合理;成功轨迹进入 Experience Bank,后续按 query similarity 检索给 Executor 作为经验提示。这相当于在训练数据阶段就把“先想清楚再看视频”的行为模板显式写进轨迹。

3.4 GRPO objective 与 Reward Shaping

EVA 使用 KL-regularized GRPO,reference policy 由 SFT+KTO 初始化。论文写出的优化目标为: $ \max_\theta; \mathbb{E}{\tau\sim\pi\theta}[R(\tau)]

  • \lambda,\mathbb{E}{(s,a)\sim\pi\theta} \left[\mathrm{KL}\left(\pi_\theta(\cdot\mid s),|,\pi_\mathrm{ref}(\cdot\mid s)\right)\right]. R(\tau)=w_\mathrm{acc} r_\mathrm{acc} + w_\mathrm{fmt} r_\mathrm{fmt}. r_\mathrm{acc}= \begin{cases} r_\mathrm{csv}, & \text{if multiple-choice,}\ r_\mathrm{rouge}, & \text{if open-ended.} \end{cases} r_\mathrm{csv}=1 r_\mathrm{rouge}=\frac{1}{3}(R_1+R_2+R_L)\in[0,1]. 0.050.200.25$,因此不会让模型通过“格式正确但乱猜”拿到高回报。

3.5 Why planning-before-perception works

Figure 7 解读:appendix 把 EVA 与 perception-first pipeline 放在一起对比。perception-first 先看到一堆均匀帧,可能被无关动作或 sampling bias 误导;EVA 先产生文本计划,再带着目标观察视频,相当于把视觉证据获取变成 hypothesis-driven search,而不是被动帧消费。

Figure 9 解读:四个子图显示 EVA 在不同轮次如何分配计算。第一轮通常使用更多 frames 和更长 time range 做粗扫;第二轮起 nframes 和 time range 明显下降,而 resize 上升,说明 agent 学到先用低成本概览定位,再 zoom in 获取细节。这正是 planning-before-perception 想实现的预算调度。

Figure 4 解读:该图把不同训练阶段在 benchmarks 上的 visual tokens 与 rounds 放在一起。SFT 阶段主要学会格式,因此仍会消耗较多帧和轮次;KTO 降低无效探索;GRPO 进一步减少每轮视觉 token,但允许更有目的的多轮推理。这个趋势支持“训练 curriculum 改变 exploration strategy”的论点。

3.6 Released code inspection 与 paper-code gap

论文公式与 released code 实现差异:官方 repo wangruohui/EfficientVideoAgent 当前是 evaluation code + model/checkpoint reference results,并未发布 SFT/KTO/GRPO 训练脚本、reward 代码或 launch configs。因此,训练超参数只能从论文 Experiment Settings 读取;source-code-grounded pseudocode 只能覆盖 evaluation-time rollout、tool parsing、visual-token cap 和 frame extraction。另一个差异是 released eval-eva.py 显式加入每次 tool call 的 token fallback:默认 --max-visual-tokens=12000--maxp=720--factor=28--fallback=True,这些工程约束没有出现在论文的 GRPO objective 中。官方 README 的 reference results 也与论文表格存在少量四舍五入/版本差异,例如 README 报告 LSDBench 49.3113914 tokens,而论文 Table 1 报告 EVA 51.010.3k visual tokens;本笔记实验结论以论文表格为主,代码复现信息以 repo README/results 为准。

Pseudocode 1:evaluation-time EVA rollout(基于 eval-eva.py::single

async def run_eva_rollout(model, tokenizer, item, dataset_cfg, max_turns=6):
    video = os.path.join(dataset_cfg["video_root"], item["videos"][0])
    video_length, resolution = await ffprobe_video_stream_meta(video)
    messages = build_message_from_rl(item["prompt"], video_length, resolution)
    estimated_visual_tokens = 0
 
    for turn in range(max_turns):
        response = await aclient.chat.completions.create(
            model=model,
            messages=messages,
            temperature=0.0,
            max_tokens=2048,
            timeout=9999,
        )
        assistant_text = response.choices[0].message.content
        messages.append({"role": "assistant", "content": assistant_text})
 
        answer = extract_answer_anyway(assistant_text)
        if answer:
            return {"answer": answer, "stop_reason": "answer_found"}
 
        tool_jsons = parse_frame_select_calls(assistant_text)
        if not tool_jsons:
            return {"answer": "", "stop_reason": "no_valid_tool_call"}
 
        frame_paths, timestamps = [], []
        for args in tool_jsons:
            args = cap_visual_budget(args, resolution, max_visual_tokens=12000, maxp=720)
            imgs, secs = await call_frame_select(video, args, fallback=True)
            frame_paths.extend(imgs)
            timestamps.extend(secs)
            estimated_visual_tokens += estimate_tokens(args, resolution)
 
        messages.append(build_tool_response(frame_paths, timestamps, item["prompt"]))
 
    return {"answer": "", "stop_reason": "max_turns_exceeded"}

Pseudocode 2:visual-token fallback(基于 eval-eva.py lines 253–360)

def cap_visual_budget(args, resolution, max_visual_tokens=12000, maxp=720):
    width, height = map(int, resolution.split("x"))
    video_p = min(width, height)
    nframes = int(args["nframes"])
    resize = 1.0 if args.get("resize") is None else float(args.get("resize", 1.0))
 
    def estimated_tokens(nframes, resize):
        h_units = max(1, round((height * resize) / 28))
        w_units = max(1, round((width * resize) / 28))
        return int(nframes) * h_units * w_units
 
    current = estimated_tokens(nframes, resize)
    if current > max_visual_tokens:
        resize = min(resize, min(1.0, maxp / video_p))
        current = estimated_tokens(nframes, resize)
        if current > max_visual_tokens:
            r = (max_visual_tokens / current) ** (1 / 3)
            nframes = max(1, int(nframes * r))
            resize = resize * r
 
    return {**args, "nframes": nframes, "resize": resize}

Pseudocode 3:frame extraction tool(基于 select_frame_fallback.py::extract_frames

def extract_frames(video_path, start_time=0.0, end_time=None, nframes=32,
                   resize=None, factor=1, backend="auto", clamp_to_stream=False):
    backend_order = ["decord", "torchcodec"] if backend == "auto" else [backend]
    errors = {}
 
    for backend_name in backend_order:
        try:
            decoder = BACKENDS[backend_name](video_path)
            stream_begin, stream_end = decoder.get_stream_bounds()
            start, end = apply_time_bounds(
                start_time, end_time, stream_begin, stream_end, clamp_to_stream
            )
            timestamps = np.linspace(start, end - 1e-3, nframes).tolist()
            frames = decoder.get_frames_by_timestamps(timestamps)
            if resize is not None:
                frames = resize_with_opencv(frames, resize, factor=factor)
            return frames, timestamps, backend_name
        except Exception as exc:
            errors[backend_name] = str(exc)
 
    raise RuntimeError(errors)

Pseudocode 4:paper-level reward(训练代码未发布,基于论文公式)

def eva_reward(task_type, pred, gt, final_images, judge_model, has_tool_call):
    if task_type == "multiple_choice":
        judge_correct = judge_model.check(question=gt.question, images=final_images) == gt.answer
        model_correct = pred.answer == gt.answer
        r_acc = 1.0 if (judge_correct and model_correct) else 0.0
    else:
        r1, r2, rl = rouge_f1(pred.answer, gt.answer, stemming=True)
        r_acc = (r1 + r2 + rl) / 3.0
 
    r_fmt = 0.05 if (has_tool_call and pred.answer != gt.answer) else 0.0
    return W_ACC * r_acc + W_FMT * r_fmt

Code reference: main @ 758ad8d3 (2026-04-03) — pseudocode and mapping based on this commit

Paper ConceptSource FileKey Class/Function
Evaluation model/runtime configREADME.md, eval-eva.pyBASE_URL, MODEL_TOKENIZER_PATH, vLLM command notes
Benchmark dataset mappingeval-eva.pyDATASET_CONFIG for VideoMME, LSDBench, LVBench, VideoHolmes, LongVideoBench, MLVU
Query-only initial prompteval-eva.pybuild_message_from_rl inserts Video Length and original resolution before question
Multi-turn EVA inference loopeval-eva.pysingle, process_single_item, main
Tool-call parsing and fallbackeval-eva.pyregex over <tool_call>, call_frame_select, visual-token cap logic
Frame extraction backendselect_frame_fallback.pyDecordBackend, TorchcodecBackend, extract_frames
Temporal sampling and resizingselect_frame_fallback.py_build_timestamps, _resize_with_opencv, _apply_time_bounds
Accuracy aggregationaccuracy.pydataset-specific answer extraction and score computation
Reference eval outputsresults-12k/*.jsonl, README.mdreported Acc/Round/Token per benchmark
SFT/KTO/GRPO training, rewardsnot released in repopaper-only formulas and Experiment Settings

4. Experimental Setup (实验设置)

Datasets and scale

训练数据分三层。EVA-SFT 约 10k high-quality samples,来自 LLaVA-Video 与 CG-Bench 上由 Qwen2.5-VL-72B 生成的 agentic trajectories;EVA-KTO 约 11k labeled frame-selection strategies,包含 chosen/rejected success/failure trajectories;EVA-RL 包含 9.6k open-ended video QA 和 1.1k multiple-choice questions。实验设置中 KTO 数据按 63% correct trajectory 与 37% incorrect trajectory 配比训练;GRPO 数据按 90% open-ended QA 与 10% MCQ 混合。

Released repo 中提供的 evaluation annotation scale 为:VideoMME 2700 条,LSDBench 1304 条,LVBench 1549 条,VideoHolmes 1837 条,LongVideoBench 1337 条,MLVU-MCQ 2174 条。论文主实验覆盖 LSDBench、LongVideoBench、MLVU、VideoMME、LVBench、Video-Holmes;appendix 还评估 ELV-Halluc。

Baselines and metrics

主要 baselines 包括 closed-source GPT-4o、Gemini-1.5-Pro、Gemini-2.0-Flash;static sampling/open-source models 包括 ShareGPT4Video、LongVA、VITA-1.5-7B、Video-R1、VideoChat-R1、Qwen2.5-VL、LongVila;adaptive agents 包括 VideoAgent、FrameThinker、VideoMTR。核心指标是 accuracy,即预测正确比例;同时报告 frames、visual tokens、interaction rounds 来衡量计算效率。Video-Holmes 细分 SR、IMC、TCI、TA、MHR、PAR、CTI 七类 reasoning capability;ELV-Halluc 报告 in-video/out-video accuracy gap、Avg Acc、Avg Diff、SAH Ratio。

Training and evaluation config

基础模型是 Qwen2.5-VL-7B-Instruct,因为它支持 variable-resolution visual input,可以在低分辨率帧上节省 token。SFT 使用 EVA-SFT 与开源 agentic training data,训练 2 epochs,batch size 8,learning rate 。KTO 使用 EVA-KTO,保持同一 learning rate,,chosen/rejected 比例为 63%/37%。GRPO 使用 EVA-RL,训练 1 epoch,batch size 64,每个 sample rollout 数为 8,learning rate ,硬件为 32 H100 GPUs。

Released repo 的 evaluation 默认值来自 eval-eva.py,包括 --max-concurrent=30--max-turns=6--max-visual-tokens=12000--maxp=720--fallback=True,并通过 select_frame_fallback.py 使用 decord 优先、torchcodec fallback 的 frame extraction。README 要求本地以 vLLM 提供 OpenAI-compatible endpoint,并下载 WRHC/EfficientVideoAgenthf_model/

5. Experimental Results (实验结果)

Main results from paper tables

Sampling Dilemma Bench (LSDBench) 中,Gemini-2.0-Flash 达到 56.2% 但消耗 696.6k visual tokens;Qwen2.5-VL* 32 frames 达到 49.2%/21.0k tokens;Qwen2.5-VL(RHS) 达到 52.2%/146.2k tokens;EVA 达到 51.0% 且只用 76.9 frames、10.3k visual tokens。正文段落曾写 51.8%/6.2k tokens,但 Table 1 最终数字是 51.0%/10.3k,本笔记以表格为准。

ModelLongVideoBench AccMLVU AccVideoMME Long/OverallLVBench Acc
GPT-4o58.264.665.3 / 71.948.9
Gemini-1.5-Pro55.2-67.4 / 75.033.1
Video-R152.760.249.4 / 59.935.3
VideoChat-R149.154.346.2 / -34.3
FrameThinker52.959.147.6 / -36.6
EVA-SFT49.952.345.8 / 56.026.5
EVA-KTO53.257.445.1 / 56.536.0
EVA-GRPO55.068.348.4 / 60.243.3

Table 2 显示,GRPO 后 EVA 在 MLVU 与 LVBench 上提升最明显:MLVU 从 EVA-KTO 的 57.4 提升到 68.3,LVBench 从 36.0 提升到 43.3;LongVideoBench 也从 53.2 到 55.0。论文正文 line 18 的括号数字 55.1/60.5/59.9/38.1 与最终表格不完全一致,因此实际比较应优先读 Table 2。

Video-Holmes zero-shot 结果中,EVA-GRPO 使用估计 36.8 frames,SR 49.3、IMC 39.5、TCI 30.4、TA 44.5、MHR 27.1、PAR 37.6、CTI 35.2、Overall 37.2;对比 Video-R1 Overall 36.5、VideoChat-R1 33.0、SEED-Bench-R1 33.5,说明 planning-before-perception 对多步 reasoning 和 temporal causal inference 有迁移性。

ELV-Halluc appendix 中,EVA-7B 的 Avg Acc 为 26.2,Avg Diff 为 3.8,SAH Ratio 为 5.0。相比 Qwen2.5VL-7B 的 Avg Acc 18.1、Avg Diff 7.6、SAH Ratio 8.8,EVA 同时提高准确率并降低 hallucination-related gap;相比 InternVL3-38B 的 Avg Acc 26.1,EVA 用 7B LLM 达到相近甚至略高的 Avg Acc。

Ablations and behavior findings

Figure 5 解读:左侧曲线/分布说明 mixed data 比 OE-only 或 MC-only 更稳定;右侧结果图显示 MC 与 OE 混合能在 VideoMME 上带来更有效的训练环境。论文解释是:KTO 虽然扩大探索空间,但模型仍可能在视觉证据不足时产生 plausible guess;open-ended data 会迫使 agent grounding 到视觉内容,MCQ 则提供明确判别信号,二者混合能缓解 reward hacking。

Figure 6 解读:case study 展示 EVA 对不同问题产生不同 workflow:有的问题先稀疏扫全局,再 zoom in;有的问题直接密集采样短片段;有的问题多轮反思后才提交答案。这说明 EVA 学到的不是固定“几轮、几帧”模板,而是根据 query 和已获得证据动态调整 action sequence。

训练阶段 ablation 的核心结论是:SFT 让模型遵守 tool-calling 格式,但仍像 format-following imitator;KTO 通过 chosen/rejected trajectories 降低典型失败策略;GRPO 则把视觉 token 分配变得更精细,减少每轮帧数但允许更有目的的多轮推理。总体上,EVA 的结果支持作者主张:长视频 agent 的瓶颈不是单纯更大上下文,而是能否主动规划视觉证据获取过程。

Limitations

论文没有系统展开 failure taxonomy,但从方法和代码可以看到三点限制。第一,训练依赖 teacher MLLM 生成高质量 SFT/RL 数据,数据质量和 prompt 设计会影响 agent policy。第二,released repo 尚未包含训练代码、reward 实现或 launch config,复现 SFT/KTO/GRPO 只能依赖论文描述。第三,EVA 的效率来自每次 tool call 的预算控制与主动采样;如果问题需要持续跟踪全视频细节,过强的 token cap 或错误的 early plan 仍可能漏掉证据。