跳到主要内容
Vane Data / 核心概念

AI 函数

Vane AI Function 是由 provider 驱动、以有状态 batch UDF 执行的 Expression。它会在每个输入行旁生成一个模型结果,因此标识、源文本和其他 审查字段可以保留在同一个 projection 中。

本页只介绍 Expression UDF。SQL 和 Python 是构建同一个保持行数操作的两种 写法;切换写法不会改变执行语义。

1. Expression 契约

Vane 目前提供两种 AI Expression 操作:

操作SQL ExpressionPython Expression结果支持的 provider
生成文本或结构化输出ai_prompt(messages, ...)vane.ai.prompt(expression, ...)每个输入行得到一个 VARCHAR 或原生 STRUCTopenaigoogleanthropicvllm
生成 embeddingai_embed(text, ...)vane.ai.embed(expression, ...)每个输入行得到一个定长 FLOAT[n]openaigoogletransformers

两个操作都会保持行数。请把后续需要的源列保留在 projection 中,使用 SQL AS 或 Python .alias() 命名生成列,并携带稳定 ID,让每个 provider 结果 都能追溯到输入。

SQL options 是规划配置,而不是逐行数据。providermodel 等选择项及公共 操作设置使用 named argument;provider 请求参数和执行设置通过 options := struct_pack(...) 传入。这些值必须由常量组成;同一个 Expression 中的 provider、model 和执行设置不能随输入行变化。

Expression 没有分类函数。上面的 provider 能力表有意只列出返回 Expression 的操作。

2. Provider

Provider adapter 会把同一个 Expression 契约映射到不同的托管 API 或本地 模型 runtime。先安装 Vane;Vane 随后会延迟加载 provider adapter,因此只需 再添加实际使用的 provider 库。

shell
uv pip install vane-ai
ProviderPromptEmbedRuntime 与配置
openai支持支持OpenAI API 或 OpenAI-compatible endpoint;安装 vane-ai[openai],并在 worker 环境设置 OPENAI_API_KEY
google支持支持Google Generative AI;安装 vane-ai[google],并在 worker 环境设置 GOOGLE_API_KEY
anthropic支持不支持Anthropic Messages API;安装 vane-ai[anthropic],并在 worker 环境设置 ANTHROPIC_API_KEY
vllm支持不支持本地或远程 vLLM engine;安装 vane-ai[vllm],提供模型访问能力;需要 GPU actor 时使用 Ray
transformers不支持支持本地 SentenceTransformers 模型;安装 vane-ai[transformers]

需要可复现结果时,请显式设置 providermodel。模型 ID、限制和可用性 由所配置的 endpoint 决定,因此应选择该 endpoint 支持的模型。

3. 配置 OpenAI

下面的示例使用 OpenAI provider。先安装客户端,并把凭据提供给实际执行查询 的进程:

shell
uv pip install 'vane-ai[openai]'
export OPENAI_API_KEY="<your-token>"


# 可选:仅在使用 OpenAI-compatible endpoint 时设置。
export OPENAI_BASE_URL="https://provider.example/v1"

OpenAI client 会在 worker 上创建,并在创建时读取这两个环境变量。 OPENAI_API_KEY 既可以保存 OpenAI API key,也可以保存 compatible service 签发的 token。直接使用 OpenAI API 时可以不设置 OPENAI_BASE_URL,client 会 使用官方 API 根地址。对于 Ray 作业,每个可能执行 Expression 的 worker 都 必须安装 client 并配置这些环境变量。

下面的示例同时展示另一种支持的方式:在 struct_pack(...) 或 Python keyword 中显式传入非敏感的 base_url。使用 compatible service 时请替换该值。显式 option 的优先级高于 OPENAI_BASE_URL;如果依赖环境变量,请从 Expression 中省略这个 option。两种方式都应使用通常以 /v1 结尾的 API 根地址,而不是 /chat/completions 这样的具体 operation path。如果 compatible endpoint 实现了 Chat Completions、但没有实现 OpenAI Responses API,还要在 SQL 中设置 use_chat_completions := true,或在 Python 中设置 use_chat_completions=True

Token 应始终保存在 OPENAI_API_KEY 中。不要把它放入 SQL、Python options、 notebook 输出或已提交文件;SQL binding 会拒绝疑似凭据的 option 字段。

4. SQL Expression

当周围的转换本来就是 query 时,SQL 是简洁的默认选择。Vane connection 会 注册 ai_promptai_embedprovidermodel 等选择项及公共操作设置使用 named argument,options struct 包含 provider 请求参数和执行设置。Ray 是 Vane 的默认 runner,示例中的 show() 会通过 RayRunner 物化 relation。只有 需要覆盖已有的 local runner 设置时,才在创建 connection 前调用 vane.configure(runner="ray")

使用 ai_prompt 生成文本

example.py
import vane


con = vane.connect()
documents = con.sql("""
    SELECT *
    FROM (VALUES
        (1, 'The customer asked for a refund after a duplicate charge.'),
        (2, 'The shipment is delayed because the address is incomplete.')
    ) AS t(document_id, text)
""")


prompted = con.sql("""
    SELECT
        document_id,
        text,
        ai_prompt(
            text,
            system_message := 'Write one short support summary. Return plain text only.',
            provider := 'openai',
            model := 'gpt-4o-mini',
            options := struct_pack(
                base_url := 'https://api.openai.com/v1',
                timeout := 60.0,
                actor_number := 1,
                max_concurrency_per_actor := 4,
                max_output_tokens := 64,
                temperature := 0.0
            )
        ) AS summary
    FROM documents
    ORDER BY document_id
""")


prompted.show()

actor_number 选择 provider actor 数量。对于 prompt 调用, max_concurrency_per_actor 限制每个 actor 内同时进行的 API request 数。请从保守 值开始,只在 endpoint 的速率与容量限制内提高任一参数。

使用 ai_embed 生成向量

example.py
embedded = con.sql("""
    SELECT
        document_id,
        text,
        ai_embed(
            text,
            provider := 'openai',
            model := 'text-embedding-3-small',
            options := struct_pack(
                base_url := 'https://api.openai.com/v1',
                encoding_format := 'float',
                normalize := true,
                actor_number := 1
            )
        ) AS embedding
    FROM documents
    ORDER BY document_id
""")


embedded.show()

每个 embedding Expression 的结果都是定长 FLOAT[n]。Vane 已知受支持官方 模型的默认维度。使用 OpenAI-compatible endpoint,或请求模型支持的缩短 embedding 时,应显式传入正的 named argument dimensions := nnormalize := true 会对每个非空向量执行 L2 normalization。

5. Python Expression

Python Expression 具有相同的输出和执行契约。它使用封闭的 keyword surface 集中传递 provider、request 和执行 options,并拒绝未知名称。

example.py
import vane


con = vane.connect()
documents = con.sql("""
    SELECT *
    FROM (VALUES
        (1, 'The customer asked for a refund after a duplicate charge.'),
        (2, 'The shipment is delayed because the address is incomplete.')
    ) AS t(document_id, text)
""")


prompted = documents.select(
    vane.col("document_id"),
    vane.col("text"),
    vane.ai.prompt(
        vane.col("text"),
        provider="openai",
        model="gpt-4o-mini",
        base_url="https://api.openai.com/v1",
        timeout=60.0,
        actor_number=1,
        max_concurrency_per_actor=4,
        max_output_tokens=64,
        temperature=0.0,
        system_message="Write one short support summary. Return plain text only.",
    ).alias("summary"),
).order("document_id")


embedded = documents.select(
    vane.col("document_id"),
    vane.col("text"),
    vane.ai.embed(
        vane.col("text"),
        provider="openai",
        model="text-embedding-3-small",
        base_url="https://api.openai.com/v1",
        timeout=60.0,
        actor_number=1,
        encoding_format="float",
        normalize=True,
    ).alias("embedding"),
).order("document_id")


prompted.show()
embedded.show()

同一组 keyword 也适用于返回 relation 的调用,例如 vane.ai.prompt(documents, vane.col("text"), ...)。凭据应保留在 worker 环境 中;疑似凭据的 option 名称会被拒绝,不会序列化到 plan 中。