开源 AI 食谱文档
使用法学 LLM 清理现有偏好数据集
并获得增强的文档体验
开始使用
使用法学 LLM 清理现有偏好数据集
作者:David Berenstein 和 Sara Han Díaz
- 库:argilla,hf-inference-endpoints
- 组件:LoadDataFromDicts, UltraFeedback, KeepColumns, PreferenceToArgilla, InferenceEndpointsLLM, GlobalStep
在本教程中,我们将使用 distilabel 通过提供关于数据质量的 AI 反馈,使用法学 LLM 清理数据集。distilabel 是一个合成数据和 AI 反馈框架,适用于需要基于经过验证的研究论文构建快速、可靠且可扩展的管道的工程师。查看此处的文档。
为了评估响应,我们将使用与 distilabel 集成的无服务器 HF 推理 API。这是免费的,但有速率限制,允许您通过简单的 HTTP 请求,在 Hugging Face 共享基础设施上快速推理,测试和评估超过 150,000 个公共模型或您自己的私有模型。如果您需要更多计算能力,可以使用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 推理终端。登录即可在本笔记本中直接使用它。
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
的 LLM 的UltraFeedback
任务 - 输入列:
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 上更新