用一个 O(1) 的感知哈希,把视觉大模型推理成本砍掉 80%
高频截图 + 视觉模型,绝大多数帧什么都没变。在昂贵的模型调用前加一道 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 |
1× |
基准 |
|
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 的落地,欢迎交流更多"不靠魔改模型就能降本"的工程技巧。
更多推荐

所有评论(0)