現今大語言模型的指令遵循能力日益重要,本文探討如何微調語言模型以提升其指令遵循效能。我們首先介紹如何使用Python程式碼生成模型回應,接著討論人工評估方法的侷限性,並提出使用另一個大語言模型(如Llama 3)進行自動評估的方案。最後,我們示範如何使用Ollama在本機執行Llama 3模型,並透過REST API與其互動,以自動評估微調模型生成的回應品質。
微調語言模型以遵循指令
在完成回應指令的步驟中,我們使用generate函式。接著,我們將模型的回應與測試集中的預期答案並列印出,以便比較前三個測試集條目:
torch.manual_seed(123)
for entry in test_data[:3]:
input_text = format_input(entry)
token_ids = generate(
model=model,
idx=text_to_token_ids(input_text, tokenizer).to(device),
max_new_tokens=256,
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()
)
內容解密:
- 固定隨機種子:使用
torch.manual_seed(123)確保實驗的可重複性。 - 迭代測試資料:遍歷測試集中的前三個條目。
- 生成模型回應:使用
generate函式根據輸入文字生成模型的回應。 - 後處理生成的文字:從生成的文字中提取模型的回應,並進行必要的清理,如移除“### Response:”標籤。
提取和儲存回應
print(input_text)
print(f"\n正確回應:\n>> {entry['output']}")
print(f"\n模型回應:\n>> {response_text.strip()}")
print("
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
--")
內容解密:
- 印出輸入文字:顯示輸入模型的指令和文字。
- 印出正確與模型回應:並列印出測試集中的正確回應和模型的回應,以便比較。
- 分隔線:使用分隔線來區分不同的測試案例。
比較模型的回應與正確回應
以下是模型的回應與測試集中的正確回應的例子:
指令:使用比喻重寫句子。
輸入:這輛車非常快。
正確回應:>> 這輛車像閃電一樣快。
模型回應:>> 這輛車像子彈一樣快。
指令:什麼型別的雲通常與雷暴有關?
正確回應:>> 與雷暴相關的雲型別是積雨雲。
模型回應:>> 與雷暴相關的雲是積雲。
指令:‘傲慢與偏見’的作者是誰?
正確回應:>> 簡·奧斯汀。
模型回應:>> ‘傲慢與偏見’的作者是簡·奧斯汀。
內容解密:
- 評估模型表現:透過比較模型的回應和正確回應,可以評估模型的表現。
- 多種評估方法:由於指令微調的LLM評估不像簡單的分類別任務那樣直接,實踐中會使用多種評估方法,包括多選題、人工評估和自動對話評估等。
對話效能評估
對話效能是指LLM能夠進行類別人溝通的能力,包括理解上下文、細微差別和意圖。它涵蓋了提供相關且連貫的回應、保持一致性以及適應不同話題和互動風格的能力。
圖示說明
此圖示展示了指令微調LLM的三階段過程,包括準備資料集、微調LLM和評估LLM。在評估階段,會提取模型的回應並進行人工和自動對話評估。
7.7 自動生成與儲存模型回應
人工評估雖然能提供寶貴的洞察,但處理大量回應時卻相當耗時耗力。例如,要閱讀並評分全部1,100個回應需要投入大量的精力。
因此,為了更有效地評估模型效能,我們採用了一種類別似於自動化對話基準測試的方法,利用另一個大語言模型(LLM)自動評估回應。這種方法使我們能夠在無需大量人工參與的情況下,高效地評估生成的回應品質,從而節省時間和資源,同時獲得有意義的效能指標。
我們採用了一種受AlpacaEval啟發的方法,利用另一個LLM來評估我們微調後的模型的回應。然而,我們並未依賴公開可用的基準測試資料集,而是使用了自定義的測試集。這種自定義使我們能夠在預定的使用案例中,更有針對性地評估模型的效能。
生成測試集回應
為了準備評估過程所需的回應,我們將生成的模型回應附加到test_set字典中,並將更新後的資料儲存為"instruction-data-with-response.json"檔案,以便於記錄。此外,透過儲存此檔案,我們可以在稍後的Python會話中輕鬆載入和分析回應。
程式碼 7.9:生成測試集回應
from tqdm import tqdm
for i, entry in tqdm(enumerate(test_data), total=len(test_data)):
input_text = format_input(entry)
token_ids = generate(
model=model,
idx=text_to_token_ids(input_text, tokenizer).to(device),
max_new_tokens=256,
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()
)
test_data[i]["model_response"] = response_text
with open("instruction-data-with-response.json", "w") as file:
json.dump(test_data, file, indent=4)
內容解密:
- 迴圈處理測試資料: 使用
tqdm函式庫顯示進度條,遍歷test_data中的每個條目。 - 格式化輸入文字: 使用
format_input函式將每個條目格式化為輸入文字。 - 生成模型回應: 呼叫
generate函式生成模型的回應,並將其轉換為文字。 - 處理生成的回應文字: 去除不必要的字首和空白字元,將處理後的回應儲存在
test_data字典中。 - 儲存更新後的測試資料: 將包含模型回應的
test_data儲存為JSON檔案。
處理資料集在A100 GPU上大約需要1分鐘,在M3 MacBook Air上需要6分鐘。
驗證和儲存模型
透過檢查test_data[0],我們可以驗證模型回應是否已正確新增。最後,我們將模型儲存為"gpt2-medium355M-sft.pth"檔案,以便於在未來專案中重複使用。
7.8 評估微調後的LLM
之前,我們透過觀察模型在測試集中的三個範例上的表現來判斷其效能。雖然這給了我們一個粗略的概念,但這種方法並不能很好地擴充套件到大量的回應。因此,我們實施了一種方法,利用另一個更大的LLM自動評估微調後的LLM的回應,如圖7.19所示。
自動評估測試集回應
為了自動評估測試集回應,我們使用了Meta AI開發的指令微調後的8億引數Llama 3模型。該模型可以使用開源的Ollama應用程式在本機執行。
使用Ollama執行Llama 3模型
- 安裝Ollama: 存取https://ollama.com,按照指示為您的作業系統安裝Ollama。
- 下載Llama 3模型: 在命令列終端中使用Ollama下載Llama 3模型,並驗證其是否正確運作。
圖7.19 指令微調LLM的三階段過程
在指令微調流程的最後一步,我們實施了一種方法,透過對微調後的模型生成的測試集回應進行評分,量化其效能。
未來改進方向
除了使用本地執行的Llama 3模型,還可以透過OpenAI API利用GPT-4等大型專有LLM來評估生成的模型回應。相關的可選程式碼筆記本可在本文的配套材料中找到。
使用Ollama執行Llama 3模型
要使用Ollama執行8億引數的Llama 3模型,首先需要在另一個終端機中執行Ollama應用程式或ollama serve命令。接著,在命令列中(而不是在Python會話中)執行以下命令:
ollama run llama3
第一次執行此命令時,模型將自動下載,佔用4.7 GB的儲存空間。輸出結果如下:
pulling manifest
pulling 6a0746a1ec1a... 100% |████████████████| 4.7 GB
pulling 4fa551d4f938... 100% |████████████████| 12 KB
pulling 8ab4849b038c... 100% |████████████████| 254 B
pulling 577073ffcc6c... 100% |████████████████| 110 B
pulling 3f8eb4da87fa... 100% |████████████████| 485 B
verifying sha256 digest
writing manifest
removing any unused layers
success
下載完成後,將進入一個命令列介面,可以與模型互動。例如,詢問模型「What do llamas eat?」:
>>> What do llamas eat?
Llamas are ruminant animals, which means they have a four-chambered stomach and eat plants that are high in fiber. In the wild, llamas typically feed on:
1. Grasses: They love to graze on various types of grasses, including tall grasses, wheat, oats, and barley.
可以使用/bye指令結束此次會話。
驗證Ollama是否正在執行
在評估測試集回應之前,需要驗證Ollama是否正在執行:
import psutil
def check_if_running(process_name):
running = False
for proc in psutil.process_iter(["name"]):
if process_name in proc.info["name"]:
running = True
break
return running
ollama_running = check_if_running("ollama")
if not ollama_running:
raise RuntimeError("Ollama not running. Launch ollama before proceeding.")
print("Ollama running:", check_if_running("ollama"))
程式碼解密:
psutil函式庫用於檢查系統中正在執行的行程。check_if_running函式遍歷所有正在執行的行程,檢查是否包含指定的行程名稱(此例中為"ollama")。- 若未發現Ollama正在執行,則引發
RuntimeError。
使用REST API與Ollama互動
除了使用命令列介面外,也可以使用Python透過REST API與Ollama互動。以下為範例函式:
import urllib.request
import json
def query_model(prompt, model="llama3", url="http://localhost:11434/api/chat"):
data = {
"model": model,
"messages": [{"role": "user", "content": prompt}],
"options": {"seed": 123, "temperature": 0, "num_ctx": 2048}
}
payload = json.dumps(data).encode("utf-8")
request = urllib.request.Request(url, data=payload, method="POST")
request.add_header("Content-Type", "application/json")
response_data = ""
with urllib.request.urlopen(request) as 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
result = query_model("What do Llamas eat?", "llama3")
print(result)
程式碼解密:
query_model函式使用指定的提示(prompt)和模型(預設為"llama3")向Ollama的REST API傳送請求。- 請求資料包含模型名稱、使用者訊息和選項(種子值、溫度、上下文長度)。
- 請求成功後,回應資料被解碼並傳回。
評估微調後的LLM
使用query_model函式,可以評估由微調模型生成的回應。透過提示Llama 3模型根據給定的測試集回應對微調模型的回應進行評分(0至100分)。
Plantuml圖示:評估流程圖
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title 微調語言模型指令遵循
package "指令微調流程" {
package "訓練階段" {
component [指令資料集] as dataset
component [格式化輸入] as format
component [模型微調] as finetune
}
package "生成階段" {
component [generate 函式] as generate
component [回應提取] as extract
component [後處理] as postprocess
}
}
package "評估方法" {
component [人工評估] as manual
component [Llama 3 自動評估] as llama
component [Ollama 本地執行] as ollama
component [AlpacaEval] as alpaca
}
dataset --> format : 指令+輸入
format --> finetune : 訓練樣本
finetune --> generate : 微調模型
generate --> extract : Token IDs
extract --> postprocess : 清理回應
postprocess --> llama : 品質評分
llama --> ollama : REST API
ollama --> alpaca : 基準測試
note right of llama
評估流程:
- 特徵選擇
- 特徵轉換
- 降維處理
end note
note right of eval
評估指標:
- 準確率/召回率
- F1 Score
- AUC-ROC
end note
@enduml
此圖示描述了評估微調後LLM的流程,從載入測試資料到收集Llama 3模型的評分結果。