在 Xinference 中部署 WeMM-Embedding-4B:多模态嵌入模型的完整实战指南
【免费下载链接】inferenceSwap GPT for any LLM by changing a single line of code. Xinference lets you run open-source, speech, and multimodal models on cloud, on-prem, or your laptop — all through one unified, production-ready inference API.项目地址: https://gitcode.com/GitHub_Trending/in/inference
WeMM-Embedding-4B 是 Xinference 内置的腾讯多模态嵌入模型,支持中文与英文文本,并原生支持图像(vision)与视频(video)模态,最大上下文长度达 262144 tokens。本篇基于 Xinference 仓库中的内置模型文档与对应源码实现,讲解如何启动该模型、两种推理后端(sentence_transformers 与 vLLM)的差异、多模态输入的组织方式,以及 Matryoshka 维度截断等关键参数在底层的具体处理逻辑,帮助你在生产环境中快速接入一个"文本+图像+视频"统一向量化服务。
一、模型规格:从官方文档到 model_spec.json 的完整信息
Xinference 内置模型文档 wemm-embedding-4b.rst 给出的基础信息如下:
| 项目 | 值 |
|---|---|
| 模型名 | WeMM-Embedding-4B |
| 支持语言 | zh(中文)、en(英文) |
| 能力(Abilities) | embed(向量嵌入) |
| 向量维度(Dimensions) | 2560 |
| 最大 Token 数(Max Tokens) | 262144 |
| 模型 ID | tencent/WeMM-Embedding-4B |
| 模型仓库 | Hugging Face 与 ModelScope(Tencent-Hunyuan 组织)均提供下载 |
文档中只列出了embed这一能力,但从仓库的模型规格文件 model_spec.json 可以看到更完整的定义:该模型的model_ability为["vision", "video"],即它不只是文本嵌入模型,而是一个可以消费图像与视频输入的多模态嵌入模型。此外规格中还明确了:
- 模型格式仅支持
pytorch,量化方式仅支持none(不做 GGUF 等量化格式); - 同一系列还有 WeMM-Embedding-2B(2048 维,featured 标记为 true)与 WeMM-Embedding-9B(4096 维),三者
max_tokens均为 262144,规格中统一维护在tencent/WeMM-Embedding-*(Hugging Face)与Tencent-Hunyuan/WeMM-Embedding-*(ModelScope)两个来源。
向量维度 2560 是模型的默认全量输出维度;由于该系列模型支持 Matryoshka 表示学习(源码中通过模型 config 的matryoshka_dimensions字段声明合法截断维度),你可以通过 API 的dimensions参数请求更短的向量,这一点后文会结合源码展开。
二、启动模型:一条命令与背后的依赖环境
文档给出的启动命令如下:
xinference launch --model-name WeMM-Embedding-4B --model-type embedding执行该命令时,Xinference 会根据model_spec.json中声明的virtualenv字段自动准备隔离的模型虚拟环境。WeMM-Embedding-4B 声明的依赖(见 model_spec.json)按推理引擎(#engine#)条件划分为两组:
sentence_transformers 引擎(默认):
sentence-transformers==5.7.0 transformers==5.2.0 accelerate>=1.1.0 qwen-vl-utils==0.0.14 #system_torch# #system_torchvision#vLLM 引擎:
vllm>=0.27.0这些版本约束并非随意指定,引擎选择逻辑(match_json)会在启动时逐一校验。以 sentence_transformers 后端为例,sentence_transformers/core.py 中的匹配函数要求:
sentence-transformers >= 5.7.0——WeMM 依赖 Sentence Transformers 5.7 引入的模态感知encode()路径(能自动区分文本/图像/视频输入);transformers >= 5.2.0;qwen-vl-utils >= 0.0.14——该库负责视觉与视频输入的预处理(WeMM 系列沿用了 Qwen-VL 风格的视觉处理管线);- 模型格式必须为
pytorch,否则直接返回 "WeMM-Embedding supports pytorch format only"。
对于 vLLM 后端,vllm/core.py 在加载时会显式检查vllm >= 0.27.0,不满足则抛出WeMM-Embedding requires vLLM>=0.27.0。测试用例 test_wemm_embedding.py 验证了这一约束:vLLM 0.27.0 + pytorch 格式匹配成功,而 ggufv2 格式被拒绝。
三、多模态输入格式:Xinference 如何归一化你的请求
WeMM 系列的输入归一化逻辑集中在独立模块 wemm.py 中,这是理解该模型 API 使用方式的关键。is_wemm_model()以WeMM-Embedding-前缀识别该系列模型(wemm.py),随后normalize_wemm_inputs()(wemm.py)将 API 输入统一转换为"聊天消息"形式。它支持三种等价的输入写法:
1. 纯文本字符串——最简单形式,会被包装为单条 user 消息:
"一段用于嵌入的文本"2. 扁平字典(flat dictionary)——同一条输入中按顺序组合 text、image、video 字段(image_url/video_url也接受):
{ "image": "https://example.com/photo.jpg", "text": "描述这张图片" }3. 角色/内容消息或消息列表——表达交错的多模态内容或多轮对话:
{ "role": "user", "content": [ {"type": "image", "image": "https://example.com/photo.jpg"}, {"type": "text", "text": "这张图讲了什么"} ] }以及多消息形式{"messages": [ ... ]}。归一化过程中的关键规则(见_normalize_content_item,wemm.py):
- 明确拒绝音频输入:任何
audio/audio_url/input_audio字段都会抛出WeMM-Embedding does not support audio input.——这与规格中只有 vision/video 两项能力一致; - 图像/视频字段兼容
image、image_url(含{"url": ...}包装)等多种写法,统一归一为{"type": "image", "image": <value>}; - 文本必须是字符串,content 必须是非空列表或字符串,否则抛出明确的 ValueError。
本地文件路径在 vLLM 后端有专门的处理:_media_url()(vllm/core.py)会将http://、https://、data:、file://开头的值原样透传,而普通本地路径会转换为file://绝对 URI,路径不存在时抛出WeMM-Embedding image/video not found错误。
四、后端实现剖析(一):sentence_transformers 路径
当使用默认引擎时,请求会走 sentence_transformers/core.py 中专门为 WeMM 开辟的分支。源码注释解释了为什么这样做:
"WeMM relies on Sentence Transformers 5.7's modality-aware
encodepath. The local text-only helper above bypasses its role/content conversion and vision preprocessing."
也就是说,Xinference 不复用自己内置的纯文本encode()辅助函数(它只处理 tokenization 与 forward,无法处理视觉预处理),而是直接调用SentenceTransformer.encode()的原生多模态路径。该分支做了三件重要的参数翻译工作:
- 维度截断:API 参数
dimensions被转换为 Sentence Transformers 的truncate_dim参数,并先经过_validate_wemm_dimensions()校验(sentence_transformers/core.py)——合法取值来自模型 config 中的matryoshka_dimensions列表,不在列表中则抛出WeMM-Embedding dimensions must be one of [...], got X。这保证了你请求的截断维度确实是模型训练时支持的原生档位; - 归一化参数:OpenAI 风格的
normalize_embedding被重命名为 Sentence Transformers 认识的normalize_embeddings(默认开启 L2 归一化,便于用点积代替余弦相似度计算); - 批处理限制:
batch_size默认强制为 1(wemm_kwargs.setdefault("batch_size", 1)),与多模态输入的单条推理语义保持一致。
视频读取的兼容性补丁是这一后端另一个值得注意的细节。ensure_wemm_video_reader()(wemm.py)解决的问题是:torchvision 0.24+ 移除了io.read_video,而 qwen-vl-utils 0.0.14 在 decord/torchcodec 不可用时仍会回退到该函数。Xinference 通过向qwen_vl_utils.vision_process.VIDEO_READER_BACKENDS["torchvision"]注入一个基于 PyAV 的替代读取器(PyAV 本就是 qwen-vl-utils 的必需依赖)来修复这一断链。该替代实现支持file://路径与data:base64 数据 URI、按时间区间截取片段(video_start/video_end),并用smart_nframes+torch.linspace均匀抽帧,最终返回带video_backend: "pyav"元信息的张量。补丁以幂等方式安装(通过_xinference_wemm_pyav_fallback标记防重复注入),并会记录 "Using PyAV as the WeMM-Embedding video reader fallback." 日志,方便你在排查视频输入问题时确认是否生效。
五、后端实现剖析(二):vLLM 路径
选择 vLLM 引擎时,加载与推理流程都不同:
加载阶段(vllm/core.py):
- 要求
vllm >= 0.27.0; - 从模型目录读取
embedding_chat_template.jinja聊天模板(文件缺失会报Missing WeMM-Embedding chat template),WeMM 需要把多模态消息渲染为模型约定的 prompt 格式; - 以
LLM(model=..., runner="pooling", ...)构造池化(pooling)推理器,并默认设置gpu_memory_utilization=0.6(用户显式传参则保留覆盖值,由测试 test_wemm_vllm_load_uses_memory_default_and_preserves_override 验证); - 注意:vLLM 后端对其他嵌入模型会执行"超过上下文长度自动截断"逻辑,但对 WeMM 模型跳过了该截断(vllm/core.py 中
not is_wemm_model(...)条件),这是因为它 262144 的超大上下文由模型侧自身管理。
推理阶段(_embed_wemm(),vllm/core.py):
- 调用同一个
normalize_wemm_inputs()得到标准消息(两个后端共享 wemm.py 的归一化逻辑); - 用
tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=False, chat_template=<模板>)渲染出 prompt 文本; - 通过
iter_wemm_media()遍历消息中的 image/video 项,用 vLLM 的fetch_image/fetch_video拉取媒体,组装为multi_modal_data(单个媒体取标量、多个取列表); - 最终调用
model.embed(vllm_inputs, use_tqdm=False, pooling_params=pool_params),其中pooling_params携带dimensions(Matryoshka 截断)与归一化开关。
这一流程由测试 test_wemm_vllm_builds_prompt_and_multimodal_data 完整覆盖:图像+文本+视频交错的输入,最终产出渲染后的 prompt 与{"image": "image:file://...", "video": "video:file://..."}形式的多模态数据。
六、行为验证:单元测试给出的可复现结论
仓库中的测试用例可以作为 API 行为的"活文档",关键结论如下:
- 交错输入保持原样传递:sentence_transformers 后端测试(test_wemm_embedding.py)断言
{"role": "user", "content": [{"type": "image", ...}, {"type": "text", ...}]}会被原样包成[[input_value]]传给encode(),且truncate_dim、normalize_embeddings=True、batch_size=1三个参数如预期生效; - 批量请求的基数守恒:传入
["text", {"image": "x.jpg"}, {"video": "x.mp4"}]混合批次,返回data长度严格为 3(test_wemm_embedding.py); - 依赖与格式匹配:vLLM 后端仅匹配
WeMM-Embedding-前缀 + pytorch 格式,且要求 vLLM 版本达标(test_wemm_embedding.py)。
七、总结与适用前提
WeMM-Embedding-4B 在 Xinference 中的定位是"多模态统一嵌入":文本、图像、视频走同一接口、产出同一向量空间中的表示,262144 tokens 的上下文使其适合长文档与长视频场景。落地时需要注意:
- 启动使用
xinference launch --model-name WeMM-Embedding-4B --model-type embedding,模型从 Hugging Face 的tencent/WeMM-Embedding-4B或 ModelScope 的Tencent-Hunyuan/WeMM-Embedding-4B自动下载,仅支持 pytorch 格式与none量化; - 默认 sentence_transformers 引擎要求 sentence-transformers 5.7.0 / transformers 5.2.0 / qwen-vl-utils 0.0.14 的精确组合(由虚拟环境自动安装),vLLM 引擎则要求 vLLM 0.27.0+;
- 不支持音频输入;
dimensions参数只能取模型matryoshka_dimensions声明的合法档位; - 视频输入在缺少 decord/torchcodec 的环境中会自动切换 PyAV 回退读取器,日志中可观察到相应提示信息。
核心实现均可在仓库中溯源:输入归一化与视频回退见 xinference/model/embedding/wemm.py,两种后端的接入点分别在 xinference/model/embedding/sentence_transformers/core.py 与 xinference/model/embedding/vllm/core.py,模型规格定义在 xinference/model/embedding/model_spec.json。
【免费下载链接】inferenceSwap GPT for any LLM by changing a single line of code. Xinference lets you run open-source, speech, and multimodal models on cloud, on-prem, or your laptop — all through one unified, production-ready inference API.项目地址: https://gitcode.com/GitHub_Trending/in/inference
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考