MLX-VLM 中的 LocateAnything:在 Mac 上运行 NVIDIA 3B 视觉定位模型的完整指南
2026/9/18 0:29:16 网站建设 项目流程

MLX-VLM 中的 LocateAnything:在 Mac 上运行 NVIDIA 3B 视觉定位模型的完整指南

【免费下载链接】mlx-vlmMLX-VLM is a package for inference and fine-tuning of Vision Language Models (VLMs) on your Mac using MLX.项目地址: https://gitcode.com/GitHub_Trending/ml/mlx-vlm

LocateAnything 是 NVIDIA 发布的 3B 视觉语言定位模型(vision-language grounding model),专门用于在图像中定位目标对象与指代区域(referred regions)。本仓库(mlx-vlm)已将其完整移植到 Apple Silicon 上运行:包括 MoonViT 视觉编码塔、Qwen2.5 文本骨干、自定义图像处理器,以及模型专属的 Parallel Box Decoding(并行框解码)路径。读完本文,你将掌握如何通过 CLI 与 Python API 在 Mac 上运行 LocateAnything 的两种生成方式(自回归与并行框解码),并理解其从视觉塔到坐标 token 的完整架构原理。

模型概览

LocateAnything 是一个约 30 亿参数的视觉语言模型,核心任务覆盖视觉定位(visual grounding)、开放词汇目标定位(open-vocabulary object localization)与指代表达定位(referring expression localization),即根据自然语言描述在图像中输出目标的位置坐标框。其关键信息如下表:

项目内容
Model IDnvidia/LocateAnything-3B
架构MoonViT 视觉编码器 + MLP 连接器 + Qwen2.5 语言模型
参数量3B
模态图像 + 文本
核心任务视觉定位、开放词汇目标定位、指代表达定位

在 mlx-vlm 中,该模型位于 mlx_vlm/models/locateanything/ 目录,模型类型标识为locateanything(见 config.py),并通过 mlx_vlm/models/init.py 注册到模型工厂,因此可以直接使用nvidia/LocateAnything-3B作为模型 ID 加载。

通过 CLI 运行

与多数视觉语言模型一致,LocateAnything 支持标准的自回归生成(autoregressive generation),使用仓库提供的mlx_vlm.generate命令行入口即可:

mlx_vlm.generate \ --model nvidia/LocateAnything-3B \ --image examples/images/cats.jpg \ --prompt "Locate the cats." \ --max-tokens 128 \ --temperature 0.0

参数说明:

  • --model:指定 Hugging Face 上的模型标识符nvidia/LocateAnything-3B,首次运行会自动下载权重;
  • --image:输入图像路径,这里使用仓库自带的示例图 examples/images/cats.jpg;
  • --prompt:定位指令,例如"Locate the cats."
  • --max-tokens:最大生成 token 数。README 特别提示,场景中目标对象较多时应适当增大该值(例如 256 或 512),以保证每个对象都能被完整输出;
  • --temperature:采样温度,定位任务推荐设为0.0(贪心解码),保证输出坐标的确定性。

通过 Python API 运行

自回归生成

在 Python 中使用load加载模型与处理器,配合apply_chat_template组装提示词,再调用generate完成推理:

from mlx_vlm import generate, load from mlx_vlm.prompt_utils import apply_chat_template model, processor = load("nvidia/LocateAnything-3B") prompt = apply_chat_template( processor, model.config, "Locate the cats.", num_images=1, ) result = generate( model=model, processor=processor, prompt=prompt, image="examples/images/cats.jpg", max_tokens=128, temperature=0.0, ) print(result.text)

要点:

  • apply_chat_template需要传入num_images=1,因为模板中需要放置<image-N>占位符(见下文「处理器与图像占位符展开」);
  • 生成结果result.text中包含模型输出的坐标 token 序列,需要按模型约定解析为边界框;
  • max_tokens=128对于单目标场景足够,多目标场景请按 README 建议增大。

Parallel Box Decoding(并行框解码)

LocateAnything 相比普通 VLM 的特殊之处在于它暴露了model.pbd_generate这一直接模型 API,用于fasthybridslow三种生成模式。该路径不走高层generate,而是自行准备输入后直接调用模型方法:

from mlx_vlm import load from mlx_vlm.prompt_utils import apply_chat_template from mlx_vlm.utils import prepare_inputs model, processor = load("nvidia/LocateAnything-3B") prompt = apply_chat_template( processor, model.config, "Locate the cats.", num_images=1, ) inputs = prepare_inputs( processor, images=["examples/images/cats.jpg"], prompts=prompt, ) input_ids = inputs.pop("input_ids") inputs.pop("attention_mask", None) tokens = model.pbd_generate( input_ids, generation_mode="hybrid", max_tokens=128, **inputs, ) print(processor.decode(tokens, skip_special_tokens=False))

几个值得注意的细节:

  • prepare_inputs返回的input_ids需要从字典中取出单独传入,attention_mask会被显式丢弃(inputs.pop("attention_mask", None)),因为 PBD 解码器内部使用自建的块状掩码而非标准因果掩码;
  • model.pbd_generate的实现位于 locateanything.py:它先通过get_input_embeddings计算输入嵌入(若未提供缓存视觉特征则前向视觉塔与连接器),再构造PBDDecoder并驱动生成循环;
  • 解码结果直接是 token id 列表,需要调用processor.decode(..., skip_special_tokens=False)还原为包含特殊标记的文本,才能看到完整的<box>...</box>结构。

generation_mode 的三种模式

generation_mode参数接受以下取值,对应 pbd.py 中PBDDecoder的三种运行策略:

模式行为
hybrid先用 Parallel Box Decoding 生成,遇到无法并行处理的模式(如error_box)时自动回退到自回归解码,是默认推荐模式
fast仅使用 Parallel Box Decoding,任何非标准框模式都会被强制按coord_box处理,速度最快但可能牺牲精度
slow完全走自回归解码,但经由 LocateAnything 的 PBD 包装器(即复用同一套 PBD 调用框架,只是内部逐 token 生成)

架构解析

README 用五点概括了模型架构,下面结合源码逐一展开(主模型定义见 locateanything.py)。

视觉塔:MoonViT 图像编码器

MoonViT 视觉塔的配置在 config.py 的VisionConfig中定义:hidden size 1152、27 层、16 个注意力头、intermediate size 4304,patch size 为 14,并带 2×2 的 patch 合并核(merge_kernel_size=[2, 2])。

实现位于 vision.py 的VisionModel,其关键组件包括:

  • PatchEmbed(vision.py):14×14 卷积切 patch,并使用Learnable2DInterpPosEmb学习式二维插值位置编码——位置编码以 64×64 的初始网格预置,遇到不同分辨率输入时通过双三次插值(bicubic)适配任意 grid 尺寸;
  • 二维 RoPERope2DPosEmb,vision.py):在 512×512 的网格上预计算二维频率(x/y 两个方向各自编码),按输入图像的实际 grid 形状切片使用,从而为任意长宽比图像提供位置信息;
  • patch mergingpatch_merger,vision.py):将 2×2 邻域 patch 的特征在空间维度上拼接到 channel 维,输出序列长度缩减为原来的 1/4,与处理器中的merge_kernel_size对应;
  • 块状注意力掩码make_block_attention_mask,vision.py):多图输入时按cu_seqlens将各图的 token 分组,禁止跨图注意力。

连接器:LayerNorm + 两层线性

LocateAnythingMultiModalProjector(locateanything.py)将合并后的视觉特征投影到语言模型的 hidden size:输入维度为vit_hidden * merge_kernel[0] * merge_kernel[1](即 1152×2×2 = 4608),经过 LayerNorm → Linear → GELU → Linear 后输出 2048 维(即 Qwen2.5 的 hidden size)。

语言模型:Qwen2 风格解码器

文本骨干是 Qwen2 风格解码器,配置见 config.py 的TextConfig:hidden size 2048、36 层、16 个注意力头、2 个 KV 头(GQA)、rope_theta=1e6、最大位置 32768,并开启权重绑定tie_word_embeddings=True,同时vocab_size=152681)。

实现位于 language.py 的LanguageModel:绑定权重时直接通过embed_tokens.as_linear(out)输出 logits,省去独立的 lm_head 层(因此 locateanything.py 的sanitize会跳过language_model.lm_head.weight)。

特殊 token 体系

模型使用一组专用 token id 表达坐标框结构(config.py):

tokenid含义
image_token_index151665图像占位符 token
box_start_token_id151668框开始
box_end_token_id151669框结束
ref_start_token_id151672指代对象开始
ref_end_token_id151673指代对象结束
coord_start_token_id151677坐标范围开始
coord_end_token_id152677坐标范围结束
none_token_id4064空框标记
text_mask_token_id151676MTP 掩码 token(block_size=6
null_token_id152678空位填充 token
switch_token_id152679模式切换 token

其中block_size=6是 PBD 并行块的大小——pbd.py 在初始化时强制断言其为 6,因为handle_pattern/decode_ref的逻辑均假设单个框块恰好包含 6 个 token。

处理器:图像占位符展开

LocateAnythingProcessor(processing_locateanything.py)的核心职责是把文本中的<image-N>占位符展开为<img>...<IMG_CONTEXT>...</img>的 token 序列:先由LocateAnythingImageProcessor把图像切成 patch 并返回image_grid_hws(每张图的 grid 高宽),再根据merge_kernel_size计算每个占位符应展开的<IMG_CONTEXT>数量(grid_h * grid_w // merge_length),并校验占位符数量与图像数量一致,否则抛出异常。

图像预处理(image_processing_locateanything.py)遵循「先缩放、后补齐」的策略:若 patch 总数超过in_token_limit(默认 25600)则按比例缩小;随后把宽高向上取整到merge_kernel * patch_size的整数倍(例如 2×14=28 的倍数),保证图像能被 2×2 合并核完整切分;最后校验 grid 不超过 512×512(否则超过 RoPE 预置范围报错)。

此外,README 特别注明该自定义处理器支持save_pretrained():调用后会写出processor_config.jsonpreprocessor_config.jsonchat_template.json三个文件(processing_locateanything.py),其中preprocessor_config.json记录了image_meanimage_stdin_token_limitmerge_kernel_sizepatch_size等完整预处理参数,便于本地保存与复加载。

PBD:并行框解码器

PBDDecoder(pbd.py)是整个 LocateAnything 移植最具特色的部分。其核心思想是:利用模型的多 token 预测(MTP)能力,一次性前向产出 6 个位置的 logits 块,然后通过模式识别从概率分布中直接「解析」出一整个坐标框 token 块,而不是逐 token 解码。

关键子流程:

  • 块前向(MTP)_forward_mtp_mtp_prefill将「上一步生成的最后一个 token + 5 个掩码 token」作为窗口送入语言模型,配合build_magi_block_mask(language.py)构造的块状注意力掩码与错位 position ids,一次性获得 6 个位置各自的 logits,随后cache.trim(B)回退 KV 缓存;
  • 框合法性判定is_valid_box_frame(pbd.py)检查box_start概率是否超过阈值(默认 0.6)、是否被im_end/null抢占,从而区分legal_boxempty_boxillegal_box
  • 坐标平均解码decode_bbox_avg(pbd.py)对中间 4 个坐标位置各自取 top-k(默认 5)候选,筛选出落在coord_start..coord_end范围内的 token id;hybrid模式下若首候选概率低于 0.9 且候选跨度超过 60,判定为异常并输出 0(坐标原点),否则输出首候选;
  • 模式回退handle_pattern(pbd.py)将解码结果分类为im_end(终止)、empty_boxcoord_box(4 坐标框)、point_box(2 坐标点)、error_boxref_object(指代对象);其中只有error_box会触发need_switch_to_ar,即hybrid模式在此回退到自回归逐 token 解码,而fast模式则强制按coord_box处理以保持全并行。

目录结构

本模型在仓库中的完整文件布局如下:

mlx_vlm/models/locateanything/ __init__.py # 导出 Model / Processor / 各 Config config.py # VisionConfig / TextConfig / ModelConfig image_processing_locateanything.py # 图像缩放、归一化、patchify language.py # Qwen2 风格语言模型 + MTP 块掩码 locateanything.py # 主模型、投影器、pbd_generate、权重清洗 pbd.py # PBD 解码器与坐标解析逻辑 processing_locateanything.py # 处理器:占位符展开、save_pretrained vision.py # MoonViT 视觉塔(PatchEmbed/RoPE/合并)

入口文件init.py 将ModelLanguageModelVisionModelProcessorImageProcessor及各配置类统一导出,供模型工厂自动发现与加载。

使用注意事项

  • 多图输入:当 prompt 中包含多张图像时,apply_chat_templatenum_images必须传len(images),同时generate/prepare_inputs中传入相同数量的图像,保证占位符与图像一一对应;
  • max-tokens 与场景复杂度:README 明确建议在对象较多的场景增大--max-tokens,否则可能截断后续对象的坐标输出;
  • 解码模式选择:追求速度且场景简单可用fast;追求鲁棒性用默认hybridslow相当于经 PBD 包装器的纯自回归基线;
  • 保存处理器processor.save_pretrained(<目录>)会同时写出processor_config.jsonpreprocessor_config.jsonchat_template.json,后续可通过LocateAnythingProcessor.from_pretrained(processing_locateanything.py)从本地目录恢复,包含完整的图像预处理参数与聊天模板。

【免费下载链接】mlx-vlmMLX-VLM is a package for inference and fine-tuning of Vision Language Models (VLMs) on your Mac using MLX.项目地址: https://gitcode.com/GitHub_Trending/ml/mlx-vlm

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询