通用调用

更新时间:
复制 MD 格式

本文介绍如何在 Flink 中使用 ML_PREDICT 函数调用 AI 模型,涵盖语法与入参说明、调用级参数、内容类型配置、列级参数设置,以及文本、图片、多模态等多种调用示例。

快速开始

前提条件

以下示例演示如何使用 ML_PREDICT 调用 Flink 内置模型。请在数据开发 > ETL页面,新建作业、复制代码后点击调试。

CREATE TEMPORARY TABLE text_source (
  user_input STRING
) WITH ('connector' = 'datagen');

CREATE TEMPORARY TABLE result_sink (
  user_input STRING,
  ai_analysis STRING
) WITH ('connector' = 'print');

CREATE TEMPORARY MODEL text_model
INPUT (user_input STRING)
OUTPUT (content STRING)
WITH (
  'provider' = 'openai-compat',
  'model' = 'qwen3.6-flash',
  'task' = 'chat/completions',
  'system-prompt' = '分析内容乱码程度,给0-100的评分'
);

INSERT INTO result_sink
SELECT user_input, content as ai_analysis FROM
    ML_PREDICT(
        TABLE text_source,
        MODEL text_model,
        DESCRIPTOR(user_input)
);

使用限制

  • 仅实时计算引擎 VVR 11.1 及以上版本支持。

  • 部分参数仅在使用 Flink AI 服务(内置模型)时支持,仅支持 VVR 11.8及以上版本。

  • ML_PREDICT 算子的吞吐量受百炼平台限流限制。触及流量上限时,作业会出现以 ML_PREDICT 算子为瓶颈的反压现象,严重时可能触发超时报错及作业重启。详情参见百炼平台限流。

  • content-types 中的类型数量及 Descriptor 中的列数,必须与 CREATE MODEL 中 INPUT 的列数一致。

  • image_url 类型的列必须为 STRING,multi_image_urls 类型的列必须为 ARRAY<STRING>。

  • base64 图片必须包含 data:image/<格式>;base64, 前缀,不支持纯 base64 字符串和本地文件路径。

语法

ML_PREDICT(TABLE <table_name>, MODEL <model_name>, DESCRIPTOR(<input_columns>) [, CONFIG => MAP[...]])        

入参

参数

数据类型

说明

TABLE

TABLE

模型推断的输入数据流,可以是物理表名或视图名。

MODEL

MODEL

已注册的模型服务名称。详情参见模型设置。

DESCRIPTOR()

—

用于模型推断的输入列。

说明

VVR 11.8 及以上版本支持输入多列,且仅在使用 Flink AI 服务(内置模型)时支持。强制要求 DESCRIPTOR 列数 = CREATE MODEL INPUT 列数。

CONFIG => MAP[...]

MAP

可选。详情参见调用级参数。

说明

仅VVR 11.8 及以上版本支持,且使用 Flink AI 服务(内置模型)。

调用级参数

用户可以在使用 ML_PREDICT 时指定调用级参数。若 CREATE MODEL 中已设置参数值,则调用 ML_PREDICT 时以新指定的参数为准,但不会持久化改写 MODEL 中的参数值。

参数

说明

示例

user-prompt

指定用户提示词。传空字符串时则不使用MODEL 级参数值。

MAP['user-prompt', '请用英文回答']

content-type

仅输入单列时,指定内容类型。

MAP['content-type', 'text']

content-types

输入多列时,指定内容类型。
content-types 中的类型数量必须与 CREATE MODEL 中 INPUT 的列数一致。

MAP['content-types', 'text;image_url']

{列名}.{参数名}

指定列级参数。

MAP['image_input.min_pixels', '100']

extra-body

指定附加参数(JSON 字符串)。

MAP['extra-body', '{"enable_search": true}']

bundle-size

Bundle 大小。

MAP[
  'bundle-size', '10',
  'bundle-allow-latency', '5s'
]
说明

Bundle 处理仅支持 VVR 11.9 及以上版本。

bundle-allow-latency

Bundle 允许的延迟时间。

内容类型参数

  • 仅输入单列时,可通过 content-type 指定内容类型,支持的值:text、image_url。

  • 输入多列时,可通过 content-types 指定每列内容类型,支持的值和 Flink SQL 列类型的映射关系:

content-types 内容类型

Flink SQL 类型

说明

text

STRING

-

image_url

STRING

-

image_bytes

BYTES

VVR 11.9 及以上版本支持

multi_image_bytes

ARRAY<BYTES>

VVR 11.9 及以上版本支持

multi_image_urls

ARRAY<STRING>

VVR 11.8 及以上版本支持

video_bytes

BYTES

VVR 11.9 及以上版本支持

video_url

STRING

VVR 11.9 及以上版本支持

  • 请在参数中优先指定content-types,若同时设置 content-type 和 content-types 框架会报错提示。注意:content-type 和 content-types在模型参数中设置和调用时设置是相互影响的:

创建模型时指定参数

调用级参数可使用

调用级参数不可使用

说明

content-type(单列)

content-type

content-types

可在 text 和 image_url 间切换

content-types(多列)

content-types

content-type

可改变类型组合,如 text;image_url → text;text

未指定 content-type 或 content-types

content-type
content-types

—

同上

列级参数

参数

说明

参数值

示例

{列名}.min_pixels

设定输入图像或视频帧的最小像素阈值。当输入图像或视频帧的像素小于 min_pixels 时,会将其进行放大,直到总像素高于 min_pixels。

Qwen3.7、Qwen3.6、Qwen3.5:默认值和最小值均为 65536。

MAP['image_input.min_pixels', '100']

{列名}.max_pixels

设定输入图像或视频帧的最大像素阈值。当输入图像或视频的像素在 [min_pixels, max_pixels] 区间内时,模型会按原图进行识别。当输入图像像素大于 max_pixels 时,会将图像进行缩小,直到总像素低于 max_pixels。

Qwen3.7、Qwen3.6、Qwen3.5:默认值为 2621440,最大值为 16777216。

MAP['image_input.max_pixels', '10000']

{列名}.total_pixels

限制从视频中抽取的所有帧的总像素(单帧图像像素 × 总帧数)。如果视频总像素超过此限制,系统将对视频帧进行缩放,但仍会确保单帧图像的像素值在 [min_pixels, max_pixels] 范围内。
对于抽帧数量较多的长视频,可适当降低此值以减少 Token 消耗和处理时间,但这可能会导致图像细节丢失。

Qwen3.7系列、Qwen3.6系列、Qwen3.5系列:默认值和最大值均为 819200000,该值对应 800000 个图像 Token(每 32×32 像素对应 1 个图像 Token)。

MAP['image_input.total_pixels', '1000000']

{列名}.cache_control

用于开启显式缓存。

{"type": "ephemeral"}

MAP['content.cache_control', '{"type": "ephemeral"}']

{列名}.fps

用户设置视频理解的抽帧频率

取值范围为 [0.1, 10],默认值为 2.0

MAP['video_input.fps', '1.0']

Bundle 处理

  • 处理方式:Bundle 处理会先将多条输入数据聚合成一个批次,再统一调用 AI 模型。这种处理方式可以减少模型调用次数,但会增加单次请求的模型推理时间,在数据被有效聚合时能明显提升算子吞吐量。

  • 参数说明:bundle-size 用于指定单个批次最多积累的数据条数;bundle-allow-latency 用于指定批次未达到 bundle-size 时允许等待的最长时间。达到批次大小或等待时长任一条件时触发处理。

  • 支持条件:(仅支持内置模型)Bundle 处理按模型的输入输出形态生效。

    • 文本生成:模型任务类型为 chat/completions 时,输入恰好一列 STRING 文本列,输出恰好一列 STRING 或 VARIANT 列。多列输入以及图片、视频、音频等多模态输入不支持。

    • 文本向量化:模型任务类型为 embeddings 时,输入恰好一列 STRING 列,输出恰好一列 ARRAY<FLOAT> 列。

  • 适用函数:ML_PREDICT、文本分类(AI_CLASSIFY)、情感分析(AI_SENTIMENT)、信息提取(AI_EXTRACT)、文本摘要(AI_SUMMARIZE)、文本翻译(AI_TRANSLATE)、数据脱敏(AI_MASK)及文本向量化(AI_EMBED)。其中,ML_PREDICT 仅在所注册模型满足上述形态要求时支持 Bundle 处理。

  • 全局配置:对作业内满足上述形态要求的所有 ML_PREDICT 和垂类 AI Function 调用生效。使用以下全局参数开启 Bundle 处理:

    -- Bundle 处理仅支持 VVR 11.9 及以上版本。
    SET 'table.exec.ml-predict.bundle-size' = '10';
    SET 'table.exec.ml-predict.bundle-allow-latency' = '5s';
  • 调用级配置:仅对配置了参数的函数调用生效;ML_PREDICT 与上述垂类函数的配置方式相同。具体参数和示例请参见调用级参数。

错误处理

使用限制

  • 仅实时计算引擎 VVR 11.9 及以上版本支持。

  • 不支持在模型调用同步执行模式下,开启错误处理能力。

  • 暂不支持与向量化结果缓存(CACHE_TABLE)一起使用。

开启方式

在使用 AI 函数时增加参数FAIL_ON_ERROR => FALSE。

前置条件:保持模型默认的重试配置 error-handling-strategy='retry'、retry-fallback-strategy='failover'。模型参数详情请参见模型设置。

参数

说明

是否必填

默认值

FAIL_ON_ERROR

最终调用失败时是否让作业报错。设为 FALSE 后,失败记录转为错误行输出,作业继续运行。

否

TRUE

说明

FAIL_ON_ERROR 默认值为 TRUE,重试耗尽后作业报错。设为 FALSE 仅改变失败记录的处理方式,不改变重试行为。

输出变化

开启后,系统会在原有输出字段末尾追加错误信息列 err_msg,类型为可空的 VARIANT。该列由系统生成,无需在输入表或 CREATE MODEL 的 OUTPUT 中声明。

  • 调用成功:err_msg 为 NULL。

  • 最终失败:模型结果字段均为 NULL,err_msg 包含错误信息。

使用 SELECT * 时,结果会包含新增的错误信息列;显式选择字段时,需手动指定该列。默认列名为 err_msg;若与已有输出列重名,系统会自动追加数字后缀(如 err_msg0),引用时请使用实际列名。

重要

请以错误信息列是否为 NULL 判断调用是否失败:非 NULL 表示失败。模型结果字段为 NULL 不一定表示调用失败。

对象内字段

内容

SQL 读取方式

message

错误原因,日常排查先看这一项。

CAST(err_msg['message'] AS STRING)

stack_trace

更详细的排查信息,需要进一步定位时查看。

CAST(err_msg['stack_trace'] AS STRING)

details(optional字段)

当底层报错有实际有额外信息绑定时,会有该字段。

err_msg['details'],若没有字段会返回NULL, 若存在该字段返回的类型为Variant。

示例

AI_SENTIMENT 保留失败记录

准备一个已创建、支持异步调用的情感分析模型 ai_sentiment_model。

CREATE TEMPORARY VIEW input_data AS
SELECT *
FROM (VALUES
  (1, CAST('xxxx(反人类的暴力冲突描述)' AS STRING), 'negative'),
  (2, CAST('中国的治安一直是世界上数一数二的级别' AS STRING), 'positive')
) AS t(id, input_text, expected_label);

CREATE TEMPORARY VIEW ai_results AS
SELECT i.id, i.input_text, i.expected_label,
       r.score, r.label, r.confidence, r.err_msg
FROM input_data AS i,
LATERAL TABLE(AI_SENTIMENT(
  MODEL => MODEL ai_sentiment_model,
  INPUT => i.input_text,
  FAIL_ON_ERROR => FALSE,
  CONFIG => MAP['async', 'true']
)) AS r(score, label, confidence, err_msg);

SELECT * FROM ai_results;

查询输出依次为以下列。

输出列

类型

来源与含义

id

INT

保留输入记录编号。

input_text

STRING

保留待处理的原文。

score / label / confidence

STRING

AI_SENTIMENT 返回内容,失败时为 NULL。

err_msg

VARIANT,可为 NULL

开启错误处理后自动增加。成功时为 NULL,最终失败时为错误VARIANT对象。

上述实际输出如下。摘要和错误内容为示意,实际以运行结果为准。

id

input_text

score / label / confidence

err_msg

1

xxxx(反人类的暴力冲突描述)

NULL

{"message":"com.openai.errors.BadRequestException: 400: <400> InternalError.Algo.DataInspectionFailed: Input text data may contain inappropriate content..... "stack_trace":"org.apache.flink.table.api.TableException: Failed to execute asynchronously prediction with input row xxx}

2

中国的治安一直是世界上数一数二的级别

1.0 / positive / 0.99

NULL

其他报错示例

以通用调用为例子,展示timeout示例。

message: 
java.util.concurrent.TimeoutException: AsyncPredictFunction did not complete within the configured timeout. Increase the ML_PREDICT timeout or check external service connectivity.

stack_trace:
java.util.concurrent.TimeoutException: AsyncPredictFunction did not complete within the configured timeout. Increase the ML_PREDICT timeout or check external service connectivity.
at org.apache.flink.table.runtime.operators.predict.AsyncMLPredictRunner.timeout(AsyncMLPredictRunner.java:153)
at org.apache.flink.table.runtime.operators.predict.AsyncMLPredictRunner.timeout(AsyncMLPredictRunner.java:51)
at org.apache.flink.table.runtime.operators.TableKeyedAsyncWaitOperator$KeyedResultHandler.timerTriggered(TableKeyedAsyncWaitOperator.java:462)
at org.apache.flink.table.runtime.operators.TableKeyedAsyncWaitOperator$KeyedResultHandler.lambda$registerTimeout$1(TableKeyedAsyncWaitOperator.java:457)
at org.apache.flink.table.runtime.operators.TableKeyedAsyncWaitOperator.lambda$registerTimer$4(TableKeyedAsyncWaitOperator.java:486)
at org.apache.flink.streaming.runtime.tasks.StreamTask.invokeProcessingTimeCallback(StreamTask.java:2285)
at org.apache.flink.streaming.runtime.tasks.StreamTask.lambda$deferCallbackToMailbox$28(StreamTask.java:2276)
at org.apache.flink.streaming.runtime.tasks.StreamTaskActionExecutor$1.runThrowing(StreamTaskActionExecutor.java:50)
at org.apache.flink.streaming.runtime.tasks.mailbox.Mail.run(Mail.java:115)
at org.apache.flink.streaming.runtime.tasks.mailbox.MailboxProcessor.runMail(MailboxProcessor.java:415)
at org.apache.flink.streaming.runtime.tasks.mailbox.MailboxProcessor.processMailsWhenDefaultActionUnavailable(MailboxProcessor.java:384)
at org.apache.flink.streaming.runtime.tasks.mailbox.MailboxProcessor.processMail(MailboxProcessor.java:369)
at org.apache.flink.streaming.runtime.tasks.mailbox.MailboxProcessor.runMailboxLoop(MailboxProcessor.java:229)
at org.apache.flink.streaming.runtime.tasks.StreamTask.runMailboxLoop(StreamTask.java:1273)
at org.apache.flink.streaming.runtime.tasks.StreamTask.invoke(StreamTask.java:1217)
at org.apache.flink.runtime.taskmanager.Task.runWithSystemExitMonitoring(Task.java:1133)
at org.apache.flink.runtime.taskmanager.Task.restoreAndInvoke(Task.java:1110)
at org.apache.flink.runtime.taskmanager.Task.doRun(Task.java:914)
at org.apache.flink.runtime.taskmanager.Task.run(Task.java:716)
at java.base/java.lang.Thread.run(Thread.java:991)

各类错误的处理方式

以下为已开启错误处理、保持默认重试配置时的行为。错误行指保留输入、模型结果为空、err_msg 包含失败原因的一行数据。

错误类型/原因

系统如何处理

最终输出

网络连接失败、限流或部分临时服务错误(429、500、502、503)

按配置等待后重试。

重试成功则正常输出;最终失败则输出错误行。

参数不合法、输入过长、密钥错误、无权限或模型不存在(400、401、403、404、422)

通常不重试,直接返回失败。

输出错误行,记录服务返回的原因。

内容审核拒绝,或余额、配额不足

按服务实际返回的错误决定是否重试。

恢复成功则正常输出;最终失败则输出错误行。

要求 JSON 结果,但模型回复无法解析

尝试重新请求。

成功则正常输出;最终失败则输出错误行。

超过设定的等待时间

结束本次等待。

输出错误行,提示超时。

批量处理时,最终失败或超时

按批次内的输入分别记录失败。

每条输入各输出一条错误行,记录同一个失败原因。

示例

文本

以下示例注册并引用 Flink AI 服务提供的内置模型,对输入文本进行情感分类。调用示例 1 复用 MODEL 级参数,调用示例 2 在调用时指定参数 user-prompt。

-- 注册引用内置模型,不指定 content-type 时默认为 text
CREATE MODEL sentiment_model
INPUT (prompt STRING)
OUTPUT (response STRING)
WITH (
  'provider' = 'openai-compat',
  'task' = 'chat/completions',
  'model' = 'qwen3.6-flash',
  'system-prompt' = '你是一个情感分类模型,输出标签:负面、正面、中性'
);

-- 创建源表:模拟商品评价数据
CREATE TEMPORARY VIEW input_table(id, content)
AS VALUES 
  (1, '质量很好,面料柔软亲肤,尺码也很标准,好评'),
  (2, '收到就有线头,洗了一次严重褪色,不值这个价'),
  (3, '衣服已收到,和图片一致'),
  (4, '穿了两周起球严重,客服还不给退货,差评'),
  (5, '版型显瘦,颜色比图片还好看,已经回购第三件了');

-- 创建结果表
CREATE TEMPORARY TABLE output_table (
  id INT,
  content STRING,
  sentiment STRING
) WITH (
  'connector' = 'print'
);

-- 使用 ML_PREDICT 进行实时推理
-- 调用示例 1:复用 MODEL 级参数
INSERT INTO output_table
SELECT
  id,
  content,
  response AS sentiment
FROM ML_PREDICT(
  TABLE input_table, 
  MODEL sentiment_model, 
  DESCRIPTOR(content));

-- 调用示例 2:指定调用级参数
INSERT INTO output_table
SELECT
  id,
  content,
  response AS sentiment
FROM ML_PREDICT(
  TABLE input_table, 
  MODEL sentiment_model, 
  DESCRIPTOR(content),
  MAP['user-prompt', '请用英文回复']);

调用示例 1 输出结果:

id

content

sentiment

1

质量很好,面料柔软亲肤,尺码也很标准,好评

正面

2

收到就有线头,洗了一次严重褪色,不值这个价

负面

3

衣服已收到,和图片一致

正面

4

穿了两周起球严重,客服还不给退货,差评

负面

5

版型显瘦,颜色比图片还好看,已经回购第三件了

正面

调用示例 2 输出结果:

id

content

sentiment

1

质量很好,面料柔软亲肤,尺码也很标准,好评

Positive

2

收到就有线头,洗了一次严重褪色,不值这个价

Negative

3

衣服已收到,和图片一致

Positive

4

穿了两周起球严重,客服还不给退货,差评

Negative

5

版型显瘦,颜色比图片还好看,已经回购第三件了

Positive

图片

以下示例注册一个多模态模型,对输入图片进行分类。

图片输入列(content-type为image_url)为STRING类型,支持以下两种内容形式:

输入形式

用法

限制

公网URL

直接传入模型服务可通过公网访问的HTTP/HTTPS URL字符串,由模型服务自行拉取图片。

URL必须可被模型服务所在环境通过公网访问;若URL具有时效性,有效期需覆盖模型调用耗时;图片格式与大小受模型服务侧限制。

Base64 Data URL

传入以data:image/<格式>;base64,为前缀的字符串。不支持纯Base64字符串和本地文件路径。

图片字节需经Flink作业传输,会增加作业网络开销;Base64编码后数据体积增大;数据量受模型服务侧输入限制约束。

如果图片存储在使用Paimon Catalog的Blob列中,可以利用Paimon提供的Blob预签名URL功能生成公网URL作为输入,详情请参见流式数据湖仓Paimon。

-- 注册引用内置模型,指定 content-type 为 image_url
CREATE TEMPORARY MODEL sentiment_model
INPUT (prompt STRING)
OUTPUT (response STRING)
WITH (
  'provider' = 'openai-compat',
  'task' = 'chat/completions',
  'model' = 'qwen3.6-flash',
  'content-type' = 'image_url'
);

-- 使用 ML_PREDICT 进行实时推理
INSERT INTO output_table
SELECT
  id,
  content,
  response AS sentiment
FROM ML_PREDICT(
  TABLE input_table, 
  MODEL sentiment_model, 
  DESCRIPTOR(content));

视频

以下示例注册一个多模态模型,对输入视频进行理解。

CREATE TEMPORARY MODEL sentiment_model
INPUT (video_url STRING)
OUTPUT (response STRING)
WITH (
  'provider' = 'openai-compat',
  'task' = 'chat/completions',
  'model' = 'qwen3.6-plus',
  'content-types' = 'video_url',
  'system-prompt' = '请简单描述下视频内容'
);

CREATE TEMPORARY VIEW input_table(content)
AS VALUES ('https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20251111/ckgcxt/%E5%8D%95%E4%BA%BA%E8%AF%B4%E8%AF%9D-1.mp4');

SELECT
  content,
  response AS sentiment
FROM ML_PREDICT(
  TABLE input_table, 
  MODEL sentiment_model, 
  DESCRIPTOR(content));

文本 + 单张图片

以下示例注册一个多模态模型,对输入的文本和图片进行对话推理。

CREATE MODEL vl_model
INPUT (text_input STRING, image_input STRING)
OUTPUT (content STRING)
WITH (
  'provider' = 'openai-compat',
  'model' = 'qwen3.5-plus',
  'task' = 'chat/completions',
  'content-types' = 'text;image_url'
);

INSERT INTO result_sink
SELECT content FROM TABLE(ML_PREDICT(
  TABLE image_source,
  MODEL vl_model,
  DESCRIPTOR(text_input, image_input)
));         

文本 + 多张图片(多列)

通过多个 INPUT 列分别传入每张图片,content-types 中为每列指定 image_url。

CREATE MODEL vl_model_multi
INPUT (prompt STRING, img1 STRING, img2 STRING)
OUTPUT (content STRING)
WITH (
  'provider' = 'openai-compat',
  'model' = 'qwen3.5-plus',
  'task' = 'chat/completions',
  'content-types' = 'text;image_url;image_url'
);

SELECT content FROM TABLE(ML_PREDICT(
  TABLE my_source,
  MODEL vl_model_multi,
  DESCRIPTOR(prompt, img1, img2)
));          

文本 + 多张图片(数组)

通过 ARRAY<STRING> 类型列传入多张图片,content-types 中使用 multi_image_urls。

CREATE MODEL vl_model_array
INPUT (prompt STRING, images ARRAY<STRING>)
OUTPUT (content STRING)
WITH (
  'provider' = 'openai-compat',
  'model' = 'qwen3.5-plus',
  'task' = 'chat/completions',
  'content-types' = 'text;multi_image_urls'
);

SELECT content FROM TABLE(ML_PREDICT(
  TABLE my_source,
  MODEL vl_model_array,
  DESCRIPTOR(prompt, images)
)); 

文本 + 视频

CREATE TEMPORARY MODEL sentiment_model
INPUT (video_url STRING, question STRING)
OUTPUT (response STRING)
WITH (
  'provider' = 'openai-compat',
  'task' = 'chat/completions',
  'model' = 'qwen3.6-plus',
  'content-types' = 'video_url;text'
);

CREATE TEMPORARY VIEW input_table(content, question)
AS VALUES ('https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20251111/ckgcxt/%E5%8D%95%E4%BA%BA%E8%AF%B4%E8%AF%9D-1.mp4', '有几个人');

SELECT
  content,
  response AS sentiment
FROM ML_PREDICT(
  TABLE input_table, 
  MODEL sentiment_model, 
  DESCRIPTOR(content, question));

调用时指定参数

示例 1:指定内容类型参数

-- CREATE MODEL 时未指定 content-type / content-types,默认 content-type = text
CREATE MODEL model_single
INPUT (input STRING)
OUTPUT (content STRING)
WITH (
  'provider' = 'openai-compat',
  'model' = 'qwen3.5-plus',
  'task' = 'chat/completions'
);

-- 调用 1:沿用 MODEL 参数,内容类型为 text
SELECT content FROM TABLE(ML_PREDICT(
  TABLE source_text, 
  MODEL model_single, 
  DESCRIPTOR(input)
));

-- 调用 2:调用时指定内容类型为图片
SELECT content FROM TABLE(ML_PREDICT(
  TABLE source_img, 
  MODEL model_single, 
  DESCRIPTOR(input),
  MAP['content-type', 'image_url']
));

示例 2:指定 user-prompt 及列级参数

-- CREATE MODEL 时设置默认配置(多列模型)
CREATE MODEL vl_model
INPUT (text_input STRING, image_input STRING)
OUTPUT (content STRING)
WITH (
  'provider' = 'openai-compat',
  'model' = 'qwen3.5-plus',
  'task' = 'chat/completions',
  'content-types' = 'text;image_url',
  'user-prompt' = '请描述图片内容'
);

-- 调用 1:使用默认配置
SELECT content FROM TABLE(ML_PREDICT(
  TABLE source_a, MODEL vl_model, DESCRIPTOR(text_input, image_input)
));

-- 调用 2:覆盖 user-prompt 和列级参数
SELECT content FROM TABLE(ML_PREDICT(
  TABLE source_b, MODEL vl_model, DESCRIPTOR(text_input, image_input),
  MAP[
    'user-prompt', '请用英文回答',
    'image_input.min_pixels', '100',
    'image_input.max_pixels', '5000'
  ]
));

-- 调用 3:覆盖 content-types,改变类型组合(两列都当文本处理)
SELECT content FROM TABLE(ML_PREDICT(
  TABLE source_c, MODEL vl_model, DESCRIPTOR(text_input, image_input),
  MAP['content-types', 'text;text']
));

-- 调用 4:覆盖 content-types,改变类型组合(翻转顺序)
SELECT content FROM TABLE(ML_PREDICT(
  TABLE source_c, MODEL vl_model, DESCRIPTOR(text_input, image_input),
  MAP['content-types', 'image_url;text']
));