Преобразование опыта клиентов: как точно настроенная модель Llama 2 может расширить возможности продукта

Недавние достижения в области искусственного интеллекта с особым акцентом на генеративный ИИ не только вызвали интерес широкой общественности, но и проиллюстрировали то, что эксперты в этой области понимали в течение значительного времени. Эти достижения обещают позволить людям совершать выдающиеся подвиги, открывая новую эру экономических, технологических и социальных возможностей. Они предоставляют новые возможности для личного самовыражения, укрепляя связи между отдельными людьми, творцами и предприятиями.

Большие языковые модели (LLM) предварительно обучаются на разнообразной коллекции текстовых данных. Например, при рассмотрении Ламы 2 мы обладаем ограниченными знаниями о конкретном составе ее обучающего набора данных, за исключением того факта, что он включает обширные 2 триллиона токенов с двойной длиной контекста, чем Лама 1. Как упоминалось здесь, модель была обучена на более чем 1 миллионе человеческих аннотаций. Чтобы представить это в перспективе, более ранняя модель BERT от 2018 года была обучена на наборе данных, состоящем из BookCorpus (800 миллионов слов) и английской Википедии (2500 миллионов слов). Стоит отметить, что этот процесс предварительного обучения является не только ресурсоемким, но и трудоемким, часто сопровождающимся множеством проблем, связанных с аппаратным обеспечением.

Это вторая и последняя часть серии LLM. Первая часть включала создание парсера для получения данных для точной настройки модели здесь, а я задокументировал процесс здесь. Набор данных содержит список из 1750 пар Вопрос-ответ. Эти пары представляют общие темы для продуктов и услуг Safaricom. Safaricom — крупнейшая телекоммуникационная компания Кении с 43,8 миллионами абонентов. Он также управляет одной из лучших в мире платформ мобильных денег под названием MPESA.

В этой части серии я подробно расскажу, как модель Llama 2 с открытым исходным кодом была обучена с помощью пар вопросов и ответов Safaricom, связанных с продуктами и услугами. Такие модели, как Llama 2, обладают способностью прогнозировать следующий токен в последовательности. Однако сама по себе эта предсказательная способность не делает их высокоэффективными виртуальными помощниками, поскольку они по своей сути не реагируют на явные инструкции. Чтобы устранить этот разрыв, применяется метод, известный как настройка инструкций, позволяющий более точно согласовать их ответы с человеческими ожиданиями. Этот процесс тонкой настройки включает в себя две основные методологии:

  1. Обучение с подкреплением на основе обратной связи с человеком (RLHF). Здесь модели учатся посредством взаимодействия с окружающей средой и механизмов обратной связи. Целью обучения является максимизация сигнала вознаграждения, часто с использованием Оптимизации проксимальной политики (PPO). Этот сигнал вознаграждения обычно получается на основе оценок человеком результатов модели, что позволяет модели адаптировать и улучшать свои ответы на основе человеческих предпочтений и обратной связи.
  2. Точная настройка с учителем (SFT):. При этом подходе модели подвергаются обучению на наборе данных, состоящем из парных инструкций и соответствующих ответов, как в нашем случае с Вопрос-Ответпары. Цель состоит в том, чтобы оптимизировать внутренние параметры модели в рамках LLM, чтобы минимизировать несоответствие между сгенерированными ответами и достоверными ответами, которые служат эталонными метками.

Эти стратегии тонкой настройки играют ключевую роль в повышении полезности авторегрессионных моделей, превращая их в более способных и отзывчивых виртуальных помощников, соответствующих человеческим ожиданиям.

Давайте углубимся в детали:

  1. Установка и импорт необходимых пакетов Python
!pip install -q accelerate==0.21.0 peft==0.4.0 bitsandbytes==0.40.2 transformers==4.31.0 trl==0.4.7
import locale
def getpreferredencoding(do_setlocale = True):
    return "UTF-8"
locale.getpreferredencoding = getpreferredencoding


import os
import torch
import pandas as pd
from datasets import load_dataset,DatasetDict,Dataset
from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    BitsAndBytesConfig,
    HfArgumentParser,
    TrainingArguments,
    LlamaForCausalLM,
    LlamaTokenizer,
    GenerationConfig,
    pipeline,
    logging
)

from peft import LoraConfig, PeftModel
from trl import SFTTrainer

2. Шаблоны подсказок

Одним из важнейших аспектов качества данных, особенно в моделях Llama 2, является шаблон подсказки. Авторы модели предлагают использовать следующий формат при подготовке данных.

<s>[INST] <<SYS>>
System prompt
<</SYS>>

User prompt [/INST] Model answer </s>

Тот же формат использовался при подготовке набора данных часто задаваемых вопросов для точной настройки модели. На данный момент я определил класс CONFIG только с одним значением, как показано ниже. Другие определения, связанные с моделью, также можно добавить в класс позже.

Набор данных представлен в формате CSV, в котором в качестве значений столбцов указаны вопросы и связанные с ними ответы. Доступ к нему можно получить здесь.

#Dataset
df = pd.read_csv("Final_FAQs.csv")
df1 = df.drop(['Unnamed: 0'], axis=1)
df1['Answer'] = df1['Answer'].str.replace('\n', ' ') #replace  \n witn space 
df2 = df1.copy()
df3 = df2.dropna()

Затем эту функцию можно использовать для преобразования кадра данных в шаблон приглашения чата Llama 2, как упоминалось выше.

def transform_dataset_format(df):
    """Transform the dataframe into a specified format."""

    def transform(row):
        user_text = row["Question"]
        assistant_text = row["Answer"]

        return f"<s>[INST] "f"{user_text} [/INST] {assistant_text} </s>"

    transformed_data = df.apply(transform, axis=1)
    transformed_df = transformed_data.to_frame(name="text")

    return transformed_df

df4 = transform_dataset_format(df3)
df4.to_csv("Transformed_csv.csv",index=False)

Выходные данные вышеуказанной функции представляют собой преобразованный фрейм данных только с одним столбцом «текст», который затем загружается как набор данных после преобразования в CSV. Таким образом, мы загрузим его в формате Hugging Face как словарь набора данных с 1750 ненулевыми значениями строк.

from datasets import load_dataset
dataset = load_dataset('csv', data_files='Transformed_data.csv')

3. Точная настройка Ламы 2

Процесс точной настройки модели Llama 2 с 7 миллиардами параметров происходит на графическом процессоре T4 с использованием методов точной настройки с эффективным использованием параметров (PEFT), таких как LoRA или QLoRA. .

Чтобы существенно минимизировать потребление VRAM, необходимо точно настроить модель с точностью до 4 бит. Вот почему мы будем использовать QLoRA в этом контексте.

Процесс тонкой настройки включает использование модели llama-2-7b-chat-hf (модель чата) в качестве базовой модели и ее обучение на наборе данных FAQ, как описано выше.

QLoRA настроен на использование ранга 64 вместе с параметром масштабирования, установленным на 16. Затем модель Llama 2 напрямую загружается с 4-битной точностью с использованием типа NF4 и обучается в одной эпохе. Проверьте соответствующие ссылки для получения дополнительной информации о PeftModel, TrainingArguments и SFTtrainer, а также о параметрах LoRA.

В приведенном ниже коде подробно описан пошаговый процесс загрузки всего в процессе тонкой настройки. Первым шагом является загрузка модели llama-2–7b-chat-hf и создание имени для новой точно настроенной модели, которое будет сохранено позже. Определены параметры QLORA, а также выбор графического процессора для обработки.

# The model that you want to train from the Hugging Face hub

model_name = "meta-llama/Llama-2-7b-chat-hf" #Need to apply for  access 
new_model = "llama-2-7b-saf3" # Fine-tuned model name

# QLoRA parameters
################################################################################
# LoRA attention dimension
lora_r = 64
# Alpha parameter for LoRA scaling
lora_alpha = 16
# Dropout probability for LoRA layers
lora_dropout = 0.1
################################################################################
# bitsandbytes parameters
################################################################################
# Activate 4-bit precision base model loading
use_4bit = True
# Compute dtype for 4-bit base models
bnb_4bit_compute_dtype = "float16"
# Quantization type (fp4 or nf4)
bnb_4bit_quant_type = "nf4"
# Activate nested quantization for 4-bit base models (double quantization)
use_nested_quant = False
################################################################################
# TrainingArguments parameters
################################################################################
# Output directory where the model predictions and checkpoints will be stored
output_dir = "./results"
# Number of training epochs
num_train_epochs = 1
# Enable fp16/bf16 training (set bf16 to True with an A100)
fp16 = False
bf16 = False
# Batch size per GPU for training
per_device_train_batch_size = 4
# Batch size per GPU for evaluation
per_device_eval_batch_size = 4
# Number of update steps to accumulate the gradients for
gradient_accumulation_steps = 1
# Enable gradient checkpointing
gradient_checkpointing = True
# Maximum gradient normal (gradient clipping)
max_grad_norm = 0.3
# Initial learning rate (AdamW optimizer)
learning_rate = 2e-4
# Weight decay to apply to all layers except bias/LayerNorm weights
weight_decay = 0.001
# Optimizer to use
optim = "paged_adamw_32bit"
# Learning rate schedule
lr_scheduler_type = "cosine"
# Number of training steps (overrides num_train_epochs)
max_steps = -1
# Ratio of steps for a linear warmup (from 0 to learning rate)
warmup_ratio = 0.03
# Group sequences into batches with same length
# Saves memory and speeds up training considerably
group_by_length = True
# Save checkpoint every X updates steps
save_steps = 0
# Log every X updates steps
logging_steps = 25
################################################################################
# SFT parameters
################################################################################
# Maximum sequence length to use
max_seq_length = None
# Pack multiple short examples in the same input sequence to increase efficiency
packing = False
# Load the entire model on the GPU 0
device_map = {"": 0}

Приведенный ниже код позволяет войти в Hugging Face Hub, чтобы можно было перенести веса модели в Hugging Face позже после тренировки и объединения весов.

from huggingface_hub import notebook_login
notebook_login()

Далее настраивается bitsandbytes для 4-битного квантования с последующей загрузкой модели с 4-битной точностью на графический процессор с соответствующим токенизатором.

Последний фрагмент приведенного ниже кода загружает конфигурации QLoRA и параметры обучения и передает все в SFTtrainer. Процесс обучения занял около часа, а финальная модель — здесь. Время точной настройки может варьироваться в зависимости от размера набора данных, а также настроек других параметров.

# Load tokenizer and model with QLoRA configuration
compute_dtype = getattr(torch, bnb_4bit_compute_dtype)
bnb_config = BitsAndBytesConfig(
    load_in_4bit=use_4bit,
    bnb_4bit_quant_type=bnb_4bit_quant_type,
    bnb_4bit_compute_dtype=compute_dtype,
    bnb_4bit_use_double_quant=use_nested_quant,
)
# Check GPU compatibility with bfloat16
if compute_dtype == torch.float16 and use_4bit:
    major, _ = torch.cuda.get_device_capability()
    if major >= 8:
        print("=" * 80)
        print("Your GPU supports bfloat16: accelerate training with bf16=True")
        print("=" * 80)

# Load base model
model = LlamaForCausalLM.from_pretrained(
    model_name,
    quantization_config=bnb_config,
    device_map=device_map,
    temperature=0.1,
    do_sample=True
)

model.config.use_cache = False
model.config.pretraining_tp = 1

# Load LLaMA tokenizer
tokenizer = LlamaTokenizer.from_pretrained(model_name, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right" # Fix weird overflow issue with fp16 training
# Load LoRA configuration
peft_config = LoraConfig(
    lora_alpha=lora_alpha,
    lora_dropout=lora_dropout,
    r=lora_r,
    bias="none",
    task_type="CAUSAL_LM",
)
# Set training parameters
training_arguments = TrainingArguments(
    output_dir=output_dir,
    num_train_epochs=num_train_epochs,
    per_device_train_batch_size=per_device_train_batch_size,
    gradient_accumulation_steps=gradient_accumulation_steps,
    optim=optim,
    save_steps=save_steps,
    logging_steps=logging_steps,
    learning_rate=learning_rate,
    weight_decay=weight_decay,
    fp16=fp16,
    bf16=bf16,
    max_grad_norm=max_grad_norm,
    max_steps=max_steps,
    warmup_ratio=warmup_ratio,
    group_by_length=group_by_length,
    lr_scheduler_type=lr_scheduler_type,
    report_to="tensorboard"
)
# Set supervised fine-tuning parameters
trainer = SFTTrainer(
    model=model,
    train_dataset=dataset["train"],
    peft_config=peft_config,
    dataset_text_field="text",
    max_seq_length=1024,
    tokenizer=tokenizer,
    args=training_arguments,
    packing=packing,
)

# Train model
trainer.train()
# Save trained model
trainer.model.save_pretrained(new_model)

После обучения модель была протестирована по ряду вопросов, как показано ниже:

  1. Пример вопроса 1:
# Ignore warnings
logging.set_verbosity(logging.CRITICAL)

# Run text generation pipeline with our next model
prompt = "Can a non-Kenyan register for MPESA? What options do they have?"
pipe = pipeline(task="text-generation", model=model, tokenizer=tokenizer, max_length=200)
result = pipe(f"<s>[INST] {prompt} [/INST]")
print(result[0]['generated_text'])

Ответ:

<s>[INST] Can a non-Kenyan register for MPESA? What options do they have? [/INST]  

Yes, a non-Kenyan can register for MPESA. However, they will need to have a valid passport or national ID number.

Here are the options available for non-Kenyan customers:

1. Register for MPESA as a Non-Kenyan Individual:

Non-Kenyan individuals can register for MPESA by providing their passport or national ID number. They will also need to provide their name, address, and phone number.

2. Register for MPESA as a Business:

Non-Kenyan businesses can register for MPESA by providing their business registration documents, including their certificate of incorporation, VAT registration, and business license.

3. Register for MPESA as a Non-Resident:

2. Пример вопроса 2:

# Ignore warnings
logging.set_verbosity(logging.CRITICAL)

# Run text generation pipeline with our next model
prompt = "I'm an American and just arrived in Kenya a few minutes ago. I need a SIM card to communicate. What requirememnts are  needed for me to register for the SIM card and  all services related to it?"
pipe = pipeline(task="text-generation", model=model, tokenizer=tokenizer, max_length=200)
result = pipe(f"<s>[INST] {prompt} [/INST]")
print(result[0]['generated_text'])

Ответ:

<s>[INST] I'm an American and just arrived in Kenya a few minutes ago. I need a SIM card to communicate. What requirememnts are  needed for me to register for the SIM card and  all services related to it? [/INST]  

Congratulations on your arrival in Kenya! To get a SIM card, you will need to provide the following documents:

1. Valid passport: You will need to provide your passport as proof of identity.
2. Visa: If you are a non-resident, you will need to obtain a visa before purchasing a SIM card.
3. Proof of address: You will need to provide proof of address, such as a hotel reservation or a letter from your employer.
4. Proof of payment: You will need to pay for the SIM card and any additional services you want to purchase.

3. Пример вопроса 3:

# Ignore warnings
logging.set_verbosity(logging.CRITICAL)

# Run text generation pipeline with our next model
prompt = "What is Make Ur Bundle??"
pipe = pipeline(task="text-generation", model=model, tokenizer=tokenizer, max_length=200)
result = pipe(f"<s>[INST] {prompt} [/INST]")
print(result[0]['generated_text'])

Ответ:

<s>[INST] What is Make Ur Bundle?? [/INST]  

Make Ur Bundle is a service that allows you to create a customized bundle of your preferred data, voice and SMS bundles. You can choose the amount of data, voice and SMS you want to purchase and the duration of the bundle. Once you have created your bundle, you can purchase it and use it to make calls, send messages, and browse the internet.

The service is available to all Safaricom customers and can be accessed through the MySafaricom App or by dialing *544#.

Here are some of the benefits of Make Ur Bundle:

1. Customization: You can choose the amount of data, voice and SMS you want to purchase, making it easy to manage your resources.
2. Flexibility: You can purchase a bundle for a duration of 1 day, 3 days, 7 days

4. Пример вопроса 4:

# Ignore warnings
logging.set_verbosity(logging.CRITICAL)

# Run text generation pipeline with our next model
prompt = "When my Make Ur Bundle expires, what will happen to my unused data?"
pipe = pipeline(task="text-generation", model=model, tokenizer=tokenizer, max_length=200)
result = pipe(f"<s>[INST] {prompt} [/INST]")
print(result[0]['generated_text'])

Ответ:

<s>[INST] When my Make Ur Bundle expires, what will happen to my unused data? [/INST]  

If you have unused data in your Make Ur Bundle when it expires, you will be able'}
 everybody. You will be able to use the data until it expires. If you do not use the data before the expiration date, it will be lost.

If you have a Make Ur Bundle with a data rollover option, any unused data will roll over to the next month. You will be able to use the rolled over data until it expires.

If you have a Make Ur Bundle with a data cap, any unused data will not roll over to the next month. You will need to purchase a new Make Ur Bundle with a data cap to continue using data.

If you have a Make Ur Bundle with a data rollover option and you do not use the data before the expiration date,

5. Пример вопроса 5:

# Ignore warnings
logging.set_verbosity(logging.CRITICAL)

# Run text generation pipeline with our next model
prompt = "Can I register two lines to MPESA with the same ID?"
pipe = pipeline(task="text-generation", model=model, tokenizer=tokenizer, max_length=200)
result = pipe(f"<s>[INST] {prompt} [/INST]")
print(result[0]['generated_text'])

Ответ:

<s>[INST] Can I register two lines to MPESA with the same ID? [/INST]  

No, you cannot register two lines to MPESA with the same ID. everybody has a unique ID.

If you have two lines, you will need to register them separately.

To register a new line, you will need to have your ID and a valid passport photo.

You can register a new line by following these steps:

1. Dial *544#
2. Select “Register a new line”
3. Enter your ID number
4. Enter your passport photo
5. Select “Next”
6. Enter your PIN
7. Select “Confirm”

Once you have registered your new line, you will be able to access all the features of MPESA, including sending and receiving money, paying bills, and buying airtime.

Вы можете пойти дальше и поиграть с моделью, предложив ей несколько сложных сценариев и записав результаты. Модель дает ответы, которые являются логичными и по существу верными на основе приведенных выше результатов. Однако не реагируйте на результаты модели, поскольку модель имеет тенденцию галлюцинировать на некоторые темы. Лучше перепроверьте каждую деталь на сайте Safaricom.

Для хранения llama-2–7b-saf необходимо объединить веса LoRA и базовой модели. Как упоминал Максим здесь, сделать это немного сложно из-за ограничений памяти, поскольку базовую модель необходимо перезагружать с точностью FP16 и использовать peft для их объединения, как показано в коде. ниже. Таким образом, завершение текущей среды выполнения и повторное выполнение первых двух и четвертого шагов должно сработать.

# Reload model in FP16 and merge it with LoRA weights
base_model = AutoModelForCausalLM.from_pretrained(
    model_name,
    low_cpu_mem_usage=True,
    return_dict=True,
    torch_dtype=torch.float16,
    device_map=device_map,
)
model = PeftModel.from_pretrained(base_model, new_model)
model = model.merge_and_unload()

# Reload tokenizer to save it
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
tokenizer.add_special_tokens({'pad_token': '[PAD]'})
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"

Объединенную модель и ее веса можно затем отправить в Hugging Face Hub для повторного использования в других приложениях. Теперь его можно загрузить, как и любую другую модель Llama 2, здесь. Кроме того, эту модель можно дополнительно настроить с помощью других наборов данных, чтобы она соответствовала соответствующим сценариям. Взаимодействовать с моделью можно в этомблокноте Colab через чат Gradio.

Заключение

Мы рассмотрели процесс тонкой настройки модели Llama 2 7B с использованием пар Вопрос и Ответ, связанных с продуктом, в качестве часто задаваемых вопросов, связанных с продуктом и услугой. Крупнейшая телекоммуникационная компания Кении Safaricom. В первой части подробно описаны общие сведения о LLM, а также о том, как был подготовлен набор данных и загружен правильный шаблон подсказки. Во второй части были затронуты детали тонкой настройки.

Наконец, модель была протестирована на несколько вопросов и были даны примеры ответов. Надеюсь, вам понравилось читать эту статью, и желаю вам всего наилучшего в настройке ваших моделей. Заключительной частью серии станет чат-бот, которого Safaricom сможет развернуть для более интуитивной обработки запросов клиентов. Следите за последним чат-ботом.