
StreamVLN首次把连续导航过程定义为无限接续的多轮对话任务——原理拆解源码复现真机部署目录01 Video-LLM 做导航卡在哪里02 核心框架流式多轮对话03 技术原理SlowFast 上下文建模Fast 路径滑动窗口 KV CacheSlow 路径基于体素的空间剪枝记忆04 开源复现教程手把手搭建环境环境准备数据集准备模型权重下载运行评估05 核心代码解析模型核心streamvln/model/stream_video_vln.py推理 Agentstreamvln/streamvln_agent.py训练入口streamvln/streamvln_train.py06 真实世界部署Unitree Go2 机器狗07 总结与思考“StreamVLN 好复现吗”这是前不久在「深蓝具身智能」读者群中被问到的一个问题。熟悉 StreamVLN 的读者知道这一模型提出了一套快慢上下文建模机制用滑动窗口 KV Cache 保持低延迟用体素空间剪枝压缩历史记忆在 R2R-CE 和 RxR-CE 两个主流基准上均达到纯 RGB 方法的最优水平并成功部署到 Unitree Go2 真实机器狗上相关介绍见本文2-3部分。伴随每个热门模型的开源随之而来的落地门槛、复现难度及实操流程更是目前领域内广泛关注的核心议题。因此本文将更多篇幅集中于StreamVLN复现本身从环境搭建、数据集准备、模型权重下载到运行评估与真实部署的工程细节逐环节给出可复现的操作指引第4部分起为复现内容。我们希望为有意基于 StreamVLN 进行复现或二次开发的研究者提供一份切实可用的参考手册。01 Video-LLM 做导航卡在哪里视觉语言导航VLN要求机器人根据自然语言指令在连续的真实环境中规划运动路径。随着 Video-LLM 的快速发展研究者们开始将其扩展为视觉-语言-动作模型VLA直接从视频流中生成底层控制动作。然而将这类模型部署到真实机器人上必须面对两个核心矛盾第一实时性要求。机器人需要以较低延迟持续生成动作而大模型的推理本身就耗时如果每一步都要重新处理所有历史帧延迟会随对话轮数线性增长在实际部署中难以接受。第二长程记忆管理。一次完整的导航任务可能持续数分钟对应数百帧视觉观察。如果将所有帧的 Token 都保留在上下文中不仅显存占用巨大2K Token 约占 5GB还会超出大模型的最大上下文长度导致性能下降。NaVid、NaVILA 等已有工作在这两个问题上都有所妥协。StreamVLN 的出发点是能否在不牺牲视觉分辨率的前提下通过更精细的上下文管理同时解决这两个问题02 核心框架流式多轮对话StreamVLN 将整个导航过程建模为一个持续进行的多轮对话。每一步机器人接收当前帧的 RGB-D 观测作为新一轮对话的输入模型输出下一步的动作前进、左转、右转、停止。这种建模方式的好处在于Transformer 架构天然支持通过 KV Cache 复用已计算的历史 Token 状态从而避免重复计算。但如果不加限制地保留所有历史 KV显存会无限增长。▲图 | StreamVLN 整体框架示意图。StreamVLN 的核心贡献正是设计了一套快慢双路的上下文管理策略。如图上方为连续视频帧输入流经过视觉编码器和投影层后转换为 Token 序列中间的大语言模型通过 KV Cache 维护对话上下文其中实线框为当前活跃的滑动窗口虚线框为已卸载的历史窗口下方展示了历史 Token 经过时间采样和体素空间剪枝后被压缩为记忆 Token 的过程。03 技术原理SlowFast 上下文建模Fast 路径滑动窗口 KV Cache在多轮对话中如果每次生成动作都要重新 Prefill 所有历史 Token延迟会随对话轮数线性增加。StreamVLN 引入了滑动窗口 KV Cache只在 GPU 显存中保留最近 N 轮对话默认 N8的 KV 状态。在窗口内生成新动作时只需对当前帧的 Token 做 Prefill历史 Token 直接复用 KV Cache延迟极低且稳定。当对话轮数超过窗口大小时最旧的一轮 KV 被卸载出窗口其对应的视觉 Token 则被转交给 Slow 路径处理。▲图 | 三种 KV Cache 策略在多轮对话中的推理延迟对比。蓝线Full Turns延迟最低但显存无限增长黄线Single Turn延迟随轮数线性上升红线Sliding Window窗口大小8在窗口切换时有短暂峰值但整体延迟可控。Slow 路径基于体素的空间剪枝记忆被卸载出滑动窗口的历史帧不能直接丢弃它们包含了机器人走过的路的空间信息对长程推理至关重要。StreamVLN 将这些历史帧压缩为慢速更新的记忆上下文Memory Context。压缩的关键挑战是如何在减少 Token 数量的同时保留尽可能多的空间信息StreamVLN 提出了一种创新的3D 体素空间剪枝策略利用深度信息将 2D 图像的每个 Patch Token 反投影到 3D 空间坐标将 3D 空间均匀划分为体素Voxel网格对于落在同一体素内的多帧 Token只保留时间上最新的一帧其余标记为已剪枝对于某一帧中被剪枝 Token 数量超过阈值的帧整帧丢弃避免过于稀疏的帧引入噪声。▲图 | 体素空间剪枝算法Algorithm 1伪代码。算法遍历所有历史帧的 Token将其映射到体素坐标若同一体素已有更新的 Token 则将旧 Token 标记为剪枝最后对稀疏帧整体丢弃。整个过程不修改保留 Token 的特征值可直接复用 KV Cache。04 开源复现教程手把手搭建环境环境准备官方测试环境为 Python 3.9、PyTorch 2.1.2、CUDA 12.4。# 第一步创建 conda 环境并安装 habitat-sim conda create -n streamvln python3.9 conda activate streamvln conda install habitat-sim0.2.4 withbullet headless \ -c conda-forge -c aihabitat # 第二步安装 habitat-lab 和 habitat-baselines git clone --branch v0.2.4 \ https://github.com/facebookresearch/habitat-lab.git cd habitat-lab pip install -e habitat-lab pip install -e habitat-baselines # 第三步克隆 StreamVLN 仓库 cd .. git clone https://github.com/OpenRobotLab/StreamVLN.git cd StreamVLN数据集准备数据准备是 VLN 复现中最耗时的步骤需要按照以下结构组织 data/ 目录场景数据Scene DatasetsR2R、RxR、EnvDrop 使用 Matterport3DMP3D场景从官方项目页下载后放入 data/scene_datasets/mp3d/ScaleVLN 使用 HM3D 场景从 habitat-matterport-3dresearch 下载后放入 data/scene_datasets/hm3d/。VLN-CE Episodes分别下载 r2r、rxr、envdrop、scalevln 的 episodes 文件解压至 data/datasets/ 目录并按照 README 中的说明重命名文件夹。轨迹数据Trajectory Data官方在 Hugging Face 上提供了预收集的 R2R 和 RxR 轨迹数据下载后解压至 data/trajectory_data/。EnvDrop 和 ScaleVLN 的轨迹数据需要自行收集README 中有详细说明。协同训练数据Co-training DataLLaVA-Video-178K 和 MMC4 从各自官方渠道下载ScanQA 的标注文件可从 Hugging Face 获取统一放入 data/co-training_data/。Plain Text data/ ├── datasets/ │ ├── r2r/ │ ├── rxr/ │ ├── envdrop/ │ └── scalevln/ ├── scene_datasets/ │ ├── mp3d/ │ └── hm3d/ ├── trajectory_data/ │ ├── R2R/ │ ├── RxR/ │ ├── EnvDrop/ │ └── ScaleVLN/ ├── dagger_data/ └── co-training_data/ ├── ScanNet/ ├── LLaVA-Video-178K/ └── MMC4-core/模型权重下载官方提供两个版本的 checkpoint真实部署版本针对初始旋转动作和障碍物规避做了专项优化不建议用于基准测试。运行评估# 多 GPU 评估默认使用 8 张 GPU sh scripts/streamvln_eval_multi_gpu.sh 评估脚本内容如下可根据实际情况修改 CHECKPOINT 路径和 GPU 数量 Bash export MAGNUM_LOGquiet HABITAT_SIM_LOGquiet MASTER_PORT$((RANDOM % 101 20000)) CHECKPOINTStreamVLN_Video_qwen_1_5_r2r_rxr_envdrop_scalevln echo CHECKPOINT: ${CHECKPOINT} torchrun --nproc_per_node8 --master_port$MASTER_PORT \ streamvln/streamvln_eval.py --model_path $CHECKPOINT⚠️提示 官方曾修复过一个严重 Bug评估时 num_history 参数未正确设置导致记忆机制无法正常工作。复现时需确保使用最新代码git pull 更新后再运行。05 核心代码解析StreamVLN 的代码结构清晰核心逻辑集中在 streamvln/ 目录下以下重点介绍几个关键文件。模型核心streamvln/model/stream_video_vln.py这个文件定义了 StreamVLNForCausalLM 类继承自 Qwen2 并融合了 LLaVA-Video 的多模态架构。最核心的函数是 encode_rgbd负责处理输入的图像和深度信息并区分当前帧特征与历史记忆特征# streamvln/model/stream_video_vln.py节选 def encode_rgbd(self, images, depths, poses, intrinsics, time_idsNone, task_idsNone): # ... 提取基础图像特征 ... if num_view ! 1: memory_features [] image_features_ [] for b in range(batch_size): history_idx self.model.num_history # 当前滑动窗口内的图像特征直接送入 LLM image_features_.append(image_features[b, history_idx:]) # 历史帧特征经过 projector 和 2D 池化后作为记忆 Token his_image_feature image_features[b, :history_idx] his_image_feature his_image_feature.flatten(2, 3).permute(0, 2, 1) his_image_feature self.get_model().mm_projector(his_image_feature) his_image_feature self.get_2dPool(his_image_feature, 2) memory_features.append( his_image_feature.flatten(0, 1).unsqueeze(0) ) return image_features, memory_features这段代码的逻辑是通过判断 start_idx基于 time_ids以 num_history 为分界线history_idx 之后的帧属于当前滑动窗口直接作为高分辨率图像 Token 送入 LLMhistory_idx 之前的历史帧则经过投影和 2D 池化压缩转换为低分辨率的记忆 Tokenmemory_features。在 prepare_inputs_labels_for_multimodal 函数中模型通过识别特殊的 image TokenIMAGE_TOKEN_INDEX和 memory TokenMEMORY_TOKEN_INDEX将上述两类特征正确插入到输入序列的对应位置。这两个特殊 Token 的定义位于 streamvln/utils/utils.py# streamvln/utils/utils.py节选 IMAGE_TOKEN_INDEX -200 DEFAULT_IMAGE_TOKEN image MEMORY_TOKEN_INDEX -300 DEFAULT_MEMORY_TOKEN memory推理 Agentstreamvln/streamvln_agent.py这个文件定义了 VLNEvaluator 类负责与真实环境或硬件接口对接运行推理。它的核心职责是维护多轮对话的状态在每一步将当前帧的 RGB-D 观测转换为模型输入并将生成的动作 Token 追加到对话历史中实现流式的连续推理。对于仿真环境评估则由 streamvln/streamvln_eval.py 中的 VLNEvaluator 负责。训练入口streamvln/streamvln_train.py训练脚本基于 LLaVA 的 LLaVATrainer 构建。值得注意的是find_all_linear_names 函数在确定 LoRA 微调范围时明确排除了多模态相关的模块vision_tower、mm_projector、mem_projector 等确保 LoRA 只作用于语言模型的线性层# streamvln/streamvln_train.py节选 def find_all_linear_names(model): cls torch.nn.Linear lora_module_names set() # 排除多模态模块LoRA 只作用于语言模型线性层 multimodal_keywords [ vision_tower, mm_projector, mem_projector, point_projector, vision_resampler, mem_resampler, pointnet ] for name, module in model.named_modules(): if any(mm_keyword in name for mm_keyword in multimodal_keywords): continue if isinstance(module, cls): names name.split(.) lora_module_names.add(names[0] if len(names) 1 else names[-1]) if lm_head in lora_module_names: lora_module_names.remove(lm_head) return list(lora_module_names)06 真实世界部署Unitree Go2 机器狗StreamVLN 团队将模型部署到了 Unitree Go2 四足机器狗上验证了其在真实物理世界中的可行性。硬件架构采用端云协同模式Go2 搭载 Intel RealSense D455 深度相机将 RGB-D 视频流实时回传给配备 RTX 4090 显卡的远程工作站工作站运行 StreamVLN 模型推理将生成的控制指令发回机器狗执行。在延迟方面模型生成 4 个动作的平均推理时间为 0.27 秒室内通信延迟约 0.2 秒室外约 1.0 秒整体满足实时导航的需求。测试场景涵盖家居Home、工作区Workspace、商场Mall和户外Outdoor等多种环境机器狗能够根据复杂的自然语言指令如绕过桌子看到黑色雨伞后左转走到沙发旁找到蓝色柜子停下完成长程导航任务。▲图 | StreamVLN 在真实世界多种场景下的导航演示。从上到下依次为家居Home、工作区Workspace、商场Mall和户外Outdoor场景。机器狗能够根据包含多个地标关键词的复杂指令完成导航指令中的关键地标词以红色高亮标注。真实世界部署的代码和详细指南已在 realworld/realworld.md 中开源。07 总结与思考所以StreamVLN 好复现吗综合本文的复现实践结论是代码开源完整核心模块清晰但门槛不低。首先从数据依赖来看完整复现需要下载和处理数量庞大的多源数据集MP3D 场景、HM3D 场景、多个 VLN-CE episodes、轨迹数据和协同训练数据对存储和网络条件要求较高这是复现时需要提前规划的。其次项目自身也指出了当前方案存在的三个主要问题这并不影响复现本身但有助于大家理性评估该方法的适用边界第一直接从原始视觉观测端到端生成底层动作对视角变化和遮挡的鲁棒性有限第二在更长程的导航任务中当前的混合上下文建模策略仍面临挑战如何确保关键信息在长序列推理中保持一致性仍有待解决第三将动作历史作为对话上下文的一部分在异步推理和部署时需要额外的同步机制增加了工程复杂度。整体来看 StreamVLN 为基于 Video-LLM 的具身导航提供了一个系统性的解决方案希望这篇从复现视角出发的实操解读对各位有所帮助。想具体了解哪个模型的具体复现过程欢迎评论区留言。Ref论文题目StreamVLN: Streaming Vision-and-Language Navigation via SlowFast Context Modeling论文地址https://arxiv.org/pdf/2507.05240项目地址https://streamvln.github.io/