RayData 多模态与AI推理算子

更新时间:
复制 MD 格式

本文介绍如何在云原生多模数据库 Lindorm 的 RAY 资源组中,使用 Ray Data 多模态与 AI 算子完成数据清洗、过滤、转换以及推理。

概览

RAY 资源组为 ray.data.Dataset 提供了以下数据处理与 AI 推理方法:

调用方式

功能

Dataset.datajuicer.map

使用 Data-Juicer Mapper 算子进行数据转换,例如清理 HTML、邮箱地址和链接。

Dataset.datajuicer.filter

使用 Data-Juicer Filter 算子过滤不符合条件的数据。

Dataset.ai.prompt

根据文本或消息内容生成回复,适用于摘要、改写和问答等场景。

Dataset.ai.embed_text

将文本转换为向量,适用于语义检索、相似度计算等场景。

Dataset.ai.inference

传入自定义结构的请求并获取完整响应,适用于服务支持的多模态等推理场景。

这些算子可与 Ray Data 原生算子链式组合,并使用 Ray Data 的惰性执行、流水线和分布式调度能力。

前提条件

  • 已开通 RAY 资源组。具体操作,请参见开通与管理。

  • 已使用 Lindorm 提供的 Ray 运行环境。

使用 Data-Juicer 算子

LindormRay 完全兼容 Data-Juicer 算子。可以直接在 Ray Data Dataset 上按算子名称调用 Data-Juicer 算子,并与其他 Ray Data 算子组合使用。

支持的通用参数如下:

参数

说明

op_name

Data-Juicer 算子的名称,例如 clean_email_mapper、text_length_filter。

batch_size

每批处理的行数;不指定时使用 Data-Juicer 算子的批大小。

concurrency

并发执行数,可指定整数;使用 Actor 执行时也可指定 (最小值, 最大值)。不指定时使用算子的 num_proc 配置。

num_cpus

每个执行任务或 Actor 需要的 CPU 核数。

num_gpus

每个执行任务或 Actor 需要的 GPU 数量。

**op_kwargs

可选,所选 Data-Juicer 算子的其他参数,例如 min_len、max_len。

在 op_kwargs 中配置 Data-Juicer 算子的 batch_size、num_proc、num_cpus、num_gpus 等参数时,LindormRay 会自动将其转换为对应的 Ray Data 执行配置,例如将 num_proc 转换为 concurrency。调用时显式传入的 Ray Data 执行参数优先于算子自身配置。

使用 Data-Juicer Mapper 算子进行数据转换

LindormRay 提供 Dataset.datajuicer.map(op_name, **op_kwargs) 方法对接 Data-Juicer Mapper 算子,通过 op_name 指定算子名称,并通过 op_kwargs 配置对应算子的参数。

以下示例中的 Data-Juicer Mapper 算子(默认处理 text 字段)依次清理 HTML 标签、邮箱地址和链接,并为邮箱清理算子指定并发数及 CPU 资源。处理后 id 列保留,text 列更新为清洗后的内容:

import ray

ray.init()

ds = ray.data.from_items(
    [
        {
            "id": 1,
            "text": "<p>Contact admin@example.com for product information.</p>",
        },
        {
            "id": 2,
            "text": "<div>Read the user guide at https://example.com/docs.</div>",
        },
    ]
)

cleaned_ds = (
    ds.datajuicer.map("clean_html_mapper")
    .datajuicer.map("clean_email_mapper", concurrency=2, num_cpus=1)
    .datajuicer.map("clean_links_mapper")
)

print(cleaned_ds.take_all())

使用 Data-Juicer Filter 算子进行数据过滤

LindormRay 提供 Dataset.datajuicer.filter(op_name, **op_kwargs) 方法对接 Data-Juicer Filter 算子,通过 op_name 指定算子名称,并通过 op_kwargs 配置对应算子的参数。

以下示例中的 Data-Juicer Filter 算子(默认处理 text 字段)接着过滤 cleaned_ds,仅保留长度为 10~200 个字符且单词数为 3~50 的文本:

filtered_ds = (
    cleaned_ds.datajuicer.filter(
        "text_length_filter",
        min_len=10,
        max_len=200,
        concurrency=2,
        num_cpus=1,
    )
    .datajuicer.filter(
        "words_num_filter",
        min_num=3,
        max_num=50,
    )
)

print(filtered_ds.take_all())

Data-Juicer Mapper 和 Filter 可以相互串联,也可以与 Ray Data 原生算子组合。Filter 结果可能包含 Data-Juicer 生成的统计字段;例如,可以在输出前选择需要的业务列:

output_ds = filtered_ds.select_columns(["id", "text"])

使用内置 AI 推理算子

LindormRay 内置 prompt、embed_text 和 inference 算子,支撑文本生成、向量化和自定义请求等不同场景的 AI 推理需求。

AI 推理算子公共参数如下:

参数

说明

input

输入列名,列中的数据类型由具体算子决定。

output

结果写入的列名。算子会保留输入 Dataset 的原有列;如果输出列已存在,其值会被覆盖。

url

完整的推理服务接口地址,需包含具体请求路径,例如 https://YOUR_ADDRESS/v1/chat/completions。

headers

可选,请求头,例如鉴权信息。

重要

使用 AI 算子前,请确保 RAY 资源组可以访问 url 指定的推理服务地址。

使用 prompt 算子生成文本

prompt 算子根据输入文本生成回复,可用于摘要、改写和问答。输入列可以是字符串,也可以是非空的消息列表;输出列为生成的文本。

  • 参数说明:

    参数

    说明

    公共参数(input、output、url、headers)

    详见上方公共参数列表。

    model

    可选,服务使用的模型名称。

    system_message

    可选,添加到每条请求开头的系统提示词。

  • 使用示例:

    以下示例对 Dataset 中的文本生成摘要:

    import os
    import ray
    
    ray.init()
    
    ds = ray.data.from_items([{"text": "Ray Data 可以并行处理大规模数据。"}])
    
    result_ds = ds.ai.prompt(
        input="text",
        output="summary",
        url=os.environ["PROMPT_ENDPOINT"],
        headers={"Authorization": f"Bearer {os.environ['INFERENCE_API_KEY']}"},
        model="<model-name>",
        system_message="请用一句话概括输入内容。",
    )
    
    print(result_ds.take(1))
    

使用 embed_text 算子生成文本向量

embed_text 算子将文本转换为向量,可用于语义检索和相似度计算。输入列必须是字符串;输出列为浮点数向量。

  • 参数说明:

    参数

    说明

    公共参数(input、output、url、headers)

    详见上方公共参数列表。

    model

    可选,服务使用的模型名称。

    dimensions

    可选,输出向量的维度。是否支持及可选值取决于模型。

  • 使用示例:

    以下示例为 Dataset 中的文本生成向量。

    import os
    import ray
    
    ray.init()
    
    ds = ray.data.from_items([{"text": "Ray Data 可以并行处理大规模数据。"}])
    
    result_ds = ds.ai.embed_text(
        input="text",
        output="embedding",
        url=os.environ["EMBEDDING_ENDPOINT"],
        headers={"Authorization": f"Bearer {os.environ['INFERENCE_API_KEY']}"},
        model="<embedding-model-name>",
    )
    
    print(result_ds.take(1))
    

使用 inference 算子调用推理服务

inference 算子可将自定义结构的请求传给推理服务,适用于服务支持的文本、图像等推理场景。输入列必须是字典,其内容应符合目标服务的请求格式;输出列保存服务返回的完整响应。

  • 参数说明:

    参数

    说明

    公共参数(input、output、url、headers)

    详见上方公共参数列表。

  • 使用示例:

    以下示例使用 Dataset 中的请求内容调用推理服务。

    import os
    import ray
    
    ray.init()
    
    request_ds = ray.data.from_items(
        [
            {
                "request": {
                    "model": "<model-name>",
                    "messages": [
                        {
                            "role": "user",
                            "content": "Explain Ray Data in one sentence.",
                        }
                    ],
                },
            }
        ]
    )
    
    response_ds = request_ds.ai.inference(
        input="request",
        output="response",
        url=os.environ["INFERENCE_ENDPOINT"],
        headers={"Authorization": f"Bearer {os.environ['INFERENCE_API_KEY']}"},
    )
    
    print(response_ds.take(1))
    

完整示例:清洗、过滤并生成文本向量

以下示例展示如何将 Data-Juicer Mapper、Filter 和 embed_text 算子组成一条 Ray Data 流水线:

import os
import ray


def main():
    ray.init()

    source_ds = ray.data.from_items(
        [
            {
                "id": 1,
                "text": "<p>Ray Data processes data in parallel."
                " Contact data@example.com.</p>",
            },
            {"id": 2, "text": "<p>short</p>"},
        ]
    )

    result_ds = (
        source_ds.datajuicer.map("clean_html_mapper")
        .datajuicer.map("clean_email_mapper")
        .datajuicer.filter(
            "text_length_filter",
            min_len=10,
            max_len=1000,
        )
        .ai.embed_text(
            input="text",
            output="embedding",
            url=os.environ["EMBEDDING_ENDPOINT"],
            headers={
                "Authorization": f"Bearer {os.environ['INFERENCE_API_KEY']}",
            },
            model=os.environ["EMBEDDING_MODEL"],
        )
        .select_columns(["id", "text", "embedding"])
    )

    print(result_ds.take_all())


if __name__ == "__main__":
    main()

作业编写完成后,提交和查看作业的方式请参见使用RAY常驻资源组或向Ray非常驻资源组提交作业。