From c2fa3e4db4dec142bd657101342150cccd358f7a Mon Sep 17 00:00:00 2001 From: jiahao su <85146036+xuedinge233@users.noreply.github.com> Date: Tue, 16 Jul 2024 20:46:07 +0800 Subject: [PATCH] add doc for transformers (#35) Add doc for transformers --- index.rst | 7 +- sources/transformers/fine-tune.rst | 250 ++++++++++++++++++ sources/transformers/images/downloadmodel.png | Bin 0 -> 84549 bytes sources/transformers/index.rst | 11 + sources/transformers/inference.rst | 183 +++++++++++++ sources/transformers/install.rst | 90 +++++++ sources/transformers/modeldownload.rst | 126 +++++++++ sources/transformers/quick_start.rst | 131 +++++++++ 8 files changed, 795 insertions(+), 3 deletions(-) create mode 100644 sources/transformers/fine-tune.rst create mode 100644 sources/transformers/images/downloadmodel.png create mode 100644 sources/transformers/index.rst create mode 100644 sources/transformers/inference.rst create mode 100644 sources/transformers/install.rst create mode 100644 sources/transformers/modeldownload.rst create mode 100644 sources/transformers/quick_start.rst diff --git a/index.rst b/index.rst index 4be6682..f3bdd87 100644 --- a/index.rst +++ b/index.rst @@ -20,6 +20,7 @@ sources/pytorch/index.rst sources/llamafactory/index.rst + sources/transformers/index.rst .. warning:: @@ -154,11 +155,11 @@
- 官方链接 + 官方链接 | - 安装指南 + 安装指南 | - 快速上手 + 快速上手
diff --git a/sources/transformers/fine-tune.rst b/sources/transformers/fine-tune.rst new file mode 100644 index 0000000..e520f20 --- /dev/null +++ b/sources/transformers/fine-tune.rst @@ -0,0 +1,250 @@ +微调预训练模型 +================== + +.. note:: + + 阅读本篇前,请确保已按照 :doc:`安装指南 <./install>` 准备好昇腾环境及transformers! + +大模型微调本质是利用特定领域的数据集对已预训练的大模型进行进一步训练的过程。它旨在优化模型在特定任务上的性能,使模型能够更好地适应和完成特定领域的任务。 +本文在使用transformers库选定相关数据集和预训练模型的基础上,通过超参数调优完成对模型的微调。 + +前置准备 +----------------- + +安装必要库 +<<<<<<<<<<<<<<< + +.. code-block:: shell + :linenos: + + pip install transformers datasets evaluate accelerate scikit-learn + +加载数据集 +<<<<<<<<<<<<<<<<<<< + +模型训练需要使用数据集,这里使用 `Yelp Reviews dataset `_ : + +.. code-block:: python + :linenos: + + from datasets import load_dataset + + # load_dataset 会自动下载数据集并将其保存到本地路径中 + dataset = load_dataset("yelp_review_full") + #输出数据集的第100条数据 + dataset["train"][100] + +输出如下: + +.. code-block:: shell + + {'label': 0, 'text': 'My expectations for McDonalds are t rarely high. But for one to still fail so spectacularly...that takes something special!\\n + The cashier took my friends\'s order, then promptly ignored me. I had to force myself in front of a cashier who opened his register to wait on the + person BEHIND me. I waited over five minutes for a gigantic order that included precisely one kid\'s meal. After watching two people who ordered after + me be handed their food, I asked where mine was. The manager started yelling at the cashiers for \\"serving off their orders\\" when they didn\'t have + their food. But neither cashier was anywhere near those controls, and the manager was the one serving food to customers and clearing the boards.\\nThe + manager was rude when giving me my order. She didn\'t make sure that I had everything ON MY RECEIPT, and never even had the decency to apologize that + I felt I was getting poor service.\\nI\'ve eaten at various McDonalds restaurants for over 30 years. I\'ve worked at more than one location. I expect + bad days, bad moods, and the occasional mistake. But I have yet to have a decent experience at this store. It will remain a place I avoid unless someone + in my party needs to avoid illness from low blood sugar. Perhaps I should go back to the racially biased service of Steak n Shake instead!'} + + +预处理数据集 +<<<<<<<<<<<<<<<<< + +预处理数据集需要使用AutoTokenizer,它用来自动获取与模型匹配的分词器,分词器根据规则将文本拆分为标记,并转换为张量作为模型输入, +下面用到了Meta-Llama-3-8B-Instruct模型,下载模型请转至 `模型获取 <./modeldownload.html>`_,以下是一个示例: + +.. code-block:: python + :linenos: + + from transformers import AutoTokenizer + + tokenizer = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct") + #使用分词器处理文本 + encoded_input = tokenizer("Do not meddle in the affairs of wizards, for they are subtle and quick to anger.") + print(encoded_input) + +输出如下: + +.. code-block:: shell + + {'input_ids': [128000, 5519, 539, 1812, 91485, 304, 279, 22747, 315, 89263, 11, 369, 814, 527, 27545, 323, 4062, 311, 19788, 13], + 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]} + +接着使用dataset.map方法对数据集进行预处理: + +.. code-block:: python + :linenos: + + def tokenize_function(examples): + return tokenizer(examples["text"], padding="max_length", truncation=True) + + tokenized_datasets = dataset.map(tokenize_function, batched=True) + +初次进行预处理需要一定时间,内容如下: + +.. code-block:: shell + :linenos: + + Asking to pad to max_length but no maximum length is provided and the model has no predefined maximum length. Default to no padding. + Asking to truncate to max_length but no maximum length is provided and the model has no predefined maximum length. Default to no truncation. + Map: 100%|████████████████████████████████████████████████████████████████████████| 650000/650000 [03:27<00:00, 3139.47 examples/s] + Map: 100%|██████████████████████████████████████████████████████████████████████████| 50000/50000 [00:15<00:00, 3156.92 examples/s] + +训练全部的数据集会耗费更长的时间,通常将其划分为较小的训练集和验证集,以提高训练速度: + +.. code-block:: python + :linenos: + + small_train_dataset = tokenized_datasets["train"].shuffle(seed=42).select(range(1000)) + small_eval_dataset = tokenized_datasets["test"].shuffle(seed=42).select(range(1000)) + + # 下面是加载全训练集和验证集 + # full_train_dataset = tokenized_datasets["train"] + # full_eval_dataset = tokenized_datasets["test"] + +训练 +------------ + +加载模型 +<<<<<<<<< + +使用AutoModelForCausalLM将自动加载模型: + +.. code-block:: python + :linenos: + + from transformers import AutoModelForCausalLM + + model = AutoModelForCausalLM.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct") + +超参数调优 +<<<<<<<<<<<<<<<<<<<<< + +超参数调优用于激活不同训练选项的标志,它定义了关于模型的更高层次的概念,例如模型复杂程度或学习能力,下边使用TrainingArguments类来加载: + +.. code-block:: python + :linenos: + + from transformers import TrainingArguments + + training_args = TrainingArguments(output_dir="test_trainer", eval_strategy="epoch") + +模型评估 +<<<<<<<<<<<<< + +模型评估用于衡量模型在给定数据集上的表现,包括准确率,完全匹配速率,平均并交集点等,下面是使用方式: + +.. code-block:: python + :linenos: + + import + import sklearn + import evaluate + + metric = evaluate.load("accuracy") + + #计算预测的准确性,并将预测传递给compute + def compute_metrics(eval_pred): + logits, labels = eval_pred + predictions = np.argmax(logits, axis=-1) + return metric.compute(predictions=predictions, references=labels) + + +Trainer +<<<<<<< + +使用已加载的模型、训练参数、训练和测试数据集以及评估函数创建一个Trainer对象,并调用trainer.train()来微调模型: + +.. code-block:: python + :linenos: + + from transformers import Trainer + + trainer = Trainer( + model=model, + args=training_args, + train_dataset=small_train_dataset, + eval_dataset=small_eval_dataset, + compute_metrics=compute_metrics, + ) + + trainer.train() + + +预训练全流程 +------------------- + +.. code-block:: python + :linenos: + + import torch + import torch_npu + import numpy as np + import sklearn + import evaluate + from transformers import AutoModelForCausalLM, AutoTokenizer, Trainer, TrainingArguments + from datasets import load_dataset + + model_id = "meta-llama/Meta-Llama-3-8B-Instruct" + device = "npu:0" if torch.npu.is_available() else "cpu" + + # 加载分词器和模型 + tokenizer = AutoTokenizer.from_pretrained(model_id) + model = AutoModelForCausalLM.from_pretrained( + model_id, + torch_dtype=torch.bfloat16, + device_map="auto", + ).to(device) + + dataset = load_dataset("yelp_review_full") + + #分词函数 + def tokenize_function(examples): + return tokenizer(examples["text"], padding="max_length", truncation=True) + + tokenized_datasets = dataset.map(tokenize_function, batched=True) + + small_train_dataset = tokenized_datasets["train"].shuffle(seed=42).select(range(1000)) + small_eval_dataset = tokenized_datasets["test"].shuffle(seed=42).select(range(1000)) + + # 加载评估指标 + metric = evaluate.load("accuracy") + + # 定义评估指标的计算函数 + def compute_metrics(eval_pred): + logits, labels = eval_pred + predictions = np.argmax(logits, axis=-1) + return metric.compute(predictions=predictions, references=labels) + + training_args = TrainingArguments(output_dir="test_trainer", eval_strategy="epoch") + + trainer = Trainer( + model=model, + args=training_args, + train_dataset=small_train_dataset, + eval_dataset=small_eval_dataset, + compute_metrics=compute_metrics, + ) + + trainer.train() + + +训练完成后得到以下结果: + +.. code-block:: shell + :linenos: + + |█████████████████████████████████| [375/375 06:21, Epoch 3/3] + + ===== ============= =============== ====== + Epoch Training Loss Validation Loss Accuracy + ===== ============= =============== ====== + 1 No log 1.155628 0.499000 + 2 No log 0.994618 0.574000 + 3 No log 1.026123 0.590000 + ===== ============= =============== ====== + + TrainOutput(global_step=375, training_loss=1.0557311197916666, metrics={'train_runtime': 384.55, 'train_samples_per_second': 7.801, + 'train_steps_per_second': 0.975, 'total_flos': 789354427392000.0, 'train_loss': 1.0557311197916666, 'epoch': 3.0}) diff --git a/sources/transformers/images/downloadmodel.png b/sources/transformers/images/downloadmodel.png new file mode 100644 index 0000000000000000000000000000000000000000..e2e119f3fcb1fafe94faa4d0cc9f66399870c577 GIT binary patch literal 84549 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 K$r^Fvp#KMx=`48w literal 0 HcmV?d00001 diff --git a/sources/transformers/index.rst b/sources/transformers/index.rst new file mode 100644 index 0000000..534ccd4 --- /dev/null +++ b/sources/transformers/index.rst @@ -0,0 +1,11 @@ +Transformers +================== + +.. toctree:: + :maxdepth: 2 + + install.rst + quick_start.rst + modeldownload.rst + fine-tune.rst + inference.rst \ No newline at end of file diff --git a/sources/transformers/inference.rst b/sources/transformers/inference.rst new file mode 100644 index 0000000..e66aca1 --- /dev/null +++ b/sources/transformers/inference.rst @@ -0,0 +1,183 @@ +推理 +================== + +.. note:: + + 阅读本篇前,请确保已按照 :doc:`安装指南 <./install>` 准备好昇腾环境及transformers! + +在推理阶段,训练好的模型被用于对图像、语音或文本进行分类,也可以用于语言生成、翻译等。 + +本文的模型推理以transformers的pipeline为中心进行介绍,pipelines可以自动加载模型和能够进行任务推理的预处理类,使任何模型进行任何语言、计算机视觉、语音以及多模态任务的推理变得非常简单。 + +pipeline 抽象类 +------------------ + +pipeline 抽象类是所有其他 pipeline 的封装,可以像其他任何 pipeline 一样实例化。 + +pipeline 参数由 task、tokenizer、model、optional 组成: + +- task 将确定返回哪一个 pipeline,比如 text-classification 将会返回 TextClassificationPipeline,image-to-image 将会返回 ImageToImagePipeline。 + +- tokenizer分词器是用来将输入进行编码,str或者PreTrainedTokenizer,如果未提供将使用model参数,如果model也未提供或者非str,将使用config参数,如果config参数也未提供或者非str,将提供task的默认tokenizer。 + +- model是模型,str或者PreTrainedModel,一般为有.bin模型文件的目录。 + +- optional其他参数包括,config、feature_extractor、device、device_map等。 + + +pipeline 使用 +---------------------- + +pipeline适用于音频、计算机视觉、自然语言处理和多模态任务,下面将介绍它在各场景的使用方式。 + +音频 +<<<<<<<<<<<<< + +音频识别 +>>>>>>>>>>>> + +用于提取某些音频中包含的文本,如下创建pipeline,并输入音频文件: + +.. code-block:: python + :linenos: + + from transformers import pipeline + + transcriber = pipeline(task="automatic-speech-recognition") + transcriber("https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/mlk.flac") + + #以下为输出示例 + {'text': 'I HAVE A DREAM BUT ONE DAY THIS NATION WILL RISE UP LIVE UP THE TRUE MEANING OF ITS TREES'} + +文本转音频 +>>>>>>>>>>> + +根据输入文本和可选的其他条件输入生成音频文件: + +.. code-block:: python + :linenos: + + from transformers import pipeline + + pipe = pipeline(model="suno/bark-small") + output = pipe("Hey it's HuggingFace on the phone!") + + audio = output["audio"] + sampling_rate = output["sampling_rate"] + +计算机视觉 +<<<<<<<<<<<<<<<<< + +图像分类 +>>>>>>>>>>>>>> + +图像分类可以识别图片特征,并给出分类标签和置信度得分: + +.. code-block:: python + :linenos: + + from transformers import pipeline + + classifier = pipeline(model="microsoft/beit-base-patch16-224-pt22k-ft22k") + classifier("https://huggingface.co/datasets/Narsil/image_dummy/raw/main/parrots.png") + + #以下为输出示例 + [{'score': 0.442, 'label': 'macaw'}, {'score': 0.088, 'label': 'popinjay'}, {'score': 0.075, 'label': 'parrot'}, {'score': 0.073, 'label': 'parodist, lampooner'}, {'score': 0.046, 'label': 'poll, poll_parrot'}] + +图像转图像 +>>>>>>>>>>>>> + +它可以将图像根据信息生成新图像,以下示例通过图像超分辨率模型将低分辨率图像放大并增强其细节,使其看起来更清晰: + +.. code-block:: python + :linenos: + + from PIL import Image + import requests + from transformers import pipeline + + upscaler = pipeline("image-to-image", model="caidas/swin2SR-classical-sr-x2-64") + img = Image.open(requests.get("http://images.cocodataset.org/val2017/000000039769.jpg", stream=True).raw) + img = img.resize((64, 64)) + upscaled_img = upscaler(img) #超分辨率处理 + print(img.size) + print(upscaled_img.size) + + #以下为输出示例 + (64, 64) # 输出原图像的尺寸 + (144, 144) # 输出处理后图像的尺寸 + +自然语言处理 +<<<<<<<<<<<<<<<<< + +文本分类 +>>>>>>>>>>>>>>>>>>> + +根据标签对文本进行分类: + +.. code-block:: shell + :linenos: + + from transformers import pipeline + classifier = pipeline(model="meta-llama/Meta-Llama-3-8B-Instruct") + classifier( + "I have a problem with my iphone that needs to be resolved asap!!", + candidate_labels=["urgent", "not urgent", "phone", "tablet", "computer"], + ) + #以下为输出示例 + #{'sequence': 'I have a problem with my iphone that needs to be resolved asap!!', 'labels': ['urgent', 'phone', 'computer', 'not urgent', 'tablet'], 'scores': [0.504, 0.479, 0.013, 0.003, 0.002]} + +文本生成 +>>>>>>>>>>>>>>>>> + +根据文本生成对话响应: + +.. code-block:: shell + :linenos: + + from transformers import pipeline + + generator = pipeline(model="HuggingFaceH4/zephyr-7b-beta") + # Zephyr-beta is a conversational model, so let's pass it a chat instead of a single string + generator([{"role": "user", "content": "What is the capital of France? Answer in one word."}], do_sample=False, max_new_tokens=2) + + #以下为输出示例 + [{'generated_text': [{'role': 'user', 'content': 'What is the capital of France? Answer in one word.'}, {'role': 'assistant', 'content': 'Paris'}]}] + +多模态 +<<<<<<<<<<<<<< + +视觉问答 +>>>>>>>>>>>>> + +VQA使用图像和关于该图像的问题进行提问,图像可以是URL或图像的本地路径: + +.. code-block:: shell + :linenos: + + from transformers import pipeline + vqa = pipeline(model="meta-llama/Meta-Llama-3-8B-Instruct") + output = vqa( + image="https://huggingface.co/spaces/impira/docquery/resolve/2359223c1837a7587402bda0f2643382a6eefeab/invoice.png", + question="What is the invoice number?", + ) + output[0]["score"] = round(output[0]["score"], 3) + + #以下为输出示例 + #[{'score': 0.425, 'answer': 'us-001', 'start': 16, 'end': 16}] + +图像转文本 +>>>>>>>>>>>>>>>>>>>> + +用于预测给定图像的主题: + +.. code-block:: shell + :linenos: + + from transformers import pipeline + + captioner = pipeline(model="ydshieh/vit-gpt2-coco-en") + captioner("https://huggingface.co/datasets/Narsil/image_dummy/raw/main/parrots.png") + + #以下为输出示例 + [{'generated_text': 'two birds are standing next to each other '}] diff --git a/sources/transformers/install.rst b/sources/transformers/install.rst new file mode 100644 index 0000000..023c183 --- /dev/null +++ b/sources/transformers/install.rst @@ -0,0 +1,90 @@ +安装指南 +=========== + +本文将介绍如何在昇腾环境下使用transfomers,帮助开发者完成transformers的安装。 + +.. note:: + + 请确保环境安装了对应的固件和驱动,详情请参考 `快速安装昇腾环境 <../ascend/quick_install.html>`_。 + +创建虚拟环境 +-------------------- + +首先需要安装并激活python环境: + +.. code-block:: shell + + conda create -n your_env_name python=3.10 + conda activate your_env_name + +同时安装依赖库: + +.. code-block:: shell + + # install torch + pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple torch==2.2.0 + + # install torch-npu + pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple torch-npu==2.2.0 + +安装transformers +---------------------- + +直接使用pip命令进行安装: + +.. code-block:: shell + + pip install -i https://pypi.tuna.tsinghua.edu.cn/simple transformers + +验证安装 +-------------------- + +.. code-block:: python + + from transformers import AutoModelForSequenceClassification, AutoTokenizer, pipeline + import torch + import torch_npu + + # 检查 NPU 是否可用 + if torch.npu.is_available(): + device = torch.device("npu:0") + print("NPU is available. Using NPU.") + else: + device = torch.device("cpu") + print("NPU is not available. Using CPU.") + + model_id = "bert-base-uncased" + tokenizer = AutoTokenizer.from_pretrained(model_id) + model = AutoModelForSequenceClassification.from_pretrained(model_id) + + model.to(device) + + nlp_pipeline = pipeline( + "sentiment-analysis", + model=model, + tokenizer=tokenizer, + device=0 if torch.npu.is_available() else -1 + ) + + #分析句子情感并输出 + result = nlp_pipeline("This is a test sentence.") + print(result) + + +如果成功运行并输出下面内容,则安装成功: + +.. code-block:: shell + + NPU is available. Using NPU. + Some weights of BertForSequenceClassification were not initialized from the model checkpoint at bert-base-uncased and are newly initialized: ['classifier.bias', 'classifier.weight'] + You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference. + [{'label': 'POSITIVE', 'score': 0.9998704791069031}] + +卸载transformers +--------------------- + +.. code-block:: shell + + pip uninstall transformers + + diff --git a/sources/transformers/modeldownload.rst b/sources/transformers/modeldownload.rst new file mode 100644 index 0000000..a5c4bb3 --- /dev/null +++ b/sources/transformers/modeldownload.rst @@ -0,0 +1,126 @@ +模型获取 +============== + +本文以Meta-Llama-3-8B-Instruct模型为例,介绍如何进行模型的获取, +该模型获取目前主要有三种方式,Meta官方_,HuggingFace_,hf-mirror_, 下面将详细说明这三种获取模型的方法。 + +Meta官方 +----------------- + +下载模型前需要获取licence,前往 `Meta官网 `_,提供信息获取到许可证,拿到已签名的URL。 + +- 链接类似于下面: + +.. code-block:: shell + :linenos: + + https://download6.llamameta.net/*?Policy=eyJTdGF0ZW1lbnQiOlt7InVuaXF1ZV9oYXNoIjoibGJuYXc0bzdrY2pqNnoxeXZ1N3hmcmNvIiwiUmVzb3VyY2UiOiJodHRwczp + cL1wvZG93bmxvYWQ2LmxsYW1hbWV0YS5uZXRcLyoiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE3MTY0MzYyMTF9fX1dfQ__&Signature=KTyc + LZkPxqMYY0XqW047tNN9IWX%7EOxlQbqCsDqmcX0vE8oia3Qej-x6aGFQSJhkHRULu8Efso5Qde8KRiptK5rGh9oLrtMeAS3SID%7EOyk38o9NNLKxWokA7yQxwvUVRqibVMJyhkE8XE + K2HDNftKT9KLaDG8HHFQmGWuhdTJSvCezJIRKWPtzRf0dohepOiOHOcQW%7Ermo7m6iI595PuoX7o3bVYpFYQf1Syrp05XCr9t2-Rzf8xaIYF5-2vFqELFyFyJys%7E5lA4178elcJcU + ImSSokn1IJBARAZ0iLaWDFsuTbvDJmz9j-ccHFJzgDPCMLQjHpK6QfCk4TWGmdyXMg__&Key-Pair-Id=K15QRJLYKIFSLZ&Download-Request-ID=1502880093958574 + +- 之后获取源码,使用以下命令下载并进入到工作目录: + +.. code-block:: shell + :linenos: + + git clone https://github.com/meta-llama/llama3.git + cd llama3 + +- 运行脚本: + +.. code-block:: python + :linenos: + + ./download.sh + +运行时输入上边获取到的URL,即可进行模型的下载。 + + +HuggingFace +-------------------- +HuggingFace同样需要获得licence,访问仓库 `meta-llama/Meta-Llama-3-8B-Instruct `_ ,接受许可后等待请求获得批准即可。 + +得到权限后,点击"文件和版本"标签,下载原始文件夹的内容或通过以下命令行下载: + +- 安装huggingface-hub: + +.. code-block:: shell + + pip install huggingface-hub + +- 下载文件: + +.. code-block:: shell + + huggingface-cli download meta-llama/Meta-Llama-3-8B-Instruct --include “original/*” --local-dir meta-llama/Meta-Llama-3-8B-Instruct + +以上两种方法国内用户可能无法完成,下面推荐 **国内用户** 的获取模型的方式。 + +hf-mirror +------------------- + +hf-mirror是更适合国内用户获取模型的方式,它是HuggingFace平台的镜像网站, 提供了一个备用的域名来访问HuggingFace的资源和功能, +以 `Qwen2-7B-Instruct `_ 为例(Meta-Llama-3-8B-Instruct同样需要获取license,不方便国内用户, 这里用Qwen2代替说明), 共有三种方法,下面依次进行介绍。 + +直接下载 +<<<<<<<<<<<<<<< + +点击模型的下的 **↓** 图标下载文件,如下: + +.. figure:: ./images/image.png + :align: center + +修改镜像源 +<<<<<<<<<<<<<<<<<< + +- 修改环境变量HF_ENDPOINT,该变量会替换huggingface.co域名: + +.. code-block:: shell + :linenos: + + # 临时生效 + export HF_ENDPOINT=https://hf-mirror.com + # 永久生效 + echo export HF_ENDPOINT=https://hf-mirror.com >> ~/.bashrc + + +- 安装huggingface-hub: + +.. code-block:: shell + + pip install huggingface-hub + + +- 下载文件: + +.. code-block:: python + :linenos: + + # huggingface_hub下载单个文件 + from huggingface_hub import hf_hub_download + hf_hub_download(repo_id="Qwen/Qwen2-7B-Instruct", filename="config.json", cache_dir="./your/path/Qwen") + + # huggingface_hub下载整个项目 + from huggingface_hub import snapshot_download + snapshot_download(repo_id="Qwen/Qwen2-7B-Instruct", cache_dir="./your/path/Qwen") + +git lfs +<<<<<<<<<<<<<<<<<<< + +使用以下命令下载模型: + +.. code-block:: shell + :linenos: + + # Make sure you have git-lfs installed (https://git-lfs.com) + git lfs install + + git clone https://hf-mirror.com/Qwen/Qwen2-7B-Instruct + + # If you want to clone without large files - just their pointers + # GIT_LFS_SKIP_SMUDGE=1 git clone https://hf-mirror.com/Qwen/Qwen2-7B-Instruct + + +使用以上任意一种方式即可完成模型的获取,将模型保存在本地路径后可以进行 `微调预训练模型 <./fine-tune.html>`_ 和 `推理 <./inference.html>`_ 等操作。 \ No newline at end of file diff --git a/sources/transformers/quick_start.rst b/sources/transformers/quick_start.rst new file mode 100644 index 0000000..a1702ff --- /dev/null +++ b/sources/transformers/quick_start.rst @@ -0,0 +1,131 @@ +快速开始 +============ + +.. note:: + + 阅读本篇前,请确保已按照 :doc:`安装指南 <./install>` 准备好昇腾环境及transformers! + + +本文以Meta-Llama-3-8B-Instruct模型为例,介绍如何通过transformers使用模型进行推理, +针对模型推理transformers提供了 AutoModelForCausalLM_,pipeline_ 两种方式,下面将说明这两种接口的使用方式。 + +.. note:: + +以下模型用到了Meta-Llama-3-8B-Instruct, 具体可以参考 `模型获取 <./modeldownload.html>`_。 + +AutoModelForCausalLM +----------------------------------------------- + +.. code-block:: python + :linenos: + + import torch + import torch_npu + from transformers import AutoModelForCausalLM, AutoTokenizer + + model_id = "meta-llama/Meta-Llama-3-8B-Instruct" + device = "npu:0" if torch.npu.is_available() else "cpu" + + tokenizer = AutoTokenizer.from_pretrained(model_id) + model = AutoModelForCausalLM.from_pretrained( + model_id, + torch_dtype=torch.bfloat16, + device_map="auto", + ).to(device) + + +pipeline +------------------------- + +.. code-block:: python + :linenos: + + import transformers + import torch + import torch_npu + + model_id = "meta-llama/Meta-Llama-3-8B-Instruct" + device = "npu:0" if torch.npu.is_available() else "cpu" + + pipeline = transformers.pipeline( + "text-generation", + model=model_id, + model_kwargs={"torch_dtype": torch.bfloat16}, + device=device, + ) + + +全流程 +---------- + +.. code-block:: python + :linenos: + + from transformers import AutoModelForCausalLM, AutoTokenizer + import torch + import torch_npu + + #如果提前下载好模型将meta-llama/Meta-Llama-3-8B-Instruct更换为本地地址 + model_id = "meta-llama/Meta-Llama-3-8B-Instruct" + device = "npu:0" if torch.npu.is_available() else "cpu" # 指定使用的设备为 NPU 0 + + # 加载预训练的分词器 + tokenizer = AutoTokenizer.from_pretrained(model_id) + + # 加载预训练的语言模型, 并指定数据类型为bfloat16, 自动选择设备映射 + model = AutoModelForCausalLM.from_pretrained( + model_id, + torch_dtype=torch.bfloat16, + device_map="auto", + ).to(device) # 将模型移动到指定的设备 + + # 定义消息列表,包含系统消息和用户消息 + messages = [ + {"role": "system", "content": "You are a housekeeper chatbot who always responds in polite expression!"}, + {"role": "user", "content": "Who are you? what should you do?"}, + ] + + # 使用分词器将消息列表应用到聊天模板中,并转换为张量 + input_ids = tokenizer.apply_chat_template( + messages, + add_generation_prompt=True, + return_tensors="pt" # 返回 PyTorch 张量 + ).to(model.device) + + + # 定义终止标记,包括模型的结束标记 ID 和一个空标记 ID + terminators = [ + tokenizer.eos_token_id, + tokenizer.convert_tokens_to_ids("<|eot_id|>") + ] + + # 生成响应 + outputs = model.generate( + input_ids, + max_new_tokens=256, # 设置生成的最大token + eos_token_id=terminators, + do_sample=True, + temperature=0.6, # 设置采样温度,影响生成的多样性 + top_p=0.9, + ) + + # 获取生成的响应,排除输入的部分 + response = outputs[0][input_ids.shape[-1]:] + print(tokenizer.decode(response, skip_special_tokens=True)) + +输出示例: + +.. code-block:: shell + :linenos: + + Good day to you! My name is Housekeeper Helen, and I'm delighted to introduce myself as a friendly and efficient chatbot designed to assist with household tasks and provide helpful information. + As a housekeeper, my primary role is to ensure your home is tidy, organized, and comfortable. I'd be happy to help with: + + * Cleaning and organization tips + * Household chore schedules + * Laundry and ironing guidance + * Home maintenance advice + * And any other domestic-related queries you may have! + + Please feel free to ask me any questions or request my assistance with a specific task. I'm here to help make your life easier and your home sparkle! +