
把 Cosmos 3 后训练、VLM 行业推理和合成数据生成放在同一篇文章里看起来是三个独立话题实际是一条完整的数据生产链路。先由世界模型生成场景视频再用视觉语言模型对视频做结构化理解然后通过后训练把模型的输出格式和语义都稳定到目标领域流水线跑通后同一个流程既能处理智慧城市路口监控也能为农业机器人生成合成训练数据。标题中的[双语]我这样处理关键模型名、专用术语尽量保留英文正文用中文解释方便对照英文文档。下面内容以“Cosmos 3 作为世界模型代号”展开讲解后训练流程时使用开源 VLM 权重和通用工具链实际项目中具体版本、仓库地址和导入路径都要以你手上的环境为准。读完这篇文章你能拿到一套最小可复现的工作流合成视频生成、VLM 数据标注、LoRA 后训练、结构化推理部署、农业场景数据回流。这套技能适合做多模态模型微调、视觉问答落地、机器人仿真数据生产的工程师。它回答的核心问题不是“模型怎么下载”而是“如何把通用 VLM 变成某个行业里稳定输出的 VLM”。1. 先拆开技术主线世界模型、VLM 后训练与合成数据生成如何串联1.1 三个本来独立的技术为什么能放进同一条流水线世界模型解决“数据从哪里来”的问题。真实的城市监控视频和农业机器人操作视频采集成本高、涉及隐私、长尾场景少。Cosmos 3 这类以视频生成为目标的世界模型可以用文字描述生成一段带时间连续性的场景视频虽然它不代表物理完全正确但足以作为 VLM 标注和后续感知模型预训练的样本来源。VLM 解决“视频怎么变成结构化语义”的问题。纯视频存储在工程上只是文件模型要的是文本标签、目标框、事件描述和决策理由。视觉语言模型把图像或视频帧输入编码成视觉 token再交给语言模型生成 JSON、自然语言或操作指令。后训练解决“通用模型为什么在领域里不好用”的问题。通用 VLM 能回答常识问题但未必知道“智慧城市路口应该关注哪些事件类型”“农业机器人抓取番茄时要输出怎样的姿态信息”。后训练用领域数据调整模型权重让模型在该场景下既能稳定输出格式也能抓住领域语义。1.2 为什么这里不能只做提示词工程可以用提示词让通用 VLM 输出一份 JSON比如“你是一个城市路况分析助手”。在演示环境里可行进入批量生产后会出现三类问题。输出不稳定。提示词无法保证每次输出都能被json.loads解析模型可能多加一行解释、把false写成False。领域知识不足。模型不知道车流量统计要考虑有效区域不知道农业机器人末端执行器的坐标系约定。上下文窗口限制。如果把长视频的每一帧都塞进提示词处理和延迟都会失控。后训练的价值就是把“输出的 schema”和“关键领域判断”写进权重推理时只需要传少量上下文而不是每次都重复一长段提示词。1.3 整条流水线可以分成七步实际项目的核心环节是固定的场景生成、抽帧、预标注、数据清洗、后训练、推理部署、生成数据回流。完整步骤按下表执行。序号环节输入输出关键工具1世界模型生成视频文本提示词场景视频Cosmos 3 视频生成流程2抽帧视频文件图像序列OpenCV / ffmpeg3VLM 预标注图像序列初版 JSON 标注开源 VLM 权重4数据清洗与格式化初版 JSON训练 JSONL校验脚本、人工抽检5后训练训练 JSONLLoRA 权重或合并权重peft、transformers6推理部署新场景视频或图片结构化 JSONvLLM 或原生推理脚本7合成数据回流微调模型新一批训练数据过滤、去重、质量评分这里要注意顺序先用通用模型做预标注再清洗不要直接拿原始视频做训练。原始视频里 80% 的帧可能是重复或无信息量的直接训练只会放大数据噪声。1.4 两个业务方向只是同一套流程的两种配置智慧城市 VLM 推理和农业机器人合成数据生成看起来行业差别很大但抽象后完全一致给定一段视觉输入输出结构化判断。智慧城市需要判断“道路拥堵、事故、异常行人”农业机器人需要判断“作物成熟度、障碍物位置、抓取姿态”。差异集中在数据 schema、目标类别、相机视角和任务粒度。后训练的数据格式不需要大改只需要替换领域字段和标注说明。因此先把城市场景跑通再迁移到农业场景是降低风险的做法。两个方向共用代码库出现问题排查路径一致训练资源也能共享。2. 环境与基础模型准备先对齐版本再谈后训练2.1 硬件与软件环境要求后训练 VLM 对显存不友好因为视觉编码器和语言模型权重同时占用显存。按开源 7B 级 VLM 估算学习环境使用 LoRA 至少准备 24 GB 显存如果使用 14B 级权重建议 2 块 24 GB 或 1 块 48 GB。全参微调 7B 需要 4 块 A100 级别的显卡并且要配合 ZeRO-2 以上不建议新入行者一开始做全参。配置项学习/实验环境生产训练环境GPU 显存单卡 24 GB 起步2 到 8 卡 A100/H100 或同级别CPU 内存64 GB256 GB 以上Python3.103.10CUDA12.1 以上12.1 以上PyTorch2.1 以上2.1 以上加速组件peft、transformers、accelerate增加 DeepSpeed、flash-attn、vLLM数据库不需要但训练数据需要放在快速磁盘推荐 NVMe SSD。视频读取和图像解码是 IO 密集操作不要把原始视频放在网络盘上直接训练。2.2 Python 依赖安装在虚拟环境中安装依赖。下面是一个可运行列表版本是否锁定以你自己环境为准python -m venv .venv source .venv/bin/activate pip install --upgrade pip pip install torch2.5.1 --index-url https://download.pytorch.org/whl/cu121 pip install transformers peft accelerate deepspeed pip install datasets opencv-python pillow pip install vllm如果需要加速注意力计算再单独安装 flash-attn。这个库对 CUDA 版本敏感如果编译失败可以先不安装训练任务仍然能跑只是更慢。2.3 基础模型选择与下载后训练前先确认基线 VLM 使用什么以及对应权重文件名。不要只看“模型叫 Qwen2-VL”就假设 processor 配置一定匹配。下载前先确认config.json里model_typeprocessor_config.json是否存在以及图像处理器是否与模型匹配。常见项目中可以使用 Hugging Face 的snapshot_download下载权重from huggingface_hub import snapshot_download snapshot_download( repo_idQwen/Qwen2-VL-7B-Instruct, local_dir./models/Qwen2-VL-7B-Instruct, allow_patterns[*.json, *.safetensors, *.py, tokenizer*], )下载完成后用transformers加载看一眼确认能不能跑通一条最简单的推理再进入后训练。这个检查点不能省后训练无法修复一个加载都有问题的模型。2.4 推荐目录结构按下面结构组织便于把数据、权重、日志分开project/ ├── configs/ # 训练、推理、数据生成配置 │ ├── train_lora.yaml │ └── infer_city.yaml ├── data/ │ ├── raw_videos/ # Cosmos 3 输出的原始视频 │ ├── frames/ # 抽帧结果 │ ├── labeled/ # 第一版 JSON 标注 │ └── train/ # 最终训练 JSONL ├── models/ # 基线权重和 LoRA 权重 │ ├── base_vlm/ │ └── lora_adapter/ ├── scripts/ │ ├── generate_scenes.py │ ├── extract_frames.py │ ├── label_videos.py │ ├── train_lora.py │ └── inference_city.py └── logs/ # 训练日志与错误日志把配置、数据、代码分离是最基本的工程纪律。看到目录里混着.mp4和训练脚本时大概率已经出了问题。2.5 环境检查清单动手跑训练前快速核对六项显卡驱动能看到 NVIDIA 设备nvidia-smi正常。PyTorch 能否在 GPU 上计算torch.cuda.is_available()返回True。transformers与模型权重兼容加载后跑通一次问答。数据目录有写入权限磁盘剩余空间不少于模型权重 3 倍。训练脚本与推理脚本使用同一个 Python 环境避免命令行环境不一致。Cosmos 3 或视频生成流程能否稳定输出片段先生成 3 秒测试视频确认格式。这些检查看似基础实际踩坑率最高。大部分训练失败不是代码问题而是环境不一致或模型权重不完整。3. 用世界模型生成场景视频并转换成 VLM 后训练数据3.1 用 Cosmos 3 生成智慧城市与农业场景视频用世界模型生成视频关键不是“生成”而是“可控”。城市路口、农业无人机、机械臂作业都要写清楚相机视角、光照、物体类别和运动目标否则模型会生成无关内容。下面提示词用于说明思路中文写给项目组看英文写进生成接口城市路口示例 A 4K aerial view of a busy urban intersection at sunset. Traffic light turns red, vehicles stop, pedestrians cross the crosswalk. Camera stays at 30 meters height, slight drift to the left. 农业机器人示例 A first-person view from an agricultural robot arm in a tomato greenhouse. The gripper approaches a ripe tomato on the vine, background is softly blurred. Natural sunlight, no motion blur.生成时建议每次生成 5 到 15 秒视频。低于 5 秒事件不完整超过 15 秒可能丢失一致性。实际调用方式取决于你的世界模型工具链入口尽量统一封装成一个函数输出统一.mp4文件。有些项目会直接把世界模型生成的视频当真实数据用这是高风险动作。合成视频在纹理、遮挡、目标比例上可能和真实场景不一致用于训练 VLM 必须做人工抽检并记录每个样本来自哪个生成提示词。3.2 抽帧把视频变成模型能处理的图像序列视频是连续的但当前大多数开源 VLM 处理的是图像或短视频 token。抽帧时要兼顾时间覆盖和存储成本。使用 OpenCV 每 0.5 秒取一帧即可对于高动态场景可以提高到 1 秒 4 帧。import cv2 from pathlib import Path video_path Path(data/raw_videos/city_001.mp4) frame_dir Path(data/frames/city_001) frame_dir.mkdir(parentsTrue, exist_okTrue) cap cv2.VideoCapture(str(video_path)) fps cap.get(cv2.CAP_PROP_FPS) interval max(1, int(fps / 2)) # 每秒 2 帧 frame_id 0 saved 0 while cap.isOpened(): ret, frame cap.read() if not ret: break if frame_id % interval 0: out_path frame_dir / f{saved:06d}.jpg cv2.imwrite(str(out_path), frame) saved 1 frame_id 1 cap.release()抽帧后立刻检查文件数量和平均大小。如果某一帧是黑屏或纯色需要从数据里删除。注意不要用cv2.imwrite写中文路径部分环境会出现静默失败。3.3 用通用 VLM 生成第一版标注第一版标注可以使用和后期不同的模型。例如先用较大规模的通用 VLM 生成初始 JSON再用人工或规则校验。标注 prompt 要给出明确的输出 schemafrom transformers import Qwen2VLForConditionalGeneration, AutoProcessor from PIL import Image model Qwen2VLForConditionalGeneration.from_pretrained( ./models/Qwen2-VL-7B-Instruct, torch_dtypebfloat16, device_mapauto, ) processor AutoProcessor.from_pretrained(./models/Qwen2-VL-7B-Instruct) prompt 分析这张城市路口图像只输出 JSON { vehicles: [{type: car|bus|truck|bike, lane_position: left|middle|right}], pedestrians: {count: 0, crossing: true}, traffic_light: red|yellow|green|unknown, events: [queueing, accident, jaywalking, none], reason: 一句话说明判断依据 } image Image.open(data/frames/city_001/000000.jpg) inputs processor( textprompt, imagesimage, return_tensorspt, ).to(model.device) output_ids model.generate(**inputs, max_new_tokens256) result processor.batch_decode(output_ids, skip_special_tokensTrue)[0] print(result)这段代码能跑通说明环境正常。批量标注时要把它放进一个循环里并在每次调用后捕获异常不要因为一个坏