更新时间:2025-08-07 GMT+08:00
分享

启动推理服务(多模态模型)

什么是多模态

多模态(Multimodality)是集成和处理两种或两种以上不同类型的信息或数据的方法和技术。具体来说,在机器学习和人工智能领域,多模态涉及的数据类型通常包括但不限于文本、图像、视频、音频和传感器数据。

多模态的主要目标是利用来自多种模态的信息来提升任务的表现力,提供更丰富的用户体验,或是获取更全面的数据分析结果。例如,在实际应用场景中,可以通过结合图像和文本信息来进行更好的对象识别或情感分析。

此外,多模态还可以细分为以下几个方面:

  • 多模态理解:如何让计算机从不同种类的数据源中抽取有用的信息,并将其综合起来形成有意义的知识。
  • 视觉大模型:这类模型专门针对图像和其他视觉数据设计,帮助计算机更好地理解和解释视觉世界。
  • 多模态检索:这是指利用多种数据模态(如文本、图像、视频、音频等)进行信息检索的技术,旨在通过整合不同形式的数据,提供更精准的结果。

综上所述,多模态不仅仅是简单的特征融合,而是涵盖了广泛的理论基础及实践应用。这里的多模态是指多模态理解。

约束限制

机器以及最大卡数见各模型支持的最小卡数和最大序列

启动多模态推理服务

当前支持InternVL2.5、Qwen2.5-vl系列模型,具体模型和权重地址参见支持的模型列表,推荐显卡数量参见表1

如果使用Qwen2.5-vl系列模型进行推理时报错,可能是transformers版本问题,具体解决方案参见问题1:使用Qwen2.5-vl系列模型进行推理时报错

离线推理

使用如下脚本https://github.com/vllm-project/vllm/blob/v0.7.2/examples/offline_inference/vision_language.py进行多模态离线推理

  1. 找到对应系列模型的入口函数,修改模型权重位置,例如qwen2.5-vl,将下图红框修改为模型权重位置:
    图1 修改模型权重位置
  2. 修改模型参数,在对应系列模型的入口函数中的LLM中设置参数。

    参数说明:

    • model:模型地址,模型格式是huggingface的目录格式
    • max_num_seqs:最大同时处理的请求数
    • max_model_len:推理时最大输入+最大输出tokens数量,输入超过该数量会直接返回
    • max_num_batched_tokens:prefill阶段,最多会使用多少token,必须大于或等于--max-model-len,推荐使用4096或8192
    • dtype:模型推理的数据类型
    • tensor_parallel_size:模型并行数(即使用几卡)
    • block_size:PagedAttention的block大小,推荐设置为128
    • gpu_memory_utilization:NPU使用的显存比例,复用原vLLM的入参名称,默认为0.9
    • trust_remote_code:是否相信远程代码
    • distributed_executor_backend="ray":使用ray通信
  3. 修改模型参数,在SamplingParams中设置参数。
    图2 在SamplingParams中设置参数

    表1 参数说明

    参数

    是否必选

    默认值

    参数类型

    描述

    max_tokens

    16

    Int

    每个输出序列要生成的最大tokens数量。

    top_k

    -1

    Int

    控制要考虑的前几个tokens的数量的整数。设置为-1表示考虑所有tokens。适当降低该值可以减少采样时间。

    top_p

    1.0

    Float

    控制要考虑的前几个tokens的累积概率的浮点数。必须在 (0, 1] 范围内。设置为1表示考虑所有tokens。

    temperature

    1.0

    Float

    控制采样的随机性的浮点数。较低的值使模型更加确定性,较高的值使模型更加随机。0表示贪婪采样。

    stream

    False

    Bool

    是否开启流式推理。默认为False,表示不开启流式推理。

    ignore_eos

    False

    Bool

    ignore_eos表示是否忽略EOS并且继续生成token。

    repetition_penalty

    1.0

    Float

    减少重复生成文本的概率。

    stop_token_ids

    None

    Int

    停止tokens列表。Internvl2.5需要传入,参考离线推理脚本examples/offline_inference_vision_language.py的stop_token_ids。

  4. 指定图片路径。指定本地图片路径需在文件开头增加代码from PIL import Image,在get_multi_modal_input函数中新增如下代码image = Image.open("{图片路径}").convert('RGB')。
    图3 指定图片路径
  5. 指定输入文本。
    图4 指定输入文本
  6. 启动推理脚本

    qwen2.5-vl系列模型启动命令

    python vision_language.py --model-type qwen2_5_vl

    脚本运行参数说明:

    --model-type:模型类型,目前可选参数为internvl_chat、qwen2_5_vl。

    --num-prompts:单次运行输入的prompt的数量,默认为4。

    --modality:输入类型,目前可选参数为image、video,默认为image。

    --num-frames:从视频中提取的帧数,默认为16。

在线推理

export VLLM_IMAGE_FETCH_TIMEOUT=100
export VLLM_ENGINE_ITERATION_TIMEOUT_S=600
# PYTORCH_NPU_ALLOC_CONF优先设置为expandable_segments:True
# 如果有涉及虚拟显存相关的报错,可设置为expandable_segments:False
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True

python -m vllm.entrypoints.openai.api_server --model ${container_model_path} \
--max-num-seqs=256 \
--max-model-len=4096 \
--max-num-batched-tokens=4096 \
--tensor-parallel-size=1 \
--block-size=128 \
--chat-template ${chat_template_path} \
--dtype ${dtype} \
--host=${docker_ip} \
--port=${port} \
--gpu-memory-utilization=0.9 \
--trust-remote-code

多模态推理服务启动模板参数说明如下,其余参数设置参考启动推理服务(大语言模型)基础参数说明。

  • VLLM_IMAGE_FETCH_TIMEOUT:图片下载时间环境变量。
  • VLLM_ENGINE_ITERATION_TIMEOUT_S:服务间隔最大时长,超过会报timeout错误。
  • PYTORCH_NPU_ALLOC_CONF=expandable_segments:True;允许分配器最初创建一个段,然后在以后需要更多内存时扩展它的大小。开启时可能提升模型性能。报错则关闭。
  • --model ${container_model_path}:模型地址,模型格式是HuggingFace的目录格式。即上传的HuggingFace权重文件存放目录。如果使用的是训练后模型转换为HuggingFace格式的地址,还需要有Tokenizer原始文件。
  • --max-num-seqs:最大同时处理的请求数,超过后在等待池等候处理。
  • --max-model-len:推理时最大输入+最大输出tokens数量,输入超过该数量会直接返回。max-model-len的值必须小于config.json文件中的"seq_length"的值,否则推理预测会报错。config.json存在模型对应的路径下,例如:${container_work_dir}/chatglm3-6b/config.json。不同模型推理支持的max-model-len长度不同,具体差异请参见表1
  • --max-num-batched-tokens:prefill阶段,最多会使用多少token,必须大于或等于--max-model-len,推荐使用4096或8192。
  • --dtype:模型推理的数据类型。支持FP16和BF16数据类型推理。float16表示FP16,bfloat16表示BF16。如果不指定,则根据输入数据自动匹配数据类型。使用不同的dtype会影响模型精度。如果使用开源权重,建议不指定dtype,使用开源权重默认的dtype。
  • --tensor-parallel-size:模型并行数。模型并行与流水线并行的乘积取值需要和启动的NPU卡数保持一致,可以参考表1。此处举例为1,表示使用单卡启动服务。
  • --block-size:kv-cache的block大小,推荐设置为128。
  • --host=${docker_ip}:服务部署的IP,${docker_ip}替换为宿主机实际的IP地址,默认为None,举例:参数可以设置为0.0.0.0。
  • --port:服务部署的端口。
  • --gpu-memory-utilization:NPU使用的显存比例,复用原vLLM的入参名称,默认为0.9。
  • --trust-remote-code:是否相信远程代码。
  • --chat-template:对话构建模板,可选参数。如:llava chat-template:${vllm_path}/examples/template_llava.jinja

多模态推理请求

通过online_serving.py方式发送请求(单图单轮对话)

由于多模态推理涉及图片的编解码,所以采用脚本方式调用服务API。脚本中需要配置的参数如表1 脚本参数说明所示。

import base64
import requests
import argparse
import json
from typing import List
# Function to encode the image
def encode_image(image_path):
  with open(image_path, "rb") as image_file:
    return base64.b64encode(image_file.read()).decode('utf-8')

def get_stop_token_ids(model_path):
    with open(f"{model_path}/config.json") as file:
        data = json.load(file)
        if data.get('architectures')[0] == "InternVLChatModel":
            return [0, 92543, 92542]
    return None

def post_img(args):
    # Path to your image
    image_path = args.image_path
    # Getting the base64 string
    image_base64 = encode_image(image_path)
    stop_token_ids = args.stop_token_ids if args.stop_token_ids is not None else get_stop_token_ids(args.model_path)
    headers = {
      "Content-Type": "application/json"
    }
    payload = {
      "model": args.model_path,
      "messages": [
        {
          "role": "user",
          "content": [
            {
              "type": "text",
              "text": args.text
            },
            {
              "type": "image_url",
              "image_url": {
                "url": f"data:image/jpeg;base64,{image_base64}"
              }
            }
          ]
        }
      ],
      "max_tokens": args.max_tokens,
      "temperature": args.temperature,
      "ignore_eos": args.ignore_eos,
      "stream": args.stream,
      "top_k": args.top_k,
      "top_p": args.top_p,
      "stop_token_ids": stop_token_ids,
      "repetition_penalty": args.repetition_penalty,
    }
    response = requests.post(f"http://{args.docker_ip}:{args.served_port}/v1/chat/completions", headers=headers, json=payload)
    print(response.json())

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    # 必填
    parser.add_argument("--model-path", type=str, required=True)
    parser.add_argument("--image-path", type=str, required=True)
    parser.add_argument("--docker-ip", type=str, required=True)
    parser.add_argument("--served-port", type=str, required=True)
    parser.add_argument("--text", type=str, required=True)
    # 选填
    parser.add_argument("--temperature", type=float, default=0) # 输出结果的随机性。可选
    parser.add_argument("--ignore-eos", type=bool, default=False) # 在生成过程中是否忽略结束符号,在生成EOS token后继续生成token。可选
    parser.add_argument("--top-k", type=int, default=-1) # 参数控制着生成结果的多样性。其值越小,生成的文本就越独特,但可能缺乏连贯性。相反,其值越大,文本就越连贯,但多样性也会降低。可选
    parser.add_argument("--top-p", type=int, default=1.0) # 参数的取值范围为0到1。值越小,生成的内容就越意外,但可能牺牲连贯性。值越大,内容就越连贯,但意外性也会减弱。可选
    parser.add_argument("--stream", type=int, default=False) # 是否开启流式推理。默认为False,表示不开启流式推理。
    parser.add_argument("--max-tokens", type=int, default=16) # 生成序列的最大长度。必选
    parser.add_argument("--repetition-penalty", type=float, default=1.0) # 减少重复生成文本的概率。可选
    parser.add_argument("--stop-token-ids", nargs='+', type=int, default=None) # 停止tokens列表。可选
    args = parser.parse_args()
    post_img(args)
运行此脚本:
python online_serving.py --model-path ${container_model_path} --image-path ${image_path} --docker-ip ${docker_ip} --served-port ${port} --text 图片内容是什么

相关请求参数说明参照多模态相关请求参数说明

图5 输入示例图

推理输出结果如下图所示。

图6 推理输出结果示意图

多模态相关请求参数说明

表2 脚本参数说明

参数

是否必须

参数类型

描述

container_model_path

str

模型权重路径

image_path

str

传给模型的图片路径

payload

json

单图单轮对话的post请求json, 可参考表3 请求服务json参数说明

docker_ip

str

启动多模态openAI服务的主机ip

served_port

str

启动多模态openAI服务的端口号

表3 请求服务json参数说明

参数

是否必须

默认值

参数类型

描述

model

Str

通过OpenAI服务API接口启动服务时,推理请求必须填写此参数。取值必须和启动推理服务时的model ${container_model_path}参数保持一致。

messages

-

Dict

请求输入的问题和图片。

role表示消息的发送者,这里只能为用户。content表示消息的内容,类型为list。

单图单轮对话content必须包含两个元素,第一个元素type字段取值为text,表示文本类型, text字段取值为输入问题的字符串。 第二个元素type字段取值为image_url, 表示图片类型,image_url字段取值为是输入图片的base64编码。

max_tokens

16

Int

每个输出序列要生成的最大tokens数量。

top_k

-1

Int

控制要考虑的前几个tokens的数量的整数。设置为-1表示考虑所有tokens。适当降低该值可以减少采样时间。

top_p

1.0

Float

控制要考虑的前几个tokens的累积概率的浮点数。必须在 (0,1] 范围内。设置为1表示考虑所有tokens。

temperature

1.0

Float

控制采样的随机性的浮点数。较低的值使模型更加确定性,较高的值使模型更加随机。0表示贪婪采样。

stream

False

Bool

是否开启流式推理。默认为False,表示不开启流式推理。

ignore_eos

False

Bool

ignore_eos表示是否忽略EOS并且继续生成token。

repetition_penalty

1.0

Float

减少重复生成文本的概率。

stop_token_ids

None

Int

停止tokens列表。internvl2和minicpmv需要传入,参考离线推理脚本examples/offline_inference_vision_language.py的stop_token_ids。

相关文档