mistral.rs Python SDK 实战:用 Runner 多模态接口推理 Qwen3-VL 视觉语言模型
【免费下载链接】mistral.rsFast, flexible LLM inference项目地址: https://gitcode.com/GitHub_Trending/mi/mistral.rs
本文围绕 mistral.rs 的 Python SDK 示例qwen3_vl展开:展示如何仅用十余行 Python 代码,通过Runner+Which.MultimodalPlain加载 Qwen3-VL 模型并向其发送“图片 + 文本”的 Chat Completion 请求,同时结合仓库源码解析该示例背后MultimodalPlain构造参数、Qwen3VL 加载器能力与视觉编码器配置的实现细节,帮助你把同一套消息格式平滑迁移到 mistral.rs 服务端(OpenAI 兼容 API)。
完整示例:一个可运行的 Qwen3-VL 推理脚本
官方文档中的示例源码即 examples/python/qwen3_vl.py,完整代码可直接复制运行:
from mistralrs import Runner, Which, ChatCompletionRequest, MultimodalArchitecture MODEL_ID = "Qwen/Qwen3-VL-4B-Thinking" runner = Runner( which=Which.MultimodalPlain( model_id=MODEL_ID, arch=MultimodalArchitecture.Qwen3VL, ), ) res = runner.send_chat_completion_request( ChatCompletionRequest( model="default", messages=[ { "role": "user", "content": [ { "type": "image_url", "image_url": { "url": "https://www.garden-treasures.com/cdn/shop/products/IMG_6245.jpg" }, }, { "type": "text", "text": "What type of flower is this? Give some fun facts.", }, ], } ], max_tokens=256, presence_penalty=1.0, top_p=0.1, temperature=0.1, ) ) print(res.choices[0].message.content) print(res.usage)脚本做了三件事:
- 以
MultimodalPlain方式加载 Hugging Face 上的Qwen/Qwen3-VL-4B-Thinking权重(首次运行会自动下载缓存); - 构造一条 OpenAI 风格的多模态消息,
content是一个部件数组(part array),按顺序混合了image_url与text两种类型; - 调用
send_chat_completion_request获取完整响应,打印模型回复正文与 token 用量。
核心 API 解析:Runner 与 Which.MultimodalPlain
示例的关键在于Which.MultimodalPlain构造器。对照 PyO3 绑定层源码 mistralrs-pyo3/src/which.rs,它的完整参数签名为:
#[pyo3(constructor = ( model_id, arch = None, tokenizer_json = None, topology = None, write_uqff = None, from_uqff = None, dtype = ModelDType::Auto, max_edge = None, calibration_file = None, imatrix = None, auto_map_params = None, hf_cache_path = None, matformer_config_path = None, matformer_slice_name = None, organization = None, encoder_cache_memory_bytes = None, ))] MultimodalPlain { ... }其中与 Qwen3-VL 示例最相关的参数说明如下:
| 参数 | 示例取值 | 说明 |
|---|---|---|
model_id | "Qwen/Qwen3-VL-4B-Thinking" | 模型仓库 ID 或本地权重目录路径,必填 |
arch | MultimodalArchitecture.Qwen3VL | 显式指定架构;省略时由仓库config.json的architectures字段自动推断(见下文加载器章节) |
dtype | 默认ModelDType::Auto | 权重数据类型,默认自动选择 |
max_edge | 默认None | 图像长边缩放上限,控制送入视觉编码器的分辨率上界 |
auto_map_params | 默认None | MultimodalAutoMapParams,可设max_seq_len、max_batch_size、max_num_images、max_image_length,用于自动设备映射时的容量规划(定义见 which.rs) |
encoder_cache_memory_bytes | 默认None | 视觉编码器缓存预留内存,配合加载器的 encoder cache 能力使用 |
tokenizer_json | 默认None | 指定 tokenizer 文件路径,省略时从模型仓库获取 |
hf_cache_path | 默认None | 自定义 Hugging Face 缓存目录 |
arch枚举MultimodalArchitecture在 Python 侧与 Rust 内部MultimodalLoaderType一一对应,Qwen 视觉家族的映射见 which.rs:
MultimodalArchitecture::Qwen3VL => MultimodalLoaderType::Qwen3VL, MultimodalArchitecture::Qwen3VLMoE => MultimodalLoaderType::Qwen3VLMoE,对应的枚举参考表收录在 docs/src/content/docs/reference/python/enums.md(MultimodalArchitecture.Qwen3VL→ 字符串值'Qwen3VL')。
多模态消息格式:OpenAI 兼容的 content 部件
示例中的messages结构与 OpenAI Chat Completions 的多模态格式一致:
- 顶层
messages是消息数组,每条消息含role(user/assistant/system)与content; - 纯文本请求中
content是字符串;多模态请求中content是部件数组,每个部件带type字段:image_url:image_url.url为图片地址,SDK 侧会自动下载并交由 Processor 预处理;text:text字段为文本内容;
- 采样参数
max_tokens=256、temperature=0.1、top_p=0.1、presence_penalty=1.0与标准 Chat Completion 语义相同,这里低温 + presence penalty 的配置意在让模型稳定地给出简洁、低重复的回答。
值得注意的是,Qwen3-VL 的 prompt 前缀逻辑是“no-op”。在加载器实现 mistralrs-core/src/pipeline/loaders/multimodal_loaders.rs 中:
pub struct Qwen3VLPrefixer; impl MultimodalPromptPrefixer for Qwen3VLPrefixer { // No-op: With MessagesAction::Keep, the chat template handles image tokens // when it sees {"type": "image"} entries in the content. }即 mistral.rs 不在引擎侧手工拼接<|image_pad|>等图像占位符,而是将结构化消息原样交给模型的 chat template,由模板看到{"type": "image"}条目后自行生成图像 token。这也解释了为什么示例消息里不需要任何手写占位符。
底层实现:Qwen3VLLoader 支持哪些模态与特性
arch不显式指定时的自动识别,以及加载能力的声明,都集中在Qwen3VLLoader(multimodal_loaders.rs):
fn modalities(&self, _config: &str) -> Result<Modalities> { Ok(Modalities { input: vec![ SupportedModality::Text, SupportedModality::Vision, SupportedModality::Video, ], output: vec![SupportedModality::Text], }) }- 输入模态:文本、图像、视频;输出模态:文本。除图像 URL 外,该架构同样支持在消息中提供视频帧序列,视频采样使用与 Qwen3-VL/3.5 家族共享的默认参数(源码注释
HF Qwen3VLVideoProcessor sampling defaults, shared by the Qwen3-VL/3.5 family)。 - 性能特性开关:
supports_paged_attention返回true(支持分页注意力)、supports_encoder_cache返回true(视觉编码器输出可缓存,可通过encoder_cache_memory_bytes参数控制预算)、supports_prefix_cacher返回true(支持前缀缓存,多轮对话中重复的图像前缀可命中缓存); - 架构名映射:
Qwen3VLForConditionalGeneration→Qwen3VL、Qwen3VLMoeForConditionalGeneration→Qwen3VLMoE(multimodal_loaders.rs)。因此Qwen/Qwen3-VL-4B-Instruct与示例中的Qwen/Qwen3-VL-4B-Thinking均可自动识别为同一加载器,arch参数在大多数情况下是可选的; - 量化支持:该加载器同时实现了
IsqModelLoader与DeviceMappedModelLoader接口(multimodal_loaders.rs),即支持 ISQ 在线量化与自动设备映射(此时auto_map_params参数才会派上用场)。
视觉编码器配置:从 config.rs 看默认结构
Qwen3-VL 的视觉塔配置解析在 mistralrs-core/src/vision_models/qwen3_vl/config.rs,VisionConfig为缺失字段提供了与 4B 规格一致的默认值:
| 字段 | 默认值 | 含义 |
|---|---|---|
depth | 27 | ViT 层数 |
hidden_size | 1152 | 视觉隐藏层维度 |
out_hidden_size | 3584 | 投影到语言模型的输出维度 |
patch_size | 16 | 图像 patch 大小 |
spatial_merge_size | 2 | 空间合并倍率(token 压缩) |
temporal_patch_size | 2 | 时间维 patch 大小(视频抽帧合并) |
deepstack_visual_indexes | [8, 16, 24] | DeepStack 视觉特征注入层索引 |
文本塔TextConfig中包含rope_scaling: MRopeScaling { mrope_section }字段,表明 Qwen3-VL 使用 M-RoPE(多模态旋转位置编码);其 RoPE 实现为独立的Qwen3VLRotaryEmbedding(mistralrs-core/src/layers.rs),并带有针对长上下文的 YaRN 变体测试用例。实际推理时这些字段全部来自模型仓库的config.json,上表默认值仅用于字段缺省时兜底,不必手工配置。
服务端视角:同一份消息可发给 OpenAI 兼容 API
如果你在部署 mistral.rs server 而不是进程内 SDK,examples/server/qwen3_vl.py 展示了完全对应的服务端用法——消息体与 SDK 示例逐字相同,只是改为通过 OpenAI 客户端发送:
from openai import OpenAI client = OpenAI(api_key="foobar", base_url="http://localhost:1234/v1/") completion = client.chat.completions.create( model="default", messages=[ { "role": "user", "content": [ { "type": "image_url", "image_url": { "url": "https://www.garden-treasures.com/cdn/shop/products/IMG_6245.jpg" }, }, { "type": "text", "text": "What type of flower is this? Give some fun facts.", }, ], }, ], max_tokens=256, frequency_penalty=1.0, top_p=0.1, temperature=0, ) resp = completion.choices[0].message.content print(resp)这带来一个实用推论:SDK 侧验证过的消息格式、采样参数与image_url部件结构,可以直接复用到任何 OpenAI 兼容客户端,两套入口之间没有格式鸿沟。
模型支持层面的对照表见 docs/src/content/docs/reference/supported-models.md,其中列出了两类架构及对应的 CLI 启动命令:
Qwen3VLForConditionalGeneration(Qwen3-VL):mistralrs run -m Qwen/Qwen3-VL-4B-InstructQwen3VLMoeForConditionalGeneration(Qwen3-VL MoE):mistralrs run -m Qwen/Qwen3-VL-235B-A22B-Instruct
对应地,Python SDK 中 MoE 版本只需把arch换成MultimodalArchitecture.Qwen3VLMoE,其加载器Qwen3VLMoELoader与 Dense 版结构一致(multimodal_loaders.rs)。
小结
- 用
Runner(which=Which.MultimodalPlain(model_id=..., arch=MultimodalArchitecture.Qwen3VL))即可进程内加载 Qwen3-VL,arch省略时可依赖架构名自动识别; - 多模态消息采用 OpenAI 风格的 content 部件数组(
image_url+text),图像 token 由 chat template 自动处理,无需手写占位符; - 从源码看,Qwen3-VL 加载器声明支持文本/图像/视频输入,并开启分页注意力、编码器缓存与前缀缓存三项服务特性;
- 需要长期服务或跨语言接入时,可直接使用 OpenAI 兼容端点,消息格式与 SDK 示例一致。
如需进一步阅读,可参考:SDK 完整参数类型 mistralrs-pyo3/src/which.rs、视觉模型实现目录 mistralrs-core/src/vision_models/qwen3_vl/、以及同级示例 examples/python/qwen2vl.py、examples/python/llama_vision.py 了解其他多模态架构的用法差异。
【免费下载链接】mistral.rsFast, flexible LLM inference项目地址: https://gitcode.com/GitHub_Trending/mi/mistral.rs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考