使用 DeepSeek R1 模型通过 Distilabel pipeline 来生成文本响应
使用 DeepSeek R1 模型通过 Distilabel pipeline 来生成文本响应
flyfish
文末有完整示例代码
概述
Distilabel 是一个专为工程师打造的用于合成数据和获取 AI 反馈的框架,它能基于经过验证的研究论文构建快速、可靠且可扩展的管道。
使用 Distilabel 的原因
- 广泛的应用场景:可用于为各类项目生成合成数据和获取 AI 反馈,涵盖传统预测性自然语言处理(如分类、提取等)以及生成式和大语言模型场景(如指令遵循、对话生成、评判等)。
- 可扩展性:其编程式方法允许用户构建用于数据生成和 AI 反馈的可扩展管道。
- 加速 AI 开发:目标是通过基于经过验证的研究方法快速生成高质量、多样化的数据集,并利用 AI 反馈进行生成和评判,从而加速 AI 开发。
- 提升 AI 输出质量:计算成本高昂且输出质量至关重要,Distilabel 帮助用户关注数据质量,从根本上解决这两个问题,协助合成和评判数据,让用户有更多时间实现并维持数据的高质量标准。
- 掌控数据和模型:微调自己的大语言模型时,数据所有权的获取并非易事,但 Distilabel 能帮助用户开启这一过程,它通过统一的 API 集成来自任何大语言模型提供商的 AI 反馈。
- 提高效率:结合最新研究论文合成和评判数据,同时确保灵活性、可扩展性和容错性,让用户专注于改进数据和训练模型。
安装说明
使用 pip install distilabel --upgrade
进行安装,要求 Python 版本为 3.9 及以上。
大语言模型集成
- anthropic:通过 AnthropicLLM 集成使用 Anthropic API 中的模型。
- cohere:通过 CohereLLM 集成使用 Cohere 中的模型。
- argilla:将生成的数据集导出到 Argilla。
- groq:通过 GroqLLM 集成使用 Groq Python 客户端调用 Groq 中的模型。
- hf - inference - endpoints:通过 InferenceEndpointsLLM 集成使用 Hugging Face 推理端点。
- hf - transformers:通过 TransformersLLM 集成使用 transformers 包中的模型。
- litellm:通过 LiteLLM 集成使用 LiteLLM 以 OpenAI 格式调用任何大语言模型。
- llama - cpp:通过 LlamaCppLLM 集成使用 llama - cpp - python 对 llama.cpp 的 Python 绑定。
- mistralai:通过 MistralAILLM 集成使用 Mistral AI API 中的模型。
- ollama:通过 OllamaLLM 集成使用 Ollama 及其可用模型。
- openai:通过 OpenAILLM 集成使用 OpenAI API 模型,或使用基于 OpenAI 并依赖其客户端的其他集成,如 AnyscaleLLM、AzureOpenAILLM 和 TogetherLLM。
- vertexai:通过 VertexAILLM 集成使用 Google Vertex AI 专有模型。
- vllm:通过 vLLM 集成使用 vllm 服务引擎。
- sentence - transformers:使用 sentence - transformers 生成句子嵌入。
- mlx:通过 MlxLLM 集成使用 MLX 模型。
结构化生成
- outlines:使用 outlines 实现大语言模型的结构化生成。
- instructor:使用 Instructor 实现大语言模型的结构化生成。
数据处理
- ray:使用 Ray 对管道进行扩展和分布式处理。
- faiss - cpu 和 faiss - gpu:使用 faiss 生成句子嵌入。
- text - clustering:使用 UMAP 和 Scikit - learn 进行文本聚类。
- minhash:使用 datasketch 和 nltk 通过 minhash 进行重复检测。
示例代码
若要运行以下示例,需使用 hf - inference - endpoints
额外功能包安装 Distilabel:
pip install "distilabel[hf - inference - endpoints]" --upgrade
如何使用 Distilabel 结合 Hugging Face 推理端点进行文本生成,并将生成的数据集推送到 Hugging Face Hub:
from datasets import load_dataset
from distilabel.models import InferenceEndpointsLLM
from distilabel.pipeline import Pipeline
from distilabel.steps.tasks import TextGeneration
with Pipeline() as pipeline:
TextGeneration(
llm=InferenceEndpointsLLM(
model_id="meta - llama/Meta - Llama - 3.1 - 8B - Instruct",
generation_kwargs={"temperature": 0.7, "max_new_tokens": 512},
),
)
if __name__ == "__main__":
dataset = load_dataset("distilabel - internal - testing/instructions", split="test")
distiset = pipeline.run(dataset=dataset)
distiset.push_to_hub(repo_id="distilabel - example")
完整例子
使用 DeepSeek R1 模型通过 Distilabel pipeline 来生成文本响应
# 导入 Optional 类型,用于表示参数可以为 None
from typing import Optional
# 从 distilabel 库中导入 OpenAILLM 类,用于与 OpenAI 或类似服务进行交互以生成文本
from distilabel.llms import OpenAILLM
# 从 distilabel 库中导入 Pipeline 类,用于构建和管理数据处理管道
from distilabel.pipeline import Pipeline
# 从 distilabel 库中导入 TextGeneration 类,用于定义文本生成任务
from distilabel.steps.tasks import TextGeneration
# 定义一个函数,用于构建 distilabel 数据处理管道
def build_distilabel_pipeline(
# 模型名称,用于指定使用的语言模型
model: str,
# 基础 URL,用于指定 API 服务的地址,默认为本地的 8000 端口
base_url: str = "http://localhost:8000/v1",
# 提示信息所在的列名,可选参数,默认为 None
prompt_column: Optional[str] = None,
# 生成文本时的温度参数,控制生成文本的随机性,可选参数,默认为 None
temperature: Optional[float] = None,
# 生成文本时的 top-p 参数,控制生成文本的词汇选择范围,可选参数,默认为 None
top_p: Optional[float] = None,
# 生成文本时允许的最大新生成的标记数量,默认为 8192
max_new_tokens: int = 8192,
# 每个输入生成的文本数量,默认为 1
num_generations: int = 1,
) -> Pipeline:
# 初始化生成参数的字典,包含最大新生成标记数量
generation_kwargs = {"max_new_tokens": max_new_tokens}
# 如果提供了温度参数,则将其添加到生成参数的字典中
if temperature is not None:
generation_kwargs["temperature"] = temperature
# 如果提供了 top-p 参数,则将其添加到生成参数的字典中
if top_p is not None:
generation_kwargs["top_p"] = top_p
# 使用 Pipeline 类创建一个新的管道,并使用 ray 进行并行处理
with Pipeline().ray() as pipeline:
# 定义一个文本生成任务
TextGeneration(
# 指定使用的语言模型,这里使用 OpenAILLM
llm=OpenAILLM(
# 指定 API 服务的基础 URL
base_url=base_url,
# 指定 API 密钥,这里使用示例值 "something"
api_key="something",
# 指定使用的模型名称
model=model,
# 设置超时时间为 10 分钟,因为思考可能需要一些时间
timeout=10 * 60,
# 传递生成参数的字典
generation_kwargs=generation_kwargs,
),
# 输入映射,将提示信息列名映射到 "instruction",如果没有提供提示信息列名,则为空字典
input_mappings={"instruction": prompt_column} if prompt_column is not None else {},
# 输入批次大小,设置为 64,在 4 个节点上,批次大小约 60 以上可能会因 KV 缓存耗尽而导致抢占
input_batch_size=64,
# 每个输入生成的文本数量
num_generations=num_generations,
)
# 返回构建好的管道
return pipeline
# 当脚本作为主程序运行时执行以下代码
if __name__ == "__main__":
# 导入 argparse 库,用于解析命令行参数
import argparse
# 从 datasets 库中导入 load_dataset 函数,用于加载 Hugging Face 数据集
from datasets import load_dataset
# 创建一个 ArgumentParser 对象,用于解析命令行参数
parser = argparse.ArgumentParser(description="Run distilabel pipeline for generating responses with DeepSeek R1")
# 添加一个必需的命令行参数,用于指定要加载的 Hugging Face 数据集名称
parser.add_argument(
"--hf-dataset",
type=str,
required=True,
help="HuggingFace dataset to load",
)
# 添加一个可选的命令行参数,用于指定数据集的配置
parser.add_argument(
"--hf-dataset-config",
type=str,
required=False,
help="Dataset config to use",
)
# 添加一个可选的命令行参数,用于指定数据集的分割,默认为 "train"
parser.add_argument(
"--hf-dataset-split",
type=str,
default="train",
help="Dataset split to use",
)
# 添加一个可选的命令行参数,用于指定提示信息所在的列名,默认为 "prompt"
parser.add_argument("--prompt-column", type=str, default="prompt")
# 添加一个必需的命令行参数,用于指定生成文本时使用的模型名称
parser.add_argument(
"--model",
type=str,
required=True,
help="Model name to use for generation",
)
# 添加一个可选的命令行参数,用于指定 vLLM 服务器的 URL,默认为本地的 8000 端口
parser.add_argument(
"--vllm-server-url",
type=str,
default="http://localhost:8000/v1",
help="URL of the vLLM server",
)
# 添加一个可选的命令行参数,用于指定生成文本时的温度参数
parser.add_argument(
"--temperature",
type=float,
help="Temperature for generation",
)
# 添加一个可选的命令行参数,用于指定生成文本时的 top-p 参数
parser.add_argument(
"--top-p",
type=float,
help="Top-p value for generation",
)
# 添加一个可选的命令行参数,用于指定生成文本时允许的最大新生成的标记数量,默认为 8192
parser.add_argument(
"--max-new-tokens",
type=int,
default=8192,
help="Maximum number of new tokens to generate",
)
# 添加一个可选的命令行参数,用于指定每个输入生成的文本数量,默认为 1
parser.add_argument(
"--num-generations",
type=int,
default=1,
help="Number of generations per problem",
)
# 添加一个可选的命令行参数,用于指定将结果推送到 Hugging Face 仓库的名称
parser.add_argument(
"--hf-output-dataset",
type=str,
required=False,
help="HuggingFace repo to push results to",
)
# 添加一个可选的命令行参数,用于指定是否将输出数据集设置为私有
parser.add_argument(
"--private",
action="store_true",
help="Whether to make the output dataset private when pushing to HF Hub",
)
# 解析命令行参数
args = parser.parse_args()
# 打印正在使用的命令行参数
print("\nRunning with arguments:")
for arg, value in vars(args).items():
print(f" {arg}: {value}")
print()
# 打印正在加载数据集的信息
print(f"Loading '{args.hf_dataset}' (config: {args.hf_dataset_config}, split: {args.hf_dataset_split}) dataset...")
# 加载指定的 Hugging Face 数据集
dataset = load_dataset(args.hf_dataset, split=args.hf_dataset_split)
# 打印数据集加载完成的信息
print("Dataset loaded!")
# 调用 build_distilabel_pipeline 函数构建数据处理管道
pipeline = build_distilabel_pipeline(
model=args.model,
base_url=args.vllm_server_url,
prompt_column=args.prompt_column,
temperature=args.temperature,
top_p=args.top_p,
max_new_tokens=args.max_new_tokens,
num_generations=args.num_generations,
)
# 打印正在运行生成管道的信息
print("Running generation pipeline...")
# 运行数据处理管道,对加载的数据集进行文本生成
distiset = pipeline.run(dataset=dataset, use_cache=False)
# 打印生成管道运行完成的信息
print("Generation pipeline finished!")
# 如果指定了输出数据集的 Hugging Face 仓库名称
if args.hf_output_dataset:
# 打印正在将结果数据集推送到指定仓库的信息
print(f"Pushing resulting dataset to '{args.hf_output_dataset}'...")
# 将生成的结果数据集推送到指定的 Hugging Face 仓库
distiset.push_to_hub(args.hf_output_dataset, private=args.private)
# 打印数据集推送完成的信息
print("Dataset pushed!")
代码作用
构建一个使用 distilabel
库的文本生成管道,利用指定的语言模型(如 OpenAILLM
)对 Hugging Face 上的数据集进行文本生成。具体步骤如下:
- 定义管道构建函数:
build_distilabel_pipeline
函数用于构建一个基于distilabel
的数据处理管道,配置了语言模型的参数(如模型名称、基础 URL、生成参数等),并使用ray
进行并行处理。 - 解析命令行参数:使用
argparse
库解析用户输入的命令行参数,包括数据集名称、模型名称、生成参数等。 - 加载数据集:使用
datasets
库的load_dataset
函数加载指定的 Hugging Face 数据集。 - 运行生成管道:调用
build_distilabel_pipeline
函数构建管道,并对加载的数据集进行文本生成。