部分大模型具备视觉理解能力,如当您传入图片时,大模型可以理解图片里视觉信息,并结合这些信息完成如描述图片等图片相关任务。通过这篇教程,您可以学习到如何通过调用大模型 API 来识别传入图片里的信息。
应用场景
您可以在以下场景中使用模型的视觉理解能力。
场景 | 场景细分 | 描述 |
---|
文字识别(OCR) | 纯文本图像的文字抽取 | 抽取包含文本图片的文字内容,如:密集文本图片、文档截图等,并支持格式化输出文本内容。 |
日常图像的文字抽取 | 对日常手机拍摄的图片中,包含的文本文字抽取,如:菜单、路标、证件等。 |
表格图像的内容抽取 | 模型能够识别图表、表格类型图片的文字、数字等内容读取,并支持格式化输出文本内容。 |
图像问答 | 图片描述 | 描述图片中的内容,包括详细描述、简短描述以及为图像分类。 |
图像内容提问 | 对图片中包含的内容进行提问。 |
创作内容 | 文案创作 | 根据图像内容,创作文案、标题等,如:点评、小红书文案、朋友圈文案等。 |
教育 | 数学题目解答 | 分析题目、考点说明、解题思路、解题结果。 |
数学题目批改 | 对数学题目的回答批改。 |
生成代码 | 前端页面生成 | 根据前端页面设计图片信息,完成前端页面。 |
图表绘制 | 根据图片信息,完成图表实现。 |
前提条件
支持的模型
当前支持视觉理解的模型有:
模型名称 | 上下文长度 | Max Tokens 最大输出 token 长度 | TPM 每分钟 token 处理数 | RPM 每分钟处理请求数 | 免费额度 (token) | 计费 | 模型说明 |
---|
Doubao-vision-pro-32k | 32k | 4k | 15w | 60 | 50w | 见视觉理解大模型 | 强视觉理解能力,精准指令理解能力。 |
Doubao-vision-lite-32k | 32k | 4k | 15w | 60 | 50w | 见视觉理解大模型 | 相较于Doubao-vision-pro更轻量级,单价更低,速度更快。 |
快速开始
支持视觉理解的大模型当前支持在请求中传入图片链接,图片信息需要作为用户角色输入信息传给大模型,即"role": "user"
,下面是简单的视觉模型调用示例代码。
import os
# 通过 pip install volcengine-python-sdk[ark] 安装方舟SDK
from volcenginesdkarkruntime import Ark
# 配置您的模型调用信息,API Key以及推理接入点
api_key = os.getenv('ARK_API_KEY')
model = "ep-202411***"
# 初始化Ark客户端
client = Ark(api_key=api_key)
# 创建一个对话请求
response = client.chat.completions.create(
# 指定您部署了视觉理解大模型的推理接入点ID
model = model,
messages = [
{
"role": "user", # 指定消息的角色为用户
"content": [ # 消息内容列表
{"type": "text", "text": "对美国人来说最安全的支付APP是什么?"}, # 文本消息
{
"type": "image_url", # 图片消息
# 图片的URL,需要大模型进行理解的图片链接
"image_url": {"url": "https://p9-arcosite.byteimg.com/tos-cn-i-goo7wpa0wc/7d2e7e810f054952aa8854fc99577260~tplv-goo7wpa0wc-image.image"}
},
],
}
],
)
print(response.choices[0])
模型回复预览:
Choice(
finish_reason="stop",
index=0,
logprobs=None,
message=ChatCompletionMessage(
content="根据图片内容,对美国人来说最安全的支付APP是PayPal,有74%的受访者认为它是最安全的。其次是Apple Pay,占比40%,Google Wallet占比35%。这些数据反映了用户对不同支付APP安全性的认知和评价。",
role="assistant",
function_call=None,
tool_calls=None,
),
)
使用规格
图片输入方式
图片 URL 或图片 Base64 编码。用图片 URL 方式时,需确保图片 URL 可被访问。
图片数量说明
受到上传数量以及模型上下文长度两个规格的限制。
- 上传数量限制:不超过 50 张,即一次请求传入图片(包含历史信息中的图片)信息无法超过 50 张。
- 模型上下文长度限制:模型上下文长度见模型规格,当输入信息过长,譬如传入图片较多,触发了模型上下文长度限制,如上下文 32k 的模型,图片超过 25 张,信息会被截断后处理。
举例说明:
- 当图片质量很高,使用模型上下文窗口限制为32k,每个图片转为1312 个 token ,单轮可传入的图片数量为 min(
32000 / 1312 = 24
, 50) = 24 张。 - 当图片细节和分辨率小,使用模型上下文窗口限制为32k,每个图片转为 256 个 token,单轮可以传入的数量为 min(
32000 / 256
, 50) = 50 张
token 用量说明
模型理解图片,会将图片转化为 token ,再进行推理计算。token 用量,根据图片宽高像素计算可得,但是单图转 token 上限不超过1312个token。具体转化 token 的公式为:
min(图片宽 * 图片高/784, 1312)
举例说明,图片尺寸为1280 px * 720 px,即宽为 1280 px,高为720 px,则理解这张图消耗的 token 为1280*720/784=1176
,因为小于 1312,所以消耗 token 数为 1176 。
图片格式说明
支持的图片格式如下表,需注意文件后缀和图片格式需要匹配,即图片文件扩展名(URL传入)、编码中图片格式声明(Base64编码传入)需要与图片实际信息一致。
图片格式 | 文件扩展名 | 内容格式 Content Type 上传图片至对象存储时设置,以及传入图片Base64编码时使用
data:image/{图片格式};base64,{Base64编码} 中替换图片image/{图片格式}
|
---|
JPEG | .jpg, .jpeg | image/jpeg
|
PNG | .apng, .png | image/png
|
GIF | .gif | image/gif
|
WEBP | .webp | image/webp
|
BMP | .bmp | image/bmp
|
TIFF | .tiff, .tif | image/tiff
|
ICO | .ico | image/x-icon
|
DIB | .dib | image/bmp
|
ICNS | .icns | image/icns
|
SGI | .sgi | image/sgi
|
JPEG2000 | .j2c, .j2k, .jp2, .jpc, .jpf, .jpx | image/jp2
|
参数字段说明
以下字段视觉理解暂不支持。
- 不支持 functioncall,无
tools
字段。 - 不支持设置频率惩罚系数,无
frequency_penalty
字段。 - 不支持设置存在惩罚系数,
presence_penalty
字段。 - 不支持为每个请求生成多个 chatcompletions,只能生成 1 个,无
n
字段。
多图像输入
API 可以支持接受和处理多个图像输入,这些图像可以通过图片可访问 URL 或图片转为Base64 编码后输入,模型将结合所有传入的图像中的信息来回答问题。
import os
# 通过 pip install volcengine-python-sdk[ark] 安装方舟SDK
from volcenginesdkarkruntime import Ark
# 从环境变量中获取API Key
client = Ark(api_key=os.getenv('ARK_API_KEY'))
response = client.chat.completions.create(
# 部署了视觉理解大模型的推理接入点 ID
model="ep-202411*****",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "对美国人来说最安全的支付APP是什么?同时,告诉我实例有哪几种计费方式?"},
{
"type": "image_url",
# 第一张图片链接
"image_url": {"url": "https://p9-arcosite.byteimg.com/tos-cn-i-goo7wpa0wc/7d2e7e810f054952aa8854fc99577260~tplv-goo7wpa0wc-image.image"
}
},
{
"type": "image_url",
# 第二章图片链接
"image_url": {"url": "https://portal.volccdn.com/obj/volcfe/cloud-universal-doc/upload_69eb098ceb9b1a1ffa760bff6842bc72.png"
}
},
],
}
],
)
print(response.choices[0])
Base64 编码输入
如果你要传入的图片在本地,你可以将这个图片转化为 Base64 编码,然后提交给大模型。下面是一个简单的示例代码。
注意
传入Base64 编码格式时,传入的格式如下:
data:image/<图片格式>;base64,<Base64编码>
- 图片格式:
jpeg
、png
、gif
等,支持的图片格式详细见图片格式说明。 - Base64 编码:图片的 Base64 编码。
import base64
import os
# 通过 pip install volcengine-python-sdk[ark] 安装方舟SDK
from volcenginesdkarkruntime import Ark
# 初始化一个Client对象,从环境变量中获取API Key
client = Ark(api_key=os.getenv('ARK_API_KEY'))
# 定义方法将指定路径图片转为Base64编码
def encode_image(image_path):
with open(image_path, "rb") as image_file:
return base64.b64encode(image_file.read()).decode('utf-8')
# 需要传给大模型的图片
image_path = "path_to_your_image.jpg"
# 将图片转为Base64编码
base64_image = encode_image(image_path)
response = client.chat.completions.create(
model="ep-2024****",
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": "图片里讲了什么?",
},
{
"type": "image_url",
"image_url": {
# 需要注意:传入Base64编码前需要增加前缀 data:image/{图片格式};base64,{Base64编码}:
# PNG图片:"url": f"data:image/png;base64,{base64_image}"
# JEPG图片:"url": f"data:image/jpeg;base64,{base64_image}"
# WEBP图片:"url": f"data:image/webp;base64,{base64_image}"
"url": f"data:image/<IMAGE_FORMAT>;base64,{base64_image}"
},
},
],
}
],
)
print(response.choices[0])
图片的理解深度控制
你可以通过detail
参数来控制模型理解图片的深度,或者说对图片细节的观察细致程度,以及返回速度,但是不影响计量计费,计费公式请参见token 用量说明。
- 默认情况下,模型将使用设置
auto
,来根据图片大小自动选择理解图片的深度。 low
:将启用“低分辨率”模式,处理速度会提高,适合图片本身细节较少或者只需要模型理解图片大致信息或者对速度有要求的场景。high
:将启用“高分辨率”模式,这代表模型会理解图片更多的细节,但是处理图片速度会降低,适合需要模型理解图像细节,图像细节丰富,需要关注图片细节的场景。
import os
# 可通过 pip install volcengine-python-sdk[ark] 安装方舟SDK
from volcenginesdkarkruntime import Ark
# 从环境变量中获取 API Key 并创建 Ark 客户端
client = Ark(api_key=os.getenv('ARK_API_KEY'))
# 调用 Ark 客户端的 chat.completions.create 方法创建聊天补全请求
response = client.chat.completions.create(
# 部署了视觉理解大模型的推理接入点 ID
model="ep-2024****",
messages=[
{
# 消息角色为用户
"role": "user",
"content": [
# 文本类型的消息内容,询问图片里有什么
{"type": "text", "text": "图片里有什么?"},
{
"type": "image_url",
# 第一张图片链接及细节设置为 high
"image_url": {
# 您可以替换图片链接为您的实际图片链接
"url": "https://p9-arcosite.byteimg.com/tos-cn-i-goo7wpa0wc/7d2e7e810f054952aa8854fc99577260~tplv-goo7wpa0wc-image.image",
"detail": "high"
}
},
],
}
],
)
print(response.choices[0])
使用说明及建议
- 模型对图片理解以及内容回复的质量,收到同时处理图片信息量的影响。过多的图片张数会导致模型回复质量下滑,为了更好的回复质量,建议您合理控制传入数量。
- 建议您对图片进行预处理,在不影响图像理解的情况下,对图片进行压缩,这样可以降低 token 消耗以及降低 TTFT(首个 token 响应时间)。
- 推荐图片文件大小:小于 500KB。
- 推荐图片分辨率:宽和高控制在 1792 像素内,在不影响理解图片内容的情况下,尽可能压缩图片文件大小。
- 视觉理解接口
ChatCompletions
是无状态的,如果您需要模型多次理解同一张图片,则每次请求时都需要传入该图片信息。 - 处理完图片后,图片会从方舟服务器删除。方舟不会保留您提交的图片以及文本信息等用户数据来训练模型。
应用案例:上传本地图片并进行图片分析
处理图片通常会与网络存储结合起来使用,下面介绍如何结合对象存储 TOS,来实现完整的图片处理流程。
代码流程
完整流程会分成以下步骤:
- 压缩图片。分辨率会影响 token 消耗数量,可以通过图片压缩,来节省网络、存储以及模型分析成本。
- 将压缩后的图片上传至对象存储 TOS,并为图片生成预签名 URL。
- 调用视觉理解大模型分析图片。
示例代码
安装依赖。
pip install -r requirements.txt
requirements.txt
文本内容如下:
Pillow
volcengine-python-sdk[ark]
tos
示例代码。
import os
import tos
from PIL import Image
from tos import HttpMethodType
from volcenginesdkarkruntime import Ark
# 从环境变量获取 AK/SK/APIKEY信息
ak = os.getenv('VOLC_ACCESSKEY')
sk = os.getenv('VOLC_SECRETKEY')
api_key = os.getenv('ARK_API_KEY')
# 配置你部署了视觉理解模型的推理接入点(Endpoint)ID
ep_id = 'ep-****-***'
# 压缩前图片
original_file = "original_image.jpeg"
# 压缩后图片存放路径
compressed_file = "comressed_image.jpeg"
# 压缩的目标图片大小,300KB
target_size = 300 * 1024
# endpoint 和 region 填写Bucket 所在区域对应的Endpoint。
# 以华北2(北京)为例,region 填写 cn-beijing。
# 公网域名endpoint 填写 tos-cn-beijing.volces.com
endpoint, region = "tos-cn-beijing.volces.com", "cn-beijing"
# 对象桶名称
bucket_name = "demo-bucket-test"
# 对象名称,例如 images 下的 compressed_image.jpeg 文件,则填写为 images/compressed_image.jpeg
object_key = "images/compressed_image.jpeg"
def compress_image(input_path, output_path):
img = Image.open(input_path)
current_size = os.path.getsize(input_path)
# 粗略的估计压缩质量,也可以从常量开始,逐步减小压缩质量,直到文件大小小于目标大小
image_quality = int(float(target_size / current_size) * 100)
img.save(output_path, optimize=True, quality=int(float(target_size / current_size) * 100))
# 如果压缩后文件大小仍然大于目标大小,则继续压缩
# 压缩质量递减,直到文件大小小于目标大小
while os.path.getsize(output_path) > target_size:
img = Image.open(output_path)
image_quality -= 10
if image_quality <= 0:
break
img.save(output_path, optimize=True, quality=image_quality)
return image_quality
def upload_tos(filename, tos_endpoint, tos_region, tos_bucket_name, tos_object_key):
# 创建 TosClientV2 对象,对桶和对象的操作都通过 TosClientV2 实现
tos_client, inner_tos_client = tos.TosClientV2(ak, sk, tos_endpoint, tos_region), tos.TosClientV2(ak, sk,
tos_endpoint,
tos_region)
try:
# 将本地文件上传到目标桶中, filename为本地压缩后图片的完整路径
tos_client.put_object_from_file(tos_bucket_name, tos_object_key, filename)
# 获取上传后预签名的 url
return inner_tos_client.pre_signed_url(HttpMethodType.Http_Method_Get, tos_bucket_name, tos_object_key)
except Exception as e:
if isinstance(e, tos.exceptions.TosClientError):
# 操作失败,捕获客户端异常,一般情况为非法请求参数或网络异常
print('fail with client error, message:{}, cause: {}'.format(e.message, e.cause))
elif isinstance(e, tos.exceptions.TosServerError):
# 操作失败,捕获服务端异常,可从返回信息中获取详细错误信息
print('fail with server error, code: {}'.format(e.code))
# request id 可定位具体问题,强烈建议日志中保存
print('error with request id: {}'.format(e.request_id))
print('error with message: {}'.format(e.message))
print('error with http code: {}'.format(e.status_code))
else:
print('fail with unknown error: {}'.format(e))
raise e
if __name__ == "__main__":
print("----- 压缩图片 -----")
quality = compress_image(original_file, compressed_file)
print("Compressed Image Quality: {}".format(quality))
print("----- 上传至TOS -----")
pre_signed_url_output = upload_tos(compressed_file, endpoint, region, bucket_name, object_key)
print("Pre-signed TOS URL: {}".format(pre_signed_url_output.signed_url))
print("----- 传入图片调用视觉理解模型 -----")
client = Ark(api_key=api_key)
# 图片输入:
response = client.chat.completions.create(
# 配置你的推理接入点(Endpoint)ID
model=ep_id,
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "Which is the most secure payment app according to Americans?"},
{
"type": "image_url",
"image_url": {
"url": pre_signed_url_output.signed_url
}
},
],
}
],
)
print(response.choices[0])
package main
import (
"context"
"fmt"
"image"
"image/jpeg"
"os"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos/enum"
"github.com/volcengine/volcengine-go-sdk/service/arkruntime"
"github.com/volcengine/volcengine-go-sdk/service/arkruntime/model"
)
const (
targetSize = int64(300 * 1024) // 300KB
originalImageFile = "original_image.jpeg" // 压缩前图片路径
compressedImageFile = "compressed_image.jpeg" // 压缩后图片存放路径
ep_id = "ep-****-***" //配置你部署了视觉理解模型的推理接入点(Endpoint)ID
// Bucket 对应的 Endpoint,以华北2(北京)为例
// 公网域名地址:https://tos-cn-beijing.volces.com
endpoint, region = "https://tos-cn-beijing.volces.com", "cn-beijing"
// 填写 对象存储BucketName
bucketName = "*** Provide your bucket name ***"
// 将文件上传到 images 目录下的 compressed_image.jpeg 文件
objectKey = "images/compressed_image.jpeg"
)
var (
accessKey = os.Getenv("VOLC_ACCESSKEY")
secretKey = os.Getenv("VOLC_SECRETKEY")
apiKey = os.Getenv("ARK_API_KEY")
)
func compressImage(inputPath, outputPath string, targetSize int64) (int, error) {
file, err := os.Open(inputPath)
if err != nil {
return -1, err
}
defer file.Close()
img, _, err := image.Decode(file)
if err != nil {
return -1, err
}
outputFile, err := os.Create(outputPath)
if err != nil {
return -1, err
}
defer outputFile.Close()
originalImageInfo, err := file.Stat()
if err != nil {
return -1, err
}
quality := int(float64(targetSize) / float64(originalImageInfo.Size()) * 100)
for {
err = jpeg.Encode(outputFile, img, &jpeg.Options{Quality: quality})
if err != nil {
return -1, err
}
info, err := outputFile.Stat()
if err != nil {
return -1, err
}
if info.Size() <= targetSize {
break
}
quality -= 10
if quality <= 0 {
return -1, fmt.Errorf("无法压缩到目标大小")
}
outputFile.Close()
outputFile, err = os.Create(outputPath)
if err != nil {
return -1, err
}
}
return quality, nil
}
func uploadTos(ctx context.Context, endpoint, region, bucketName, objectKey, filePath string) (*tos.PreSignedURLOutput, error) {
// 初始化客户端
client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey)))
if err != nil {
return nil, err
}
// 将压缩后的图片上传到tos
output, err := client.PutObjectFromFile(ctx, &tos.PutObjectFromFileInput{
PutObjectBasicInput: tos.PutObjectBasicInput{
Bucket: bucketName,
Key: objectKey,
},
FilePath: filePath,
})
if err != nil {
return nil, err
}
fmt.Println("PutObjectV2 Request ID:", output.RequestID)
// 获取预签名下载链接
innerClient, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey)))
if err != nil {
return nil, err
}
return innerClient.PreSignedURL(&tos.PreSignedURLInput{
HTTPMethod: enum.HttpMethodGet,
Bucket: bucketName,
Key: objectKey,
})
}
func main() {
ctx := context.Background()
fmt.Println("----- Compress Image -----")
quality, err := compressImage(originalImageFile, compressedImageFile, targetSize)
if err != nil {
panic(err)
}
fmt.Println("Compressed Image Quality:", quality)
fmt.Println("----- Upload Image To TOS -----")
preSignedUrl, err := uploadTos(ctx, endpoint, region, bucketName, objectKey, compressedImageFile)
if err != nil {
return
}
fmt.Println("PreSignedUrl:", preSignedUrl.SignedUrl)
fmt.Println("----- Image Input Chat -----")
client := arkruntime.NewClientWithApiKey(apiKey)
req := model.ChatCompletionRequest{
Model: ep_id,
Messages: []*model.ChatCompletionMessage{
{
Role: model.ChatMessageRoleUser,
Content: &model.ChatCompletionMessageContent{
ListValue: []*model.ChatCompletionMessageContentPart{
{
Type: model.ChatCompletionMessageContentPartTypeText,
Text: "Which is the most secure payment app according to Americans?",
},
{
Type: model.ChatCompletionMessageContentPartTypeImageURL,
ImageURL: &model.ChatMessageImageURL{
URL: preSignedUrl.SignedUrl,
},
},
},
},
},
},
}
resp, err := client.CreateChatCompletion(ctx, req)
if err != nil {
fmt.Printf("standard chat error: %v
", err)
return
}
fmt.Println(*resp.Choices[0].Message.Content.StringValue)
}
package com.volcengine.ark.runtime;
import com.volcengine.ark.runtime.model.completion.chat.ChatCompletionContentPart;
import com.volcengine.ark.runtime.model.completion.chat.ChatMessage;
import com.volcengine.ark.runtime.model.completion.chat.ChatMessageRole;
import com.volcengine.ark.runtime.service.ArkService;
import com.volcengine.tos.TOSV2;
import com.volcengine.tos.TOSV2ClientBuilder;
import com.volcengine.tos.TosClientException;
import com.volcengine.tos.TosServerException;
import com.volcengine.tos.comm.HttpMethod;
import com.volcengine.tos.model.object.PreSignedURLInput;
import com.volcengine.tos.model.object.PreSignedURLOutput;
import com.volcengine.tos.model.object.PutObjectInput;
import com.volcengine.tos.model.object.PutObjectOutput;
import com.volcengine.ark.runtime.model.completion.chat.ChatCompletionRequest;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
public class VLMChatExample {
private static final String TOS_ENDPOINT = "https://tos-cn-beijing.volces.com";
private static final String REGION = "cn-beijing";
private static final String ARK_API_KEY = System.getenv("ARK_API_KEY");
private static final String VOLC_ACCESSKEY = System.getenv("VOLC_ACCESSKEY");
private static final String VOLC_SECRETKEY = System.getenv("VOLC_SECRETKEY");
private static final long TOS_EXPIRE_TIME = 3600;
public static void compressImage(String inputImagePath, String outputImagePath, long targetSizeInBytes) throws IOException {
File inputFile = new File(inputImagePath);
BufferedImage img = ImageIO.read(inputFile);
float quality = targetSizeInBytes * 1.0f / inputFile.length();
try (ImageOutputStream ios = ImageIO.createImageOutputStream(new File(outputImagePath))) {
ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next();
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(quality);
writer.setOutput(ios);
writer.write(null, new javax.imageio.IIOImage(img, null, null), param);
writer.dispose();
}
}
public static void uploadImageToTOS(String filePath, String bucketName, String objectKey) throws Throwable {
TOSV2 tos = new TOSV2ClientBuilder().build(REGION, TOS_ENDPOINT, VOLC_ACCESSKEY, VOLC_SECRETKEY);
// step 1. 上传本地图片到tos
File file = new File(filePath);
try (FileInputStream inputStream = new FileInputStream(file)) {
PutObjectInput putObjectInput = new PutObjectInput().setBucket(bucketName)
.setKey(objectKey).setContent(inputStream).setContentLength(file.length());
PutObjectOutput output = tos.putObject(putObjectInput);
System.out.println("putObject succeed, object's etag is " + output.getEtag());
System.out.println("putObject succeed, object's crc64 is " + output.getHashCrc64ecma());
} catch (IOException e) {
System.out.println("putObject read file failed");
e.printStackTrace();
throw e;
} catch (TosClientException e) {
// 操作失败,捕获客户端异常,一般情况是请求参数错误,此时请求并未发送
System.out.println("putObject failed");
System.out.println("Message: " + e.getMessage());
if (e.getCause() != null) {
e.getCause().printStackTrace();
}
throw e;
} catch (TosServerException e) {
// 操作失败,捕获服务端异常,可以获取到从服务端返回的详细错误信息
System.out.println("putObject failed");
System.out.println("StatusCode: " + e.getStatusCode());
System.out.println("Code: " + e.getCode());
System.out.println("Message: " + e.getMessage());
System.out.println("RequestID: " + e.getRequestID());
throw e;
} catch (Throwable t) {
// 作为兜底捕获其他异常,一般不会执行到这里
System.out.println("putObject failed");
System.out.println("unexpected exception, message: " + t.getMessage());
throw t;
}
}
public static String getPreSignedURL(String bucketName, String objectKey) throws Throwable {
TOSV2 tos = new TOSV2ClientBuilder().build(REGION, TOS_ENDPOINT, VOLC_ACCESSKEY, VOLC_SECRETKEY);
// 生成预签名链接
try {
PreSignedURLInput input = new PreSignedURLInput().setBucket(bucketName).setKey(objectKey)
.setHttpMethod(HttpMethod.GET).setExpires(TOS_EXPIRE_TIME);
PreSignedURLOutput output = tos.preSignedURL(input);
System.out.println("preSignedURL succeed, the signed url is " + output.getSignedUrl());
System.out.println("preSignedURL succeed, the signed header is " + output.getSignedHeader());
return output.getSignedUrl();
} catch (TosClientException e) {
// 操作失败,捕获客户端异常,一般情况是请求参数错误,此时请求并未发送
System.out.println("preSignedURL failed");
System.out.println("Message: " + e.getMessage());
if (e.getCause() != null) {
e.getCause().printStackTrace();
}
throw e;
} catch (Throwable t) {
// 作为兜底捕获其他异常,一般不会执行到这里
System.out.println("preSignedURL failed");
System.out.println("unexpected exception, message: " + t.getMessage());
throw t;
}
}
public static void main(String[] args) throws Throwable {
String filePath = "/your/path/to/your/image.jpeg";
String compressedPath = "/your/path/to/compress/image.jpeg";
String tosBucket = "{your bucket name}";
String objectKey = "{your object key}";
// 1. 压缩图片
try {
compressImage(filePath, compressedPath, 300 * 1024);
} catch (IOException e) {
System.out.println("compressImage failed");
e.printStackTrace();
throw e;
}
// 2. 上传TOS
try {
uploadImageToTOS(compressedPath, tosBucket, objectKey);
} catch (Throwable t) {
System.out.println("uploadImageToTOS failed");
t.printStackTrace();
throw t;
}
// 3. 生成预签名链接
String preSignedURL = "";
try {
preSignedURL = getPreSignedURL(tosBucket, objectKey);
} catch (Throwable t) {
System.out.println("getPreSignedURL failed");
t.printStackTrace();
throw t;
}
// 4. 调用大模型Chat
ArkService service = new ArkService(ARK_API_KEY);
System.out.println("----- image input -----");
final List<ChatMessage> messages = new ArrayList<>();
final List<ChatCompletionContentPart> multiParts = new ArrayList<>();
multiParts.add(ChatCompletionContentPart.builder().type("text").text(
"Which is the most secure payment app according to Americans?"
).build());
multiParts.add(ChatCompletionContentPart.builder().type("image_url").imageUrl(
new ChatCompletionContentPart.ChatCompletionContentPartImageURL(preSignedURL)
).build());
final ChatMessage userMessage = ChatMessage.builder().role(ChatMessageRole.USER)
.multiContent(multiParts).build();
messages.add(userMessage);
ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
.model("{your ark model endpoint id}")
.messages(messages)
.build();
service.createChatCompletion(chatCompletionRequest).getChoices().forEach(choice -> System.out.println(choice.getMessage().getContent()));
// shutdown service
service.shutdownExecutor();
}
}
相关文档
常见问题
使用视觉理解模型时,报错InvalidParameter?