MiniCPM-o 2.6 FastAPI 部署调用实战:从环境配置到图片/视频多模态对话 📅 发布时间:2026/9/12 5:33:13 👁 浏览次数: MiniCPM-o 2.6 FastAPI 部署调用实战从环境配置到图片/视频多模态对话【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm导读本篇文章基于开源仓库 self-llm 中 models/MiniCPM-o/01MiniCPM-o 2 6 FastApi部署调用 .md 整理而成完整讲解如何在 Linux 环境下用 FastAPI 将 MiniCPM-o 2.6 全模态大模型封装为 HTTP 服务。读完本文你将掌握依赖环境搭建、模型下载、api_server.py服务端代码的全量逻辑以及单图单轮、单图多轮、多图比较、视频理解四类客户端调用的可运行代码可直接复制到自己的 GPU 服务器上跑通整个部署—调用闭环。MiniCPM-o 2.6 是 OpenBMB 推出的全模态omni大模型默认加载时会同时初始化视觉、音频与 TTS 模块详细能力可参考同目录文档 03-MiniCPM-o-2.6 多模态语音能力.md既能看图、读视频也具备端到端语音理解与生成能力。本文聚焦其中最常用的视觉理解链路以 FastAPI 搭建统一的服务端点客户端通过 JSON/Base64 协议上传图片、视频与文本即可获得模型的多模态回复。环境配置基础环境清单本文的部署环境以 Ubuntu CUDA PyTorch 为核心参考环境版本如下---------------- ubuntu 22.04 Python 3.12.3 cuda 12.1 pytorch 2.3.0 ----------------其中cuda 12.1与pytorch 2.3.0是保证AutoModel.from_pretrained能以 CUDA 后端加载模型的关键前提请确保nvidia-smi与python -c import torch; print(torch.cuda.is_available())均输出正常。pip 换源与依赖安装打开终端或新建Jupyter.ipynb文件先执行 pip 换源加速并安装魔搭ModelScope依赖用于后续从魔搭社区下载模型pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple pip install modelscope1.20.0依赖安装有两条路径任选其一方式一使用官方打包的环境文件一键安装。官方提供了requirements_o2.6.txt环境打包文件将其下载到项目路径下执行pip install -r requirements_o2.6.txt方式二手动 pip 安装。逐项指定关键依赖版本保证与 MiniCPM-o 2.6 的模型代码兼容pip install Pillow10.1.0 torch2.3.1 torchaudio2.3.1 torchvision0.18.1 transformers4.44.2 sentencepiece0.2.0 vector-quantize-pytorch1.18.5 vocos0.1.0 accelerate1.2.1 timm0.9.10 soundfile0.12.1 librosa0.9.0 decord moviepy fastapi uvicorn python-multipart上述依赖中有几个与本文的 API 服务直接相关值得留意fastapi、uvicorn、python-multipart构建并运行 HTTP 服务decord视频解码服务端用它按帧读取视频Pillow图片对象转换与处理transformers4.44.2加载模型与分词器版本需与模型的trust_remote_code实现匹配vector-quantize-pytorch、vocos模型内部的音频/编解码组件全模态模型加载时依赖。安装完成后在终端检查是否漏装或报错pip check python -c import fastapi, uvicorn, decord, librosa, transformers; print(deps ok)提示如果手动配置环境遇到困难可以在 AutoDL 平台直接使用官方社区准备的 MiniCPM-o 环境镜像创建实例镜像中已预装好上述全部依赖创建后可直接跳到模型下载一节。模型下载使用modelscope中的snapshot_download函数下载 MiniCPM-o 2.6 模型文件。第一个参数为模型名称参数cache_dir为模型的下载路径需要根据自己机器实际目录修改from modelscope import snapshot_download # cache_dir记得修改为自己的目录路径 model_dir snapshot_download(OpenBMB/MiniCPM-o-2_6, cache_dir/root/autodl-tmp, revisionmaster)执行后模型会被下载到/root/autodl-tmp/OpenBMB/MiniCPM-o-2_6目录下revisionmaster表示拉取 master 分支的最新代码与权重。模型整体约 18GB 左右下载时长取决于网络环境一般需要 530 分钟请耐心等待。魔搭社区同步提供了MiniCPM-o-2_6模型库页面可直接在页面内查看模型说明、文件列表与 License 信息若下载中断重新执行同一脚本会自动续传。搭建 FastAPI 服务端服务端完整代码新建api_server.py文件并粘贴以下代码已带详细注释。启动前请检查主程序入口中model、tokenizer的模型路径是否已替换为自己刚下载的模型文件具体路径# 导入必要的库 from fastapi import FastAPI, Request # FastAPI框架相关 from transformers import AutoModel, AutoTokenizer # Hugging Face transformers模型相关 from PIL import Image # 图像处理 from decord import VideoReader, cpu # 视频处理 import uvicorn # ASGI服务器 import json # JSON数据处理 import datetime # 时间处理 import torch # PyTorch深度学习框架 import base64 # Base64编解码 import io # IO操作 import os # 操作系统接口 # 设置GPU相关参数 DEVICE cuda # 使用CUDA设备 DEVICE_ID 0 # CUDA设备ID CUDA_DEVICE f{DEVICE}:{DEVICE_ID} if DEVICE_ID else DEVICE # 组合CUDA设备信息 MAX_NUM_FRAMES 64 # 视频处理的最大帧数如果显存不足可以设置更小的值 def torch_gc(): 清理GPU内存的函数 if torch.cuda.is_available(): with torch.cuda.device(CUDA_DEVICE): torch.cuda.empty_cache() # 清空CUDA缓存 torch.cuda.ipc_collect() # 收集CUDA IPC内存 def decode_base64_to_image(base64_string): 将base64字符串转换为PIL Image对象 Args: base64_string: base64编码的图片字符串 Returns: PIL.Image: 解码后的图片对象如果解码失败返回None try: # 移除可能的data URI前缀如 data:image/jpeg;base64, if , in base64_string: base64_string base64_string.split(,, 1)[1] # 解码base64并转换为图片对象 image_data base64.b64decode(base64_string) image Image.open(io.BytesIO(image_data)) return image.convert(RGB) # 转换为RGB格式 except Exception as e: print(f图片解码错误: {str(e)}) return None def encode_video(video_path): 处理视频文件提取帧 Args: video_path: 视频文件路径 Returns: list: 提取的视频帧列表每一帧为PIL Image对象 def uniform_sample(lst, n): 均匀采样函数 Args: lst: 要采样的列表 n: 需要的样本数 Returns: list: 采样后的列表 gap len(lst) / n idxs [int(i * gap gap / 2) for i in range(n)] return [lst[i] for i in idxs] # 使用decord读取视频 vr VideoReader(video_path, ctxcpu(0)) sample_fps round(vr.get_avg_fps() / 1) # 获取采样帧率 frame_idx [i for i in range(0, len(vr), sample_fps)] # 生成帧索引 # 如果帧数超过最大限制进行均匀采样 if len(frame_idx) MAX_NUM_FRAMES: frame_idx uniform_sample(frame_idx, MAX_NUM_FRAMES) # 获取视频帧并转换为PIL Image格式 frames vr.get_batch(frame_idx).asnumpy() frames [Image.fromarray(v.astype(uint8)) for v in frames] print(num frames:, len(frames)) return frames # 创建FastAPI应用 app FastAPI() app.post(/) async def create_item(request: Request): 处理POST请求的端点 Args: request: FastAPI请求对象 Returns: dict: 包含模型响应的JSON对象 global model, tokenizer try: # 解析请求数据 json_post_raw await request.json() json_post json.dumps(json_post_raw) json_post_list json.loads(json_post) # 获取请求参数 prompt json_post_list.get(prompt) # 提示文本 video_path json_post_list.get(video_path) # 视频路径 history json_post_list.get(history, []) # 对话历史 if video_path: # 处理视频输入 frames encode_video(video_path) msgs [{role: user, content: frames [prompt]}] else: # 处理图片或其他输入 current_msgs [] for msg in history: if msg[role] user and isinstance(msg[content], list): new_content [] for item in msg[content]: # 处理base64编码的图片 if isinstance(item, str) and (item.startswith(data:image) or ;base64, in item): image decode_base64_to_image(item) if image: new_content.append(image) else: new_content.append(item) msg[content] new_content current_msgs.append(msg) msgs current_msgs # 设置模型参数 params { use_image_id: False, max_slice_nums: 2 # 如果显存不足且视频分辨率448*448时使用1 } # 调用模型生成回答 responds model.chat( msgsmsgs, tokenizertokenizer, **params ) # 生成响应 now datetime.datetime.now() time now.strftime(%Y-%m-%d %H:%M:%S) answer { response: responds, status: 200, time: time } # 记录日志 log [ time ] , prompt: prompt , response: repr(responds) print(log) # 清理GPU内存 torch_gc() return answer except Exception as e: print(fError: {str(e)}) return {error: str(e), status: 500} # 主程序入口 if __name__ __main__: # 设置随机种子 torch.manual_seed(1000) # 加载模型和分词器 model AutoModel.from_pretrained( autodl-tmp/OpenBMB/MiniCPM-o-2_6, # 替换为自己的具体路径 trust_remote_codeTrue, attn_implementationsdpa, torch_dtypetorch.bfloat16 ) model model.eval().cuda() # 将模型设置为评估模式并移到GPU tokenizer AutoTokenizer.from_pretrained( autodl-tmp/OpenBMB/MiniCPM-o-2_6, # 替换为自己的具体路径 trust_remote_codeTrue ) # 启动FastAPI服务器 uvicorn.run(app, host0.0.0.0, port6006, workers1)服务端代码要点解析1媒体输入的统一协议设计。服务端设计了一个统一的POST /端点请求体为 JSON可携带三个字段字段类型说明promptstring用户提问的文本提示video_pathstring可选视频文件在服务器本地的路径传入时走视频理解分支historyarray可选对话历史content列表中可混排 Base64 图片与文本图片不走文件路径而是以 Base64 字符串内嵌在history的content列表中传输天然适合跨机调用视频则要求调用方先把视频放到服务器可访问的路径再传video_path。2Base64 图片解码。decode_base64_to_image先剥离data:image/jpeg;base64,这类 data URI 前缀再解码为 PIL 图片并统一转成 RGB保证送入模型的图像通道格式一致。3视频抽帧采样。encode_video基于decord在 CPU 上以约 1 FPS 的采样率抽取视频帧sample_fps round(vr.get_avg_fps() / 1)若抽帧数超过MAX_NUM_FRAMES 64则通过uniform_sample均匀抽到 64 帧以内从而把超长视频压缩为固定上限的帧序列控制显存占用。4模型加载参数。加载时使用attn_implementationsdpa开启 PyTorch 的 scaled dot-product attention 加速路径同目录的 WebDemo 脚本 02minicpm-o-2.6WebDemo_streamlit.py 也采用相同加载方式并以torch_dtypetorch.bfloat16半精度加载、trust_remote_codeTrue信任模型自带的自定义代码。服务以workers1启动避免多进程重复加载 18GB 级模型造成显存溢出。5推理参数。每次调用设置use_image_idFalse不注入图片 ID 标记、max_slice_nums2允许把高分辨率图切分为最多 2 个子图处理提高细节理解能力显存不足或视频分辨率 448×448 时可改为 1。启动 FastAPI 服务在终端输入以下命令启动服务请先cd到自己存放代码的路径# cd到自己存放代码的文件的路径如 cd /root/autodl-tmp python api_server.py首次启动会加载模型与分词器需要等待一段时间。出现类似 Uvicorn running on http://0.0.0.0:6006 的信息即表示启动成功服务默认部署在6006端口调用场景一单张图片输入单轮对话新建1image_1conv.py文件并粘贴以下代码注意在注释位置修改为自己输入图片的实际存放路径import requests import base64, os def send_request(data): 发送请求并处理响应 response requests.post(http://localhost:6006, jsondata) try: result response.json() if result.get(status) 200: print(fMiniCPM-o: {result.get(response)}) else: print(f错误: {result.get(error)}) except Exception as e: print(f解析响应时出错: {str(e)}) print(f原始响应: {response.text}) print(\n 测试单张图片分析 ) with open(autodl-tmp/input/1-01.jpg, rb) as f: # 注意修改为自己输入图片的存放路径 image_base64 fdata:image/jpeg;base64,{base64.b64encode(f.read()).decode(utf-8)} send_request({ prompt: 这张图片里有什么, history: [ { role: user, content: [image_base64, 这张图片里有什么] } ] })脚本逻辑非常直观读取本地图片 → 编码为带data:image/jpeg;base64,前缀的 Base64 字符串 → 与提问文本一起放入history的用户消息content列表中 → POST 到http://localhost:6006→ 打印模型回复。运行命令进行单张图片单轮对话# cd到自己存放代码的文件的路径如 cd /root/autodl-tmp python 1image_1conv.py以一只猫的样例图片为例模型返回对图片内容的自然语言描述调用结果如下调用场景二单张图片输入多次对话视觉对话的精髓在于基于同一张图连续追问。新建1image_mconv.py文件并粘贴以下代码同样注意修改为自己图片的存放路径import requests import base64 with open(autodl-tmp/input/1-01.jpg, rb) as f: # 在这里修改为自己图片的具体路径 image_base64 fdata:image/jpeg;base64,{base64.b64encode(f.read()).decode(utf-8)} question 这张图片里有什么 msgs [{role: user, content: [image_base64, question]}] response requests.post( http://localhost:6006, json{ prompt: question, history: msgs } ) if response.status_code 200: first_response response.json().get(response) print(first_response) msgs.append({role: assistant, content: [first_response]}) question 你觉得它下一步会做什么 msgs.append({role: user, content: [question]}) response requests.post( http://localhost:6006, json{ prompt: question, history: msgs } ) if response.status_code 200: print(response.json().get(response))多轮对话的关键在于对话历史的累积与回传第一轮结束后把模型回答以assistant角色追加进msgs再追加新的user提问第二次请求把完整的msgs作为history传给服务端。服务端会遍历history将用户消息中的 Base64 图片字符串解码为 PIL 图片与文本一起组装成msgs交给model.chat从而让模型记住上一轮看过的图和自己的回答。沿用上一节的样例图片第一轮问这张图片里有什么第二轮追问你觉得它下一步会做什么运行python 1image_mconv.py调用结果如下可以看到模型在第二轮回答时已经结合了第一轮的多模态上下文调用场景三多张图片输入对话MiniCPM-o 2.6 还支持同时输入多张图片进行对比理解。新建mimage.py文件并粘贴以下代码同样注意修改图片存放路径import requests import base64, os def send_request(data): 发送请求并处理响应 response requests.post(http://localhost:6006, jsondata) try: result response.json() if result.get(status) 200: print(fMiniCPM-o: {result.get(response)}) else: print(f错误: {result.get(error)}) except Exception as e: print(f解析响应时出错: {str(e)}) print(f原始响应: {response.text}) # 多张图片比较 print(\n 测试多张图片比较 ) with open(autodl-tmp/input/1-01.jpg, rb) as f: # 在这里修改 image1_base64 fdata:image/jpeg;base64,{base64.b64encode(f.read()).decode(utf-8)} with open(autodl-tmp/input/1-02.jpg, rb) as f: # 在这里修改 image2_base64 fdata:image/jpeg;base64,{base64.b64encode(f.read()).decode(utf-8)} send_request({ prompt: 比较这两张图片的区别, history: [ { role: user, content: [ image1_base64, image2_base64, 比较这两张图片的区别 ] } ] })多图输入与单图的唯一区别是在content列表中依次放入多张 Base64 图片最后跟提问文本。服务端对content列表逐项判断——是 Base64 图片字符串就解码成 PIL 图片对象是普通文本则原样保留最终按图片 1、图片 2、文本的顺序组装成模型的视觉输入序列。运行命令python mimage.py以猫猫和狗狗两张样例图片做对比测试模型能正确描述两张图片各自的内容差异调用结果如下调用场景四视频输入对话视频理解走的是独立的video_path分支。新建1video.py文件并粘贴以下代码修改为自己输入视频的实际存放路径import requests import base64, os def send_request(data): 发送请求并处理响应 response requests.post(http://localhost:6006, jsondata) try: result response.json() if result.get(status) 200: print(fMiniCPM-o: {result.get(response)}) else: print(f错误: {result.get(error)}) except Exception as e: print(f解析响应时出错: {str(e)}) print(f原始响应: {response.text}) print(\n 测试视频分析 ) video_path os.path.join(os.path.expanduser(~), autodl-tmp, input, 1-04.mp4) # 在这里修改 if os.path.exists(video_path): send_request({ prompt: 描述这个视频的内容, video_path: video_path }) else: print(f错误: 找不到视频文件 {video_path})与图片模式不同客户端不传图片而是把视频文件的服务器本地绝对路径放进video_path字段。服务端收到后调用encode_video先用decord按约 1 FPS 抽帧帧数超过 64 时均匀采样压缩再把帧列表与prompt合并为[帧1, 帧2, ..., prompt]的用户消息交给模型做视频内容理解。运行命令python 1video.py以一段样例视频为例模型能描述视频中的画面内容与动作调用结果如下服务端参数与调用协议补充说明为便于读者按需调优这里把服务端与调用协议中的关键参数集中归纳参数/字段位置默认/示例值作用与调优建议attn_implementation模型加载sdpa注意力实现SDPA 速度快、省显存可替换为flash_attention_2需安装 flash-attntorch_dtype模型加载torch.bfloat16半精度加载显存占用约为 FP32 的一半MAX_NUM_FRAMES服务端常量64视频最大抽帧数显存不足时调小如 32/16max_slice_nums推理参数2高分辨率图片切片数显存不足或视频分辨率 448×448 时改为 1use_image_id推理参数False是否注入图片 ID 标记多图场景可开启以增强图文对应port服务启动6006FastAPI 监听端口可按需修改客户端 URL 需同步调整history请求字段[]多轮对话必须累积user/assistant消息并回传否则模型无上下文记忆video_path请求字段无仅视频模式使用图片模式一律走history内嵌 Base64关于推理侧更多的采样参数sampling、top_p、top_k、temperature、repetition_penalty、max_new_tokens、流式输出stream等可参考同目录 WebDemo 脚本 02minicpm-o-2.6WebDemo_streamlit.py 中params字典的配置方式其中视频模式还额外设置了max_inp_length4352限制输入序列长度高分辨率视频下若 OOM 可将max_slice_nums调至 1。常见问题与调优建议1. 显存不足CUDA out of memory。优先依次尝试将MAX_NUM_FRAMES调小64 → 32 → 16将max_slice_nums由 2 改为 1视频模式可参考 WebDemo 中设置max_inp_length限制输入长度最后再考虑更换更大显存的 GPU。2. 模型加载失败或报错。检查模型路径是否与实际下载目录一致默认autodl-tmp/OpenBMB/MiniCPM-o-2_6下载到其他目录时务必替换api_server.py中两处from_pretrained的路径确认transformers4.44.2等关键依赖版本与官方requirements_o2.6.txt一致。3. 视频抽帧报错。确认视频文件真实存在于服务端路径客户端先做os.path.exists校验且decord支持该视频编码格式超大视频建议先转码为 mp4 再调用。4. 跨机调用。服务端监听0.0.0.0:6006因此把客户端脚本中的localhost:6006换成服务器公网/内网 IP 即可跨机器调用如需对外开放请自行做好防火墙与鉴权例如在 FastAPI 层增加 Token 校验。5. 进一步探索。部署完成后若想体验语音对话TTS/语音克隆、audio_assistant助手模式等可阅读 03-MiniCPM-o-2.6 多模态语音能力.md想要可视化交互界面可参考 02minicpm-o-2.6WebDemo部署.md需要对模型做下游任务微调可参考 04-MiniCPM-0-2.6 Lora微调.md。至此一套可复用的 MiniCPM-o 2.6 FastAPI 多模态服务已完成搭建并跑通了图片、视频、多轮对话三种主流调用方式后续无论是接入业务系统还是二次开发都可以在这套 HTTP 协议之上继续扩展。【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考