Code Llama: Llama 2 學會程式設計
引言
Code Llama 是 Llama 2 的一套先進的開放訪問版本,專門用於程式碼任務,我們很高興能在 Hugging Face 生態系統中釋出整合!Code Llama 已以與 Llama 2 相同的寬鬆社群許可釋出,並可用於商業用途。
今天,我們很高興釋出:
- Hub 上的模型及其模型卡和許可證
- Transformers 整合
- 與 Text Generation Inference 整合,用於快速高效的生產級推理
- 與推理端點整合
- 與 VS Code 擴充套件整合
- 程式碼基準測試
程式碼 LLM 對軟體工程師來說是一項激動人心的發展,因為它們可以透過 IDE 中的程式碼自動補全、處理編寫文件字串等重複或繁瑣的任務,或建立單元測試來提高生產力。
目錄
什麼是 Code Llama?
Code Llama 釋出了 70 億、130 億和 340 億引數的模型家族。基礎模型在 Llama 2 的基礎上進行初始化,然後使用 5000 億個程式碼資料令牌進行訓練。Meta 對這些基礎模型進行了兩種不同的微調:一種是 Python 專家(額外 1000 億個令牌),另一種是指令微調版本,可以理解自然語言指令。
這些模型在 Python、C++、Java、PHP、C#、TypeScript 和 Bash 中表現出最先進的效能。7B 和 13B 基礎模型以及指令變體支援基於周圍內容的填充,使其成為程式碼助手的理想選擇。
Code Llama 在 16k 上下文視窗上進行了訓練。此外,這三種模型變體還進行了額外的長上下文微調,使其能夠管理高達 100,000 個令牌的上下文視窗。
將 Llama 2 的 4k 上下文視窗擴充套件到 Code Llama 的 16k(可推斷到 100k)得益於 RoPE 擴充套件的最新發展。社群發現 Llama 的位置嵌入可以線性插值或在頻域中插值,這透過微調簡化了到更大上下文視窗的轉換。在 Code Llama 的情況下,頻域縮放是在鬆弛狀態下完成的:微調長度是縮放後的預訓練長度的一部分,這賦予了模型強大的外推能力。
所有模型最初都在一個接近去重化的公開可用程式碼資料集上使用 5000 億個令牌進行訓練。該資料集還包含一些自然語言資料集,例如關於程式碼和程式碼片段的討論。不幸的是,沒有更多關於該資料集的資訊。
對於指令模型,他們使用了兩個資料集:為 Llama 2 Chat 收集的指令微調資料集和一個自指令資料集。自指令資料集是使用 Llama 2 建立面試程式設計問題,然後使用 Code Llama 生成單元測試和解決方案,這些解決方案隨後透過執行測試進行評估。
如何使用 Code Llama?
Code Llama 已在 Hugging Face 生態系統中使用,從 transformers
4.33 版開始。
演示
您可以在 此空間 或下面的嵌入式操場中輕鬆試用 Code Llama 模型(130 億引數!)
該操場在底層使用了 Hugging Face 的 Text Generation Inference,與 HuggingChat 使用的技術相同,我們將在以下部分分享更多資訊。
如果您想嘗試更大的指令微調 34B 模型,它現在已在 HuggingChat 上可用!您可以在這裡嘗試:hf.co/chat。請務必指定 Code Llama 模型。您還可以檢視 此基於聊天的演示 並複製它供您使用 – 它是自包含的,因此您可以檢查原始碼並根據需要進行調整!
Transformers
從 transformers
4.33 開始,您可以使用 Code Llama 並利用 HF 生態系統中的所有工具,例如
- 訓練和推理指令碼以及示例
- 安全檔案格式 (
safetensors
) - 與
bitsandbytes
(4 位量化)和 PEFT(引數高效微調)等工具的整合 - 用於模型生成執行的實用程式和輔助函式
- 匯出模型以進行部署的機制
!pip install --upgrade transformers
關於資料型別(dtypes)的注意事項
在使用 Code Llama 等模型時,重要的是要注意模型的資料型別。
- 32 位浮點數(
float32
):PyTorch 模型初始化約定是以float32
載入模型,無論模型權重以何種精度儲存。transformers
也遵循此約定以與 PyTorch 保持一致。 - 16 位腦浮點數(
bfloat16
):Code Llama 以此精度進行訓練,因此我們建議將其用於進一步訓練或微調。 - 16 位浮點數(
float16
):我們建議使用此精度進行推理,因為它通常比bfloat16
快,並且評估指標顯示與bfloat16
相比沒有明顯退化。您也可以使用bfloat16
進行推理,我們建議您在微調後使用float16
和bfloat16
檢查推理結果。
如上所述,transformers
使用 float32
載入權重(無論模型儲存在何種精度下),因此在載入模型時指定所需的 dtype
很重要。如果要微調 Code Llama,建議使用 bfloat16
,因為使用 float16
可能會導致溢位和 NaN。如果您執行推理,我們建議使用 float16
,因為 bfloat16
可能較慢。
程式碼補全
7B 和 13B 模型可用於文字/程式碼補全或填充。以下程式碼片段使用 pipeline
介面演示文字補全。只要您選擇 GPU 執行時,它就可以在 Colab 的免費層上執行。
from transformers import AutoTokenizer
import transformers
import torch
tokenizer = AutoTokenizer.from_pretrained("codellama/CodeLlama-7b-hf")
pipeline = transformers.pipeline(
"text-generation",
model="codellama/CodeLlama-7b-hf",
torch_dtype=torch.float16,
device_map="auto",
)
sequences = pipeline(
'def fibonacci(',
do_sample=True,
temperature=0.2,
top_p=0.9,
num_return_sequences=1,
eos_token_id=tokenizer.eos_token_id,
max_length=100,
)
for seq in sequences:
print(f"Result: {seq['generated_text']}")
這可能會產生如下輸出:
Result: def fibonacci(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n-1) + fibonacci(n-2)
def fibonacci_memo(n, memo={}):
if n == 0:
return 0
elif n == 1:
return
Code Llama 專注於程式碼理解,但它本身就是一個語言模型。您可以使用相同的生成策略來自動完成註釋或一般文字。
程式碼填充
這是一項特定於程式碼模型的特殊任務。模型經過訓練,可以生成最匹配現有字首和字尾的程式碼(包括註釋)。這是程式碼助手通常使用的策略:它們被要求填充當前游標位置,同時考慮其前後出現的內容。
此任務在 7B 和 13B 模型的基礎和指令變體中可用。它不適用於任何 34B 模型或 Python 版本。
要成功使用此功能,您需要密切注意用於訓練模型此任務的格式,因為它使用特殊分隔符來標識提示的不同部分。幸運的是,Transformers 的 CodeLlamaTokenizer
使這變得非常容易,如下所示:
from transformers import AutoTokenizer, AutoModelForCausalLM
import transformers
import torch
model_id = "codellama/CodeLlama-7b-hf"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
model_id,
torch_dtype=torch.float16
).to("cuda")
prompt = '''def remove_non_ascii(s: str) -> str:
""" <FILL_ME>
return result
'''
input_ids = tokenizer(prompt, return_tensors="pt")["input_ids"].to("cuda")
output = model.generate(
input_ids,
max_new_tokens=200,
)
output = output[0].to("cpu")
filling = tokenizer.decode(output[input_ids.shape[1]:], skip_special_tokens=True)
print(prompt.replace("<FILL_ME>", filling))
def remove_non_ascii(s: str) -> str:
""" Remove non-ASCII characters from a string.
Args:
s: The string to remove non-ASCII characters from.
Returns:
The string with non-ASCII characters removed.
"""
result = ""
for c in s:
if ord(c) < 128:
result += c
return result
在底層,分詞器會自動透過 <FILL_ME>
進行分割,以建立遵循原始訓練模式的格式化輸入字串。這比自己準備模式更健壯:它避免了諸如令牌粘連之類的難以除錯的陷阱。
會話指令
基礎模型可以用於補全和填充,如前所述。Code Llama 釋出還包括一個指令微調模型,可用於會話介面。
為了準備此任務的輸入,我們必須使用一個提示模板,如我們在 Llama 2 部落格文章中描述的那樣,我們在此處再次複製。
<s>[INST] <<SYS>>
{{ system_prompt }}
<</SYS>>
{{ user_msg_1 }} [/INST] {{ model_answer_1 }} </s><s>[INST] {{ user_msg_2 }} [/INST]
請注意,系統提示是可選的——模型在沒有它的情況下也能工作,但您可以使用它來進一步配置其行為或樣式。例如,如果您總是希望以 JavaScript 獲得答案,您可以在此處宣告。在系統提示之後,您需要提供對話中所有先前的互動:使用者提問的內容和模型回答的內容。與填充情況一樣,您需要注意使用的分隔符。輸入的最後一部分必須始終是新的使用者指令,這將是模型提供答案的訊號。
以下程式碼片段演示了該模板在實踐中是如何工作的。
- 第一個使用者查詢,沒有系統提示
user = 'In Bash, how do I list all text files in the current directory (excluding subdirectories) that have been modified in the last month?'
prompt = f"<s>[INST] {user.strip()} [/INST]"
inputs = tokenizer(prompt, return_tensors="pt", add_special_tokens=False).to("cuda")
- 帶有系統提示的第一個使用者查詢
system = "Provide answers in JavaScript"
user = "Write a function that computes the set of sums of all contiguous sublists of a given list."
prompt = f"<s>[INST] <<SYS>>\\n{system}\\n<</SYS>>\\n\\n{user}[/INST]"
inputs = tokenizer(prompt, return_tensors="pt", add_special_tokens=False).to("cuda")
- 與先前答案進行的持續對話
過程與 Llama 2 中相同。為了最大限度地清晰,我們沒有使用迴圈或泛化此示例程式碼
system = "System prompt"
user_1 = "user_prompt_1"
answer_1 = "answer_1"
user_2 = "user_prompt_2"
answer_2 = "answer_2"
user_3 = "user_prompt_3"
prompt = f"<<SYS>>\n{system}\n<</SYS>>\n\n{user_1}"
prompt = f"<s>[INST] {prompt.strip()} [/INST] {answer_1.strip()} </s>"
prompt += f"<s>[INST] {user_2.strip()} [/INST] {answer_2.strip()} </s>"
prompt += f"<s>[INST] {user_3.strip()} [/INST]"
inputs = tokenizer(prompt, return_tensors="pt", add_special_tokens=False).to("cuda")
4 位載入
Code Llama 在 Transformers 中的整合意味著您可以立即獲得高階功能支援,例如 4 位載入。這允許您在 Nvidia 3090 等消費級 GPU 上執行大型 32B 引數模型!
以下是在 4 位模式下執行推理的方法:
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
import torch
model_id = "codellama/CodeLlama-34b-hf"
quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.float16
)
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
model_id,
quantization_config=quantization_config,
device_map="auto",
)
prompt = 'def remove_non_ascii(s: str) -> str:\n """ '
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
output = model.generate(
inputs["input_ids"],
max_new_tokens=200,
do_sample=True,
top_p=0.9,
temperature=0.1,
)
output = output[0].to("cpu")
print(tokenizer.decode(output))
使用 text-generation-inference 和 Inference Endpoints
Text Generation Inference 是 Hugging Face 開發的生產級推理容器,可輕鬆部署大型語言模型。它具有連續批處理、令牌流式傳輸、用於在多個 GPU 上進行快速推理的張量並行化以及生產級日誌記錄和跟蹤等功能。
您可以在自己的基礎設施上試用 Text Generation Inference,也可以使用 Hugging Face 的 Inference Endpoints。要部署 Codellama 2 模型,請訪問 模型頁面 並單擊 部署 -> Inference Endpoints 小部件。
- 對於 7B 模型,我們建議您選擇“GPU [中] - 1x Nvidia A10G”。
- 對於 13B 模型,我們建議您選擇“GPU [xlarge] - 1x Nvidia A100”。
- 對於 34B 模型,我們建議您選擇“GPU [1xlarge] - 1x Nvidia A100”並啟用
bitsandbytes
量化,或選擇“GPU [2xlarge] - 2x Nvidia A100”。
注意:您可能需要透過電子郵件向 api-enterprise@huggingface.co 申請配額升級才能訪問 A100。
您可以在我們的部落格中瞭解更多關於如何使用 Hugging Face Inference Endpoints 部署 LLM 的資訊。該部落格包含有關支援的超引數以及如何使用 Python 和 Javascript 流式傳輸響應的資訊。
使用 VS Code 擴充套件
HF Code Autocomplete 是一個 VS Code 擴充套件,用於測試開原始碼補全模型。該擴充套件是 StarCoder 專案的一部分,並已更新以支援中型基礎模型 Code Llama 13B。有關如何安裝和使用 Code Llama 擴充套件的更多資訊,請參閱此處。
評估
程式碼語言模型通常在 HumanEval 等資料集上進行基準測試。它包括程式設計挑戰,其中模型會獲得一個函式簽名和文件字串,並被要求完成函式體。然後,透過執行一組預定義的單元測試來驗證所提出的解決方案。最後,報告一個透過率,它描述了有多少解決方案通過了所有測試。pass@1 率描述了模型在一次嘗試中生成透過解決方案的頻率,而 pass@10 描述了在 10 個提出的候選方案中至少有一個解決方案透過的頻率。
雖然 HumanEval 是一個 Python 基準測試,但已經有很多努力將其翻譯成更多的程式語言,從而實現更全面的評估。其中一種方法是 MultiPL-E,它將 HumanEval 翻譯成十多種語言。我們正在基於它託管一個多語言程式碼排行榜,以便社群可以比較不同語言的模型,以評估哪個模型最適合其用例。
模型 | 許可證 | 已知資料集 | 商業用途? | 預訓練長度 [令牌] | Python | JavaScript | 排行榜平均分數 |
---|---|---|---|---|---|---|---|
CodeLlaMa-34B | Llama 2 許可證 | ❌ | ✅ | 2,500B | 45.11 | 41.66 | 33.89 |
CodeLlaMa-13B | Llama 2 許可證 | ❌ | ✅ | 2,500B | 35.07 | 38.26 | 28.35 |
CodeLlaMa-7B | Llama 2 許可證 | ❌ | ✅ | 2,500B | 29.98 | 31.8 | 24.36 |
CodeLlaMa-34B-Python | Llama 2 許可證 | ❌ | ✅ | 2,620B | 53.29 | 44.72 | 33.87 |
CodeLlaMa-13B-Python | Llama 2 許可證 | ❌ | ✅ | 2,620B | 42.89 | 40.66 | 28.67 |
CodeLlaMa-7B-Python | Llama 2 許可證 | ❌ | ✅ | 2,620B | 40.48 | 36.34 | 23.5 |
CodeLlaMa-34B-Instruct | Llama 2 許可證 | ❌ | ✅ | 2,620B | 50.79 | 45.85 | 35.09 |
CodeLlaMa-13B-Instruct | Llama 2 許可證 | ❌ | ✅ | 2,620B | 50.6 | 40.91 | 31.29 |
CodeLlaMa-7B-Instruct | Llama 2 許可證 | ❌ | ✅ | 2,620B | 45.65 | 33.11 | 26.45 |
StarCoder-15B | BigCode-OpenRail-M | ✅ | ✅ | 1,035B | 33.57 | 30.79 | 22.74 |
StarCoderBase-15B | BigCode-OpenRail-M | ✅ | ✅ | 1,000B | 30.35 | 31.7 | 22.4 |
WizardCoder-15B | BigCode-OpenRail-M | ❌ | ✅ | 1,035B | 58.12 | 41.91 | 32.07 |
OctoCoder-15B | BigCode-OpenRail-M | ✅ | ✅ | 1,000B | 45.3 | 32.8 | 24.01 |
CodeGeeX-2-6B | CodeGeeX 許可證 | ❌ | ❌ | 2,000B | 33.49 | 29.9 | 21.23 |
CodeGen-2.5-7B-Mono | Apache-2.0 | ✅ | ✅ | 1400B | 45.65 | 23.22 | 12.1 |
CodeGen-2.5-7B-Multi | Apache-2.0 | ✅ | ✅ | 1400B | 28.7 | 26.27 | 20.04 |
注意: 上表中的分數來源於釋出時我們的程式碼排行榜。分數會隨著新模型的釋出而變化,因為模型之間會進行比較。欲瞭解更多詳情,請參閱排行榜。