mistral.rs 部署 Phi-3.5-Vision:HTTP 服务端多模态推理实战指南
【免费下载链接】mistral.rsFast, flexible LLM inference项目地址: https://gitcode.com/GitHub_Trending/mi/mistral.rs
本篇技术指南讲解如何在 mistral.rs 中通过 OpenAI 兼容的 HTTP 服务接口部署并调用microsoft/Phi-3.5-vision-instruct多模态模型(架构代号phi3v/Phi3VForCausalLM),覆盖服务端启动、Python 客户端三种图片输入方式(URL、Base64、本地文件)、采样参数调优,并结合仓库源码解析图像预处理(HD transform)与 token 占位机制。读完你可以直接在自己的环境中搭建一个支持图片理解的本地推理服务。
一、背景:为什么在 mistral.rs 里用 Phi-3.5-Vision
Phi-3.5-Vision 是微软推出的小尺寸多模态语言模型,能接受「图片 + 文本」混合输入并输出对图像内容的自然语言描述。mistral.rs 将其作为第一梯队的多模态架构原生支持:从源码看,supported-models.md 明确列出Phi3VForCausalLM对应microsoft/Phi-3.5-vision-instruct;在 multimodal_loaders.rs 中,序列化名"phi3v"与Phi3V枚举直接绑定,加载器Phi3VLoader负责读取模型配置并构建视觉编码器。这意味着你不需要自己拼接图像嵌入,mistral.rs 会在内部完成图片编码、占位符替换与注意力拼接。
与服务端示例配套的还有进程内(in-process)示例 examples/python/phi3v.py,它用Runner+Which.MultimodalPlain直接加载模型,适合不需要 HTTP 的场景;而本文聚焦更通用、更易集成的 HTTP 服务方式。
二、启动服务:加载 phi3v 模型
2.1 使用 CLI 一键启动
mistral.rs 的serve命令即可拉起 OpenAI 兼容的/v1服务,并内置 Web UI(http://localhost:1234/ui)。根据 supported-models.md 给出的官方命令:
mistralrs serve -m microsoft/Phi-3.5-vision-instruct启动后默认监听http://localhost:1234,OpenAI 兼容端点位于http://localhost:1234/v1。如需自定义端口,可追加--port <端口号>等参数;若显存紧张,还可使用-i <量化级别>(ISQ 量化)进一步压缩模型体积,具体参数以mistralrs serve --help为准。
2.2 服务端如何识别模型
从源码看,mistral.rs 通过多种方式识别该架构:multimodal_loaders.rs 中"Phi3VForCausalLM"(config.json 中的architectures字段)与"phi3v"(手动指定架构名)都会解析为Phi3V多模态类型,随后由Phi3VLoader完成模型加载(multimodal_loaders.rs)。因此在大多数情况下,你只需提供模型名,mistral.rs 会自动探测架构。
三、客户端调用:OpenAI SDK 发送图片 + 文本
服务端示例 examples/server/phi3v.py(即本文档对应的可运行源码)展示了标准的调用姿势:使用openaiPython SDK,把base_url指向本地服务,然后在messages的content数组中混合image_url与text两种类型的消息块。
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.nhmagazine.com/content/uploads/2019/05/mtwashingtonFranconia-2-19-18-108-Edit-Edit.jpg" }, }, { "type": "text", "text": "What is shown in this image? Write a detailed response analyzing the scene.", }, ], }, ], max_tokens=256, frequency_penalty=1.0, top_p=0.1, temperature=0, ) resp = completion.choices[0].message.content print(resp)要点说明:
base_url使用/v1/结尾,api_key任意非空字符串即可(本地服务不做鉴权校验);model传"default",指向当前加载的唯一模型;content列表内先放图片、再放文本,文本提问紧随图片之后;- 采样参数:
temperature=0让输出接近贪心解码、top_p=0.1进一步收窄候选集、frequency_penalty=1.0抑制重复词,适合追求稳定描述性输出的视觉问答场景。
3.1 调试利器:打印完整请求与响应
示例中附带了一个可选的log_response钩子,通过 httpx 的event_hooks打印每次请求的 method、URL、Header 与 Body,以及响应的状态码与 Header,其中对authorization、cookie、set-cookie等敏感字段做了脱敏处理:
import httpx import textwrap import json def log_response(response: httpx.Response): request = response.request print(f"Request: {request.method} {request.url}") print(" Headers:") for key, value in request.headers.items(): if key.lower() == "authorization": value = "[...]" if key.lower() == "cookie": value = value.split("=")[0] + "=..." print(f" {key}: {value}") print(" Body:") try: request_body = json.loads(request.content) print(textwrap.indent(json.dumps(request_body, indent=2), " ")) except json.JSONDecodeError: print(textwrap.indent(request.content.decode(), " ")) print(f"Response: status_code={response.status_code}") print(" Headers:") for key, value in response.headers.items(): if key.lower() == "set-cookie": value = value.split("=")[0] + "=..." print(f" {key}: {value}") # 启用日志 # client._client = httpx.Client( # event_hooks={"request": [print], "response": [log_response]} # )当调用异常或想确认服务端究竟收到了什么时,取消注释即可观察到完整报文。
四、三种图片输入方式
除了上述 URL 直传,服务端还支持 Base64 内嵌与本地文件路径两种方式,对应示例 examples/server/phi3v_base64.py 与 examples/server/phi3v_local_img.py。
4.1 方式一:远程图片 URL
即第三节的写法,image_url.url直接填 HTTPS 图片地址。服务端会在内部下载该图片并解码。适用于公开可访问的图片资源。
4.2 方式二:Base64 内嵌(适合隐私图片 / 离线场景)
本地图片经base64编码后,以data:image/png;base64,<编码串>形式内嵌在请求中,图片内容不出本机即可完成推理:
import requests import base64 BASE_URL = "http://localhost:1234/v1" FILENAME = "picture.jpg" with open(FILENAME, "rb") as image_file: encoded_string = base64.b64encode(image_file.read()).decode("utf-8") headers = {"Content-Type": "application/json"} payload = { "model": "phi3v", "messages": [ { "role": "user", "content": [ { "type": "image_url", "image_url": { "url": f"data:image/png;base64,{encoded_string}", }, }, { "type": "text", "text": "What is shown in this image? Write a detailed response analyzing the scene.", }, ], } ], "max_tokens": 300, } response = requests.post(f"{BASE_URL}/chat/completions", headers=headers, json=payload) print(response.json())注意:该示例用requests直接 POST/chat/completions,与 OpenAI SDK 等价;model传"phi3v"同样可用(服务端对模型名校验宽松,"default"亦可)。
4.3 方式三:本地文件路径(服务端可访问的文件)
若图片已存放在运行服务的机器上,可把image_url.url直接写成文件名或路径(如"picture.jpg"),mistral.rs 会按本地文件读取:
import requests BASE_URL = "http://localhost:1234/v1" FILENAME = "picture.jpg" headers = {"Content-Type": "application/json"} payload = { "model": "phi3v", "messages": [ { "role": "user", "content": [ { "type": "image_url", "image_url": {"url": FILENAME}, }, { "type": "text", "text": "What is shown in this image? Write a detailed response analyzing the scene.", }, ], } ], "max_tokens": 300, } response = requests.post(f"{BASE_URL}/chat/completions", headers=headers, json=payload) print(response.json())三种方式的请求结构完全一致,仅image_url.url的取值形态不同,可依场景自由切换。相关文档还包括 phi3v-base64.md 与 phi3v-local-img.md,可直接对照阅读。
五、进程内调用(不需要 HTTP)
如果不希望起服务,mistral.rs 也提供 Python 进程内推理路径。参考 examples/python/phi3v.py:通过Which.MultimodalPlain显式指定模型 ID 与MultimodalArchitecture.Phi3V,然后直接发送 ChatCompletionRequest:
from mistralrs import Runner, Which, ChatCompletionRequest, MultimodalArchitecture runner = Runner( which=Which.MultimodalPlain( model_id="microsoft/Phi-3.5-vision-instruct", arch=MultimodalArchitecture.Phi3V, ), ) res = runner.send_chat_completion_request( ChatCompletionRequest( model="default", messages=[ { "role": "user", "content": [ { "type": "image_url", "image_url": { "url": "https://www.nhmagazine.com/content/uploads/2019/05/mtwashingtonFranconia-2-19-18-108-Edit-Edit.jpg" }, }, { "type": "text", "text": "What is shown in this image? Write a detailed response analyzing the scene.", }, ], } ], max_tokens=256, presence_penalty=1.0, top_p=0.1, temperature=0.1, ) ) print(res.choices[0].message.content) print(res.usage)注意这里用的是presence_penalty,而服务端示例用的是frequency_penalty——两者都是 OpenAI 兼容参数,作用略有差异(前者惩罚「话题重复」,后者惩罚「字面重复」),可按需选用。
六、底层原理:图片如何变成模型输入
理解底层能帮你排查 token 数量、显存占用等问题。核心实现在 phi3_inputs_processor.rs,关键点如下。
6.1 占位标签与图像 token 计数
Phi-3.5-Vision 的 chat template 用<|image_N|>形式占位(N 为图片序号,从 1 开始)。phi3_inputs_processor.rs 中Phi3InputsProcessor使用正则r"<\|image_\d+\|>"切分提示词;每个占位符会被替换为一串负 token id(-(image_id as i64),见 phi3_inputs_processor.rs),用于标记「此处应插入图像嵌入」。
一张图到底占多少 token?phi3_image_token_count给出计算公式(phi3_inputs_processor.rs):
(h * w + 1) * 144 + (h + 1) * 12 + 1其中h、w是 HD transform 后图像按 336 像素网格切分的块数。这个公式同样出现在预处理阶段(phi3_inputs_processor.rs),并且仓库自带单测planning_token_count_matches_preprocessor验证「规划阶段的 token 计数」与「实际预处理输出」一致(phi3_inputs_processor.rs),说明该计数是精确、可预测的。
6.2 HD transform:高清图处理
Phi-3.5-Vision 对高清图采用「HD transform」策略:先把竖图旋转 90° 转为横图,按num_crops(可配置的 crop 数量)计算缩放系数,将图缩放并 padding 到 336 的整数倍,再切成若干 336×336 的 patch(phi3_inputs_processor.rs)。随后:
- 全局视图 resize 到 336×336;
- 每个 HD patch 与全局视图拼接,pad 到
num_crops + 1个 patch(phi3_inputs_processor.rs); - 归一化使用 CLIP 风格均值/方差(phi3_inputs_processor.rs)——这也解释了为什么模型同时依赖 CLIP 视觉编码器(见 mod.rs 中对
ClipVisionTransformer的引用)。
6.3 注意力布局与并发批处理
处理完成的图像嵌入会按MultimodalItemLayout拼接到文本嵌入中,支持在同一批次内混合「带图请求」与「纯文本请求」的 packed prefill,单测packed_layout_splices_media_and_preserves_text_request验证了该拼接逻辑(phi3_inputs_processor.rs)。同时,纯文本请求会自动退化为常规文本输入管线(phi3_inputs_processor.rs),这意味着服务端可以灵活混跑视觉与文本负载。
七、常见问题与排查建议
| 现象 | 可能原因 | 排查/解决方向 |
|---|---|---|
| 请求 4xx / 报图片标签格式错误 | prompt 中<\|image_N\|>占位与图片数不匹配 | 检查content数组中图片与文本块的顺序与数量 |
| 图片 token 数超出上下文 | 高清大图经 HD transform 后 token 较多 | 用 6.1 节公式预估;可降低num_crops或换小图 |
| 显存不足(OOM) | 未量化模型较大 | 启动时加-i启用 ISQ 量化 |
| 想确认服务端收到什么 | 报文不一致 | 开启 3.1 节的 httpx 日志钩子打印请求/响应 |
| 图片在服务端机器上 | 外网 URL 不可达 | 改用本地路径或 Base64 方式 |
八、小结
本文围绕 docs/src/content/docs/examples/server/phi3v.md 展开,完整覆盖了 phi3v 模型的 HTTP 服务部署与三种客户端输入方式。整体链路可以归纳为:
mistralrs serve -m microsoft/Phi-3.5-vision-instruct拉起 OpenAI 兼容服务;- 客户端在
messages[].content中混合image_url与text块,URL / Base64 / 本地路径三选一; - 服务端
Phi3VLoader加载模型,Phi3InputsProcessor完成 HD transform、占位符替换与图像嵌入拼接; - 返回
choices[0].message.content即为模型的图像理解结果。
参考源码入口:服务端示例 examples/server/phi3v.py、Base64 示例 examples/server/phi3v_base64.py、本地图片示例 examples/server/phi3v_local_img.py,以及输入处理实现 phi3_inputs_processor.rs 与模型定义 mod.rs。
【免费下载链接】mistral.rsFast, flexible LLM inference项目地址: https://gitcode.com/GitHub_Trending/mi/mistral.rs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考