File Jupyter NoteBook của bài viết này có thể xem tại đây
1. Instruction fine-tuning
Sau giai đoạn tiền huấn luyện, mô hình đã có thể sinh văn bản khá tốt. Tuy nhiên, để có thể "hiểu" được hết các yêu cầu của người dùng thì chưa !
Với Instruction fine-tuning, mô hình sau khi được học qua các mẫu câu hỏi + câu trả lời cho trước sẽ có khả năng nắm bắt ý muốn người dùng hơn.
2. Chuẩn bị dữ liệu
Chúng ta sẽ tải và sử dụng bộ dữ liệu chứa hơn 1100 bộ câu hỏi - câu trả lời
. Tiếp đó chia dữ liệu thành 3 tập train, test và val luôn.
import json
import os
import urllib.request def download_and_load_file(file_path, url): if not os.path.exists(file_path): with urllib.request.urlopen(url) as response: text_data = response.read().decode("utf-8") with open(file_path, "w", encoding="utf-8") as file: file.write(text_data) with open(file_path, "r", encoding="utf-8") as file: data = json.load(file) return data file_path = "instruction-data.json"
url = ( "https://raw.githubusercontent.com/rasbt/LLMs-from-scratch" "/main/ch07/01_main-chapter-code/instruction-data.json"
) data = download_and_load_file(file_path, url)
print("Number of entries:", len(data))
# Number of entries: 1100 train_portion = int(len(data) * 0.85) # 85% for training
test_portion = int(len(data) * 0.1) # 10% for testing
val_portion = len(data) - train_portion - test_portion # Remaining 5% for validation train_data = data[:train_portion]
test_data = data[train_portion:train_portion + test_portion]
val_data = data[train_portion + test_portion:] print("Training set length:", len(train_data))
print("Validation set length:", len(val_data))
print("Test set length:", len(test_data)) # aining set length: 935
# lidation set length: 55
# Test set length: 110
Ví dụ về 1 hướng dẫn trong file instruction-data.json
mới tải về
{ "instruction": "Identify the correct spelling of the following word.", "input": "Ocassion", "output": "The correct spelling is 'Occasion.'"
},
Ta thấy có 3 thông tin
instruction
: Thể hiện yêu cầu của câu hỏi đầu vàoinput
: Chi tiết về đối tượng được hỏioutput
: Đáp án cho câu hỏi
Yêu cầu của câu hỏi trên là Hãy xác định cách phát âm đúng của từ Ocassion.
Sau quá trình tinh chỉnh, những câu hỏi tương tự như kiểu Identify the correct spelling of the following word Worcestershire
cũng sẽ được mô hình hiểu và trả lời theo mô típ trên.
Trường input có thể trống vì ở instruction để thể hiện chi tiết về câu hỏi
{ 'instruction': "What is an antonym of 'complicated'?", 'input': '', 'output': "An antonym of 'complicated' is 'simple'." }
Cách cấu trúc dữ liệu ở trên dựa thêm phương pháp Alpaca được phát triển bởi các chuyên gia tại Đại học Stanford - Hoa Kỳ. Một phương pháp khác cũng khá nổi tiếng là Phi-3 của Microsoft có cấu trúc hơi khác 1 xíu so với Alpaca.
Dạng JSON tchưa phải cấu trúc tiêu chuẩn của alpaca mà cần định dạng lại 1 chút trước khi đưa vào mô hình .
def format_input(entry): instruction_text = ( f"Below is an instruction that describes a task. " f"Write a response that appropriately completes the request." f"\n\n### Instruction:\n{entry['instruction']}" ) input_text = f"\n\n### Input:\n{entry['input']}" if entry["input"] else "" return instruction_text + input_text model_input = format_input(data[50])
desired_response = f"\n\n### Response:\n{data[50]['output']}" print(model_input + desired_response)
Ta có kết quả:
Below is an instruction that describes a task. Write a response that appropriately completes the request. ### Instruction:
Identify the correct spelling of the following word. ### Input:
Ocassion ### Response:
The correct spelling is 'Occasion.'
3. Tổ chức dữ liệu theo các lô (batch)
Tiếp theo là đến phần "số hóa" dữ liệu như thường lệ. Trải qua các bước sau:
Tại sao bước thứ 5 lại thay thế gần hết các tokenId 50256 bằng -100 ?
- Chúng là các token được thêm vào để đảm bảo rằng tất cả các chuỗi trong batch có cùng độ dài. Tuy nhiên, những token này không mang - Chúng là các token được thêm vào để đảm bảo rằng tất cả các chuỗi trong batch có cùng độ dài. Tuy nhiên, những token này không có ý nghĩa.
- Nếu không loại bỏ, mô hình sẽ cố gắng dự đoán những token này => dẫn đến việc giảm hiệu quả huấn luyện.
- Hàm Cross-Entropy Loss trong PyTorch (và nhiều framework khác) tự động bỏ qua các nhãn có giá trị
-100
.
import torch
from torch.utils.data import Dataset
import tiktoken
tokenizer = tiktoken.get_encoding("gpt2") class InstructionDataset(Dataset): def __init__(self, data, tokenizer): self.data = data self.encoded_texts = [] for entry in data: # format instruction_plus_input = format_input(entry) response_text = f"\n\n### Response:\n{entry['output']}" full_text = instruction_plus_input + response_text # Token hóa self.encoded_texts.append( tokenizer.encode(full_text) ) def __getitem__(self, index): return self.encoded_texts[index] def __len__(self): return len(self.data)
def custom_collate_fn( batch, pad_token_id=50256, ignore_index=-100, allowed_max_length=None, device="cpu"
): # Tìm độ dài lớn nhất của các chuỗi trong batch và cộng thêm 1 batch_max_length = max(len(item)+1 for item in batch) # inputs và targets inputs_lst, targets_lst = [], [] for item in batch: new_item = item.copy() # Đệm thêm <|endoftext|> token new_item += [pad_token_id] # Đệm các chuỗi cho đến khi dài bằng batch_max_length padded = ( new_item + [pad_token_id] * (batch_max_length - len(new_item)) ) inputs = torch.tensor(padded[:-1]) targets = torch.tensor(padded[1:]) # Dịch phải một vị trí cho inputs # Thay thế các giá trị token_id=50256 bằng ignore_index mask = targets == pad_token_id indices = torch.nonzero(mask).squeeze() if indices.numel() > 1: targets[indices[1:]] = ignore_index # Nếu allowed_max_length khác None, cắt inputs và targets if allowed_max_length is not None: inputs = inputs[:allowed_max_length] targets = targets[:allowed_max_length] inputs_lst.append(inputs) targets_lst.append(targets) # Đưa inputs và targets thành dạng tensor inputs_tensor = torch.stack(inputs_lst).to(device) targets_tensor = torch.stack(targets_lst).to(device) return inputs_tensor, targets_tensor
4. Data loader
- Hàm
custom_collate_fn
ở phần trên. Khi tạo các tensor luôn phải có thêm bước.to(device)
(Nạp tensort lên CPU hoặc GPU) - Phần này ta sẽ sử dụng hàm
partial
từ thư việnfunctools
của Python, rồi tạo một hàm mới với đối sốdevice
để giúp code gọn hơn - Rồi sau đó chia các tập dữ liệu thành các lô bằng các dùng tính năng Data Loader của Pytorch.
from torch.utils.data import DataLoader num_workers = 0 # Số luồng xử lý song song (0 = chạy trên luồng chính)
batch_size = 8 # Số lượng mẫu dữ liệu trong mỗi lô
torch.manual_seed(123)
train_dataset = InstructionDataset(train_data, tokenizer) train_loader = DataLoader( train_dataset, batch_size=batch_size, collate_fn=custom_collate_fn, shuffle=True, drop_last=True, num_workers=num_workers,
) val_dataset = InstructionDataset(val_data, tokenizer)
val_loader = DataLoader( val_dataset, batch_size=batch_size, collate_fn=custom_collate_fn, shuffle=False, drop_last=False, num_workers=num_workers,
) test_dataset = InstructionDataset(test_data, tokenizer)
test_loader = DataLoader( test_dataset, batch_size=batch_size, collate_fn=custom_collate_fn, shuffle=False, drop_last=False, num_workers=num_workers,
)
Ví dụ:
inputs_1 = [0, 1, 2, 3, 4]
inputs_2 = [5, 6]
inputs_3 = [7, 8, 9] batch = ( inputs_1, inputs_2, inputs_3
) inputs, targets = custom_collate_fn(batch)
print(inputs)
print(targets)
Kết quả in ra:
tensor([[ 0, 1, 2, 3, 4], [ 5, 6, 50256, 50256, 50256], [ 7, 8, 9, 50256, 50256]]) tensor([[ 1, 2, 3, 4, 50256], [ 6, 50256, -100, -100, -100], [ 8, 9, 50256, -100, -100]])
5. Tải bộ tham số từ quá trình tiền huấn luyện
Phần này chúng ta sẽ sử dụng mô hình GPT-2 355 triệu tham số thay vì 124 triệu như ở bài viết trước. Do các mô hình quá nhỏ như gpt2-small không có đủ nhiều tham số để học và ghi nhớ các mẫu phức tạp được sử dụng trong quá trình tin chỉnh instruction-following.
BASE_CONFIG = { "vocab_size": 50257, # Vocabulary size "context_length": 1024, # Context length "drop_rate": 0.0, # Dropout rate "qkv_bias": True # Query-key-value bias
} model_configs = { "gpt2-small (124M)": {"emb_dim": 768, "n_layers": 12, "n_heads": 12}, "gpt2-medium (355M)": {"emb_dim": 1024, "n_layers": 24, "n_heads": 16}, "gpt2-large (774M)": {"emb_dim": 1280, "n_layers": 36, "n_heads": 20}, "gpt2-xl (1558M)": {"emb_dim": 1600, "n_layers": 48, "n_heads": 25},
} CHOOSE_MODEL = "gpt2-medium (355M)" BASE_CONFIG.update(model_configs[CHOOSE_MODEL]) model_size = CHOOSE_MODEL.split(" ")[-1].lstrip("(").rstrip(")")
settings, params = download_and_load_gpt2( model_size=model_size, models_dir="gpt2"
) model = GPTModel(BASE_CONFIG)
load_weights_into_gpt(model, params)
model.eval()
Trước khi tinh chỉnh, thử khả năng của mô hình với 1 yêu cầu chuyển câu chủ động sang bị động
print(val_data[0])
# 'instruction': "Convert the active sentence to passive: 'The chef cooks the meal every day.'",
# 'input': '',
# 'output': 'The meal is cooked by the chef every day.'} torch.manual_seed(123) input_text = format_input(val_data[0])
token_ids = generate( model=model, idx=text_to_token_ids(input_text, tokenizer), max_new_tokens=35, context_size=BASE_CONFIG["context_length"], eos_id=50256,
)
generated_text = token_ids_to_text(token_ids, tokenizer)
response_text = ( generated_text[len(input_text):] .replace("### Response:", "") .strip()
)
print(response_text)
"""
The chef cooks the meal every day. ### Instruction: Convert the active sentence to passive: 'The chef cooks the
"""
Mô hình chưa được tinh chỉnh gần như chỉ lặp lại câu hỏi và không trả về đúng kết quả mong muốn.
6. Thực hiện tinh chỉnh
Quá trình huấn luyện cũng không khác so với các bài trước, chúng ta sẽ sử dụng lại các hàm huấn luyện, tính toán hàm mất mát.
Lưu ý:
- Quá trình huấn luyện sẽ tốn nhiều thời gian và tài nguyên tính toán hơn một chút so với các chương trước vì chúng ta đang sử dụng mô hình lớn hơn (355 triệu tham số thay vì 124 triệu tham số).
- Thời gian chạy trên các thiết bị khác nhau được hiển thị dưới đây để tham khảo.
Mô hình | Thiết bị | Chạy 2 Epochs |
---|---|---|
gpt2-medium (355M) | CPU (M3 MacBook Air) | 15.78 minutes |
gpt2-medium (355M) | GPU (M3 MacBook Air) | 10.77 minutes |
gpt2-medium (355M) | GPU (L4) | 1.83 minutes |
gpt2-medium (355M) | GPU (A100) | 0.86 minutes |
gpt2-small (124M) | CPU (M3 MacBook Air) | 5.74 minutes |
gpt2-small (124M) | GPU (M3 MacBook Air) | 3.73 minutes |
gpt2-small (124M) | GPU (L4) | 0.69 minutes |
gpt2-small (124M) | GPU (A100) | 0.39 minutes |
def train_model_simple(model, train_loader, val_loader, optimizer, device, num_epochs, eval_freq, eval_iter, start_context, tokenizer): train_losses, val_losses, track_tokens_seen = [], [], [] tokens_seen = 0 global_step = -1 # Main training loop for epoch in range(num_epochs): model.train() # Set model to training mode for input_batch, target_batch in train_loader: optimizer.zero_grad() # Reset loss gradients from previous batch iteration loss = calc_loss_batch(input_batch, target_batch, model, device) loss.backward() # Calculate loss gradients optimizer.step() # Update model weights using loss gradients tokens_seen += input_batch.numel() global_step += 1 if global_step % eval_freq == 0: train_loss, val_loss = evaluate_model( model, train_loader, val_loader, device, eval_iter) train_losses.append(train_loss) val_losses.append(val_loss) track_tokens_seen.append(tokens_seen) print(f"Ep {epoch+1} (Step {global_step:06d}): " f"Train loss {train_loss:.3f}, Val loss {val_loss:.3f}") generate_and_print_sample( model, tokenizer, device, start_context ) return train_losses, val_losses, track_tokens_seen def calc_loss_loader(data_loader, model, device, num_batches=None): total_loss = 0. if len(data_loader) == 0: return float("nan") elif num_batches is None: num_batches = len(data_loader) else: num_batches = min(num_batches, len(data_loader)) for i, (input_batch, target_batch) in enumerate(data_loader): if i < num_batches: loss = calc_loss_batch(input_batch, target_batch, model, device) total_loss += loss.item() else: break return total_loss / num_batches
Bắt đầu huấn luyện
# File đầy đủ: https://sal.vn/8eCiBl
import time # Lưu thời gian bắt đầu
start_time = time.time() torch.manual_seed(123) optimizer = torch.optim.AdamW(model.parameters(), lr=0.00005, weight_decay=0.1) # Số chu kỳ huấn luyện là 2
num_epochs = 2 train_losses, val_losses, tokens_seen = train_model_simple( model, train_loader, val_loader, optimizer, device, num_epochs=num_epochs, eval_freq=5, eval_iter=5, start_context=format_input(val_data[0]), tokenizer=tokenizer
) # Lưu thời gian kết thúc
end_time = time.time() # Tính thời gian thực thi theo phút
execution_time_minutes = (end_time - start_time) / 60 # In ra thời gian huấn luyện
print(f"Training completed in {execution_time_minutes:.2f} minutes.")
Ep 1 (Step 000000): Train loss 2.637, Val loss 2.626
Ep 1 (Step 000005): Train loss 1.174, Val loss 1.103
Ep 1 (Step 000010): Train loss 0.872, Val loss 0.944
Ep 1 (Step 000015): Train loss 0.857, Val loss 0.906
Ep 1 (Step 000020): Train loss 0.776, Val loss 0.881
Ep 1 (Step 000025): Train loss 0.754, Val loss 0.859
Ep 1 (Step 000030): Train loss 0.799, Val loss 0.836
Ep 1 (Step 000035): Train loss 0.714, Val loss 0.808
Ep 1 (Step 000040): Train loss 0.672, Val loss 0.806
Ep 1 (Step 000045): Train loss 0.633, Val loss 0.789
Ep 1 (Step 000050): Train loss 0.663, Val loss 0.783
Ep 1 (Step 000055): Train loss 0.760, Val loss 0.763
Ep 1 (Step 000060): Train loss 0.719, Val loss 0.743
Ep 1 (Step 000065): Train loss 0.653, Val loss 0.735
Ep 1 (Step 000070): Train loss 0.533, Val loss 0.729
Ep 1 (Step 000075): Train loss 0.568, Val loss 0.729
Ep 1 (Step 000080): Train loss 0.604, Val loss 0.725
Ep 1 (Step 000085): Train loss 0.509, Val loss 0.710
Ep 1 (Step 000090): Train loss 0.563, Val loss 0.691
Ep 1 (Step 000095): Train loss 0.502, Val loss 0.681
Ep 1 (Step 000100): Train loss 0.504, Val loss 0.677
Ep 1 (Step 000105): Train loss 0.565, Val loss 0.670
Ep 1 (Step 000110): Train loss 0.554, Val loss 0.666
Ep 1 (Step 000115): Train loss 0.509, Val loss 0.663
Below is an instruction that describes a task. Write a response that appropriately completes the request. ### Instruction: Convert the active sentence to passive: 'The chef cooks the meal every day.' ### Response: The meal is prepared every day by the chef.<|endoftext|>The following is an instruction that describes a task. Write a response that appropriately completes the request. ### Instruction: Convert the active sentence to passive:
Ep 2 (Step 000120): Train loss 0.435, Val loss 0.671
Ep 2 (Step 000125): Train loss 0.451, Val loss 0.686
Ep 2 (Step 000130): Train loss 0.447, Val loss 0.682
Ep 2 (Step 000135): Train loss 0.405, Val loss 0.681
Ep 2 (Step 000140): Train loss 0.410, Val loss 0.681
Ep 2 (Step 000145): Train loss 0.369, Val loss 0.681
Ep 2 (Step 000150): Train loss 0.382, Val loss 0.675
Ep 2 (Step 000155): Train loss 0.414, Val loss 0.675
Ep 2 (Step 000160): Train loss 0.412, Val loss 0.684
Ep 2 (Step 000165): Train loss 0.379, Val loss 0.686
Ep 2 (Step 000170): Train loss 0.322, Val loss 0.680
Ep 2 (Step 000175): Train loss 0.337, Val loss 0.668
Ep 2 (Step 000180): Train loss 0.392, Val loss 0.656
Ep 2 (Step 000185): Train loss 0.414, Val loss 0.657
Ep 2 (Step 000190): Train loss 0.340, Val loss 0.648
Ep 2 (Step 000195): Train loss 0.328, Val loss 0.634
Ep 2 (Step 000200): Train loss 0.309, Val loss 0.634
Ep 2 (Step 000205): Train loss 0.353, Val loss 0.631
Ep 2 (Step 000210): Train loss 0.362, Val loss 0.631
Ep 2 (Step 000215): Train loss 0.393, Val loss 0.634
Ep 2 (Step 000220): Train loss 0.297, Val loss 0.644
Ep 2 (Step 000225): Train loss 0.341, Val loss 0.658
Ep 2 (Step 000230): Train loss 0.294, Val loss 0.656
Below is an instruction that describes a task. Write a response that appropriately completes the request. ### Instruction: Convert the active sentence to passive: 'The chef cooks the meal every day.' ### Response: The meal is cooked every day by the chef.<|endoftext|>The following is an instruction that describes a task. Write a response that appropriately completes the request. ### Instruction: What is the capital of the United Kingdom
Training completed in 3.33 minutes.
Vẽ đồ thị thể hiện giá hàm mất mát trong quá trình huấn luyện
epochs_tensor = torch.linspace(0, num_epochs, len(train_losses))
plot_losses(epochs_tensor, tokens_seen, train_losses, val_losses)
- Đầu ra quá trình huấn luyện cho thấy mô hình đang học một cách hiệu quả, các giá trị mất mát đã giảm nhiều sau 2 chu kỳ.
- Hơn nữa, các phản hồi được tạo ra ở cuối mỗi chu kỳ cho phép chúng ta kiểm tra tiến trình của mô hình trong việc hiểu và trả lời đúng đáp án kỳ vọng. Trong trường hợp này, mô hình chuyển đổi thành công câu chủ động
The chef cooks the meal every day.
thành câu bị động tương ứng:The meal is cooked every day by the chef.
- Tuy nhiên, chúng ta có thể thấy hiện tượng overfitting nhẹ xuất hiện sau khoảng 1 epoch huấn luyện (training loss giảm nhưng validation loss gần như ko giảm).
Lưu lại của mô hình vào file .pth
để có thể import lại khi cần
# export
import re
file_name = f"{re.sub(r'[ ()]', '', CHOOSE_MODEL) }-sft.pth"
torch.save(model.state_dict(), file_name)
print(f"Model saved as {file_name}") # import
model.load_state_dict(torch.load("gpt2
-medium355M-sft.pth")).
7. Đánh giá kết quả
Một mô hình được huấn luyện để phân loại email là spam hay không như ở bài trước, ta chỉ cần tính tỷ lệ phần trăm dự đoán đúng để đo độ chính xác.
Tuy nhiên, với mô hình tinh chỉnh theo phương pháp Instruction cho chatbot, việc đánh giá không đơn giản như vậy vì ngôn ngữ muôn hình vạn trạng, không có đúng/sai rõ ràng.
Một số phương pháp đánh giá quá trình Instruction fine-tuning phổ biến thường được sử dụng
Đánh giá bằng câu trả lời ngắn hoặc trắc nghiệm (Short-answer & multiple-choice benchmarks)
- Short-answer benchmarks : Đây là các bài kiểm tra mà mô hình cần đưa ra câu trả lời ngắn gọn, chính xác cho một câu hỏi. Ví dụ: "Thủ đô của Việt Nam là gì?" → Đáp án: "Hà Nội". Loại này kiểm tra khả năng của mô hình trong việc cung cấp thông tin chính xác và ngắn gọn, thường được dùng trong các tác vụ như trả lời câu hỏi
- Multiple-choice benchmarks : Đây là các bài kiểm tra mà mô hình phải chọn đáp án đúng từ một danh sách các đáp án. Loại này kiểm tra khả năng hiểu ngữ cảnh và chọn đúng từ các lựa chọn, phổ biến trong các bài kiểm tra học thuật.
Dựa trên đánh giá của con người (Human preference comparison)
Là phương pháp đánh giá có phần "phi kỹ thuật" khi dựa vào đánh giá trực tiếp từ người dùng cuối.
Ví dụ, nền tảng LMSYS chatbot arena cho phép người dùng so sánh phản hồi của nhiều mô hình chatbot và đánh giá mô hình nào có câu trả lời tốt hơn.
Đánh giá tự động bằng mô hình LLM khác (Automated conversational benchmarks)
Để thu thập đánh giá, ý kiến của nhiều người là một công việc mất nhiều công sức cũng như thời gian, Automated conversational benchmarks có thể xem là phương pháp tự động hóa của Human preference comparison.
Ý tưởng của phương pháp là sử dụng một mô hình ngôn mạnh hơn để chấm điểm, phân tích câu trả lời của mô hình đang được đánh giá
Một phương pháp đánh giá tự động nổi bật là AlpacaEval – hệ thống sử dụng GPT-4 để đánh giá các mô hình chatbot khác.
8. Ví dụ thực tế với Automated conversational benchmarks
Trong phần này, chúng ta sẽ dùng Llama 3 phiên bản 8 tỷ tham số. Chạy các mô hình trên máy cá nhân ta dùng ollama (https://ollama.com).
Chạy LLama 3 vớ Ollama
Sau khi đã cài đặt xong Ollama, tiến hành chạy Llama 3 8 tỷ tham số. Nếu cấu hình máy không đủ, có thể chạy các mô hình bé hơn như Gemma 3 1B hay Phi-3 3.8B ...
ollama run llama3
Với Docker:
docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama # Nếu không có GPU
# hoặc
docker run -d --gpus=all -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama # Nếu có GPU docker exec -it ollama ollama run llama3
Chạy xong là chúng ta có thể gõ phím để hỏi LLama 3 bất cứ thứ gì =)
Docker container Ollama mở cổng 11434, viết mô-đun để có thể gọi mô hình qua API
import urllib.request
import json def query_model( prompt, model="llama3", url="http://localhost:11434/api/chat"
): # Tạo dữ liệu payload dưới dạng từ điển data = { "model": model, "messages": [ {"role": "user", "content": prompt} ], "options": { "seed": 123, "temperature": 0, "num_ctx": 2048 } } # Chuyển thành dạng JSON và mã hóa thành bytes payload = json.dumps(data).encode("utf-8") # Tạo request object, phương thức là POST và thêm các header cần thiết request = urllib.request.Request( url, data=payload, method="POST" ) request.add_header("Content-Type", "application/json") # Gửi request và nhận response response_data = "" with urllib.request.urlopen(request) as response: # Đọc và giải mã response while True: line = response.readline().decode("utf-8") if not line: break response_json = json.loads(line) response_data += response_json["message"]["content"] return response_data model = "llama3"
result = query_model("What is LLMs ?", model)
print(result)
Kết quả trả lời từ mô hình
Dùng LLama 3 chấm điểm mô hình
Câu hỏi đầu vào, chúng ta yêu cầu mô hình "mẹ" chấm điểm cho câu trả lời theo thang điểm từ 0 đến 100
# ...File python đẩy đủ: https://sal.vn/HYHiIH def generate_model_scores(json_data, json_key, model="llama3"): scores = [] for entry in tqdm(json_data, desc="Scoring entries"): if entry[json_key] == "": scores.append(0) else: prompt = ( f"Given the input `{format_input(entry)}` " f"and correct output `{entry['output']}`, " f"score the model response `{entry[json_key]}`" f" on a scale from 0 to 100, where 100 is the best score. " f"Respond with the integer number only." ) score = query_model(prompt, model) try: scores.append(int(score)) except ValueError: print(f"Could not convert score: {score}") continue return scores