现状:感知只有一条路,而这条路的三个代价是结构性的
今天的视频感知只有一种走法:把时间窗打包成 mp4,经 OpenAI 兼容协议发给云端 多模态大模型。这条路成熟、能力全,但它同时决定了三件事:
必须有 API Key 。没有 key 就没有感知 —— 感知引擎直接落在 PREREQ_MISSING,整个"看见家里发生了什么"的能力不存在。
按 token 持续计费 。开销与摄像头数量和家里活跃程度成正比,而这是一个 24 小时常驻的负载。feat: 希望增加感知引擎参数可配置项以降低 token 消耗 #352 (希望增加感知引擎参数可配置项以降低 token 消耗)就是这个诉求的直接表达。
家庭画面必须离开本地 。对相当一部分用户,这是"要不要用这个项目"的前置问题,而不是一个可以调优的参数。
社区对"本地"的诉求是明确存在的:#144 (无法加载本地模型)有多位用户 +1。但 1.x 的做法是 miloco 自己拉起并管理模型进程(miloco-ai_engine 容器 + 面板上点「加载模型」),结果是大量环境相关失败(显卡直通 / WSL2 / 容器反复重启),最终无人跟进、stale 自动关闭。值得注意的是那个 issue 里用户自己找到的可行解:
「已放弃 ai_engine……直接安装 lm studio,宿主机 docker 装个 backend,把链接丢给 backend 就行了。」
也就是说,「miloco 不管模型进程、只消费一个本地服务」这条路本来就是通的 ,只是今天不是一等公民。这个提案是把它做成一等公民 —— 并且做对,而不是简单换个 base_url。
提议:加一条本地 通路,并且按本地模型的方式去消费它
参考实现用微软开源的 Mage-VL (Apache-2.0,4B,codec-native )。
为什么不能只是"本地起个 vLLM 然后改 base_url"
因为那样做会把这条路最值钱的部分整个丢掉。
codec-native 的意思是:模型直接消费 H.264 码流里的运动矢量与残差 ,而不是解码后的稠密帧 —— 它从原始帧里挑出重要的 16×16 patch 拼成"画布"再送进 ViT,重要性判据跟着编码代价走。而 OpenAI chat 协议根本传不了这个:模型自带的 inference.py::run_online 是把视频按帧当 image_url 发的,SGLang 的接入也只做了常规 VLM 集成。挂成 OpenAI 端点,拿到的就是一个普通的 4B 帧采样模型 ,codec 的收益一分不剩。
实测收益(RTX 5090,本项目真实家庭语料)
同一段家庭监控视频,同一个模型,两种视觉后端:
frames(均匀帧采样)
codec-native
差异
prompt token
7338
736
−90%
visual patch
28672
2304
−92%
单次推理
0.89s
0.28s
快 3.2×
端到端(HTTP 往返 + 编码 + 3 条规则判定)约 1.7s ,显存峰值 12 GB 。作为对照,同一部署下云端 omni 单次调用常在 6~18s。
削减幅度高于官方宣称的 75%,原因合理:家庭监控画面基本静止,运动矢量与残差本就稀疏 —— 这类场景恰好是 codec-native 的最佳适用面。"24 小时不停地看一个基本不动的房间"这件事,和 codec 通路的成本结构是天生匹配的。
三条代价随之改变:
云端 API(现状,保持默认)
本地视觉(本提案)
凭据
必须有模型厂商 API Key
不需要任何 Key
token 成本
按量持续计费
0
画面
离开本地
不出本地
硬件
无要求
需要一块可用的 NVIDIA GPU
云端仍是默认。 官方推荐硬件(Mac mini / 树莓派)继续走云端;有 GPU 的用户可以选本地。不主动切换的用户,行为与今天完全一致。
架构落点
这条通路落在项目已有的插拔缝 上 —— perception/engine_base.py 的 BasePerceptionEngine 抽象基类(现有云端 PerceptionEngine 就是它的实现之一)。新增一个同接口的本地实现,由 PerceptionEngineProxy 按配置二选一,流水线骨架不动。
GPU 推理放在独立边车服务 里,miloco 只通过 HTTP 认识它。两条边界是刻意的:
主包绝不引入 torch/CUDA 。miloco 的目标硬件是 CPU-only 的 Mac mini / 树莓派,不该为一个可选功能背上几个 GB 的 GPU 依赖。边车可以跑在另一台带显卡的机器上。
绝不接管模型进程的生命周期 。不下载权重、不拉起、不重启推理服务、没有「点击加载模型」按钮 —— 这条是 无法加载本地模型 #144 的直接教训:一旦 miloco 管理模型容器,故障面就扩散到显卡直通、驱动、容器,既超出项目边界也无法支持。起服务的方法放文档。
契约与模型无关 :送视频段 + 提问 + 规则 → 返回描述 + 逐条判定。任何实现同一 HTTP 接口的服务都能替换参考实现,miloco 侧不改一行代码。
能力边界(说在前面,不藏)
这条通路不是云端通路的等价替代。下面每一条都是刻意的取舍,而不是"暂未实现" ,并且会在切换前就显示在「模型」页上:
纯视觉,不产音频结论。 speeches / env_sounds 恒为空。本地视觉模型没有音频输入,让一个听不见的模型去填这两个字段,只会得到凭画面脑补的人声与环境音 —— 这与项目已有的 requires_audio 门控是同一条理由。需要音频能力就用云端通路。
不产主动建议。 suggestions 恒为空。主动建议依赖跨模态与长上下文推理,4B 级视觉模型给不出可用质量,所以不做替代实现,而不是做一个差的。
规则命中只上报,不执行设备动作。 命中作为"观察结论"投递给 agent,不含 规则里配置好的那些设备动作。既不改写成 DYNAMIC(改写会丢掉 cooldown_minutes / idempotent 这个 schema 里唯一的限流手段,以及行动台账里 source=rule 的归属),也不换条路替用户做掉。要不要动设备、动哪个,由 agent 自己判断。
这条边界要说清楚它约束的是什么:它约束感知层 不自己直连设备。规则命中仍会投递给 agent,而 agent 是可以驱动设备的 —— 风险是被"先经一次 LLM 判断"所缓解 ,不是被消除。
认人不走大模型,用本地 ReID。 这一条本来打算照搬云端方案,实测证明搬不了 —— 见下。
关于认人:一条值得单独说的实测结论
最初的做法是把云端那套原样移植:成员参考图 + 完整片段 + bbox 指人 + 要求 JSON 输出。在 7 个真实双人场景上实测(人工核对真值):
逐人正确,名单顺序 小亮 在前 8/14
逐人正确,名单顺序 阳阳 在前 0/14
退化基线 4/14 与 10/14
纯本地 ReID,同批场景同一个库 14/14
两种顺序合起来 29%,低于二选一瞎猜的 50% ;把名单里两个人的先后调换,7 个场景有 4 个答案会变。最决定性的一次:把待识别的那张图换成一张纯灰图 ,它照样报出一个人名。模型本身不瞎 —— 只问性别和衣着是 5/5 —— 但跨图细粒度同人比对不是这个量级的视频模型的能力 。
所以认人整条改成不经过大模型:检测 → ReID 取特征 → 与身份库余弦比对 → 得到名册,再把「谁在画面的哪个位置」以文本随提问送给模型,模型只负责把给定的名字贴到给定的坐标上 —— 这件事它做得很稳(同批场景 7/7)。
这里没有新增任何依赖:human_body_reid_v2.onnx 仓库里本来就有、本来就在跑(用于 DeepSORT 跨帧关联),tier_a/*.npy 也是登记流程一直在写的特征 —— library.py 自己的注释就写着它们存下来是为了「后续做『未识别 track 跟已注册成员快速比对』」。这个提案就是把那个「后续」补上。
但这条路有它自己的硬限制,必须一并说明 (详见 PR 的已知限制):判成员的相似度阈值是拿电视误检标定的、从未拿人标定过 —— 未登记的人对一个健康身份库的 top1 相似度中位 0.818,实测 33 个陌生人框 33 个全被安上了成员名。本方案假定画面里只出现已登记成员。
非目标
不接管 GPU 进程生命周期 :不下载权重、不拉起/重启推理服务、不做「点击加载模型」。
不改变默认行为 :不配置本地通路的用户,行为与今天完全一致。
不绑定具体模型 / 推理框架 :契约与模型无关,Mage-VL 只是当下最合适的参考实现与实测对象。
不做云端+本地的混合模式 :本地通路目前还不够稳,不适合当常驻层。现在是二选一开关。
一点披露
Mage-VL 的模型卡写明 "released for research purposes only and are not intended for product or service deployment"(许可证本身是 Apache-2.0)。因此本提案的主体是通路与契约这个能力 ,Mage-VL 作为当下最合适的参考实现;即使项目对该模型本身有顾虑,通路依然成立 —— 换任何满足契约的本地视觉服务都能工作。
实现已经完成,并在一套真实家庭部署上连续运行验证过。PR 随后提交,会链接到本 issue。
现状:感知只有一条路,而这条路的三个代价是结构性的
今天的视频感知只有一种走法:把时间窗打包成 mp4,经 OpenAI 兼容协议发给云端多模态大模型。这条路成熟、能力全,但它同时决定了三件事:
PREREQ_MISSING,整个"看见家里发生了什么"的能力不存在。社区对"本地"的诉求是明确存在的:#144(无法加载本地模型)有多位用户 +1。但 1.x 的做法是 miloco 自己拉起并管理模型进程(
miloco-ai_engine容器 + 面板上点「加载模型」),结果是大量环境相关失败(显卡直通 / WSL2 / 容器反复重启),最终无人跟进、stale 自动关闭。值得注意的是那个 issue 里用户自己找到的可行解:也就是说,「miloco 不管模型进程、只消费一个本地服务」这条路本来就是通的,只是今天不是一等公民。这个提案是把它做成一等公民 —— 并且做对,而不是简单换个
base_url。提议:加一条本地通路,并且按本地模型的方式去消费它
参考实现用微软开源的 Mage-VL(Apache-2.0,4B,codec-native)。
为什么不能只是"本地起个 vLLM 然后改 base_url"
因为那样做会把这条路最值钱的部分整个丢掉。
codec-native 的意思是:模型直接消费 H.264 码流里的运动矢量与残差,而不是解码后的稠密帧 —— 它从原始帧里挑出重要的 16×16 patch 拼成"画布"再送进 ViT,重要性判据跟着编码代价走。而 OpenAI chat 协议根本传不了这个:模型自带的
inference.py::run_online是把视频按帧当image_url发的,SGLang 的接入也只做了常规 VLM 集成。挂成 OpenAI 端点,拿到的就是一个普通的 4B 帧采样模型,codec 的收益一分不剩。实测收益(RTX 5090,本项目真实家庭语料)
同一段家庭监控视频,同一个模型,两种视觉后端:
端到端(HTTP 往返 + 编码 + 3 条规则判定)约 1.7s,显存峰值 12 GB。作为对照,同一部署下云端 omni 单次调用常在 6~18s。
削减幅度高于官方宣称的 75%,原因合理:家庭监控画面基本静止,运动矢量与残差本就稀疏 —— 这类场景恰好是 codec-native 的最佳适用面。"24 小时不停地看一个基本不动的房间"这件事,和 codec 通路的成本结构是天生匹配的。
三条代价随之改变:
云端仍是默认。 官方推荐硬件(Mac mini / 树莓派)继续走云端;有 GPU 的用户可以选本地。不主动切换的用户,行为与今天完全一致。
架构落点
这条通路落在项目已有的插拔缝上 ——
perception/engine_base.py的BasePerceptionEngine抽象基类(现有云端PerceptionEngine就是它的实现之一)。新增一个同接口的本地实现,由PerceptionEngineProxy按配置二选一,流水线骨架不动。GPU 推理放在独立边车服务里,miloco 只通过 HTTP 认识它。两条边界是刻意的:
契约与模型无关:送视频段 + 提问 + 规则 → 返回描述 + 逐条判定。任何实现同一 HTTP 接口的服务都能替换参考实现,miloco 侧不改一行代码。
能力边界(说在前面,不藏)
这条通路不是云端通路的等价替代。下面每一条都是刻意的取舍,而不是"暂未实现",并且会在切换前就显示在「模型」页上:
纯视觉,不产音频结论。
speeches/env_sounds恒为空。本地视觉模型没有音频输入,让一个听不见的模型去填这两个字段,只会得到凭画面脑补的人声与环境音 —— 这与项目已有的requires_audio门控是同一条理由。需要音频能力就用云端通路。不产主动建议。
suggestions恒为空。主动建议依赖跨模态与长上下文推理,4B 级视觉模型给不出可用质量,所以不做替代实现,而不是做一个差的。规则命中只上报,不执行设备动作。 命中作为"观察结论"投递给 agent,不含规则里配置好的那些设备动作。既不改写成 DYNAMIC(改写会丢掉
cooldown_minutes/idempotent这个 schema 里唯一的限流手段,以及行动台账里source=rule的归属),也不换条路替用户做掉。要不要动设备、动哪个,由 agent 自己判断。这条边界要说清楚它约束的是什么:它约束感知层不自己直连设备。规则命中仍会投递给 agent,而 agent 是可以驱动设备的 —— 风险是被"先经一次 LLM 判断"所缓解,不是被消除。
认人不走大模型,用本地 ReID。 这一条本来打算照搬云端方案,实测证明搬不了 —— 见下。
关于认人:一条值得单独说的实测结论
最初的做法是把云端那套原样移植:成员参考图 + 完整片段 + bbox 指人 + 要求 JSON 输出。在 7 个真实双人场景上实测(人工核对真值):
两种顺序合起来 29%,低于二选一瞎猜的 50%;把名单里两个人的先后调换,7 个场景有 4 个答案会变。最决定性的一次:把待识别的那张图换成一张纯灰图,它照样报出一个人名。模型本身不瞎 —— 只问性别和衣着是 5/5 —— 但跨图细粒度同人比对不是这个量级的视频模型的能力。
所以认人整条改成不经过大模型:检测 → ReID 取特征 → 与身份库余弦比对 → 得到名册,再把「谁在画面的哪个位置」以文本随提问送给模型,模型只负责把给定的名字贴到给定的坐标上 —— 这件事它做得很稳(同批场景 7/7)。
这里没有新增任何依赖:
human_body_reid_v2.onnx仓库里本来就有、本来就在跑(用于 DeepSORT 跨帧关联),tier_a/*.npy也是登记流程一直在写的特征 ——library.py自己的注释就写着它们存下来是为了「后续做『未识别 track 跟已注册成员快速比对』」。这个提案就是把那个「后续」补上。但这条路有它自己的硬限制,必须一并说明(详见 PR 的已知限制):判成员的相似度阈值是拿电视误检标定的、从未拿人标定过 —— 未登记的人对一个健康身份库的 top1 相似度中位 0.818,实测 33 个陌生人框 33 个全被安上了成员名。本方案假定画面里只出现已登记成员。
非目标
一点披露
Mage-VL 的模型卡写明 "released for research purposes only and are not intended for product or service deployment"(许可证本身是 Apache-2.0)。因此本提案的主体是通路与契约这个能力,Mage-VL 作为当下最合适的参考实现;即使项目对该模型本身有顾虑,通路依然成立 —— 换任何满足契约的本地视觉服务都能工作。
实现已经完成,并在一套真实家庭部署上连续运行验证过。PR 随后提交,会链接到本 issue。