在 Jetson Orin 上用 CUDA 跑通本地视觉模型的血泪史
前言:Agent 的"眼睛"难题
2026 年了,AI Agent 已经能用 Llama、Qwen、DeepSeek 这些纯文本模型写代码、做推理、聊天对话,表现相当不错。但 Agent 活在一个充满图像的世界里——它需要看截图、读营养标签、识别物体、提取图中文字。**视觉能力不是锦上添花,是刚需。**
问题在于:绝大多数本地视觉模型的教程都默认你有一块 24GB 显存的 NVIDIA 显卡。如果你用的是 Jetson Orin(7.4GB 统一内存,ARM64 架构),那就是完全不同的故事了。
我的设备
| 配置项 | 参数 |
| 设备 | NVIDIA Jetson Orin nano super |
| 内存 | 7.4G统一内存(CPU,GPU共享) |
| CUDA | 12.6,算力8.7 |
| 系统 | Ubuntu 22.04(ARM64) |
| PyTorch | 2.5.0 |
| 网络环境 | 国内,只能访问百度/清华源等 |
折腾之路:四次失败
尝试一:Ollama 视觉模型 ❌
Jetson 上本来就装了 Ollama,里面还有 `llava-phi3:3.8b` 和 `qwen2.5vl:3b` 两个视觉模型。能用是能用,但:
- Ollama 的二进制文件没有编译 CUDA 支持,纯 CPU 推理
- `llava-phi3` 中文输出是乱码
- `qwen2.5vl:3b` 倒是准确,但一张图要 60 秒
bash
# 验证 Ollama 有没有 CUDA:
ldd $(which ollama) | grep cuda
# 输出为空——没链接任何 CUDA 库
CPU 跑到 100%,GPU 全程看戏,这谁受得了。
尝试二:从源码编译 llama.cpp + CUDA ❌
这是最"正统"的做法:克隆 llama.cpp 源码,用 CMake 开启 CUDA,编译出带 GPU 加速的 server。
bash
git clone https://github.com/ggerganov/llama.cpp.git
cd llama.cpp
cmake -B build -DGGML_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES=87
cmake --build build -j4 --target llama-server
然后噩梦开始了。llama.cpp 里有 184 个 CUDA kernel 文件,每个都要在 ARM64 的 CPU 上跑 nvcc 编译。模板实例化(`fattn-tile-instance-*`)产生了大量变体,每个编译 15-30 秒。22 分钟后,300+ 目标文件只编完了 127 个,CPU 全程 95%。
Jetson 的 ARM CPU 跑编译本来就是弱项,再加上 CUDA kernel 的海量模板实例,这个方案的编译时间直接劝退。杀掉了。
尝试三:moondream ❌
装上 `moondream` Python 包,一调用发现——1.2.2 版本已经变成纯云端 API 了(`CloudVL`),本地推理接口被砍了。此路不通。
---
尝试四:transformers 5.9 + Qwen2-VL ❌
最新版 `transformers==5.9.0` 需要 PyTorch ≥ 2.6,因为引入了 `torch.distributed.tensor.device_mesh`。Jetson 自带的 PyTorch 是 2.5.0,不兼容。import 直接报错。
最终方案:Florence-2 + PyTorch 原生 CUDA ✅
为什么是 Florence-2
[Florence-2](https://huggingface.co/microsoft/Florence-2-base) 是微软出的超轻量视觉模型:
- 0.23B 参数,比很多"小模型"还小一个数量级
- 支持 OCR、图像描述、物体检测等多种任务
- 模型文件只有 445MB,下载快、加载快
- 在 Jetson 的 7.4GB 内存里只占 0.5GB 显存
核心经验:降级 transformers 到与 PyTorch 2.5 兼容的版本,并使用国内镜像加速下载。
安装步骤
# 1. 修复 numpy 版本冲突(PyTorch 2.5 需要 numpy 1.x)
pip install "numpy<2" --force-reinstall
# 2. 安装兼容版的 transformers(清华源加速)
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple "transformers==4.45.0"
# 3. 安装依赖
pip install einops timm accelerate pillow -i https://pypi.tuna.tsinghua.edu.cn/simple
完整脚本
#!/usr/bin/env python3
"""Florence-2 CUDA 识图 —— Jetson 原生 GPU 加速"""
import sys, os, time
# 国内用户使用 HF 镜像站,否则下载模型会很慢
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
import torch
from transformers import AutoProcessor, AutoModelForCausalLM
from PIL import Image
MODEL_ID = "microsoft/Florence-2-base"
def load_model():
"""加载模型到 GPU"""
print("⏳ 正在加载 Florence-2-base 到 GPU...", flush=True)
t0 = time.time()
model = AutoModelForCausalLM.from_pretrained(
MODEL_ID,
torch_dtype=torch.float16, # 半精度,省显存
trust_remote_code=True # Florence-2 需要
).to("cuda")
processor = AutoProcessor.from_pretrained(MODEL_ID, trust_remote_code=True)
mem = torch.cuda.memory_allocated() / 1e9
print(f"✅ 加载完成,耗时 {time.time()-t0:.1f}s,占用显存 {mem:.1f}GB", flush=True)
return model, processor
def run(image_path, task, model, processor):
"""执行推理"""
img = Image.open(image_path).convert("RGB")
inputs = processor(text=task, images=img, return_tensors="pt").to("cuda", torch.float16)
t0 = time.time()
with torch.no_grad():
gen = model.generate(
input_ids=inputs["input_ids"],
pixel_values=inputs["pixel_values"],
max_new_tokens=1024,
num_beams=3,
do_sample=False
)
text = processor.batch_decode(gen, skip_special_tokens=False)[0]
result = processor.post_process_generation(
text, task=task, image_size=(img.width, img.height)
)
print(f"⚡ 推理耗时: {time.time()-t0:.2f}s", flush=True)
return result
if __name__ == "__main__":
if len(sys.argv) < 2:
print("用法: python3 vision_cuda.py <图片路径> [任务]")
print("任务选项:")
print(" ocr - 提取图中所有文字(支持中文)")
print(" desc - 详细描述图片内容")
print(" detail - 超详细描述")
print(" obj - 检测图中物体")
sys.exit(1)
path = sys.argv[1]
task_arg = sys.argv[2] if len(sys.argv) > 2 else "ocr"
TASKS = {
"ocr": "<OCR>",
"desc": "<DETAILED_CAPTION>",
"detail": "<MORE_DETAILED_CAPTION>",
"obj": "<OD>",
}
if task_arg not in TASKS:
print(f"未知任务: {task_arg},可选: {list(TASKS.keys())}")
sys.exit(1)
model, processor = load_model()
result = run(path, TASKS[task_arg], model, processor)
print(f"\n📷 识别结果:\n{result.get(TASKS[task_arg], str(result))}")
使用示例
# OCR 提取文字(中文公告、菜单、营养标签等)
python3 vision_cuda.py 营养标签.jpg ocr
# 描述图片内容
python3 vision_cuda.py 风景照.jpg desc
# 检测图中的物体
python3 vision_cuda.py 街道.jpg obj
---
性能对比
| 指标 | Ollama(CPU) | Florence-2(CUDA) |
| 推理耗时 | 60秒 | 1秒 |
| GPU显存 | 0GB(GPU闲置) | 0.5GB |
| OCR准确率 | 中文乱码,不稳定 | 准确 |
| 模型大小 | 2.9GB | 445MB |
60 倍提速。 总占用不到 1GB 存储,在 Jetson Orin 上跑得游刃有余。
---
实测效果
> 输入:一张砖地上趴着小蜥蜴的照片
| 人物 | 耗时 | 结果 |
| OCR | 0.88s | 图中无文字,返回为空 |
| 详细描述 | 1.3s | “一只小蜥蜴蹲在砖路上,周围散落着枯叶“ |
局限与展望
1. 图像描述是英文的。 Florence-2 的 caption 输出是英文。如果需要中文描述,可以加一个翻译环节,或者换用 `Qwen2-VL-2B`(需要约 4GB 显存)。
2. 不支持多轮对话。这是一个 CLI 工具,不能像 GPT-4V 那样对图片进行多轮问答。如果需要这个能力,需要更大的 VLM 模型。
3. OCR 中文支持良好。 虽然描述是英文,但 OCR 提取中文文字的效果很扎实。
---
踩坑总结
1. ARM64 + CUDA 兼容性差。预编译的二进制文件几乎不包含 ARM64 CUDA 版本。从源码编译又极慢——Jetson 的 ARM CPU 编译 CUDA kernel 是灾难级的。
2. 版本匹配是关键。永远要根据 PyTorch 版本选择 transformers 版本。Jetson 的 PyTorch 2.5 → transformers 4.45 是安全组合。
3. 小模型是 Jetson 的好朋友。 7.4GB 统一内存要同时跑系统和模型,0.23B 的 Florence-2 只占 0.5GB,剩下的 6.9GB 留给 Agent 随便用。
4. 国内用户记得配镜像。HuggingFace 用 `hf-mirror.com`,pip 用清华源 `pypi.tuna.tsinghua.edu.cn`,不然下模型能等到天荒地老。
最后
这一趟折腾下来,最大的感受是:在资源受限的设备上,选对模型比写出好代码更重要。Florence-2 这种专门为边缘设备设计的轻量模型,比硬塞一个 7B 的大模型明智得多。
如果你也在 Jetson 上跑 AI Agent,需要视觉能力,希望这篇文章能让你少走弯路。
Jetson Orin 上原创,用一只砖地上的蜥蜴测试通过。 🦎
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)