领导说跑不起来就全组加班,我连夜把 Qwen2-VL 塞进了 6G 显存笔记本
故事是这样的。
工作上突然甩过来一个很急的需求。
几千张图。准确说,后面扩到七千多张。每张里有一块短信截图区域,要把里面的验证码抠出来,再跟 Excel 表里的字段逐条比对,看一不一样。
听起来不复杂对吧。
复杂的是时间。
需求非常急。领导的原话大概是,如果第二天大模型还跑不起来,就协调全组十几个人一起干。肉眼看。一张一张看。
而这件事,指定由我来协调。
我当时心里只有两个念头。
我不想加班。
我也不想让同事加班。
你要是经历过全组一起熬夜对图,就知道那有多磨人。七千多张图,肉眼核,不是加一晚上班的事,是加好几天,还得十几个人一起埋进去。人眼会花,标准会漂,最后还不一定比机器稳。
我不信。
不是不信领导,是不信「这么发达的 AI 时代,还得靠全组人肉刷图」这件事。
于是我开始想办法。
第一反应当然是 OCR。
我也是这么想的。OCR 嘛,识别文字,听起来就该快。结果一跑,脸就绿了。
一张图大概 50 秒(这个时候已经凌晨三点了,按照计划第二天必须完成)。
你算一下,几千张乘下去,整份数据跑完要十个小时量级。更要命的是准确率,不到 50%。不到一半。等于机器干完,人还得再核一遍,甚至核得比直接人看还累。
那一刻我真的有点崩溃。
不是技术不行那种抽象崩溃,是「明天全组可能要因我加班」的具象压力。
然后我就一直问 AI。怎么办。还有没有别的路。别跟我说再调调阈值、再裁裁图,我没那个时间跟传统 OCR 谈恋爱。
AI 给了一个方案。本地跑通义的多模态大模型,Qwen2-VL,先上 2B。小,能塞进消费级显卡,数据还不出本机。
我笔记本是 RTX 3050,6G 显存。听起来寒酸,但当时顾不上寒酸不寒酸了。
我就让 Claude Code(我接入的DeepSeek V4 flash) 帮我写脚本,装环境,下模型,一点点把流程跑起来。
中间当然也不是一帆风顺。小显存 Windows 上,加载参数踩过坑,进程能无声无息蒸发。这些后面细聊。
但当它真正转起来之后,效果奇好。
奇好到什么程度呢。
比我们公司专业部门那边原来那套,还要好看。
我自己都有点懵。
不是嘲讽谁。是那种「我以为要靠人海,结果一个本地小模型就把活接住了」的失重感。同组同事因此免掉了那几天可能的集体加班。以前不太准、不太稳的字段,这次也被识别到了。
所以这篇文章,不是又一篇「如何优雅部署多模态」的说明书。
是一个打工人,在deadline压顶时,怎么用 6G 显存和 Qwen2-VL-2B,把全组从人肉核图里捞出来的笔记。
我自己也还在摸索。你就当听个真实经历。说不定你也正在被类似的需求堵在门口。
图片
先说结论,免得你悬着。
能跑。
而且不是「理论上能跑」,是 Windows 小卡也能跑,后来我在 Ubuntu 的 RTX 4090 上试更大的 Qwen2.5-VL-7B,那是后话。真正救命的第一枪,是 2B。
回到本地这块。
很多人一听本地多模态,第一反应就是,我显存不够吧,我是不是得上 24G,我是不是得量化到天昏地暗。
坦率的讲,一开始我也被这种氛围带跑了。
但真正上手之后你会发现,入门门槛比想象中低一点,坑也比教程里写的脏一点。
怎么说呢。教程往往告诉你 pip install,然后写上 device_map 等于 auto,世界就和平了。
现实会给你一记闷棍。
我在 3050 上第一次加载模型的时候,日志刚打出「加载模型」,然后,没有 Python 报错,没有 Traceback,终端直接回到提示符。
进程,没了。
我当时就愣住了。
你知道最烦的是什么吗?不是报错,是「连报错都没有」。像人突然在你面前蒸发,桌上还留着一杯没喝完的水。
后来查到,是 Windows 上的 Access Violation,那种进程级崩溃。再往下追,问题就指向一个很多人随手就写的参数,device_map 设成 auto。
在某些小显存 Windows 环境里,它不稳。
解法其实朴素得有点好笑。别让它「自动拆」,先老老实实加载,再整模搬到 `cuda`。
```python
model = Qwen2VLForConditionalGeneration.from_pretrained(
MODEL_DIR,
torch_dtype=torch.float16,
device_map=None,
low_cpu_mem_usage=True,
)
model = model.to("cuda")
```
就这。
4090 那种大卡上,device_map 设成 auto 通常没事。但小卡,我建议你先稳,再骚。
这块需要注意一下。你不是在追求最酷的加载姿势,你是在追求「今晚能跑完」。
说到这个,很多人会问,那我到底该下哪个模型?
我自己的感受是,先别盯着最大的看。
Qwen2-VL-2B-Instruct,大概 4 到 6G 显存就能转起来,适合入门、批量 OCR、字段抽取。印刷体截图、结构化字段,2B 往往已经够用。
Qwen2.5-VL-7B 更强,大概十四十六 G 往上更舒服,适合更复杂的理解和核对。
再往上,32B 量化那些,能冲准确率,但部署和调参明显更重。
我始终坚信一件事。
先把 2B 跑通,再谈 7B。
否则你很容易陷入一种很窒息的状态,模型还没看见图,人已经先被环境折磨干了。
图片
环境这块,我不想写成说明书口吻。就按我实际做过的顺序聊。
显卡要是 NVIDIA,6G 及以上更稳。驱动正常,`nvidia-smi` 能看见卡。模型本身大概 4.5G,磁盘再留点余量。
conda 开个干净环境,Python 3.10 够用。
```bash
conda create -n vlm-local python=3.10 -y
conda activate vlm-local
```
PyTorch 按你的 CUDA 装。CUDA 11.8 可以这样。
```bash
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118
```
装完先别急着下模型,先确认 GPU 真的在。
```python
import torch
print(torch.__version__)
print(torch.cuda.is_available())
print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else "no gpu")
```
如果这里都是 False,后面所有多模态故事都可以先暂停。不是模型不行,是地基没打好。
然后装推理依赖。
```bash
pip install transformers accelerate qwen-vl-utils pillow
pip install modelscope
```
模型我建议国内走 ModelScope,香。
```bash
modelscope download --model qwen/Qwen2-VL-2B-Instruct --local_dir ./Qwen2-VL-2B-Instruct
```
下完目录里会有那两块 safetensors,看着就安心。像家里囤了两袋米。
最小推理骨架,其实就一句话。
给一张图,给一句中文指令,让模型吐文本。
```python
from pathlib import Path
import torch
from transformers import Qwen2VLForConditionalGeneration, AutoProcessor
from qwen_vl_utils import process_vision_info
MODEL_DIR = "./Qwen2-VL-2B-Instruct"
IMAGE = "demo.jpg"
PROMPT = "请完整读取图片中的全部可见文字,按从上到下顺序输出,不要编造。"
model = Qwen2VLForConditionalGeneration.from_pretrained(
MODEL_DIR,
torch_dtype=torch.float16,
device_map=None,
low_cpu_mem_usage=True,
)
model = model.to("cuda")
model.eval()
processor = AutoProcessor.from_pretrained(MODEL_DIR, max_pixels=802816)
messages = [{
"role": "user",
"content": [
{"type": "image", "image": str(Path(IMAGE).resolve())},
{"type": "text", "text": PROMPT},
],
}]
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
image_inputs, video_inputs = process_vision_info(messages)
inputs = processor(
text=[text], images=image_inputs, videos=video_inputs,
padding=True, return_tensors="pt",
)
device = next(model.parameters()).device
inputs = inputs.to(device)
with torch.no_grad():
out = model.generate(**inputs, max_new_tokens=512, do_sample=False)
answer = processor.batch_decode(
out[:, inputs.input_ids.shape[1]:], skip_special_tokens=True
)[0]
print(answer.strip())
```
你看,我把 `max_pixels` 先写成了 802816。
为啥?
因为第二个大坑,叫显存爆炸。高分辨率整图会把视觉 token 顶上天。手机截图、单据特写,往往真的不需要 4K 原图。先小后大,能跑通再放开。这不是保守,这是活着。
还有个很阴的细节。如果你用了拆卡加载,`model.device` 有时会给你脸色。更稳的写法是。
```python
device = next(model.parameters()).device
inputs = inputs.to(device)
```
小坑,但能省你半小时自我怀疑。
顺着上面的,再聊聊 Prompt。
这块我以前也踩得很惨。
你会下意识觉得,模型既然能「看懂图」,那就让它像人一样随便看看呗。
结果呢?
任务越含糊,输出越漂移。
我后来给自己定了个很土的原则。任务越具体,输出越可控。
全文 OCR,就写「完整读取全部可见文字,按阅读顺序,不要编造」。
只要某个编号,就写「只输出那个编号,不要其它内容」。
抽字段,就写「找到某句式旁边的手写数字,只回答那个数字」。
你别指望 2B 拥有一个成熟打工人的默契。它更像一个很努力、但必须把需求写死的实习生。
说到实习生,就不得不提幻觉这件事。
潦草手写签名场景里,如果你逼它「一定要输出姓名」,它会很勤奋地给你编。李明,李华,张伟杰,像从某个高频姓名池里抓阄。
我第一次看到连续一串「李明」的时候,真的无语凝噎。
不是它坏,是你把「认不清」的退路堵死了,它只能表演勤奋。
更靠谱的产品形态,其实是核对式。把登记姓名作为条件,问这张签名是否像签这个名字,只回答是或否。
你以为 OCR 一定要先把字认出来,才能比对。
其实有些场景,核对比盲认更接近人的工作方式。人看到连笔签名,也经常是「对照着名字看像不像」,而不是先完美拆成三个楷书汉字。
我后来还专门拿一批样张,对比过盲认和核对。盲认那边,空结果和胡编姓名会把准确率拖得很难看。一改成核对,模型反而敢下判断了。不是它突然变聪明,是你把题出对人了。
空括号也一样。表单里括号空着,2B 有时会猜 0 或 1。这不是你 Prompt 没写好,是能力边界。难例就人工抽检,或者只把难例送云端。别跟边界死磕,死磕的通常是你的睡眠。
说到这里,你大概也能理解我为什么对「本地」这么执着了。
不是先有一篇部署教程,再去找业务。是业务先把刀架上来了。
传统 OCR 给我上的第一课很残酷。单张 50 秒,整包十小时,准确率不到一半。你加裁剪,加增强,加规则,纸糊的塔越堆越高,风一吹还是例外。
后来直接上本地多模态。Qwen2-VL-2B。Claude Code 帮我把脚本骨架拉起来,我负责把需求钉死,把显存坑填上,把批处理跑通。
效果奇好。好过公司专业部门原来那套。同组因此不用为七千多张图集体加班。
本地小模型做主力。听起来不炫,但能上线,还能救人。
坦率的讲,本地 VLM 的核心价值,不是处处碾压云。
是隐私,是成本,是可批量,还有一个常常被忽略的,是「能在 deadline 前把人从人海战术里救出来」。
你想想看。云端像外卖,又快又香,但每单都要付钱,而且食材要出小区。本地像自己开火,开火麻烦,锅还小,可一旦锅热了,夜里就能一直炒。更重要的是,锅在你工位旁边,领导问进度的时候,你看得见风扇在转。
当然也会有人说,那我直接用微信识图不就得了。
我非常理解这种感觉。
你不是天天做批量,你不是要对着 Excel 核几千个验证码,你只是偶尔拍一页书,微信当然香。
可一旦你面对的是成百上千张图,要固定字段,要可追溯报表,要尽量别让全组加班,问题就变了。工具没变贵,需求变重了。
大时代啊,朋友们。一边是 API 按次闪烁的账单,一边是自己电脑风扇突然开始起飞的声音。两种浪漫,都很贵。而我更想要的第三种浪漫,是同事不用熬夜。
如果你关心变现,这块卖点其实很清楚。数据不出本地,适合隐私敏感单据。闲鱼淘宝可以卖识别服务,客户发图你回文本或 Excel。也可以帮人做私有化部署。也可以做成发票合同字段、单据核验、书籍拍照转文字这类小工具。
技术文章本身也会获客。有人跑通了,就会来问,能不能帮我装到服务器上。
但我得把丑话说在前头。
一开始可能会有点笨拙。装环境、下模型、调显存,花的时间可能比你直接把图丢给云端还长。前两天你甚至会怀疑自己是不是在自找苦吃。
几乎所有本地部署的第一周,都有点像早年自己搭博客。你明明只是想发篇文章,结果先跟域名、报错、依赖版本纠缠了三天。可一旦跑通,那种「这东西在我机器上」的踏实,云端给不了。那种「同事不用因为我加班」的踏实,教程更给不了。
还有个小建议。别一上来就跟同事炫耀「我部署了多模态大模型」。先拿一张你自己的短信截图跑通,再拿十张相似图看看稳不稳。稳了,再谈批量。不稳,先别立 flag。愚钝如我,就是这么一点点拱出来的。
如果你也想亲自下场,我建议你别一次吃成胖子。按天来就行。
第一天,装环境,下 2B,跑通一张手机截图全文识别。
第二天,改成只抽某个字段,试不同 Prompt。
第三天,加批处理,断点续跑,导出 CSV。
第四天,压测显存,调 max_pixels,记录速度。
第五天,如果你有更大显存,再上 7B,同一批样张对比。
别跳步。跳步的人,通常死在第一步的假平静里。
写到这里,我突然想起早年那些「家用电脑也能上互联网」的故事。不是最强的机器赢了,是足够多人终于摸到了入口。多模态也一样。真正改变日常的,不一定是最大的模型,而是那个终于能在你自己桌上转起来的小模型。
6G 显存,听起来寒酸。
可寒酸有时候是门票。
屏幕前的你,如果也有一块不太体面的显卡,别先判死刑。
够你开一场很小,但很真的实验。
也够你,在某个突然砸下来的需求面前,试着把全组从加班里捞出来一次。
以上,既然看到这里了,如果觉得不错,随手点个赞、在看、转发三连吧,如果想第一时间收到推送,也可以给我个星标⭐~
谢谢你看我的文章,我们,下次再见。
另外一个风格文章:Qwen2-VL 本地部署实战:6G 显存跑多模态大模型-CSDN博客
更多推荐




所有评论(0)