跳到主要内容

VideoRAG — 架构与原理

30 秒导读: VideoRAG 让你「和视频聊天」——哪怕是几百小时的素材。它先把视频离线蒸馏成两份索引(一份文字知识图谱、一份视觉向量库),查询时两条通道并行召回相关片段,再用视觉语言模型对命中片段「精读」一遍,最后生成带时间戳引用的回答。论文 arXiv:2502.01549;本仓库还含一个基于它的桌面应用 Vimo。

1. 这是什么(零基础也能懂)

一句话定义: VideoRAG 是一个「长视频检索增强生成」框架——把视频当成知识库,用自然语言提问,它去视频里找答案。

解决什么问题 / 给谁用:

想象你有一套 100 小时的网课录像,想问「老师在哪一节讲了反向传播,怎么讲的?」。

  • 直接把 100 小时喂给大模型——上下文窗口塞不下,token 费用爆炸。
  • 只对字幕做普通 RAG——丢掉了画面信息(板书、演示、图表)。

VideoRAG 的做法是:离线时把视频压缩成紧凑的「知识」,在线时只检索并精读真正相关的几个 30 秒片段。这样单张 RTX 3090(24GB)就能处理几百小时素材(README「Technical Highlights」)。

它能做什么:

  • 索引任意长度、任意数量的视频(insert_video)。
  • 用自然语言查询,返回带「视频名 + 起止时间戳」引用的答案(querymode="videorag")。
  • 回答多选题(mode="videorag_multiple_choice",用于 benchmark 评测)。
  • 跨多个视频联合理解(图谱天然把多视频的实体连在一起)。

用起来什么样:

索引和查询是两步,分别是一段极简脚本(来自 examples/):

# 示意,浓缩自 examples/process_videos_deepseek.py + query_videos_deepseek.py
from videorag import VideoRAG, QueryParam
from videorag._llm import deepseek_bge_config

# 第一步:索引(离线,慢,吃 GPU)
rag = VideoRAG(llm=deepseek_bge_config, working_dir="./videorag-workdir")
rag.insert_video(video_path_list=["/path/lecture.mp4"])

# 第二步:查询(在线,快)
rag = VideoRAG(llm=deepseek_bge_config, working_dir="./videorag-workdir")
rag.load_caption_model(debug=False) # 加载视觉语言模型用于「精读」
param = QueryParam(mode="videorag")
print(rag.query("老师怎么讲反向传播的?", param=param))

一句话直觉/类比: 把它想成给视频做了一个「双层目录」——一层是文字大纲(知识图谱),一层是画面指纹(视觉向量)。提问时两层目录一起翻,找到候选页码(片段)后,再派一个「会看视频的助理」(视觉语言模型)去逐页精读,最后助理写报告并标注「第几页第几行」(时间戳)。

2. 顶层全景(它大概怎么转)

VideoRAG 分两个生命周期:离线索引insert_video)和 在线查询query)。中间隔着磁盘上的 working_dir——索引把知识写进去,查询从里面读。

全景图(从左到右是数据流,上半离线、下半在线)

┌──────────────── 离线索引 insert_video() ────────────────┐
原始视频 ─▶ ① 切片 ─▶ ② Whisper 转写 ─▶ ③ 视觉语言模型 字幕 ─┐
(mp4) 30s/段 (字幕文本) (画面描述) │
│ ▼
└─▶ ⑤ ImageBind 编码每段 ──────────┐ ④ 合并「字幕+转写」为段文本
(视觉向量) │ │
▼ ▼
【视频片段向量库】 【文字分块 → 实体抽取 → 知识图谱】
vdb_video_segment_feature chunk_entity_relation(graphml)
└─────────────────────── 都落到 working_dir/ ───────────────┘

┌──────────────── 在线查询 query() ──────────────────────────┐
提问 ─┬─▶ 改写成「实体检索句」 ─▶ 查实体向量库 ─▶ 图谱反查 ─▶ 相关片段集 A ─┐
├─▶ 改写成「视觉检索句」 ─▶ 查片段向量库 ──────────────▶ 相关片段集 B ─┤
└─▶ 同时:查 chunk 向量库拿「文字上下文」 │
A ∪ B = 候选片段 ▼
候选片段 ─▶ ⑥ LLM 逐段过滤(留相关) ─▶ ⑦ 视觉语言模型「精读」每段 ─▶ ⑧ 组装上下文

带时间戳引用的答案 ◀┘

怎么读这张图:离线把一份视频拆成「文字」和「视觉」两套索引;在线时提问同时走「图谱通道」和「视觉通道」两路召回,合并后再精读。这就是论文说的 dual-channel(双通道) 架构。

部件一句话职责

部件干什么在哪个文件
VideoRAG(dataclass)总编排器:装配所有存储/模型,提供 insert_video / queryvideorag/videorag.py:60
split_video把视频按 30 秒切片,抽音轨,采样帧时间点videorag/_videoutil/split.py:10
speech_to_text用 faster-whisper 给每段转写字幕videorag/_videoutil/asr.py:8
segment_caption用 MiniCPM-V 视觉语言模型给每段生成画面描述videorag/_videoutil/caption.py:17
encode_video_segments用 ImageBind 把每段视频编码成视觉向量videorag/_videoutil/feature.py:10
extract_entities从段文本抽实体/关系,建知识图谱videorag/_op.py:356
videorag_query在线查询主流程(双通道召回→过滤→精读→作答)videorag/_op.py:580
NanoVectorDBStorage向量库 / KV / 图存储后端videorag/_storage/
LLMConfig把「最强模型/便宜模型/嵌入模型」抽象成可替换 providervideorag/_llm.py:44

主线走一遍(高层)

索引: insert_video 对每个视频跑 Step0–7(videorag.py:202)——切片、转写、字幕、编码、存片段信息;最后统一调 ainsertvideorag.py:344)把段文本分块、抽实体、写图谱。

查询: query 转给 aquery,按 param.mode 分发到 videorag_queryvideorag.py:307)。该函数三路并行召回(实体图谱 / 视觉相似 / naive chunk),合并候选片段,LLM 逐段判相关性过滤,视觉语言模型对留下的片段精读,最后塞进 videorag_response 提示词作答。

阅读地图

建议顺序(由浅入深):

  1. 01-indexing-pipeline.md — 一段视频如何变成两套索引(切片/转写/字幕/编码的七步)。先读这章,因为查询依赖它产出的数据结构。
  2. 02-dual-channel-retrieval.md — 查询时双通道怎么召回、怎么过滤、怎么精读重述、怎么带时间戳引用。本框架的「价值核心」。
  3. 03-knowledge-graph.md — 知识图谱怎么建(实体抽取 + gleaning + 合并)、怎么从实体一跳邻居反查到视频片段。
  4. 04-storage-and-llm.md — 存储后端家族、LLM 多 provider 抽象、缓存。给要改后端/换模型的人。

每章末尾都有「代码地图」表,可直接 grep 符号名跳进源码。