mistral.rs 多模态流式推理实战:图像与音频联合输入的 Rust 实现
2026/9/17 8:18:53 网站建设 项目流程

mistral.rs 多模态流式推理实战:图像与音频联合输入的 Rust 实现

【免费下载链接】mistral.rsFast, flexible LLM inference项目地址: https://gitcode.com/GitHub_Trending/mi/mistral.rs

本指南围绕 mistral.rs 官方文档中的多模态示例(multimodal.md,由 multimodal/main.rs 自动渲染生成)展开,完整讲解如何用MultimodalModelBuilder加载 Phi-4 Multimodal 类模型、通过MultimodalMessages构造同时包含文本、图像、音频的多模态消息,并使用stream_chat_request实现流式解码。读完本文,你将掌握在 Rust 中一步到位地完成「图 + 音 + 文」联合输入推理的完整实战方案,并能基于源码理解其内部工作方式。

示例概览:一条命令跑通图文音联合推理

文档给出的核心示例是一个可直接运行的完整 Rust 程序,运行命令为:

cargo run --release --example multimodal -p mistralrs

它的工作流程非常清晰:通过 HTTP 分别拉取一段鸟鸣音频(Bird_singing.ogg)和一张鸟类图片,将其分别封装为AudioInputDynamicImage,构造一条同时携带图片、音频和文本提示的多模态用户消息,交给 Phi-4-multimodal-instruct 模型以流式方式生成回答,并把每个增量分块实时打印到终端。

完整源码如下(与 mistralrs/examples/models/multimodal/main.rs 完全一致):

//! Multimodal streaming with combined image and audio inputs. //! //! Run with: `cargo run --release --example multimodal -p mistralrs` use std::io::Write; use anyhow::Result; use mistralrs::{ AudioInput, ChatCompletionChunkResponse, ChunkChoice, Delta, MultimodalMessages, MultimodalModelBuilder, Response, TextMessageRole, }; #[tokio::main] async fn main() -> Result<()> { let model = MultimodalModelBuilder::new("microsoft/Phi-4-multimodal-instruct") .with_logging() .build() .await?; let audio_bytes = reqwest::get("https://upload.wikimedia.org/wikipedia/commons/4/42/Bird_singing.ogg") .await? .bytes() .await? .to_vec(); let audio = AudioInput::from_bytes(&audio_bytes)?; let image_bytes = reqwest::get("https://www.allaboutbirds.org/guide/assets/og/528129121-1200px.jpg") .await? .bytes() .await? .to_vec(); let image = image::load_from_memory(&image_bytes)?; let messages = MultimodalMessages::new().add_multimodal_message( TextMessageRole::User, "Describe in detail what is happening.", vec![image], vec![audio], vec![], ); let mut stream = model.stream_chat_request(messages).await?; while let Some(chunk) = stream.next().await { if let Response::Chunk(ChatCompletionChunkResponse { choices, .. }) = chunk { if let Some(ChunkChoice { delta: Delta { content: Some(content), .. }, .. }) = choices.first() { print!("{content}"); std::io::stdout().flush()?; }; } else { // Handle errors } } Ok(()) }

程序主要分为四个环节:构建模型准备媒体输入构造多模态消息流式请求与增量输出。下文逐一深入拆解,并补充源码级的实现细节。

构建多模态模型:MultimodalModelBuilder 详解

示例通过MultimodalModelBuilder加载模型,其定义位于 mistralrs/src/multimodal_model.rs,是一个「配置加载、运行与推理行为的各种参数」的构建器。调用new(model_id)时会自动应用以下默认值(见 multimodal_model.rs):

  • Token 来源:默认从缓存读取(TokenSource::CacheToken,即.cache/huggingface/token),私有或需鉴权的模型需先登录;
  • 最大并发序列数max_num_seqs默认为 32;
  • 设备映射:默认按AutoDeviceMapParams自动分配设备;
  • 数据类型dtype默认ModelDType::Auto,由模型自动决定;
  • 强制 CPUforce_cpu默认false,有可用 CUDA/Metal 设备时自动使用;
  • Web 搜索:默认关闭与 OpenAIweb_search_options兼容的搜索能力。

除了示例中使用的.with_logging()(启用吞吐量日志,配合--release运行可观察 tok/s 指标),该构建器还提供多个高价值配置方法:

方法作用注意事项
with_max_edge(u32)自动缩放并填充图像至指定最大边长,保持宽高比目前仅 Qwen2-VL 与 Idefics 2 支持,其余模型内部自行处理
with_max_model_len(usize)设置运行时上下文长度内部断言必须大于 0,对应测试见 multimodal_model.rs
with_hf_config_overrides(HfConfigOverrides)递归合并 Hugging Faceconfig.json覆盖项用于微调加载细节
with_encoder_cache_memory_bytes(usize)设置编码器缓存最大内存字节数断言必须非零
with_loader_type(MultimodalLoaderType)手动指定模型加载器类型不指定时自动探测
with_isq(...)/with_auto_isq(...)应用 ISQ 量化见下方多模型示例

build()是异步加载入口,内部调用build_multimodal_pipeline组装流水线后再包装成Model(multimodal_model.rs)。对于 UQFF 格式的多模态模型,仓库还提供了专用构建器UqffMultimodalModelBuilder,分片模型只需指定第一个分片文件,其余分片会自动发现。

多模态消息构造:MultimodalMessages 消息 API

MultimodalMessages是承载多模态对话历史的容器,实现在 mistralrs/src/messages.rs 中。示例使用的是最完整的add_multimodal_message,签名接受五个参数:

pub fn add_multimodal_message( self, role: TextMessageRole, // 角色:User / Assistant 等 text: impl ToString, // 文本提示 images: Vec<DynamicImage>, // 图像列表 audios: Vec<AudioInput>, // 音频列表 videos: Vec<VideoInput>, // 视频列表 ) -> Self

从源码(messages.rs)可以看到它的内部行为:

  1. 将新增的 images / audios / videos 分别追加到内部独立存储self.imagesself.audiosself.videos,并记录各自的全局索引区间;
  2. 构建 OpenAI 风格的content数组:每张图对应一个{"type": "image"}条目,每段音频对应{"type": "audio"},每个视频对应{"type": "video"},最后追加{"type": "text", "text": ...}文本条目;
  3. 将消息以IndexMap形式推入messages,同时把媒体索引登记到pending_prefixes中,等待发送时由模型注入各自的特殊前缀 token(resolve_pending_prefixes,默认实现为空操作,多模态模型会覆盖它)。

这套设计让「模型特有前缀」与「用户消息」解耦:调用方只需准备原始媒体与文本,模型专属的<|image_1|>、音频/视频占位符等前缀在send_chat_request/stream_chat_request发送时自动应用(见 messages.rs 的 doc 注释)。

此外,MultimodalMessages还提供若干便捷方法,全部内部委托给add_multimodal_message

  • add_message(role, text):纯文本消息,适合多轮对话的文本轮;
  • add_image_message(role, text, images):仅携带图像;
  • add_audio_message(role, text, audios):仅携带音频;
  • add_video_message(role, text, videos):仅携带视频。

流式推理与响应解析

示例调用model.stream_chat_request(messages)发起流式请求,返回一个可迭代的Stream(定义于 mistralrs/src/model.rs)。每次stream.next().await会得到一个Response枚举值,常见分支有:

  • Response::Chunk(ChatCompletionChunkResponse { choices, .. }):携带一个增量分块;
  • 其他变体用于错误处理(示例中以else分支占位)。

解析增量文本时,逐层解构choices.first()ChunkChoice.deltaDelta.content,当contentSome(content)时即为本次新增的文本片段,直接print!输出并flush刷新 stdout,从而在终端上实现类似 ChatGPT 的逐字输出效果。

音频输入底层:AudioInput 的解码原理

示例中的AudioInput::from_bytes(&audio_bytes)接收的是Bird_singing.ogg的原始字节流。AudioInput定义在独立的 mistralrs-audio/src/lib.rs crate 中:

pub struct AudioInput { pub samples: Vec<f32>, // PCM 采样值(归一化到浮点) pub sample_rate: u32, // 采样率(Hz) pub channels: u16, // 声道数 }

它提供两种构造方式:

  • from_bytes(&[u8]):使用symphonia解码任意常见音频容器(Ogg、MP3、WAV 等),自动探测格式、读取采样率与声道数,并逐帧解码出f32PCM 采样(lib.rs)。本示例即走此路径;
  • read_wav(path):直接读取本地 WAV 文件(基于hound),对 PCM16 整数采样按32768.0归一化,与 libsndfile/soundfile 的行为保持一致(lib.rs)。

音频在消息构造阶段以AudioInput形式进入MultimodalMessages,最终由多模态流水线中的音频编码器(如 Phi-4-multimodal 的音频塔)处理为 token 或 embedding 参与生成。

更多能力:支持模型清单、量化与多轮对话

同一个文档目录(docs/src/content/docs/examples/rust/models)还对应了仓库中其他多模态示例,可用于横向扩展:

统一多模态示例与模型清单

multimodal_models/main.rs 提供了一个「改一个常量即可切换模型」的统一示例,通过ModelBuilder+.with_auto_isq(IsqBits::Four)自动 INT4 量化加载,其注释中列出了已在仓库中测试过的多模态模型 ID 清单:

模型MODEL_ID
Llama 3.2 Visionlamm-mit/Cephalo-Llama-3.2-11B-Vision-Instruct-128k
Phi-3.5 Visionmicrosoft/Phi-3.5-vision-instruct
Phi-4 Multimodalmicrosoft/Phi-4-multimodal-instruct
LLaVA 1.5 *llava-hf/llava-1.5-7b-hf
LLaVA-NeXTllava-hf/llava-v1.6-mistral-7b-hf
LFM2.5-VLLiquidAI/LFM2.5-VL-450M
Idefics2HuggingFaceM4/idefics2-8b-chatty
Idefics3HuggingFaceM4/Idefics3-8B-Llama3
Qwen2-VLQwen/Qwen2-VL-2B-Instruct
Qwen2.5-VLQwen/Qwen2.5-VL-3B-Instruct
Qwen3-VLQwen/Qwen3-VL-4B-Instruct
SmolVLMHuggingFaceTB/SmolVLM-Instruct
Gemma 3google/gemma-3-4b-it
Gemma 3ngoogle/gemma-3n-E4B-it
Gemma 4google/gemma-4-E4B-it
DiffusionGemmagoogle/diffusiongemma-26B-A4B-it
MiniCPM-o 2.6openbmb/MiniCPM-o-2_6
Mistral Small 3.1mistralai/Mistral-Small-3.1-24B-Instruct-2503
Llama 4 Scoutmeta-llama/Llama-4-Scout-17B-16E-Instruct

注意:LLaVA 1.5 需要显式指定聊天模板,即追加.with_chat_template("chat_templates/vicuna.json")(模板文件位于 chat_templates/vicuna.json)。

多轮多模态对话

multimodal_multiturn/main.rs 展示了跨轮次携带图像的多模态对话:先用add_message发文本问候,再把模型回答以add_message(TextMessageRole::Assistant, resp)追加回历史,随后用add_image_message连续插入多张图片提问。它同时演示了两个实用点:

  • RequestBuilder::from(messages.clone()).set_sampler_max_len(100)控制单轮最大生成长度;
  • .with_isq(mistralrs::IsqType::Q8_0)做定点量化加载,降低显存占用。

音频专项示例

如果只关心音频输入,audio/main.rs 与 asr/main.rs 提供了仅携带音频消息(add_audio_message)的精简版本,可配合 Phi-4-multimodal 的语音理解与 ASR 能力使用。

小结

本文以官方文档中的 multimodal 示例为骨架,完整拆解了 mistral.rs 多模态流式推理的四个步骤:用MultimodalModelBuilder加载模型、用AudioInput/image::load_from_memory准备媒体、用MultimodalMessages::add_multimodal_message组装「图 + 音 + 文」联合消息、用stream_chat_request流式消费增量分块。配合MultimodalMessages内部「媒体独立存储 + 发送时注入模型前缀」的设计,以及mistralrs-audioAudioInput基于 symphonia 的通用音频解码能力,开发者只需少量代码即可在 Rust 侧实现与主流多模态大模型(Phi-4-multimodal、Qwen3-VL、Gemma 4、MiniCPM-o 2.6 等)的联合推理、量化部署与多轮对话。

【免费下载链接】mistral.rsFast, flexible LLM inference项目地址: https://gitcode.com/GitHub_Trending/mi/mistral.rs

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

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

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

立即咨询