1. 使用场景

视觉语言模型(VLM)是一种能够同时接受视觉(图像)和语言(文本)两种模态信息输入的大语言模型。基于视觉语言模型,可以传入图像及文本信息,模型能够理解同时理解图像及上下文中的信息并跟随指令做出响应。如:

  1. 视觉内容解读:要求模型对图片中包含的信息进行解读、描述,如包含的事物、文字,事物的空间关系,图像的颜色、气氛等;
  2. 结合视觉内容及上下文,开展多轮会话;
  3. 部分替代 OCR 等传统机器视觉模型;
  4. 随着模型能力的持续提升,未来还可以用于视觉智能体、机器人等领域。

2. 使用方式

对于 VLM 模型,可在调用 /chat/completions 接口时,构造包含 图片 urlbase64 编码图片message 消息内容进行调用。通过 detail 参数控制对图像的预处理方式。

2.1 关于图片细节控制参数说明

SiliconCloud 提供 lowhighauto 三个 detail 参数选项。 对于目前支持的模型,detail 不指定或指定为 high 时会采用 high(“高分辨率”)模式,而指定为 low 或者 auto 时会采用 low(“低分辨率”)模式。

2.2 包含图像的 message 消息格式示例

使用 InternVL 系列模型注意:建议将 {"type": "text", "text": "text-prompt here"} 放在请求体 content 的图片后面,以获得最佳效果。

使用图片 url 形式

{
    "role": "user",
    "content":[
        {
            "type": "image_url",
            "image_url": {
                "url": "https://sf-maas-uat-prod.oss-cn-shanghai.aliyuncs.com/outputs/658c7434-ec12-49cc-90e6-fe22ccccaf62_00001_.png",
                "detail":"high"
            }
        },
        {
            "type": "text",
            "text": "text-prompt here"
        }
    ]
}

2.2 base64 形式

{
    "role": "user",
    "content":[
        {
            "type": "image_url",
            "image_url": {
                "url": f"data:image/jpeg;base64,{base64_image}",
                "detail":"low"
            }
        },
        {
            "type": "text",
            "text": "text-prompt here"
        }
    ]
}

2.3 多图片形式,其中每个图片可以是上述两种形式之一

{
    "role": "user",
    "content":[
        {
            "type": "image_url",
            "image_url": {
                "url": "https://sf-maas-uat-prod.oss-cn-shanghai.aliyuncs.com/outputs/658c7434-ec12-49cc-90e6-fe22ccccaf62_00001_.png",
            }
        },
        {
            "type": "image_url",
            "image_url": {
                "url": f"data:image/jpeg;base64,{base64_image}"
            }
        },
        {
            "type": "text",
            "text": "text-prompt here"
        }
    ]
}

3. 支持模型列表

目前已支持的 VLM 模型:

  • Qwen 系列:
    • Qwen/Qwen2-VL-72B-Instruct
    • Pro/Qwen/Qwen2-VL-7B-Instruct
  • InternVL 系列:
    • OpenGVLab/InternVL2-Llama3-76B
    • OpenGVLab/InternVL2-26B
    • Pro/OpenGVLab/InternVL2-8B
注意:支持的 VLM 模型可能发生调整,请在「模型广场」筛选“视觉”标签,了解支持的模型列表。

4. 视觉输入内容计费方式

对于图片等视觉输入内容,模型会将其转化为 tokens,与文本信息一并作为模型输出的上下文信息,因此也会一并进行计费。不同模型的视觉内容转化方式不同,以下为目前支持模型的转化方式。

4.1 Qwen2-VL 系列

规则:

Qwen2-VL 最高支持像素是 3584 * 3584= 12845056,最低支持像素是 56 * 56 = 3136,会对先对每张图片长短边均放缩至28的倍数 (h * 28) * (w * 28)。如果不在最小像素和最大像素区间内,再等比缩放至该区间。

  1. detail=low 时将所有图片resize 成 448 * 448 尺寸,最终对应 256 tokens
  2. detail=high 时等比缩放,首先将长宽按照最近的 28 倍数向上取整,然后再等比缩放至像素区间 (3136, 12845056),并保证长宽均为 28 整数倍。

示例:

  • 224 * 4481024 x 10243172 x 4096 的图片,选择 detail=low 时,均消耗 256 tokens
  • 224 * 448 的图片,选择 detail=high 时,因为 224 * 448 在像素区间内,且长宽均为 28 倍数,消耗 (224/28) * (448/28) = 8 * 16 = 128 tokens
  • 1024 * 1024 的图片,选择 detail=high 时,将长宽按照 28 的倍数向上取整至 1036 * 1036,该数值在像素区间内,消耗 (1036/28) * (1036/28) = 1369 tokens
  • 3172 * 4096 的图片,选择 detail=high 时,将长宽按照 28 的倍数向上取整至 3192 * 4116,该值超过最大像素,再将长宽等比例缩小至 3136 * 4060,消耗 (3136/28) * (4060/28) = 16240 tokens

4.2 InternVL 系列

规则:

InternVL2 实际处理的像素以及消耗的 tokens 数与原始图片的长宽比例有关。最低处理像素为 448 * 448,最高为 12 * 448 * 448

  1. detail=low 时将所有图片 resize 成 448 * 448 尺寸,最终对应 256 tokens
  2. detail=high 时会根据长宽比例,将图片 resize 成长宽均为 448 的倍数,(h * 448) * (w * 448),且 1 <= h * w <=12
    • 缩放的长宽 h * w 按照如下规则选择:
      • hw 均为整数,在满足 1 <= h * w <= 12 约束下,按照 h * w 从小到大的组合遍历;
      • 对于当前 (h, w) 组合,如果原始图片长宽比例更接近 h / w ,那么选择该 (h, w) 组合;
      • 对于后续 数值更大但是比例相同(h, w) 组合,如果原始图片像素大于 0.5 * h * w * 448 * 448,那么选择数值更大的 (h, w) 组合。
    • token消耗按照如下规则:
      • 如果 h * w = 1,那么消耗 256 tokens
      • 如果 h * w > 1,按 448 * 448 滑动窗口,每个窗口均额外消耗 256 token,一共 (h * w + 1) * 256 tokens

示例:

  • 224 * 4481024 * 10242048 * 4096 的图片,选择 detail=low 时,均消耗 256 tokens
  • 224 * 448 的图片,选择 detail=high 时,长宽比为1:2,会缩放至 448 x 896,此时 h = 1, w = 2,消耗 (h * w + 1) * 256 = 768 tokens
  • 1024 * 1024 的图片,选择 detail=high 时,长宽比为1:1,会缩放至 1344 * 1344 (h = w = 3),因为 1024 * 1024 > 0.5 * 1344 * 1344. 此时 h = w = 3,消耗 (3 * 3 + 1) * 256 = 2560 tokens
  • 2048 * 4096 的图片,选择 detail=high 时,长宽比为1:2,在满足 1 <= h * w <= 12 条件下数值最大的 (h, w) 组合为 h = 2, w = 4,所以会缩放至 896 * 1792,消耗(2 * 4 + 1) * 256 = 2304 tokens

5. 使用示例

5.1. 示例 1 图片理解

import json  
from openai import OpenAI

client = OpenAI(
    api_key="您的 APIKEY", # 从https://cloud.siliconflow.cn/account/ak获取
    base_url="https://api.siliconflow.cn/v1"
)

response = client.chat.completions.create(
        model="Qwen/Qwen2-VL-72B-Instruct",
        messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image_url",
                    "image_url": {
                        "url": "https://sf-maas-uat-prod.oss-cn-shanghai.aliyuncs.com/dog.png"
                    }
                },
                {
                    "type": "text",
                    "text": "Describe the image."
                }
            ]
        }],
        stream=True
)

for chunk in response:
    chunk_message = chunk.choices[0].delta.content
    print(chunk_message, end='', flush=True)

5.2. 示例 2 多图理解

import json  
from openai import OpenAI

client = OpenAI(
    api_key="您的 APIKEY", # 从https://cloud.siliconflow.cn/account/ak获取
    base_url="https://api.siliconflow.cn/v1"
)

response = client.chat.completions.create(
        model="Qwen/Qwen2-VL-72B-Instruct",
        messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image_url",
                    "image_url": {
                        "url": "https://sf-maas-uat-prod.oss-cn-shanghai.aliyuncs.com/dog.png"
                    }
                },
                {
                    "type": "image_url",
                    "image_url": {
                        "url": "https://sf-maas-uat-prod.oss-cn-shanghai.aliyuncs.com/shark.jpg"
                    }
                },
                {
                    "type": "text",
                    "text": "Identify the similarities between these images."
                }
            ]
        }],
        stream=True
)

for chunk in response:
    chunk_message = chunk.choices[0].delta.content
    print(chunk_message, end='', flush=True)