借助 AI 从 0 到 1 搭建图像对比服务(五):VLM 看图说话——让大模型亲眼看图,说出它看见了什么
一、场景:CLIP 和 EXIF 都没解决的那个问题
前两只眼睛装好了。CLIP 能比"内容像不像",EXIF 能查"出生证"。但做着做着,我发现有个场景它俩都搞不定:
巡检牌上那行字。
举个例子。巡检现场每台设备都挂一块牌子,写着"设备编号、上次保养日期、责任人"。工人正常巡检,拍的照片上这块牌子清清楚楚;有人偷懒,拿一张"长得差不多"的图来顶,牌子上那行字其实不一样。
CLIP 看这两张图:都是厂房的牌子,构图一样,相似度 0.9——它觉得"像"。可实际上牌子上的字都对不上,这就是该出问题的巡检记录。
CLIP 不懂文字,EXIF 又只管元数据。要看出"字不一样",得有人真的把图看一遍,读出里面的字。
这就是第三只眼睛:VLM——视觉大模型,让 AI 亲眼看图。
二、VLM 是啥:先让 AI 讲人话
老规矩,先问:
VLM 是啥?它跟 CLIP 有啥区别?我在巡检场景里,能让它帮我看出什么来?AI 的回答我翻译一下:
CLIP 是"瞄一眼说像不像",VLM 是"盯着看半天,把看到的说给你听"。
区别在于输出。CLIP 忙活半天,最后只给你一个数(相似度 0.9),是个"哑巴"。而 VLM 是个"话痨"——你给它一张图,它能张口说出一大段:图里有什么字(OCR)、有什么东西(物体)、是个什么场景(描述)。
我要的就是这个——不是让它打个分,是让它把图"读出来",读到字、读到物体,我再去比两张图"读出来的内容"像不像。
通过AI匹配硬件资源,我用了 Qwen 系的视觉模型(Qwen2.5-VL),一个开源的视觉多模态大模型,本地跑,不依赖外部 API。
三、给 AI 的指令:让它"一次说全"
模型选好了,接下来是设计它"怎么个说法"。AI一开始的想法很简单:OCR 是一个任务、认物体是一个任务、描述场景又是一个任务,那就分三次调。
请分析这张图片,返回 JSON 格式: {"ocr_text": "识别到的所有文字", "objects": ["物体1", "物体2"], "description": "图片描述"} 只输出 JSON,不要输出其他内容。我想了一下:分三次调,等于每次都要把整张图再发一遍给模型,网络开销三倍、推理三倍、时间三倍。而视觉模型本来就支持"看图+答多题",一次给一张图,让它一口气把文字、物体、描述都吐出来,用 JSON 包好,最划算。
我把任务固化成一个叫all的预设(OCR + 物体 + 描述三合一),以后要单测某一项也留着独立的入口,但默认就走这个"一次说全"。
四、落地:跟一个"话痨"打交道的三件麻烦事
模型开始返回内容后,我发现跟VLM打交道,真不是把结果拿来就用,有三件麻烦事。
麻烦一:它说话不老实,爱带"包装"
明明让它"只输出 JSON",它偏要画蛇添足。有时候前面加句"好的,我来分析:",有时候把 JSON 包在 markdown 的代码块里:
```json {"ocr_text": "..."}我拿 `json.loads` 一看,根本无法解析——因为带了代码块标记和废话。 AI 给的解法是**容错解析**:先把输出里的 ```json 代码块剥掉,再从第一个 `{` 到最后一个 `}` 截取,硬抠出 JSON 对象;万一 JSON 也有问题,再退一步找第一个 `[` 到 `]`。一层层兜底,总有一层能救回来。 这个细节很能说明问题:**模型输出是"人话",不是"程序返回值"。** 你不能指望它严格守规矩,得在客户端做好容错解析。 ### 麻烦二:超时了怎么办 视觉模型看图,比纯文本慢多了。图片一复杂,可能几秒到几十秒都等不到回答。要是请求挂在那,整个接口就堵死了。 AI 的处理是:**给每次调用设超时,超时就标记为"失败",但绝不让它卡死整个流程。** 而且专门加了个"健康检查"——在正式干活前先探一下 VLM 服务还活着没(GET 一下 `/v1/models`),挂了就直接跳过,不白等。 这背后是工程里常说的"**快速失败**":宁可这次分析失败,也不让一个慢服务拖垮全局。 ### 麻烦三:VLM 挂了我怎么办 最核心的一个设计问题:**VLM 如果不可用了,整个服务是不是就得宕掉?** AI 的处理很果断:VLM 是**可选增强**,不是必需。代码里用 `enable_vlm` 控制,默认关。为什么默认关?因为它是四只眼睛里**最贵的**——每次都要下载/传图、跑一次大模型推理,CLIP 是毫秒级,VLM 是秒级,成本差一个量级。 于是定下规矩: - **VLM 没启用 / 不可用 → 不影响主流程**,其他维度照常打分; - **VLM 可用 → 权重给足**,CLIP 权重从 0.5 自动降到 0.9(把 VLM 那份让出来),总权重始终守恒。 一句话:**VLM 是锦上添花,不是雪中送炭。它坏了,服务照样跑,只是"少了一双眼睛"。** ## 五、怎么比"读出来的内容" VLM 把两张图都"读"出来了,怎么比"读得像不像"?这里又有两个维度,我逐个验收。 ### 维度一:文字像不像(OCR 相似度) 模型读出了两串文字(比如牌子上那行字),怎么比?AI 用了 Python 内置的 `difflib` 里的 `SequenceMatcher`,算两段文本的相似度,0~1。 原因很简单:**它比的是"文本序列有多像",不是"完全一样"。** 巡检牌上如果有个字被树挡了一点,OCR 可能读错一个字,SequenceMatcher 照样能给出 0.9 的高分——比死板的全等判断实用得多。 ### 维度二:物体像不像(物体重叠度) 模型还读出了两串物体列表,比如图一是 `["管道", "阀门", "仪表"]`,图二是 `["管道", "阀门", "仪表", "工人"]`。怎么比? AI 用了**Jaccard 重叠度**,公式就一句大白话: ```text 重叠度 = 两串物体都有的数量 ÷ 两串物体加起来的所有数量图一 3 个、图二 4 个,共有的是"管道、阀门、仪表"3 个,并集是"管道、阀门、仪表、工人"4 个,重叠度 = 3/4 = 0.75。
想了想合理性:它惩罚"多出来"的东西——图二多了一个"工人",说明场景里多了个人,重叠度就降了,这正好符合我"防作弊要抠细节"的需求。
合起来打分
最后,AI 把两个维度加权合成一个 VLM 内容分:
VLM 内容分 = OCR 相似度 × 0.6 + 物体重叠度 × 0.4OCR 占六成,因为对巡检防作弊来说,文字(设备编号、日期)是最硬的信息,物体只是辅助判断场景。哪个维度没数据,就只算有的那个。这个权重倾向我也认同——字对不上,比场景里多个东西严重得多。
六、小结:AI 在"整合复杂能力"上的价值
第三只眼睛装完了。这只跟前两只都不一样——CLIP 和 EXIF 是"算一个数",VLM 是把一个会说话的大模型,调教成合身的"看图助手"。我在这章最有收获的三点:
- 它帮我克制了"想当然":我以为 OCR、认物、描述要分三次调,它一句话点醒——一次调用全包了,省三倍成本。AI 会给出我没想到的优化路径。
- 它把VLM返回的自然语言变成了标准动作:容错解析、超时、健康检查、快速失败,这些跟"AI 打交道"才特有的坑,它全都提前铺好了路。跟 VLM 沟通,跟调普通 API 完全是两回事。
- 它始终坚持"主流程不被拖垮":VLM 再强也是可选项,默认关、挂了不影响大局、权重自动守恒。贵的眼睛,永远是辅助。
四只眼睛,装好三只了。剩最后一只,也是防作弊最"对症"的一只——防翻拍检测:专门对付那种"拿屏幕/照片再拍一遍"的作弊手法。
下一篇进第四只眼睛,也是最有工业味的一只。