高频截图 + 视觉模型,绝大多数帧什么都没变。在昂贵的模型调用前加一道 O(1) 的闸门,成本直接降 8 倍。

一、问题:你在为“什么都没发生”持续付费

很多视觉 Agent 的落地场景都有一个共同特征:高频、重复、低信息增量

比如这个真实案例:定时截取客服工作窗口的截图,交给视觉大模型做 OCR,识别是否有新的未读消息,有就推送到飞书。

但跑起来之后发现一个问题:每隔几十秒截一次图,画面 80%~90% 的时间里根本没有变化。每一帧都调用视觉模型,意味着你在为「什么都没发生」持续付费——而且只要服务一直跑,这笔钱就源源不断地流出。

哪怕你选的是性价比最高的视觉模型,每次调用也要几秒延迟 + 按 token 计费。在高频场景下,这个成本会被时间线性放大。

二、解法:O(1) 的前置闸门

思路其实非常朴素:如果画面和上一次相比几乎没变化,那 OCR 的结果大概率也不会变——完全没必要调模型,直接复用上一次的结论。

于是架构变成这样:

截图
  │
  ▼
算感知哈希(O(1),微秒级)
  │
  ├── 汉明距离 < 阈值 → 画面没变,跳过模型调用 ↺
  │
  └── 汉明距离 ≥ 阈值 → 画面变了,才调模型识别 ✅

绝大多数帧都在第一个分支被拦下来了,模型只在「真正有变化」时才被唤醒。

用微秒级的廉价计算,挡掉秒级的昂贵调用。​ 这笔账怎么算都划算。

三、算法选型:aHash 翻车,dHash 救场

第一版我用的是平均哈希(aHash),因为它最简单:缩小成小图 → 算全图平均灰度 → 每个像素和平均值比大小得到哈希位。

听起来合理,但实际跑起来判定极不稳定:两张只差了几行未读消息的截图,汉明距离忽大忽小,经常「画面明明变了却被判为没变」。

为什么?​ 因为 aHash 的核心是全局平均灰度。而文字在画面里是局部的、低占比的,几行小字的出现或消失,对「整幅图的平均灰度」几乎没有影响,哈希值自然也几乎不变。

这就好比评价一锅汤的味道,只测了整锅的平均盐浓度——哪怕你往一个碗里加了一勺辣椒油,对整锅的平均值来说也微不足道。

换成差异哈希(dHash)后就稳了。​ dHash 不看绝对值,而是看梯度:比较每个像素和它右邻像素的明暗关系。关键差异在于——dHash 比较的是相邻像素的关系,而不是像素和全局平均的关系。

文字的本质是边缘,而边缘恰好是像素值剧烈跳变的地方。所以 dHash 对文字的出现、消失、移动都非常敏感。换上之后判定稳定性立刻上来了,阈值也从原来的 20 收紧到 15(实现里把图缩到 16×17 灰度、逐像素比横向梯度,得到 16×16 = 256 位哈希,两帧相差不到 15 位就视为「基本没变」、直接跳过)。

算法

核心思想

对文字变化的敏感度

稳定性

aHash

像素 vs 全局平均

❌ 极低

不稳定

dHash

像素 vs 右邻

✅ 高

稳定

pHash

DCT 频域分析

✅ 高

稳定但更慢

在这个场景下,dHash 是最佳平衡点:足够敏感 + 计算极快 + 实现简单。

四、模型选型:数据说话,不拍脑袋

前置闸门解决的是「调不调」,但凡走到「调」这一步,你还是要付钱。所以第二步优化是:让每次调用的单价尽可能低。

很多人的做法是「选最强的模型」,理由是「准确最重要」。但在这个场景下这个理由站不住脚:任务只是识别有没有新消息,是相对简单的 OCR,最强模型的能力在这里是溢出的。

所以我加了一行 [Token] 日志,按真实调用采样统计输入/输出 token 均值,再按官方定价换算月成本。结论很直观(下表金额为按当时定价的估算,用于对比量级,非精确账单):

模型

相对成本

说明

GPT-4o

基准

Gemini 2.5 Flash

≈ 1/8.4×

同任务准确度差异几乎可忽略

Gemini 2.5 Flash 的成本约为 GPT-4o 的 1/8.4,而在这个 OCR 任务上的准确度差异几乎可以忽略。于是先把 GPT-4o 换掉——这不是「降级」,而是在需求明确的前提下用数据驱动选型。

但成本不是唯一维度:稳定性把我拉回现实

换到海外模型后成本是下来了,但很快撞上另一个问题——这是个 7×24 长跑的后台监控,而走 OpenRouter 调海外模型时不时报错

[HTTP] 状态: 403
{"error":{"message":"The request is prohibited due to a violation of provider Terms Of Service.","code":403}}

对一个「一直跑着、随时要能识别新消息」的监控来说,间歇性 403 意味着漏报——再便宜也没用。所以最终线上换成了 Qwen-VL-Max:国内模型、链路稳定、不再有这类拦截,同样是相对简单 OCR 场景下够用又便宜的选择。

这段小插曲让我把选型的判断维度补全了:成本只是其中一维,可用性 / 稳定性在长跑型服务里往往是更硬的门槛。​ 一个便宜但会间歇性罢工的模型,对监控系统来说是负分。

五、成本是怎么降下来的

两个优化叠加,形成乘法效应:

总成本 = 调用次数 × 单次成本
         └ dHash 前置去重       └ 换掉 GPT-4o
           挡掉 50%              单价降到约 1/8.4

优化手段

作用

效果

dHash 前置去重

减少调用次数

实测挡掉约 50%(1200 轮 / 跳过 600 次)

换掉 GPT-4o

降低单次成本

实测替代模型仅约 1/8.4;最终线上用 Qwen-VL-Max(兼顾成本与稳定)

「挡掉一半调用」乘上「剩下的单价再降一个数量级」,整体成本降低一个数量级是完全可预期的(具体降幅会因画面变化频率、截图间隔而波动)。

顺带一提一个真实的细节:为什么明明画面“看起来没变”却只跳过 50%?很可能是因为界面上那个等待时间在每秒跳(代码里有 1m7s 这种红色计时),像素每帧都在变,dHash 就 judge 成“变了”、不跳过。这其实是个很好的工程细节,比笼统说“大部分没变”更有说服力。

六、这个思路能用到哪里

「高频 + 重复度高 + 视觉模型」这个组合,在 Agent 落地里非常常见:

场景

应用方式

UI 自动化监控

判断界面是否变化,变化时才分析

游戏挂机 Bot

检测画面是否进入新场景/出现新按钮

视频流关键帧抽取

用 dHash 做场景切换检测,只给关键帧调模型

桌面助手 Agent

定期截图理解状态,无变化时跳过

工业视觉质检

静态产线画面,只在检测到异常时深入分析

核心模式都一样:用廉价的确定性计算,过滤掉不需要昂贵模糊推理的样本。

七、延伸思考:Agent 成本优化的三层漏斗

把这个案例抽象一下,会得到一个通用的成本优化框架:

┌────────────────────────────────────────────────┐
│  第 1 层:完全不调(dHash 前置判断)            │
│  挡掉"根本不需要模型"的请求 —— O(1) 哈希  ✅    │
├────────────────────────────────────────────────┤
│  第 2 层:调便宜的(模型选型 / 路由)           │
│  简单任务用小模型 —— 1/8 ~ 1/20 的单价  ✅      │
├────────────────────────────────────────────────┤
│  第 3 层:调对的(RAG / 上下文裁剪 / 缓存)     │
│  减少输入 token、复用历史结果  ✅               │
└────────────────────────────────────────────────┘

大多数团队只盯着第 3 层使劲(怎么让 Prompt 更短、RAG 更准),但第 1 层和第 2 层的收益往往更大,而且实现更简单

八、一句话总结

一个 O(1) 的感知哈希挡在前面,一次数据驱动的模型选型落在后面。不改模型架构、不调 Prompt、不做蒸馏——仅靠工程化的前置判断和理性选型,就把成本打了下来。

在 Agent 落地的战场上,工程素养比模型能力更容易被低估,也更容易产生超额收益。​ 如果你也在做视觉 Agent 落地,欢迎交流更多「不靠魔改模型就能降本」的工程技巧。



如果你也在做视觉 Agent 的落地,欢迎交流更多"不靠魔改模型就能降本"的工程技巧。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐