我们团队在做Univideo这个统一视频处理框架的时候第一批落地的是采集、转码、渲染这些“手”和“脚”第二批才轮到大脑——也就是今天这篇要聊的 Plan Agent。按系列进度这一篇就专门把它从设计动机到工程落地完整拆一遍内容包括它怎么读懂一句粗糙的需求、怎么做任务拆解、怎么在几十个原子能力里挑出趁手的工具以及我们实际跑下来最头疼的几个问题。如果你也在做类似的视频处理平台或者想给自己的系统加一个“会规划”的中间层这篇应该能帮你省不少时间。先交代一个背景。Univideo 不是单个视频处理工具而是一整套统一调度视频相关能力的框架转码、拼接、字幕烧录、语音识别、镜头切割、AI视频生成、背景音乐混音这些能力都被封装成了一个个可独立调用的“原子工具”。框架本身不关心业务要什么它只负责把底层能力管好、调度好。但问题恰恰出在这里——能力越丰富使用门槛越高调用方每接一个需求就要自己拼一大段编排逻辑拼完还不敢复用换个场景又得重来。Plan Agent 就是为了解决这个“有能力但不会自己安排”的尴尬而生的。它做的事情很纯粹把用户的一句意图描述翻译成一组有序、有依赖、有资源预估的工具调用链然后交给执行层去跑。你可以把它理解成餐厅里的点单服务员客人说“来一桌三人份的家常菜”它不会直接去炒菜而是把这句话拆成“选食材、洗切、炒三个热菜、配一份汤、餐后上果盘”交给后厨各岗位后厨只需要埋头执行自己那一步。1. 为什么非要有这一层从“人肉编排”到“规划即服务”最早我们并不想做 Plan Agent觉得用一套规则引擎就能解决问题。规则引擎确实能处理“如果输入是MP4就转成H.264”这类确定逻辑但用户的需求从来不会这么规整。真实场景里运营同事丢过来的需求是这样的“帮我把这段发布会录像剪一个30秒的预告发视频号要加字幕背景音乐轻快一点竖屏尺寸。”这句话里有剪辑、有转码、有字幕识别、有音轨混音、有分辨率适配甚至“轻快一点”这种没法直接映射到某个参数的模糊描述。规则引擎要处理这种需求得把每条分支都列出来组合数会随着工具数量爆炸。我们算过一笔账Univideo 里当时有13个核心原子工具每个工具平均2个关键参数光考虑参数组合就有上百种可能路径而规则脚本每新增一条路径就要写一堆 if-else维护成本直线上升。更重要的是规则引擎只能覆盖“写规则时能想到的情况”用户一旦提出新组合规则里没有就得重新改代码。Plan Agent 换了一种思路不追求把每条路径写死而是让模型根据当前可用的工具列表、输入输出的数据结构、资源约束现场“算”出一条路径来。它把做规划这件事本身变成了一项服务而不是散落在各个业务代码里的嵌套逻辑。这也是我坚持叫它 Agent 而不是 Scheduler 的原因——它有一定的自主决策空间给定同样的需求它会根据当前平台能力的变化调整方案而不是每次都走同一条老路。为了让大家对位置有直观概念我画一下 Univideo 的整体分层不是架构图就是职责划分接入层接收自然语言需求、结构化工单、API请求统一转成内部需求描述。规划层Plan Agent解析需求、匹配工具、构建任务图、做资源预估。执行层按任务图调度节点管理队列、重试、结果回传。原子工具层转码、剪辑、字幕、TTS、视频生成等具体执行单元。规划层是夹在「用户意图」和「工具执行」中间的翻译官。没有它用户意图要穿透到执行层执行层就得认识“剪一段”“轻快一点”这种话这显然不合理。2. Plan Agent 的第一关把一句话需求变成结构化意图2.1 需求文本的归一化处理Plan Agent 的输入不一定是自然语言也可能是结构化工单但我们实际面对的大头还是自然语言。自然语言的问题在于同一个意思有无数种说法“剪个30秒”“搞个半分钟的版本”“长度控制在30秒上下”我们都要映射成同一个内部表达duration_seconds: 30。归一化处理分两步。第一步是规则兜底用正则和关键词词典把明显的时间、分辨率、格式、角色抓出来比如“30秒”“1080p”“mp4”“竖屏”。第二步是用大模型做语义理解把规则抓不到的部分提取成结构化的槽位。这里有个关键原则规则能确定的绝不让模型猜模型只处理规则覆盖不到的模糊语义。比如“轻快一点”这种主观描述规则没法落地就让模型把它映射成“BGM风格标签light”或者“节奏参数BPM 100-120”。2.2 意图分类与槽位提取 Schema我们把用户意图先分成五类再走规划比直接进入工具匹配要稳得多意图类型典型描述主要涉及能力生成类生成一段产品宣传视频视频生成、TTS、素材合成编辑类剪掉开头和结尾加转场剪辑、转场、拼接增强类修复模糊画面、提升分辨率超分、降噪、色彩增强转换类转成MP4、压缩到10MB以内转码、压缩、封装格式转换分析类找出所有有人脸的片段人脸检测、场景切割、内容索引槽位提取则是把所有约束条件归一化到一份内部 Schema 里。我们最终用的简化版本长这样{ intent: edit, source: { file_id: video_67890, type: interview_record }, target: { resolution: 1080x1920, format: mp4, max_duration_sec: 30 }, constraints: { subtitles: auto_generate, bgm: light, remove_silence: true } }这份 JSON 就是规划器的“题目”。后面所有的任务拆解、工具筛选、依赖构建全部围绕它展开。我们在这一步踩过最大的坑就是把自然语言解析和任务规划合而为一让大模型直接输出最终的工具调用序列。看起来省事实际上准确率很差因为解析和规划是两件难度不同的事混在一起模型容易顾此失彼要么槽位抓不全要么工具链编得离谱。拆开以后每一层都做自己擅长的事整体准确率提升非常明显。3. 工具注册与发现Agent 怎么知道平台上有哪些“手”可用规划的前提是“知道有什么可用”。Univideo 的每个原子工具在启动时都要向注册中心登记登记内容不是简单的一个名字而是一份完整的工具描述文档。这份文档就是 Plan Agent 做选择时的依据所以它的质量直接决定规划质量。3.1 工具描述 Schema 的设计每个工具的描述文件包含这几块功能摘要一句话说明这个工具能干什么面向模型的自然语言描述要写得清楚不能太书面。输入参数每个参数的名称、类型、取值范围、默认值、是否必填。输出产物产物的类型、格式、以及交给下游时能消费哪些字段。资源画像预估的GPU时长、内存峰值、需要的带宽以及是否独占设备。互斥与依赖规则比如某工具必须在转码之后运行某工具不能和另一个工具共用设备。我拿“智能剪辑”工具Univideo 里叫 scene_cut举个例子它的注册片段大致是{ tool_name: scene_cut, summary: 根据镜头切换、语义节奏和用户指定的时长从长视频中提取关键片段并拼接成一个短视频, input_params: [ {name: source_video, type: file_ref, required: true}, {name: target_duration_sec, type: int, min: 5, max: 600, default: 30}, {name: include_speech, type: bool, default: true}, {name: style, type: enum, values: [fast, normal, soft], default: normal} ], outputs: [ {name: video_segments, type: segment_list}, {name: edited_video, type: file_ref} ], resource_profile: {gpu_hours: 0.2, memory_gb: 4, device_exclusive: false} }这里有一个我们反复强调的细节工具的 summary 千万别写成给程序员看的接口注释而要尽量站在“这个工具在业务上解决了什么问题”的角度描述。因为 Plan Agent 背后的大模型是靠 summary 来理解工具用途的如果 summary 写得全是技术内部术语模型很容易匹配错。3.2 工具匹配策略召回 精排规划开始后Agent 先把所有工具描述向量化和当前的意图、槽位做一次向量召回拿到候选工具集。这一步目标不是精准而是别漏然后再把候选工具丢给模型让它根据参数约束、输出需求做精排选出真正要用的那批。精排阶段有个规则必须前置硬约束判断。比如当前输入视频只有10秒而用户要30秒的预告片那把“直接剪辑”作为唯一方案就是有问题的此时应该考虑“在素材库补充相关片段”或“生成过渡素材”。这种约束判断不适合让模型自由发挥我们会预先写死一些业务规则确保模型不会提出明显违背物理常识的方案。工具匹配完还不能直接开跑。因为在真实业务里工具之间往往存在隐含的先后关系这就需要下一步把整个流程结构化起来。4. 任务图构建从一堆工具到一张可执行的 DAG4.1 为什么是 DAG而不是一个列表我们第一版规划输出的是顺序列表先转码再剪再加字幕再渲染。跑简单用例时没有任何问题一到复杂需求就露馅了。比如用户要求“既要生成字幕文件也要把音频单独提取出来供审阅”这两个操作其实可以并行再比如“先用超分提升素材质量再进行人脸识别”如果顺序颠倒了人脸识别会因为画面模糊而漏检。顺序列表无法表达叉路和分叉所以必须升级成有向无环图。DAG 的好处在于执行层可以按拓扑序跑没有依赖关系的节点能并行资源能更充分地利用同时也方便做路径追溯出了问题能一眼看出来是哪个环节失败。4.2 依赖边是怎么长出来的任务图的节点是工具调用边是依赖关系。我们在实现中把依赖分成四种来源依赖类型说明例子数据依赖下游节点需要上游的输出产物剪辑产生的片段列表是字幕工具的输入时序依赖业务上必须分先后先转码再识别避免源格式兼容问题资源互斥两个节点不能同时跑两个大模型同时占同一块 GPU 显存不够参数依赖下游参数需要上游计算的中间值总时长统计结果决定背景音乐是否需要裁剪一个真实需求“把长视频剪成30秒预告并加上字幕”经过依赖构建后大概长这样{ tasks: [ {id: t1, tool: transcode, params: {target: h264_preview}, depends_on: []}, {id: t2, tool: scene_cut, params: {target_duration_sec: 30}, depends_on: [t1]}, {id: t3, tool: asr, params: {language: zh}, depends_on: [t1]}, {id: t4, tool: subtitle_burn, params: {style: bottom_center}, depends_on: [t2, t3]}, {id: t5, tool: bgm_mix, params: {style: light}, depends_on: [t2]}, {id: t6, tool: render_final, params: {resolution: 1080x1920}, depends_on: [t4, t5]} ] }注意 t2 和 t3 都依赖 t1但它们彼此没有先后关系执行层就可以并行跑“剪辑”和“语音识别”两条线最后在 t4 汇合。这种并行能力正是从顺序列表升级到 DAG 之后最直接的收益。4.3 资源预估与冲突消解光有依赖还不够还得回答“这些任务现在能不能跑起来”。每个任务都有资源画像规划器会根据设备池的当前状态做一次预检如果任务图里有三个节点都要独占 GPU而池子里只剩两块卡规划器就要做取舍。方案有三种把第3个节点降级成 CPU 执行在不影响结果的前提下把它的参数换掉比如换一个轻量模型或者保持计划但标记“需要等待资源释放”。我们最初的想法是规划器只负责生成任务图资源调度全部扔给执行层。后来发现不行因为如果规划阶段完全不管资源生成的图经常在高峰期拿不到资源整个任务链直接被卡死。现在我们在规划阶段就加入轻量级资源预检至少保证生成的任务图在当前资源状态下是“理论可执行”的至于执行时的具体排队策略仍然交给执行层。4.4 循环依赖检测DAG 构建最怕出现循环A 依赖 BB 又依赖 A。我们在调试阶段真遇到过原因是某个工具的描述文档里写了“如果要生成音频摘要需要先有最终视频”而另一个工具写了“最终视频需要包含音频摘要”两个工具互补注册结果模型在规划的时候生成了一个环。好在检测方法很成熟——在做拓扑排序时如果发现节点没法全部入列就说明存在回路。这种问题有两个处理层规划器在生成图之后立即做一次拓扑校验发现环就把“参与构成环的节点”全部从图中剔除并重新规划如果重新规划还是环说明工具描述有问题需要告警而不是继续硬跑。这一层我多说几句。很多同学觉得自己写的规划脚本不会出现这种低级问题但一旦决策权交给了大模型它不会像人一样在脑海里过一遍逻辑闭环它只是按概率生成 token你给它多少自由度它就可能产生多离谱的作品。所以对规划结果做硬性结构校验是任何 Agent 系统的底线要求类似于给自动驾驶加的安全气囊平时用不上一旦用上就是救命级别。5. 一次完整的规划实测从“一句话需求”到可执行任务链讲了这么多原理我拿一个实际跑过的用例串一遍。需求是运营同事提的“把这段发布会录像剪一个30秒的竖屏预告要自动字幕背景音乐走轻快风格最后导出MP4。”规划端做了这么几步。第一步意图解析。这段需求命中“编辑类”提取出时长30秒、竖屏1080x1920、自动字幕、背景音乐轻快、导出格式MP4。源视频是发布会录像时长42分钟格式是原始的 MOV。第二步工具匹配。候选工具里transcode、scene_cut、asr、subtitle_burn、bgm_mix、render_final 依次进入了精排名单。为什么没有直接匹配到“视频生成”类工具因为意图是“编辑已有素材”而不是“无中生有生成新画面”这是意图分类阶段就决定好的避免模型被无关工具干扰。第三步任务依赖构建。按照第4节的方式transcode 在最前面因为它要把 MOV 转成统一的中间格式消除后续环节的格式兼容风险。scene_cut 和 asr 都依赖转码结果二者可以并行。subtitle_burn 需要拿到剪辑后的片段和识别出的文本所以排在两者汇合点。bgm_mix 依赖剪辑结果但不需要等字幕。render_final 在最后负责把字幕和背景音乐一并合成并转成竖屏 MP4。第四步资源预检。这台机器当时有两块 GPU任务图里 scene_cut、asr、render_final 都需要 GPU 资源但 asr 的模型相对轻量可以排在 CPU 上执行真正的 GPU 任务只有 scene_cut 和 render_final 两个正好并行量合适预检通过。第五步输出规划单。规划结果除了任务图还附带一份给用户看的解释文本“系统将按以下步骤处理先转换视频格式同时进行关键片段提取与语音识别之后将识别文本烧录为字幕并混入轻快风格背景音乐最后渲染输出竖屏MP4。”这一步非常重要它让用户能看到 Agent 的“思路”。如果用户觉得“我不要自动字幕”可以直接在用户确认环节打断避免执行到一半才发现理解偏差。这套 feedback loop 我们是在实际使用中发现价值很大的早期版本直接嗖嗖跑完用户不满意就得重来一遍浪费资源和时间。最终这个用例从提交需求到输出规划单耗时约1.2秒其中大模型解析和规划占了0.8秒规则预检和资源评估占了0.4秒。相比以前人工写编排脚本要半个小时起步这个速度对内部运营已经是质的飞跃。6. Plan Agent 的常见翻车现场与我的修复经验任何 Agent 类系统都绕不开稳定性问题Plan Agent 更是如此。它一次规划可能涉及七八个工具、十几个参数任何一个环节出问题整个任务链都会受影响。下面几个是我们线上踩过、并且已经针对性修复的问题应该对你会比较有用。6.1 模型幻觉规划出不存在的工具这是最先暴露的问题。模型在生成任务图时编造了一个“video_style_transfer”的工具而 Univideo 平台里根本没有这个工具。我们的工具匹配用的是向量召回理论上不该召回到库外的工具但模型在精排阶段可能在没有任何依据的情况下自己“创造”了一个合理但不存在的能力。修复方案分两层。第一层在规划结果里强制增加工具校验每个节点必须命中注册表中的有效工具 ID命中不了直接报错并触发重新规划第二层给模型加系统提示明确告知“你只能使用给定的工具列表如果列表无法满足需求请输出 mismatch 标记而不是自行创造工具”。加完之后编造工具的案例几乎清零剩下的零星误用也都是真实工具但参数不匹配进入下一类问题。6.2 参数幻觉时间码和分辨率算错模型在规划时会把参数算错。最典型的例子用户要求“剪出30秒”但模型在输出任务的 target_duration_sec 时写成了 300。后来我们定位到原因是模型的上下文里有一个训练样本涉及300秒的参数它复制了结构却复制错了数值。数值型参数是幻觉重灾区因为模型本质上不擅长精确数值计算。对策是把数值类参数做成“规则强校验”。规划器在生成任务图后会跑一个参数校验器对所有数值字段做范围检查target_duration_sec 是否在1到300之间分辨率是否在平台支持列表中码率是否在合理区间。一旦越界就回退到需求解析阶段重新取值而不是原地修改参数。因为原地修改有时候会把“30秒”改错成“35秒”反而不如重新来一遍干净。现在参数越界导致的执行失败率已经从最初的15%降到了2%以下。6.3 循环依赖与不可达节点除了前面说的环检测还有一种情况是“悬挂节点”——任务图里某个节点不在任何一条从起点到终点的路径上执行它纯属浪费资源。这种情况通常是依赖边构建出错导致的比如 t3 被声明依赖 t2 的结果但 t2 的输出里根本没有 t3 需要的字段。我们修复的办法是在拓扑排序之外加一步“可达性分析”从入口节点出发走一遍图把所有不连通的孤立节点标记为无效并删除。这个步骤很便宜但对执行层的干净度帮助很大相当于每次规划完自动做一次修剪。6.4 规划超时与降级大模型规划偶尔会卡住尤其是在工具列表特别长、需求又模糊的时候。我们设置了一个硬性超时如果规划耗时超过10秒就停止模型规划改用一套预置的 fallback 模板。Fallback 模板是我们在冷启动阶段手工编写的几种常见需求路径覆盖“转码”“剪辑”“生成字幕”“压缩”这四类高频场景。实测中约5%的请求会触发降级用户体感几乎无差别因为大多数高频需求本来就适合模板解决模型强上场反而容易出错。还有一个值得提的优化是规划缓存。基于同一个源视频、同一种意图类型的规划结果我们可以把任务图缓存起来后续相同需求直接复用省掉每次调用模型的开销。这里的 key 要包括源视频的特征值、目标参数、平台当前工具版本任何一个变了都要重新规划。缓存命中率现在大约40%省下的计算成本相当可观。6.5 工具描述文件的“坑”与维护规范最后说一个很多人容易忽略的问题工具描述文件写得好不好直接决定规划质量但它本身也需要维护。我们有几次模型规划失败的根因是某个工具的参数名改了但描述文件没同步更新导致模型按旧参数名填值生成的任务图被校验器拦下。现在我们订了一条团队规范任何工具的参数变更必须同步更新注册中心里的描述文件并且用一组“规划黄金用例”做回归测试——每次描述文件变更后自动跑一遍这些用例确认规划结果没有偏离预期。看起来是很基础的流程但它是 Plan Agent 稳定性的地基。写到这里回顾整个 Plan Agent 的搭建过程我最大的体会是这类系统的成功不取决于模型有多聪明而取决于工程护栏有多严密。模型负责打开思路规则负责兜住底线两者缺一不可。如果你也在搭建类似的规划层我建议从最小闭环开始——先接两三个工具跑通“解析—规划—校验—执行”全链路再加工具、加复杂场景。等到工具数量超过两位数你再来体会 DAG 带来的收益会发现当初围绕任务图做的那堆校验逻辑全都值回票价。