如何使用视觉大模型上传本地图像并生成回答

在本篇博客中,我将讲解如何将本地图片上传至视觉大模型,并让模型生成图像的描述,本文以 Qwen 的模型举例。

1. 什么是视觉模型?

视觉模型是一个基于大规模视觉-语言模型的工具,能够将图片与自然语言结合。通过调用该模型,你可以将图像发送给它,并让它生成对图像内容的详细描述。例如,它可以描述图像中的物体、场景甚至情感。


2. Qwen官方的 API 调用方法

Qwen 官方提供的视觉大模型调用方式是通过直接提供图像的 URL 来进行图像分析。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import os
from openai import OpenAI

client = OpenAI(
# 若没有配置环境变量,请用百炼API Key将下行替换为:api_key="sk-xxx",
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)

completion = client.chat.completions.create(
model="qwen-vl-plus", # 此处以qwen-vl-plus为例,可按需更换模型名称。
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "这是什么"},
{"type": "image_url",
"image_url": {"url": "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"}}
]
}]
)

print(completion.model_dump_json())

这个方法需要将图像的 URL(指向图片存储的网络地址)作为消息发送给模型。

但对于本地图片要上传至大模型处理,先转为 URL 显然有些繁琐。


3. 如何将本地图片上传至大模型

这里我将介绍一个本地图片上传至 Qwen 视觉模型,并让模型根据prompt生成图像的描述的方法。

以下是完整的代码模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from PIL import Image
import base64
from io import BytesIO
from openai import OpenAI

# 初始化 API 客户端
client = OpenAI(
api_key="你的百炼Key",
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)

# === 准备图像(PIL)并转为 base64 ===
def pil_image_to_base64(pil_img: Image.Image) -> str:
buffered = BytesIO()
pil_img.save(buffered, format="JPEG")
return base64.b64encode(buffered.getvalue()).decode("utf-8")

# === 构建调用内容并发送 ===
def call_qwen_vl(pil_img: Image.Image, prompt_text: str = "请描述图像内容") -> str:
img_b64 = pil_image_to_base64(pil_img)

content = [
{"type": "text", "text": prompt_text},
{"type": "image_url", "image_url": {
"url": f"data:image/jpeg;base64,{img_b64}"
}}
]

response = client.chat.completions.create(
model="qwen-vl-plus",
messages=[{"role": "user", "content": content}]
)
return response.choices[0].message.content.strip()

相比官方的 API 调用方法,这个方法通过将图像转换为 Base64 编码 字符串的方式传输图像,这样就可以将图像嵌入到请求中,直接将本地图片上传至视觉大模型进行理解


4. 代码解析

接下来,我们来看如何实现这个过程。整个代码的核心分为几个步骤:图像加载、图像转换为 base64 编码、构建 API 请求、获取并处理模型的响应。

4.1 导入必要的库

1
2
3
4
from PIL import Image
import base64
from io import BytesIO
from openai import OpenAI
  • PIL:用于打开和处理图像文件。
  • base64:用于将图像数据转换为 base64 编码,使其适合通过 HTTP 请求传输。
  • BytesIO:将图像数据保存在内存中的缓冲区,而不是写入磁盘。
  • OpenAI:用于与 OpenAI API 进行交互,调用 Qwen-VL 模型。

4.2 初始化 API 客户端

1
2
3
4
client = OpenAI(
api_key="你的百炼Key",
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)

你需要提供一个 API 密钥api_key)来进行身份验证。base_url 是 API 的地址,用来与 Qwen 模型通信。

4.3 图像转换为 Base64 编码

1
2
3
4
def pil_image_to_base64(pil_img: Image.Image) -> str:
buffered = BytesIO()
pil_img.save(buffered, format="JPEG")
return base64.b64encode(buffered.getvalue()).decode("utf-8")

这段代码的作用是将图像从 PIL 图像格式 转换为 base64 编码,并返回一个字符串。为什么要这么做呢?

  • 图像是二进制数据,而网络通信(特别是通过 HTTP 请求)更擅长处理文本数据。通过将图像转换为 base64 编码,我们可以轻松地将其嵌入到文本请求中发送给 API。
  • BytesIO() 是一个内存中的文件对象,用来暂存图像数据。
  • pil_img.save(buffered, format="JPEG") 将图像保存到内存中的缓冲区(buffered),并指定图像格式为 JPEG。
  • base64.b64encode(buffered.getvalue()) 将内存中的图像数据进行 base64 编码。
  • .decode("utf-8") 将编码后的字节数据转换为可读的字符串。

4.4 构建 API 请求并发送

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def call_qwen_vl(pil_img: Image.Image, prompt_text: str = "请描述图像内容") -> str:
img_b64 = pil_image_to_base64(pil_img)

content = [
{"type": "text", "text": prompt_text},
{"type": "image_url", "image_url": {
"url": f"data:image/jpeg;base64,{img_b64}"
}}
]

response = client.chat.completions.create(
model="qwen-vl-plus",
messages=[{"role": "user", "content": content}]
)
return response.choices[0].message.content.strip()

这一段是代码的核心,主要完成了以下工作:

  1. 将图像转换为 Base64:我们先调用前面写的 pil_image_to_base64() 函数将图像转换为 base64 编码。

  2. 构建请求内容:这里我们准备了一个内容列表 content,包括了两个部分:

    • 文本提示{"type": "text", "text": prompt_text},这是给模型的提示,告诉它需要描述图像的内容。默认的prompt文本是“请描述图像内容”。
    • 图像数据{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{img_b64}"}}。这里我们使用了一个 data:image/jpeg;base64,... 的 URL 格式来将图像数据嵌入请求中,这个过程避免了图像必须托管在网络上的限制。
  3. 发送请求client.chat.completions.create(...) 这行代码通过 OpenAI 客户端向 Qwen-VL 模型发送请求。这里指定了使用的模型 qwen-vl-plus(你可以自己跟换所需的视觉大模型),并将构建好的消息内容传递给模型。

  4. 获取响应:模型处理完图像后,会返回一个响应。我们从 response.choices[0].message.content 中提取出模型生成的描述,并使用 .strip() 去除两端的空白字符。

4.5 完整流程

  1. 加载图像:首先从本地加载图像,通常使用 PIL.Image.open() 来打开文件。
  2. 图像转换:然后我们将图像转换为 base64 编码,使其能够通过网络请求安全传输。
  3. 构建请求并发送给 Qwen-VL 模型:构建一个包含图像和文本提示的请求,发送给 Qwen-VL 模型。
  4. 接收并处理模型的响应:模型会分析图像并生成一段描述文本,我们从响应中提取并返回这段文本。

5. 示例:如何使用该代码

假设你有一个本地的图像文件 example.jpg,你想让视觉模型描述它的内容。以下是一个简单的代码示例:

1
2
3
4
5
6
7
8
9
from PIL import Image

# 打开本地图像文件
image_path = "example.jpg"
img = Image.open(image_path)

# 调用 Qwen-VL 模型获取图像描述
description = call_qwen_vl(img)
print("图像描述:", description)

5.1 结果

当你运行这段代码时,模型会分析图像并生成对该图像的描述。例如,它可能会返回类似这样的描述:

1
图像描述:这是一张包含一个绿色苹果的照片,苹果放置在白色背景上,旁边还有一些小草。

该项目代码参考 Qwen官方的视觉模型图像输入使用方法