Code Llama:Llama 2 學(xué)會寫代碼了!
引言
Code Llama 是為代碼類任務(wù)而生的一組最先進(jìn)的、開放的 Llama 2 模型,我們很高興能將其集成入 Hugging Face 生態(tài)系統(tǒng)!Code Llama 使用與 Llama 2 相同的社區(qū)許可證,且可商用。
今天,我們很高興能發(fā)布 Hugging Face 對 Code Llama 的全面支持 , 包括:
-
Hub 上的模型支持,包括模型卡及許可證 -
Transformers 已集成 Code Llama -
TGI 已集成 Code Llama,以支持對其進(jìn)行快速高效的產(chǎn)品級推理 -
推理終端 (Inference Endpoints) 已集成 Code Llama -
對 Code Llama 的代碼基準(zhǔn)測試結(jié)果已發(fā)布
代碼大語言模型的發(fā)展對于軟件工程師來說無疑是振奮人心的,因為這意味著他們可以通過 IDE 中的代碼補(bǔ)全功能來提高生產(chǎn)力,并利用其來處理重復(fù)或煩人的任務(wù),例如為代碼編寫文檔字符串或創(chuàng)建單元測試。
目錄
-
引言 -
目錄 -
Code Llama 簡介 -
如何使用 Code Llama? -
代碼補(bǔ)全 -
代碼填充 -
對話式指令 -
4 比特加載 -
演示 -
Transformers -
使用 TGI 和推理終端 -
評估 -
其他資源
Code Llama 簡介
Code Llama 包含 3 個不同參數(shù)量的版本,分別為: 7 億參數(shù)版、13 億參數(shù)版 以及 340 億參數(shù)版。在訓(xùn)練基礎(chǔ)模型時,先用同等參數(shù)量的 Llama 2 模型初始化權(quán)重,然后在 5000 億詞元的代碼數(shù)據(jù)集上訓(xùn)練。Meta 還對訓(xùn)得的基礎(chǔ)模型進(jìn)行了兩種不同風(fēng)格的微調(diào),分別為: Python 專家版 (再加 1000 億個額外詞元) ; 以及指令微調(diào)版,其可以理解自然語言指令。
這些模型在 Python、C++、Java、PHP、C#、TypeScript 和 Bash 中都展現(xiàn)出最先進(jìn)的性能。7B 和 13B 基礎(chǔ)版和指令版支持完形填空,因此非常適合用作代碼助手。
Code Llama 基于 16k 上下文窗口訓(xùn)練。此外,這三個尺寸的模型還進(jìn)行了額外的長上下文微調(diào),使其上下文窗口最多可擴(kuò)展至 10 萬詞元。
受益于 RoPE 擴(kuò)展方面的最新進(jìn)展,將 Llama 2 的 4k 上下文窗口增加到 Code Llama 的 16k (甚至可以外插至 100k) 成為可能。社區(qū)發(fā)現(xiàn)可以對 Llama 的位置嵌入進(jìn)行線性插值或頻域插值,這使得通過微調(diào)讓基礎(chǔ)模型輕松擴(kuò)展到更大的上下文窗口成為可能。在 Code Llama 中,他們把頻域縮放和松弛技術(shù)二者結(jié)合起來: 微調(diào)長度是縮放后的預(yù)訓(xùn)練長度的一小部分。這個做法賦予了模型強(qiáng)大的外推能力。
第一步是在 5000 億詞元的公開代碼數(shù)據(jù)集上訓(xùn)練出一個模型。該數(shù)據(jù)集中除了有代碼數(shù)據(jù)集外,還包含一些自然語言數(shù)據(jù)集,例如有關(guān)代碼和代碼片段的討論,且最終數(shù)據(jù)集是使用近似去重法去過重的。不幸的是,Meta 沒有披露有關(guān)該數(shù)據(jù)集的更多信息。
在對模型進(jìn)行指令微調(diào)時,使用了兩個數(shù)據(jù)集: 為 Llama 2 Chat 收集的指令微調(diào)數(shù)據(jù)集和自指令數(shù)據(jù)集。自指令數(shù)據(jù)集收集了 Llama 2 編制出的編程面試問題,然后使用 Code Llama 生成單元測試和解答,最后通過執(zhí)行測試來評估解答。
如何使用 Code Llama?
Transformers 從 4.33 版開始支持 Code Llama。在此之前,需要從主分支進(jìn)行源代碼安裝才行。
演示
我們準(zhǔn)備了 這個 Space 或下面的 Playground 以供大家嘗試 Code Llama 模型 (130 億參數(shù)!):
這個演示背后使用了 Hugging Face TGI,HuggingChat 也用了相同的技術(shù),具體內(nèi)容見下文。
你還可以玩玩 這個聊天機(jī)器人,或者復(fù)制一份到自己的賬號下以供你使用 – 它是自含的,因此你可以隨心所欲地修改代碼!
Transformers
從最新發(fā)布的 transformers 4.33 開始,你可以在 Code Llama 上應(yīng)用 HF 生態(tài)系統(tǒng)中的所有工具,例如:
-
訓(xùn)練和推理腳本和示例 -
安全的文件格式 ( safetensors) -
與 bitsandbytes(4 比特量化) 和 PEFT 等工具結(jié)合使用 -
運行模型生成所需的工具及輔助代碼 -
導(dǎo)出模型以進(jìn)行部署的機(jī)制
在 transformers 4.33 發(fā)布之前,用戶需要從主分支源碼安裝 transformers 。
!pip install git+https://github.com/huggingface/transformers.git@main accelerate
代碼補(bǔ)全
我們可以使用 7B 和 13B 模型進(jìn)行文本/代碼補(bǔ)全或填充。下述代碼演示了如何使用 pipeline 接口來進(jìn)行文本補(bǔ)全。運行時,只需選擇 GPU 即可在 Colab 的免費 GPU 上運行。
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 雖然專精于代碼理解,但其仍是一個語言模型。你仍然可以使用相同的生成策略來自動完成注釋或自然語言文本。
代碼填充
這是代碼模型才能完成的專門任務(wù)。該模型經(jīng)過訓(xùn)練后,可以生成與給定上下文最匹配的代碼 (包括注釋)。這是代碼助理的典型使用場景: 要求它們根據(jù)上下文填充當(dāng)前光標(biāo)處的代碼。
此任務(wù)需要使用 7B 和 13B 的 基礎(chǔ) 或 指令 模型。任何 34B 或 Python 版模型不能用于此任務(wù)。
填充類任務(wù)需要在生成時使用與訓(xùn)練時相同格式的輸入文本,因為訓(xùn)練時會使用特殊的分隔符來區(qū)分提示的不同部分。幸運的是, transformers 的 CodeLlamaTokenizer 已經(jīng)幫你把這事做了,如下所示:
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> 分割 并生成一個格式化的輸入字符串,其格式與 訓(xùn)練時的格式 相同。這樣做既避免了用戶自己格式化的很多麻煩,也避免了一些很難調(diào)試的陷阱,例如詞元粘合 (token glueing)。
對話式指令
如上所述,基礎(chǔ)模型可用于補(bǔ)全和填充。Code Llama 還包含一個適用于對話場景的指令微調(diào)模型。
為此類任務(wù)準(zhǔn)備輸入時,我們需要一個提示模板。一個例子是我們在 Llama 2 博文 中描述的模板,如下:
<s>[INST] <<SYS>>
{{ system_prompt }}
<</SYS>>
{{ user_msg_1 }} [/INST]{{ model_answer_1 }} </s><s>[INST]{{ user_msg_2 }} [/INST]
請注意,系統(tǒng)提示 ( system prompt ) 是可選的 - 沒有它模型也能工作,但你可以用它來進(jìn)一步指定模型的行為或風(fēng)格。例如,如果你希望獲得 JavaScript 的答案,即可在此聲明。在系統(tǒng)提示之后,你需要提供對話交互歷史: 用戶問了什么以及模型回答了什么。與填充場景一樣,你需要注意分隔符的使用。輸入的最后必須是新的用戶指令,這對模型而言是讓其提供答案的信號。
以下代碼片段演示了如何在實際工作中使用該模板。
-
首次用戶輸入,無系統(tǒng)提示
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")
-
首次用戶查詢,有系統(tǒng)提示
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><<SYS>>\\n{system}\\n<</SYS>>\\n\\n{user}"
inputs = tokenizer(prompt, return_tensors="pt", add_special_tokens=False).to("cuda")
-
含對話歷史的多輪對話
該過程與 Llama 2 中的過程相同。為了最清楚起見,我們沒有使用循環(huán)或泛化此示例代碼:
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 比特加載等高級功能的支持。這使得用戶可以在英偉達(dá) 3090 卡等消費類 GPU 上運行大型的 32B 參數(shù)量模型!
以下是在 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))
使用 TGI 和推理終端
TGI 是 Hugging Face 開發(fā)的生產(chǎn)級推理容器,可用于輕松部署大語言模型。它包含連續(xù)批處理、流式輸出、基于張量并行的多 GPU 快速推理以及生產(chǎn)級的日志記錄和跟蹤等功能。
你可以在自己的基礎(chǔ)設(shè)施上使用 TGI,也可以使用 Hugging Face 的 推理終端。要部署 Codellama 2 模型,請登陸其 模型頁面,然后單擊 Deploy -> Inference Endpoints 按鈕。
-
推理 7B 模型,我們建議選擇“GPU [medium] - 1x Nvidia A10G”。 -
推理 13B 模型,我們建議選擇“GPU [xlarge] - 1x Nvidia A100”。 -
推理 34B 模型,我們建議啟用 bitsandbytes量化并選擇“GPU [1xlarge] - 1x Nvidia A100”或“GPU [2xlarge] - 2x Nvidia A100”
注意: 你可能需要發(fā)郵件給 [email protected] 申請配額升級才能訪問 A100
你可以在我們的博文中詳細(xì)了解如何 使用 Hugging Face 推理終端部署 LLM,該 博文 還包含了有關(guān)其支持的超參以及如何使用 Python 和 Javascript API 流式生成文本的相關(guān)知識。
評估
代碼語言模型通常在 HumanEval 等數(shù)據(jù)集上進(jìn)行基準(zhǔn)測試,其包含了一系列編程題,我們將函數(shù)簽名和文檔字符串輸入給模型,模型需要完成函數(shù)體代碼的編寫。接著是運行一組預(yù)定義的單元測試來驗證所提出的解答。最后是報告通過率,即有多少解答通過了所有測試。pass@1 度量了模型一次生成即通過的頻率,而 pass@10 描述了模型生成 10 個候選解答其中至少有一個解答通過的頻率。
雖然 HumanEval 是一個 Python 基準(zhǔn)測試,但社區(qū)付出了巨大努力將其轉(zhuǎn)成更多編程語言,從而實現(xiàn)更全面的評估。其中一種方法是 MultiPL-E,它將 HumanEval 翻譯成十多種編程語言。我們正在基于其制作一個 多語言代碼排行榜,這樣社區(qū)就可以用它來比較不同模型在各種編程語言上的表現(xiàn),以評估哪個模型最適合他們的需求。
| 模型 | 許可證 | 訓(xùn)練數(shù)據(jù)集是否已知 | 是否可商用 | 預(yù)訓(xùn)練詞元數(shù) | Python | JavaScript | Leaderboard Avg Score |
|---|---|---|---|---|---|---|---|
| CodeLlaMa-34B | Llama 2 license | ? | ? | 2,500B | 45.11 | 41.66 | 33.89 |
| CodeLlaMa-13B | Llama 2 license | ? | ? | 2,500B | 35.07 | 38.26 | 28.35 |
| CodeLlaMa-7B | Llama 2 license | ? | ? | 2,500B | 29.98 | 31.8 | 24.36 |
| CodeLlaMa-34B-Python | Llama 2 license | ? | ? | 2,620B | 53.29 | 44.72 | 33.87 |
| CodeLlaMa-13B-Python | Llama 2 license | ? | ? | 2,620B | 42.89 | 40.66 | 28.67 |
| CodeLlaMa-7B-Python | Llama 2 license | ? | ? | 2,620B | 40.48 | 36.34 | 23.5 |
| CodeLlaMa-34B-Instruct | Llama 2 license | ? | ? | 2,620B | 50.79 | 45.85 | 35.09 |
| CodeLlaMa-13B-Instruct | Llama 2 license | ? | ? | 2,620B | 50.6 | 40.91 | 31.29 |
| CodeLlaMa-7B-Instruct | Llama 2 license | ? | ? | 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 License | ? | ? | 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 |
注意: 上表中的分?jǐn)?shù)來自我們的代碼排行榜,所有模型均使用相同的設(shè)置。欲了解更多詳情,請參閱 排行榜。
其他資源
-
Hub 上的模型 -
論文 -
Meta 官宣博文 -
負(fù)責(zé)任使用指南 -
演示 (代碼補(bǔ)全,流式生成) 演示 (指令微調(diào)、自含、可復(fù)制到自己的空間并修改)
?? 寶子們可以戳 閱讀原文 查看文中所有的外部鏈接喲!
英文原文: https://hf.co/blog/codellama
原文作者: Philipp Schmid,Omar Sanseviero,Pedro Cuenca,Lewis Tunstall,Leandro von Werra,Loubna Ben Allal,Arthur Zucker,Joao Gante
譯者: Matrix Yao (姚偉峰),英特爾深度學(xué)習(xí)工程師,工作方向為 transformer-family 模型在各模態(tài)數(shù)據(jù)上的應(yīng)用及大規(guī)模模型的訓(xùn)練推理。
審校/排版: zhongdongy (阿東)
