Code Llama: Llama 2 學會程式設計

釋出日期:2023 年 8 月 25 日
在 GitHub 上更新

引言

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 的情況下,頻域縮放是在鬆弛狀態下完成的:微調長度是縮放後的預訓練長度的一部分,這賦予了模型強大的外推能力。

Training Process

所有模型最初都在一個接近去重化的公開可用程式碼資料集上使用 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 進行推理,我們建議您在微調後使用 float16bfloat16 檢查推理結果。

如上所述,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 獲得答案,您可以在此處宣告。在系統提示之後,您需要提供對話中所有先前的互動:使用者提問的內容和模型回答的內容。與填充情況一樣,您需要注意使用的分隔符。輸入的最後一部分必須始終是新的使用者指令,這將是模型提供答案的訊號。

以下程式碼片段演示了該模板在實踐中是如何工作的。

  1. 第一個使用者查詢,沒有系統提示
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")
  1. 帶有系統提示的第一個使用者查詢
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")
  1. 與先前答案進行的持續對話

過程與 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 擴充套件的更多資訊,請參閱此處

VS Code extension

評估

程式碼語言模型通常在 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

注意: 上表中的分數來源於釋出時我們的程式碼排行榜。分數會隨著新模型的釋出而變化,因為模型之間會進行比較。欲瞭解更多詳情,請參閱排行榜

附加資源

社群

註冊登入 發表評論

© . This site is unofficial and not affiliated with Hugging Face, Inc.