mlx-vlm 中 Prism Bonsai 三元 2-bit 文生图模型的推理路径与 API 实战指南
【免费下载链接】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
本篇聚焦 mlx-vlm 中 Prism Bonsai 的完整推理链路:它不走文本/VLM 的 token 生成路径,而是走专用的图像生成(image generation)路径,支持三通道输出——CLI 生成 PNG 文件、Python API 返回求值后的mx.array、OpenAI 兼容的/v1/images/generations服务端点。读完后,你能够用命令行一键出图、用 Python 编程式生成并拿到 Base64 PNG,还能通过 HTTP API 把它接入现有 OpenAI 风格的图像生成工作流,同时理解三元 2-bit 量化矩阵乘法、Flow Matching 采样循环与显存淘汰策略的底层实现。
模型概览:Bonsai 在 mlx-vlm 中的定位
Prism Bonsai 是一个文生图(Text-to-image)模型。在mlx-vlm中,它被显式注册为"图像生成模型",而不是语言模型:模型实现 BonsaiImageGenerationModel 上带有is_image_generation_model = True与model_type = "bonsai"类变量,由统一的图像生成加载器 load_image_generation_model 按 model id 识别并分发。
当前支持的模型与别名(见 变体定义):
| Model | Alias | Notes |
|---|---|---|
prism-ml/bonsai-image-ternary-4B-mlx-2bit | bonsai-ternary | 三元 2-bit MLX 模型 |
从源码结构看,bonsai-ternary只是别名表中的一个入口,实际可识别的别名还包括bonsai、ternary、ternary-mlx、bonsai-ternary-mlx、2bit以及完整 repo id 本身(小写形式)。也就是说 CLI/Python 里写--model bonsai-ternary或--model 2bit都能命中同一个变体,未识别的名称会抛出带有完整别名清单的ValueError。
能力清单:
- 文生图生成:基于三元(ternary)MLX Bonsai 模型
- CLI 输出:生成 PNG 文件
- Python API 输出:返回求值后的
mx.array - OpenAI 兼容 API:通过
/v1/images/generations端点
支持的图像尺寸为每边 256 到 2048 像素,且宽、高都必须是 16 的倍数。这一约束直接来自 validate_dimensions:任何一维超出[256, 2048]或非 16 的倍数都会立即抛出ValueError;parse_size还支持WIDTH×HEIGHT(全角乘号会被归一化为x)的写法。
运行前提:三元量化的硬件依赖
Bonsai 的 transformer 使用 2-bit 三元量化权重,其矩阵乘法依赖 MLX 原生的量化 matmul kernel。pipeline 初始化 会调用_check_quantized_matmul做能力探测:若当前 MLX 运行时不支持所需的 2-bit 量化矩阵乘路径,会抛出RuntimeError,提示使用 PrismML MLX 对应版本或包含该 kernel 的其他 MLX 构建。这是使用 Bonsai 前需要确认的第一件事。
安装与模型下载
pip install -U mlx-vlm模型默认通过huggingface_hub.snapshot_download按需下载到 Hugging Face 缓存。从 download.py 可以看到:
- 若未指定本地目录,直接调用
snapshot_download(repo_id=...)落到 HF 缓存; - 若指定了
models_dir/local_dir,会先创建目录再下载到指定位置,默认落点为当前工作目录下的models/bonsai-image-4B-ternary-mlx; - 私有访问可通过
token参数或环境变量BONSAI_TOKEN传递; - 下载完成后执行
validate_model_layout校验,快照必须包含以下 4 个必需文件,缺失时会在错误信息中逐项列出:
transformer-packed-mflux/diffusion_pytorch_model.safetensors transformer-packed-mflux/quantization_config.json text_encoder-mlx-4bit/model.safetensors tokenizer/tokenizer.json你也可以直接把一个本地的 Bonsai 快照路径作为--model传入,跳过下载。
组件架构:三个子模型 + Flow Matching 采样
从 weights.py 的加载逻辑可以确认,一个完整的 Bonsai 快照由三部分组成:
- 文本编码器:
text_encoder-mlx-4bit下的 4-bit 量化 Qwen3 文本编码器(hidden_size=2560, intermediate_size=9728),加载后按bits=4, group_size=64量化; - 扩散 Transformer:
transformer-packed-mflux下的打包权重(dtype=mx.bfloat16加载),构造为 Flux2KleinFastTransformer,走 Flux.2 Klein 的双流/单流块结构(patch_size=1、guidance_embeds=False); - VAE 解码器:从
black-forest-labs/FLUX.2-small-decoder仓库按需拉取diffusion_pytorch_model.safetensors,只映射decoder.*、post_quant_conv.*、bn.*权重,并跳过.num_batches_tracked统计量、修正 4D 权重的通道顺序。
采样循环在 BonsaiImage.generate_array 中实现,是标准的 Flow Matching 离散化流程:
- 校验尺寸与
steps >= 1、prompt 非空; - 用
Flux2Tokenizer+ 4-bit 文本编码器编码 prompt(结果按(prompt, max_sequence_length, bucketed)三元组缓存); - 由
seed初始化打包的潜变量,image_seq_len = (height//16) * (width//16); - 用
FlowMatchEulerDiscreteScheduler生成steps个时间步,逐步预测噪声并scheduler.step更新潜变量,每步mx.eval同步; - 若
guidance > 1.0,额外编码空白 prompt" "作为负向嵌入,做noise = negative + guidance * (noise - negative)的 CFG 合成; - 最后把潜变量重排为
[B, C, H, W]交给 VAE 解码,解码结果经x/2 + 0.5 → clip → uint8归一化输出 HWC 的 RGBmx.array。
generate_array的默认参数与文档示例一致:seed=42、steps=4、width=512、height=512、guidance=1.0——Bonsai 本身就是一个为极少步数(4 步)设计的高效模型。
显存淘汰策略(BonsaiRuntimeConfig)
BonsaiRuntimeConfig 提供一组针对内存紧张的 Apple Silicon 的开关:
| 参数 | 默认值 | 作用 |
|---|---|---|
evict_text_encoder | True | 文本编码完成后置空并gc.collect() + mx.clear_cache(),把内存让给 transformer |
evict_transformer | False | 生成完成后清空 transformer/VAE 并释放缓存 |
bucketed_seq_len | False | prompt 编码时启用分桶序列长度 |
tiled_vae | "auto" | VAE 分块解码:auto下当max(height, width)达到 2 倍 tile 边长时自动开启(见 _resolve_tiling) |
max_sequence_length | 512 | prompt 编码的最大序列长度 |
这些参数既能在BonsaiImage.from_pretrained(...)中直接传入,也能通过 BonsaiImageGenerationModel.from_model_id 的同名 kwargs 传递,例如load("bonsai-ternary", tiled_vae="on", max_sequence_length=768)。
CLI 使用
生成一张图
python -m mlx_vlm generate_image \ --model prism-ml/bonsai-image-ternary-4B-mlx-2bit \ --prompt "A tiny glass bonsai tree on a moonlit desk" \ --size 512x512 \ --steps 4 \ --seed 9909 \ --output outputs/bonsai.png等价的 generate 命令
python -m mlx_vlm generate \ --output-modality image \ --model bonsai-ternary \ --prompt "A tiny glass bonsai tree on a moonlit desk" \ --size 512x512 \ --steps 4 \ --seed 9909 \ --output outputs/bonsai.png两条命令走同一条底层路径:run_image_generation_cli 解析参数后调用load_image_model(..., task="generate")→generate_image(model, request, output_path=...)。几个值得注意的行为细节:
--seed省略时:生成一个随机 32-bit 种子(random.randrange(2**32));--output省略时:图片写入outputs/image-{seed}.png;- 默认
--size为512x512,未传--steps时默认为 4; - 命令执行成功后会打印
Saved {path} seed=... size=WxH steps=... variant=...摘要,其中variant对 Bonsai 即ternary; - 图像生成任务对 token 类参数做了白名单式校验:
--kv-bits、--eos-tokens、--chat、--audio等文本生成参数与图像任务不兼容,传入会直接报错(见 _validate_image_generation_args)。
Python API
Python 侧的统一入口在 mlx_vlm/generate/image.py:load_image_generation_model负责按 id/别名/本地路径识别模型类,generate_image负责执行并把结果封装为 ImageGenerationResult。
基本生成
from mlx_vlm.generate.image import ( ImageGenerationRequest, generate_image, load_image_generation_model, ) model = load_image_generation_model( "prism-ml/bonsai-image-ternary-4B-mlx-2bit" ) request = ImageGenerationRequest( prompt="A tiny glass bonsai tree on a moonlit desk", seed=9909, steps=4, width=512, height=512, guidance=1.0, ) result = generate_image(model, request) # 主输出是求值后的 MLX 数组(HWC、uint8、RGB、0-255) array = result.array print(array.shape, array.dtype) result.save("outputs/bonsai.png")ImageGenerationResult除了array还携带seed、width/height、steps、guidance、prompt_tokens、peak_memory(GB)等元数据;save()会自动创建父目录并把result.path回填。
Prompt 简写形式
generate_image的第二个参数既可以是ImageGenerationRequest对象,也可以直接传 prompt 字符串,此时seed、steps、width、height、guidance等 kwargs 会被 自动组装为请求(其余未知 kwargs 非空时并入extra):
from mlx_vlm.generate.image import generate_image, load_image_generation_model model = load_image_generation_model("bonsai-ternary") result = generate_image( model, "A tiny glass bonsai tree on a moonlit desk", seed=9909, steps=4, width=512, height=512, output_path="outputs/bonsai.png", ) print(result.path)注意:request.seed is None时generate_image会就地补一个随机 32-bit 种子,保证每次调用都有确定来源的种子。
Base64 PNG 输出
from mlx_vlm.generate.image import generate_image, load_image_generation_model model = load_image_generation_model("bonsai-ternary") result = generate_image( model, "A tiny glass bonsai tree on a moonlit desk", seed=9909, steps=4, width=512, height=512, ) b64_png = result.to_b64_json()to_b64_json()内部先把mx.array转成 PIL 图像再编码为 PNG 字节做 Base64,与 OpenAI 图像接口的b64_json响应格式完全对齐,可直接塞进下游服务。
OpenAI 兼容 API
mlx-vlm 的 server 模块暴露了POST /v1/images/generations(见 server/openai.py),请求体与 OpenAI 图像生成 API 对齐:
curl http://localhost:8080/v1/images/generations \ -H "Content-Type: application/json" \ -d '{ "model": "prism-ml/bonsai-image-ternary-4B-mlx-2bit", "prompt": "A tiny glass bonsai tree on a moonlit desk", "size": "512x512", "steps": 4, "seed": 9909, "response_format": "b64_json" }'- 默认
response_format为b64_json,返回 Base64 编码的 PNG; - 需要落盘时改为
"response_format": "path",并可附带output_path或output_dir指定保存位置。
server 侧最终同样是调用generate_image(...)拿到ImageGenerationResult,再按response_format序列化,因此 API 与 CLI/Python 三条路径的输出语义(种子、尺寸、步数)完全一致。
注意事项
- 始终显式传入图像生成模型 id 或本地快照路径:Bonsai 不是 VLM 的对话模型,不能当作
--model下的默认语言模型来跑文本生成。 - 直接传纯 prompt 文本:Bonsai 的 tokenizer 应用的是它自己的 chat template,不要把已经包好 system/assistant 消息的对话结构喂进去。
- 目前只暴露 ternary 变体:binary/1-bit 模型出于策略原因暂未在变体表中开放(config.py 中
VARIANTS仅注册了ternary)。 - 本地快照识别:当传入的字符串是一个已存在的目录时,resolve_variant 会默认按
ternary变体加载;can_load会对目录执行validate_model_layout校验后再判定可加载性。测试用例 test_bonsai.py 用伪造的 transformer/VAE 覆盖了generate_array的完整采样循环与模型类识别逻辑,可作为行为参照。 - 内存与步数取舍:4 步、
guidance=1.0(无 CFG,省一次前向)是该模型的推荐配置;若要开 CFG,guidance取> 1.0即可,每一步会多一次以" "为 prompt 的前向。
小结
Prism Bonsai 在 mlx-vlm 中演示了"超低位宽扩散模型如何落地为可用产品接口"的完整闭环:三元 2-bit 量化 transformer + 4-bit 文本编码器 + 小 VAE 解码器,4 步 Flow Matching 采样,配合 prompt 缓存与文本编码器淘汰控制内存峰值;对上则同时提供 CLI、Python 与 OpenAI 兼容 API 三种一致的调用面。相关实现集中在 mlx_vlm/models/bonsai/(config、download、weights、pipeline、model、klein_fast)与 mlx_vlm/generate/image.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),仅供参考