本文介绍EMR Serverless Spark中ai_query和ai_embedding_multimodal函数的多模态用法,主要用于图片理解和图片向量生成场景。
适用版本
当前仅支持Spark 3.5.2版本,需要使用Serverless Spark esr-4.7.0及以上版本。
多模态函数及相关模型服务仅在特定地域(Region)支持,请确认您的集群所在地域已开通相关服务。
函数签名
ai_query
ai_query函数用于调用大语言模型进行推理,支持传入图片数据实现多模态理解。函数签名如下:
ai_query(prompt [, service_name] [, options][, data][, data_type])参数说明:
参数 | 是否必填 | 说明 |
| 是 | 发送给模型的完整提示词(Prompt),应包含上下文、指令和输入数据。建议明确指定输出格式以提升稳定性。 |
| 否 | 指定要调用的模型服务名称。若省略,则使用默认模型 |
| 否 | 以JSON字符串形式提供额外调用参数,用于控制生成行为。支持调整的参数详见option参数说明。 |
| 否 | 需要处理的图片数据列。仅在处理图片数据时需要填写此参数。可以是BINARY类型的图片数据或图片的 http(s) 地址,或STRING类型的图片文件路径列。 |
| 否 | 指定图片数据的传入方式。仅在处理图片数据时需要设置此参数。支持的参数值如下:
|
命名参数调用示例:
ai_query(
'提示词',
service_name => '模型服务名',
options => '{"temperature":0.1}',
data => image_col,
data_type => 'binary'
)支持的命名参数:service_name、options、data、data_type。
ai_embedding_multimodal
仅下述地域支持使用该AI Function:北京、上海、杭州、深圳、乌兰察布、成都、张家口。
ai_embedding_multimodal函数用于生成图片的embedding向量,可用于后续的相似度计算、检索等场景。函数签名如下:
ai_embedding_multimodal(data [, service_name] [, options] [, data_type])参数说明:
参数 | 是否必填 | 说明 |
| 是 | 需要生成embedding的图片数据列。可以是BINARY类型的图片数据或图片的 http(s) 地址,或STRING类型的图片文件路径列。 |
| 否 | 指定要调用的embedding模型服务名称。若省略,则使用默认模型 |
| 否 | 以JSON字符串形式提供额外调用参数,用于控制生成行为。支持的参数取决于目标embedding服务本身。 |
| 否 | 指定图片数据的传入方式。仅在处理图片数据时需要设置此参数。支持的参数值如下:
|
命名参数调用示例:
ai_embedding_multimodal(
image_col,
service_name => 'tongyi-embedding-vision-plus',
options => '{"dim":1024}',
data_type => 'binary'
)支持的命名参数:service_name、options、data_type。
说明
ai_query属于chat类型请求,当前默认行为如下:
如果用户没有在
options中传enable_thinking,系统会默认补上{"enable_thinking": false}。如果用户显式传了
enable_thinking,则以用户配置为准。
例如,以下两种写法等价,都会关闭thinking:
-- 写法一:不传 options,默认关闭 thinking
SELECT ai_query('描述图片内容', data => content) FROM image_table;
-- 写法二:显式关闭 thinking
SELECT ai_query(
'描述图片内容',
data => content,
options => '{"enable_thinking": false}'
) FROM image_table;如果确实需要打开thinking,需要显式传入:
SELECT ai_query(
'描述图片内容',
data => content,
options => '{"enable_thinking": true}'
) FROM image_table;ai_embedding_multimodal不属于chat请求,是否支持某个options字段取决于目标embedding服务本身。
使用场景
场景一:基于图片路径进行多模态数据处理
当图片存储在OSS、HDFS或其他Hadoop兼容文件系统中,表中只保存图片路径时,可通过URI模式让函数内部读取文件内容。
示例:通过图片路径识别图片中的车牌号。
SELECT
path,
ai_query(
'返回图中车牌号。IMPORTANT:只回复车牌信息;如果图片模糊无法辨认,回复''无法识别''。',
service_name => 'qwen3.5-plus',
data => path,
data_type => 'uri'
) AS plate_number
FROM (
SELECT /*+ REPARTITION(10) */ path
FROM ccpd_1m_1000
) t;data => path传入的是路径列,data_type => 'uri'表示函数内部按路径读取文件。分区数建议在内层子查询中通过
REPARTITIONhint控制,而不是直接写在包含AI函数的外层投影上。如果不传
options.enable_thinking,默认为false。
如需显式控制thinking配置,可通过options参数设置:
SELECT
path,
ai_query(
'返回图中车牌号。IMPORTANT:只回复车牌信息;如果图片模糊无法辨认,回复''无法识别''。',
service_name => 'qwen3.5-plus',
data => path,
data_type => 'uri',
options => '{"enable_thinking": false}'
) AS plate_number
FROM (
SELECT /*+ REPARTITION(10) */ path
FROM ccpd_1m_1000
) t;场景二:基于图片二进制进行多模态数据处理
当需要直接从目录批量读取图片内容时,可使用read_files函数读取图片文件,将返回的content列(BINARY类型)作为多模态输入。
示例:从OSS目录批量读取图片并识别车牌号。
SELECT
path,
ai_query(
'返回图中车牌号。IMPORTANT:只回复车牌信息。',
service_name => 'qwen3.5-plus',
data => content
) AS plate_number
FROM read_files(
'oss://bucket/path/to/images/',
suffix => 'jpg,jpeg,png'
);read_files返回path、content、modificationTime、length四个字段,其中content为BINARY类型,可直接传给data参数。此场景使用默认的
data_type => 'binary',无需显式指定。suffix为逗号分隔的后缀列表,大小写不敏感,jpg和.jpg均可。read_files默认不递归子目录;如需递归读取,传入recursive => true。read_files一般不需要额外手动REPARTITION,扫描分区粒度建议通过spark.sql.files.maxPartitionBytes参数控制。
场景三:生成图片Embedding向量
使用ai_embedding_multimodal函数可以将图片转换为embedding向量,用于后续的相似度检索、聚类分析等场景。支持URI模式和Binary模式两种方式。
方式一:通过图片路径生成embedding(URI模式)。
SELECT
path,
ai_embedding_multimodal(
path,
service_name => 'tongyi-embedding-vision-plus',
data_type => 'uri'
) AS embedding
FROM image_paths_table;方式二:通过图片二进制内容生成embedding(Binary模式)。
SELECT
path,
ai_embedding_multimodal(
content,
service_name => 'tongyi-embedding-vision-plus'
) AS embedding
FROM read_files(
'oss://bucket/path/to/images/',
suffix => 'jpg,png'
);read_files使用说明
read_files函数用于从文件系统中批量读取文件内容,常与多模态函数配合使用。函数签名如下:
read_files(path [, suffix] [, recursive])参数说明:
参数 | 是否必填 | 说明 |
| 是 | 目录或单个文件路径。 |
| 否 | 逗号分隔的文件后缀列表,例如 |
| 否 | BOOLEAN类型,是否递归读取子目录,默认 |
返回列:
列名 | 类型 | 说明 |
| STRING | 文件完整路径。 |
| BINARY | 文件二进制内容。 |
| TIMESTAMP | 文件修改时间。 |
| BIGINT | 文件大小(字节)。 |
使用示例:
-- 读取目录下所有文件
SELECT * FROM read_files('oss://bucket/images/');
-- 按后缀过滤
SELECT path, content, length
FROM read_files('oss://bucket/images/', suffix => 'jpg,jpeg,png');
-- 递归读取子目录
SELECT path, content
FROM read_files(
'oss://bucket/images/',
suffix => 'jpg,png',
recursive => true
);read_files只支持命名参数suffix和recursive。suffix过滤会下推到文件扫描阶段,避免先读取目录中的其他大文件。read_files当前不支持formatHint参数。
使用示例
以下是一个完整的SQL使用示例,演示如何通过创建临时视图控制分区后调用多模态函数:
CREATE OR REPLACE TEMPORARY VIEW car_images AS
SELECT /*+ REPARTITION(8) */ path
FROM ccpd_1m_1000;
SELECT
path,
ai_query(
'返回图中车牌号。IMPORTANT:只回复车牌信息;如果图片模糊无法辨认,回复''无法识别''。',
service_name => 'qwen3.5-plus',
data => path,
data_type => 'uri'
) AS plate_number
FROM car_images
LIMIT 20;常见错误
错误信息 | 原因 | 解决方案 |
| 图片格式不支持。 | 优先使用JPEG、PNG、WebP等常见格式,确认目标模型服务支持对应MIME类型。 |
| 文件内容不完整或不是有效图片。 | 检查源文件是否损坏,确认 |
|
| 检查模型服务名是否存在,或确认默认模型服务配置正确。 |
|
| 路径列请改用 |
性能优化建议
路径表场景使用内层子查询控制分区数
推荐把REPARTITION hint放到内层子查询,再在外层执行AI函数。也可以使用CTE或CREATE TEMPORARY VIEW的方式:
-- 方式一:子查询
SELECT
path,
ai_query('请描述图片内容', service_name => 'qwen3.5-plus', data => path, data_type => 'uri') AS result
FROM (
SELECT /*+ REPARTITION(32) */ path FROM large_image_dataset
) t;
-- 方式二:CTE
WITH car_images AS (
SELECT /*+ REPARTITION(32) */ path FROM ccpd_1m_1000
)
SELECT
path,
ai_query('请描述图片内容', service_name => 'qwen3.5-plus', data => path, data_type => 'uri') AS result
FROM car_images;
-- 方式三:临时视图
CREATE OR REPLACE TEMPORARY VIEW car_images AS
SELECT /*+ REPARTITION(32) */ path FROM ccpd_1m_1000;
SELECT
path,
ai_query('请描述图片内容', service_name => 'qwen3.5-plus', data => path, data_type => 'uri') AS result
FROM car_images;read_files场景优先用文件扫描参数控制并行度
read_files直接扫描目录时,通常不需要先手动REPARTITION。如果希望提高并行度或减小单个输入分区大小,优先调整spark.sql.files.maxPartitionBytes:
SET spark.sql.files.maxPartitionBytes = 134217728;读取时提前做后缀过滤
通过suffix参数过滤文件类型,可以减少无关文件扫描和下游AI请求量。需要递归读取子目录时,再显式加上recursive => true:
SELECT path, content
FROM read_files('oss://bucket/images/', suffix => 'jpg,jpeg,png');支持的图片格式
格式 | MIME Type | 魔数检测 |
JPEG |
|
|
PNG |
|
|
GIF |
|
|
WebP |
|
|
BMP |
|
|
TIFF |
|
|
ICO |
|
|
AVIF |
|
|
HEIF |
|
|