開源 AI 食譜文件

使用 LLM 作為評判員清理現有偏好資料集

Hugging Face's logo
加入 Hugging Face 社群

並獲得增強的文件體驗

開始使用

Open In Colab

使用 LLM 作為評判員清理現有偏好資料集

作者:David BerensteinSara Han Díaz

在本教程中,我們將使用 distilabel 透過提供關於資料質量的 AI 反饋,利用 LLM 作為評判員來清理資料集。 distilabel 是一個為工程師設計的合成數據和 AI 反饋框架,他們需要基於經過驗證的研究論文的快速、可靠和可擴充套件的管道。請在此處檢視文件

為了評估響應,我們將使用與 distilabel 整合的無伺服器 HF 推理 API。這項服務是免費的,但有速率限制,允許您透過簡單的 HTTP 請求在超過 150,000 個公共模型或您自己的私有模型上進行測試和評估,推理過程由 Hugging Face 共享基礎設施託管,速度很快。如果您需要更多的計算能力,可以使用 Hugging Face 推理端點部署您自己的推理端點。

最後,為了進一步整理資料,我們將使用 Argilla,它允許我們提供關於資料質量的人工反饋。Argilla 是一個面向 AI 工程師和領域專家的協作工具,他們需要為自己的專案構建高質量的資料集。請在此處檢視文件

開始

安裝依賴

要完成本教程,您需要透過 pip 安裝 distilabel SDK 和一些第三方庫。

!pip install "distilabel[hf-inference-endpoints]"
!pip install "transformers~=4.0" "torch~=2.0"

讓我們進行必要的匯入

import random

from datasets import load_dataset

from distilabel.llms import InferenceEndpointsLLM
from distilabel.pipeline import Pipeline
from distilabel.steps import (
    KeepColumns,
    LoadDataFromDicts,
    PreferenceToArgilla,
)
from distilabel.steps.tasks import UltraFeedback

您需要一個 `HF_TOKEN` 才能使用 HF 推理端點。登入後可直接在本 notebook 中使用。

import os
from huggingface_hub import login

login(token=os.getenv("HF_TOKEN"), add_to_git_credential=True)

(可選)部署 Argilla

您可以跳過此步驟或用任何其他資料評估工具替換它,但模型質量會因資料質量不佳而受損,因此我們確實建議您檢視您的資料。如果您已經部署了 Argilla,則可以跳過此步驟。否則,您可以按照本指南快速部署 Argilla。

此外,您還需要將 Argilla 安裝為 distilabel 的附加依賴項。

!pip install "distilabel[argilla, hf-inference-endpoints]"

資料集

在這種情況下,我們將清理一個偏好資料集,因此我們將使用來自 Hugging Face Hub 的 `Intel/orca_dpo_pairs` 資料集。

dataset = load_dataset("Intel/orca_dpo_pairs", split="train[:20]")

接下來,我們將打亂 `chosen` 和 `rejected` 列,以避免資料集中的任何偏見。

def shuffle_and_track(chosen, rejected):
    pair = [chosen, rejected]
    random.shuffle(pair)
    order = ["chosen" if x == chosen else "rejected" for x in pair]
    return {"generations": pair, "order": order}


dataset = dataset.map(lambda x: shuffle_and_track(x["chosen"], x["rejected"]))
dataset = dataset.to_list()

(可選)建立自定義步驟

步驟是 distilabel 管道中的一個塊,用於處理、生成或評估資料等任務。提供了一組預定義的步驟,但您也可以建立自己的自定義步驟。除了像上一節那樣預處理資料,還可以使用自定義步驟來打亂列。此步驟應位於一個單獨的模組中,以便在管道中匯入和使用。在這種情況下,管道將首先使用 `LoadDataFromHub` 步驟載入 `orca_dpo_pairs` 資料集,然後應用 `ShuffleStep`。

# "shuffle_step.py"
from typing import TYPE_CHECKING, List
from distilabel.steps import GlobalStep, StepInput

if TYPE_CHECKING:
    from distilabel.steps.typing import StepOutput

import random


class ShuffleStep(GlobalStep):
    @property
    def inputs(self) -> List[str]:
        return ["instruction", "chosen", "rejected"]

    @property
    def outputs(self) -> List[str]:
        return ["instruction", "generations", "order"]

    def process(self, inputs: StepInput) -> "StepOutput":
        outputs = []

        for input in inputs:
            chosen = input["chosen"]
            rejected = input["rejected"]
            pair = [chosen, rejected]
            random.shuffle(pair)
            order = ["chosen" if x == chosen else "rejected" for x in pair]

            outputs.append({"instruction": input["instruction"], "generations": pair, "order": order})

        yield outputs
from shuffle_step import ShuffleStep

定義管道

要清理現有的偏好資料集,我們需要定義一個包含所有必要步驟的 `Pipeline`。但是,類似的工作流也可用於清理 SFT 資料集。下面,我們將詳細介紹每個步驟。

載入資料集

我們將使用剛剛打亂的資料集作為源資料。

  • 元件: `LoadDataFromDicts`
  • 輸入列:`system`、`question`、`chosen`、`rejected`、`generations` 和 `order`,與載入的字典列表中的鍵相同。
  • 輸出列:`system`、`instruction`、`chosen`、`rejected`、`generations` 和 `order`。我們將使用 `output_mappings` 來重新命名列。
load_dataset = LoadDataFromDicts(
    data=dataset[:1],
    output_mappings={"question": "instruction"},
    pipeline=Pipeline(name="showcase-pipeline"),
)
load_dataset.load()
next(load_dataset.process())

評估響應

為了評估響應的質量,我們將使用 `meta-llama/Meta-Llama-3.1-70B-Instruct`,應用 `UltraFeedback` 任務,根據不同維度(幫助性、誠實性、遵循指令、真實性)對響應進行評判。對於 SFT 資料集,您可以使用`PrometheusEval`

  • 元件:使用 `InferenceEndpointsLLM` 的 `UltraFeedback` 任務與 LLM
  • 輸入列:`instruction`, `generations`
  • 輸出列:`ratings`, `rationales`, `distilabel_metadata`, `model_name`

為了您的用例和提高結果,您可以使用您選擇的任何其他 LLM

evaluate_responses = UltraFeedback(
    aspect="overall-rating",
    llm=InferenceEndpointsLLM(
        model_id="meta-llama/Meta-Llama-3.1-70B-Instruct",
        tokenizer_id="meta-llama/Meta-Llama-3.1-70B-Instruct",
        generation_kwargs={"max_new_tokens": 512, "temperature": 0.7},
    ),
    pipeline=Pipeline(name="showcase-pipeline"),
)
evaluate_responses.load()
next(
    evaluate_responses.process(
        [
            {
                "instruction": "What's the capital of Spain?",
                "generations": ["Madrid", "Barcelona"],
            }
        ]
    )
)

只保留必需的列

我們將刪除不需要的列。

  • 元件: `KeepColumns`
  • 輸入列:`system`、`instruction`、`chosen`、`rejected`、`generations`、`ratings`、`rationales`、`distilabel_metadata` 和 `model_name`
  • 輸出列:`instruction`, `chosen`, `rejected`, `generations` 和 `order`
keep_columns = KeepColumns(
    columns=[
        "instruction",
        "generations",
        "order",
        "ratings",
        "rationales",
        "model_name",
    ],
    pipeline=Pipeline(name="showcase-pipeline"),
)
keep_columns.load()
next(
    keep_columns.process(
        [
            {
                "system": "",
                "instruction": "What's the capital of Spain?",
                "chosen": "Madrid",
                "rejected": "Barcelona",
                "generations": ["Madrid", "Barcelona"],
                "order": ["chosen", "rejected"],
                "ratings": [5, 1],
                "rationales": ["", ""],
                "model_name": "meta-llama/Meta-Llama-3.1-70B-Instruct",
            }
        ]
    )
)

(可選)進一步資料整理

您可以使用 Argilla 進一步整理您的資料。

  • 元件:`PreferenceToArgilla` 步驟
  • 輸入列:`instruction`、`generations`、`generation_models`、`ratings`
  • 輸出列:`instruction`、`generations`、`generation_models`、`ratings`
to_argilla = PreferenceToArgilla(
    dataset_name="cleaned-dataset",
    dataset_workspace="argilla",
    api_url="https://[your-owner-name]-[your-space-name].hf.space",
    api_key="[your-api-key]",
    num_generations=2,
)

執行管道

下面,您可以看到完整的管道定義

with Pipeline(name="clean-dataset") as pipeline:

    load_dataset = LoadDataFromDicts(data=dataset, output_mappings={"question": "instruction"})

    evaluate_responses = UltraFeedback(
        aspect="overall-rating",
        llm=InferenceEndpointsLLM(
            model_id="meta-llama/Meta-Llama-3.1-70B-Instruct",
            tokenizer_id="meta-llama/Meta-Llama-3.1-70B-Instruct",
            generation_kwargs={"max_new_tokens": 512, "temperature": 0.7},
        ),
    )

    keep_columns = KeepColumns(
        columns=[
            "instruction",
            "generations",
            "order",
            "ratings",
            "rationales",
            "model_name",
        ]
    )

    to_argilla = PreferenceToArgilla(
        dataset_name="cleaned-dataset",
        dataset_workspace="argilla",
        api_url="https://[your-owner-name]-[your-space-name].hf.space",
        api_key="[your-api-key]",
        num_generations=2,
    )

    load_dataset.connect(evaluate_responses)
    evaluate_responses.connect(keep_columns)
    keep_columns.connect(to_argilla)

現在讓我們執行管道並清理我們的偏好資料集。

distiset = pipeline.run()

讓我們檢查一下!如果您已將資料載入到 Argilla,您可以在 Argilla UI 中開始標註

您可以將資料集推送到 Hub 以與社群共享,並嵌入它以探索資料

distiset.push_to_hub("[your-owner-name]/example-cleaned-preference-dataset")

結論

在本教程中,我們展示了使用 distilabel 構建清理偏好資料集管道的詳細步驟。但是,您可以根據自己的用例自定義此管道,例如清理 SFT 資料集或新增自定義步驟。

我們以一個偏好資料集作為起點,並打亂資料以避免任何偏見。接下來,我們使用一個模型透過無伺服器 Hugging Face 推理 API,遵循 UltraFeedback 標準來評估響應。最後,我們保留了所需的列,並使用 Argilla 進行進一步的整理。

< > 在 GitHub 上更新

© . This site is unofficial and not affiliated with Hugging Face, Inc.