
mistral.rs Python 绑定多模型实战Runner 管理多模型、model_id 路由与卸载重载机制【免费下载链接】mistral.rsFast, flexible LLM inference项目地址: https://gitcode.com/GitHub_Trending/mi/mistral.rs本文基于 mistral.rs 仓库的官方示例 multi_model_example.py 及其对应文档 multi-model-example.md系统讲解如何在 Python 侧使用Runner完成多模型场景下的五项核心操作通过Which描述符加载文本/多模态模型、按model_id向指定模型发送请求、管理默认模型、以及模型的卸载与重载。读完后你可以掌握多模型Runner的构造方式、list_models/get_default_model_id等模型管理 API 的语义以及底层引擎engine映射、UnloadedModelState状态保存等实现细节从而在有限显存下按需调度多个模型。1. 多模型能力总览在 mistral.rs 中一个Runner实例内部维护着一组并行的推理引擎每个模型对应一个 engine并记录一个“默认模型”ID。其核心数据结构定义在 mistralrs-core/src/lib.rsenginesmodel_id - 引擎实例的映射list_models()返回的即该映射的全部 keydefault_engine_id全局默认模型 ID请求未指定model_id时派发到它每个模型有明确的状态机由ModelStatus枚举表达见 mistralrs-core/src/lib.rsLoaded、Unloaded、Reloading三种取值。Python 侧的Runner通过 PyO3 将上述能力暴露出来。相关方法集中在 mistralrs-pyo3/src/lib.rs 的Runner实现中完整类型签名可在 mistralrs.pyi 中查阅。Rust SDK 侧的对应包装在 mistralrs/src/model.rs其中有一组明确的“Multi-Model Management Methods”注释区块包含list_models、get_default_model_id、set_default_model_id、add_model、remove_model、unload_model、reload_model、is_model_loaded、list_models_with_status九个方法与 Python API 一一对应。官方示例使用的两个模型与文档保持一致类别模型 ID架构枚举多模态google/gemma-4-E4B-itMultimodalArchitecture.Gemma4文本Qwen/Qwen3-4BArchitecture.Qwen32. 用 Which 描述符构造 RunnerRunner的构造入口是which参数其类型为Which枚举定义在 mistralrs-pyo3/src/which.rs。每个变体代表一类加载方式示例中用到两种Which.Plain(model_id, arch, ...)加载纯文本模型。arch为OptionArchitectureArchitecture枚举which.rs覆盖 Mistral、Gemma、Llama、Phi 系列、Qwen2/Qwen3/Qwen3Moe/Qwen3Next、GLM4、DeepSeek、GptOss 等Which.MultimodalPlain(model_id, arch, ...)加载多模态模型。arch为OptionMultimodalArchitecture该枚举which.rs包含 Phi3V、Qwen2VL、Gemma3、Llama4、Gemma4、Voxtral 等。此外还有Embedding、XLora、Lora、GGUF、XLoraGGUF、LoraGGUF、GGML及对应 XLora/Lora 变体、DiffusionPlain、Speech等。每个变体都支持topology、dtype、auto_map_params、hf_cache_path、imatrix等可选参数从源码结构看Architecture/MultimodalArchitecture枚举会经由From实现转换为 core 层的NormalLoaderType/MultimodalLoaderTypewhich.rs最终交给模型加载器。Runner的公共构造参数中in_situ_quant表示加载时即时量化in-situ quantization。示例统一使用Q4K即将 BF16 权重加载后立刻量化为 4-bit GGUF 风格格式以节省显存——这在同时驻留多个模型时尤为关键。3. 示例一Runner 与 model_id 参数完整代码与 multi_model_example.py 一致from mistralrs import ( Runner, Which, ChatCompletionRequest, Architecture, MultimodalArchitecture, ) def example_runner_with_model_id(): Demonstrate using Runner with model_id in requests. # Create a runner with Gemma 4 E4B multimodal model runner Runner( whichWhich.MultimodalPlain( model_idgoogle/gemma-4-E4B-it, archMultimodalArchitecture.Gemma4, ), in_situ_quantQ4K, ) # List available models model_ids runner.list_models() print(Available models:, model_ids) # Get default model default_model runner.get_default_model_id() print(fDefault model: {default_model}) # Send request with specific model_id messages [{role: user, content: Hello, how are you?}] request ChatCompletionRequest(messagesmessages, modeldefault) if model_ids: # Request to specific model response runner.send_chat_completion_request( requestrequest, model_idmodel_ids[0] ) print(fResponse from {model_ids[0]}:, response.choices[0].message.content) # Request without model_id (uses default) response runner.send_chat_completion_request(requestrequest) print(Response from default model:, response.choices[0].message.content)要点解析runner.list_models()返回当前engines映射中所有模型 ID 的列表底层直接遍历引擎字典的 keymistralrs-core/src/lib.rsChatCompletionRequest(messages..., modeldefault)使用 OpenAI 兼容的请求结构model字段是请求体内部的名字而真正决定派发目标的是send_chat_completion_request的model_id关键字参数——PyO3 签名为send_chat_completion_request(request, model_idNone)mistralrs-pyo3/src/lib.rs传None时落到默认模型该返回值类型为Either[ChatCompletionResponse, ChatCompletionStreamer]请求中streamFalse时得到完整响应对象streamTrue时得到可迭代的流式对象。4. 示例二模型管理操作列表、状态、默认模型切换def example_model_management(): Demonstrate model management operations. runner Runner( whichWhich.Plain( model_idQwen/Qwen3-4B, archArchitecture.Qwen3, ), in_situ_quantQ4K, ) # List models with their status print(Initial models with status:, runner.list_models_with_status()) # Get default model current_default runner.get_default_model_id() print(fCurrent default model: {current_default}) # Check if a model is loaded model_ids runner.list_models() if model_ids: is_loaded runner.is_model_loaded(model_ids[0]) print(fIs {model_ids[0]} loaded? {is_loaded}) # In a multi-model setup, you could change the default if model_ids and len(model_ids) 1: runner.set_default_model_id(model_ids[1]) print(fChanged default model to: {model_ids[1]})各 API 的语义对应 mistralrs-pyo3/mistralrs.pyi 中的声明list_models_with_status() - list[tuple[str, str]]返回(model_id, status)列表status 字符串来自ModelStatus的Display实现取值为loaded/unloaded/reloadingmistralrs-core/src/lib.rsget_default_model_id() - str | None读取default_engine_id若尚未设置则返回Noneis_model_loaded(model_id) - bool区分“已加载”与“已卸载但仍登记”两种状态set_default_model_id(model_id)将默认模型切换为指定 ID。底层实现会先校验目标模型存在于engines中否则返回Model {id} not found错误随后更新default_engine_id并打日志Default model changed: ...mistralrs-core/src/lib.rs。5. 示例三卸载与重载显存管理核心机制def example_unload_reload(): Demonstrate model unloading and reloading. runner Runner( whichWhich.MultimodalPlain( model_idgoogle/gemma-4-E4B-it, archMultimodalArchitecture.Gemma4, ), in_situ_quantQ4K, ) model_ids runner.list_models() if not model_ids: print(No models loaded) return model_id model_ids[0] print(fInitial status: {runner.list_models_with_status()}) # Unload the model to free memory # Note: This preserves the model configuration for later reload print(fUnloading model: {model_id}) runner.unload_model(model_id) # Check status after unload print(fStatus after unload: {runner.list_models_with_status()}) print(fIs {model_id} loaded? {runner.is_model_loaded(model_id)}) # Reload the model when needed print(fReloading model: {model_id}) runner.reload_model(model_id) # Check status after reload print(fStatus after reload: {runner.list_models_with_status()})这是多模型场景中最有实用价值的一组 API其底层机制值得展开卸载unload_model实现于 mistralrs-core/src/lib.rs流程为若模型已在unloaded_models中直接报ModelAlreadyUnloaded错误从engines中移除该模型并构造UnloadedModelState保存其loader_config模型来源、dtype、device、ISQ 配置、chat template 等、scheduler_config、engine_configKV cache / prefix cache 开关、tool callbacks、search embedding model 等、mcp_client_config与mistralrs_config——即“保配置、弃权重”向引擎发送Request::Terminate信号释放该模型占用的显存若被卸载的恰是当前默认模型则自动把default_engine_id切到剩余引擎中的第一个保证后续无model_id的请求依然可派发。重载reload_model实现于 mistralrs-core/src/lib.rs用reloading_models集合做重入保护避免并发重复加载重复调用会报ModelReloading取回UnloadedModelState通过LoaderBuilder依据保存的配置重新构建 loader并调用load_model_from_hf按原 dtype、device、ISQ 量化设置重新加载权重源码注释指出当请求经get_sender()路由到一个已卸载的模型时也会自动触发重载因此unload_model后即使不手动reload_model下一次向该模型发请求也会自动恢复代价是等待重新加载。另外Python API 还提供list_unloaded_models()用于列出所有“已卸载但仍登记”的模型 IDmistralrs-pyo3/src/lib.rs 中Runner的实现。6. 示例四针对指定模型的流式输出def example_streaming_with_models(): Demonstrate streaming responses from specific models. runner Runner( whichWhich.Plain( model_idQwen/Qwen3-4B, archArchitecture.Qwen3, ), in_situ_quantQ4K, ) messages [{role: user, content: Tell me a short story}] request ChatCompletionRequest(messagesmessages, modeldefault, streamTrue) model_ids runner.list_models() if model_ids: # Stream from specific model stream runner.send_chat_completion_request( requestrequest, model_idmodel_ids[0] ) print(fStreaming from {model_ids[0]}:) for chunk in stream: if chunk.choices[0].delta.content: print(chunk.choices[0].delta.content, end, flushTrue) print() # New line after streaming要点streamTrue写在ChatCompletionRequest中send_chat_completion_request因此返回ChatCompletionStreamerEither的右分支每个 chunk 的结构与 OpenAI 流式响应一致增量内容位于chunk.choices[0].delta.content可能为空如 role 片段因此示例中先判空再打印流式与非流式共用同一个model_id路由参数多模型场景下可按需对任一模型开启流式。7. 示例五多模态 文本模型组合以及 Rust 侧的动态多模型对照def example_multi_model_setup(): Example showing a real multi-model setup with multimodal and text models. This example loads: - Multimodal model: google/gemma-4-E4B-it - Text model: Qwen/Qwen3-4B # Load a multimodal model first runner Runner( whichWhich.MultimodalPlain( model_idgoogle/gemma-4-E4B-it, archMultimodalArchitecture.Gemma4, ), in_situ_quantQ4K, ) print(Initial models:, runner.list_models()) # Add a text model dynamically (if add_model is available) # runner.add_model( # model_idqwen, # whichWhich.Plain( # model_idQwen/Qwen3-4B, # archArchitecture.Qwen3, # ), # in_situ_quantQ4K, # ) # print(After add_model:, runner.list_models()) # Send a request to gemma messages [{role: user, content: What is 2 2?}] request ChatCompletionRequest(messagesmessages, modeldefault) response runner.send_chat_completion_request(request) print(fGemma response: {response.choices[0].message.content})注意示例中对runner.add_model的注释写法if add_model is availableRust SDK 层确实提供了动态添加模型的方法add_model(model_id, pipeline, method, config)mistralrs/src/model.rs但 Python 绑定当前暴露的动态多模型入口有限因此该示例以注释形式保留了调用形态供后续版本可用时直接启用。真正“同进程、双模型”的完整形态仓库中另有 Rust 端官方示例 mistralrs/examples/advanced/multi_model/main.rs它展示了MultiModelBuilder的典型用法可运行cargo run --release --example multi_model -p mistralrs// 模型 ID 为 HuggingFace 路径alias 为 API 请求中使用的短 ID const GEMMA_MODEL_ID: str google/gemma-4-E4B-it; const QWEN_MODEL_ID: str Qwen/Qwen3-4B; const GEMMA_ALIAS: str gemma-multimodal; const QWEN_ALIAS: str qwen-text; let model MultiModelBuilder::new() .add_model_with_alias( GEMMA_ALIAS, MultimodalModelBuilder::new(GEMMA_MODEL_ID) .with_auto_isq(IsqBits::Four) .with_logging(), ) .add_model_with_alias( QWEN_ALIAS, TextModelBuilder::new(QWEN_MODEL_ID).with_auto_isq(IsqBits::Four), ) .with_default_model(GEMMA_ALIAS) .build() .await?;该示例同时演示了list_models()、get_default_model_id()、list_models_with_status()在同一 Builder 上的调用与 Python 侧 API 语义完全一致如IsqBits::Four对应 Python 的in_situ_quantQ4K的自动 ISQ 路径。这印证了多模型架构的核心设计模型 ID 是路由键alias 是请求侧的友好名默认模型保证无路由请求有明确落点。8. Runner 多模型 API 速查结合 mistralrs.pyi 与 mistralrs-pyo3/src/lib.rs 的实现PythonRunner上与本主题相关的多模型 API 汇总如下API返回/作用底层依据list_models()所有已登记模型 ID 列表遍历engines的 keymistralrs-core/src/lib.rslist_models_with_status()(model_id, loaded/unloaded/reloading)列表ModelStatus枚举mistralrs-core/src/lib.rslist_unloaded_models()仅“已卸载”的模型 IDunloaded_models映射get_default_model_id()当前默认模型 ID可能为Nonedefault_engine_id读写锁保护字段set_default_model_id(model_id)切换默认模型模型不存在时报错mistralrs-core/src/lib.rsis_model_loaded(model_id)是否处于已加载状态区分engines与unloaded_modelsunload_model(model_id)终止引擎、释放显存、保留配置mistralrs-core/src/lib.rsreload_model(model_id)按保存的UnloadedModelState重新加载被请求自动路由触发时也会执行mistralrs-core/src/lib.rssend_chat_completion_request(request, model_idNone)向指定/默认模型发送 OpenAI 兼容请求支持流式mistralrs-pyo3/src/lib.rs9. 实践小结路由三层结构Which决定“怎么加载”model_id决定“请求发给谁”default_engine_id兜底“不指定时发给谁”。三者分离使得同一 Runner 内可以混载文本模型与多模态模型显存预算下的调度策略in_situ_quantQ4K降低单模型驻留成本unload_modelreload_model实现“热登记、冷加载”且重载对请求方透明自动触发适合按会话轮转模型的 Agent 场景状态可观测list_models_with_status()是排查“请求落在未加载模型上导致长时间重载等待”的首选诊断手段跨语言一致性Python API 与 RustMultiModelBuildermistralrs/examples/advanced/multi_model/main.rs共享同一 core 层实现mistralrs-core/src/lib.rs行为可互相印证。延伸阅读路径Python 示例 examples/python/multi_model_example.py、Rust 多模型示例 mistralrs/examples/advanced/multi_model/main.rs、PyO3 绑定 mistralrs-pyo3/src/lib.rs、core 层多模型管理 mistralrs-core/src/lib.rs、类型存根 mistralrs-pyo3/mistralrs.pyi。【免费下载链接】mistral.rsFast, flexible LLM inference项目地址: https://gitcode.com/GitHub_Trending/mi/mistral.rs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考