拉马2学习编程

拉马2学习编程' can be condensed to '拉马2学编程'.

介绍

Code Llama是一系列最先进的开放访问的Llama 2版本,专门用于代码任务,我们很高兴地发布了与Hugging Face生态系统的集成! Code Llama以与Llama 2相同的宽松社区许可证发布,并可用于商业用途。

今天,我们很高兴地发布:

  • 具有模型卡和许可证的Hub模型
  • 与Transformer的集成
  • 与快速高效的生产就绪推理的文本生成推理的集成
  • 与推理终端的集成
  • 代码基准

对于软件工程师来说,Code LLM是一个令人兴奋的发展,因为它们可以通过IDE中的代码自动补全提高生产力,处理重复或烦人的任务,如编写文档字符串或创建单元测试。

目录

  • 介绍
  • 目录
  • 什么是Code Llama?
  • 如何使用Code Llama?
    • 演示
    • 变压器
      • 代码补全
      • 代码填充
      • 对话指令
      • 4位加载
    • 使用文本生成推理和推理终端
  • 评估
  • 其他资源

什么是Code Llama?

Code Llama发布了一系列7, 13和34亿参数的模型。基本模型是从Llama 2初始化的,然后在5000亿个代码标记上进行训练。元微调了这些基本模型,以获得两种不同的风味: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的情况下,频域缩放是通过松弛实现的:微调长度是缩放的预训练长度的一部分,使模型具有强大的外推能力。

所有模型最初都是使用50亿个标记在一个几乎去重的公共可用代码数据集上进行训练的。该数据集还包含一些关于代码和代码片段的自然语言数据集。不幸的是,关于数据集的更多信息并不多。

对于指令模型,他们使用了两个数据集:为Llama 2 Chat收集的指令调整数据集和自我指导数据集。自我指导数据集是通过使用Llama 2创建面试编程问题,然后使用Code Llama生成单元测试和解决方案来创建的,这些问题和解决方案后来通过执行测试来评估。

如何使用Code Llama?

Code Llama在Hugging Face生态系统中可用,从transformers版本4.33开始。在transformers 4.33发布之前,请从主分支安装它。

演示

您可以在这个空间或以下嵌入的游乐场中轻松尝试Code Llama模型(130亿参数!):

在幕后,这个游乐场使用了Hugging Face的文本生成推理技术,这也是HuggingChat的技术,我们将在以下章节中分享更多信息。

变压器

在即将发布的transformers 4.33中,您可以使用Code Llama,并利用HF生态系统中的所有工具,例如:

  • 训练和推理脚本和示例
  • 安全文件格式(safetensors
  • 与工具的集成,如bitsandbytes(4位量化)和PEFT(参数高效微调)
  • 运行模型生成的实用程序和辅助工具
  • 导出模型以进行部署的机制

transformers 4.33发布之前,请从主分支安装它。

!pip install git+https://github.com/huggingface/transformers.git@main accelerate

代码自动补全

可以使用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"结果: {seq['generated_text']}")

这可能会产生以下输出:

结果: 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模型的baseinstruction变体中可用。对于任何34B模型或Python版本,此任务不可用。

要成功使用此功能,您需要密切注意为该任务训练模型时使用的格式,因为它使用特殊的分隔符来识别提示的不同部分。让我们看一个例子:

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")

prefix = 'def remove_non_ascii(s: str) -> str:\n    """ '
suffix = "\n    return result\n"

prompt = f"<PRE> {prefix} <SUF>{suffix} <MID>"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")

output = model.generate(
    inputs["input_ids"],
    max_new_tokens=200,
    do_sample=False,
)
output = output[0].to("cpu")
print(tokenizer.decode(output))

<s> <PRE> def remove_non_ascii(s: str) -> str:
    """ <SUF>
    return result
 <MID>
    Remove non-ASCII characters from a string.

    :param s: The string to remove non-ASCII characters from.
    :return: The string with non-ASCII characters removed.
    """
    result = ""
    for c in s:
        if ord(c) < 128:
            result += c <EOT></s>

为了使用补全功能,您需要处理输出,将位于<MID><EOT>标记之间的文本剪切出来 – 这是我们提供的前缀和后缀之间的内容。

对话指令

基础模型可以用于补全和填充,如前所述。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 = '在 Bash 中,如何列出当前目录中(不包括子目录)在最近一个月内修改过的所有文本文件?'

prompt = f"<s>[INST] {user.strip()} [/INST]"
inputs = tokenizer(prompt, return_tensors="pt", add_special_tokens=False).to("cuda")
  1. 第一个用户查询与系统提示
system = "使用 JavaScript 提供答案"
user = "编写一个计算给定列表中所有连续子列表之和集合的函数。"

prompt = f"<s><<SYS>>\\n{system}\\n<</SYS>>\\n\\n{user}"
inputs = tokenizer(prompt, return_tensors="pt", add_special_tokens=False).to("cuda")
  1. 正在进行的对话与先前的回答

这个过程与 Llama 2 中的相同。为了最大的清晰度,我们没有使用循环或将此示例代码泛化:

system = "系统提示"
user_1 = "用户提示_1"
answer_1 = "回答_1"
user_2 = "用户提示_2"
answer_2 = "回答_2"
user_3 = "用户提示_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 位加载等高级功能的支持。这使您可以在消费级 GPU(如 NVIDIA 3090 显卡)上运行大型 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))

使用文本生成推理和推理端点

文本生成推理是由Hugging Face开发的一个可供生产使用的推理容器,旨在实现大型语言模型的轻松部署。它具有连续批处理、令牌流处理、多GPU的张量并行等功能,能够实现快速推理,并提供生产级的日志记录和追踪。

您可以在自己的基础设施上尝试使用文本生成推理,也可以使用Hugging Face的推理端点。要部署Codellama 2模型,请转到模型页面,然后点击“部署 -> 推理端点”小部件。

  • 对于7B模型,我们建议选择“GPU [VoAGI] – 1x Nvidia A10G”。
  • 对于13B模型,我们建议选择“GPU [xlarge] – 1x Nvidia A100”。
  • 对于34B模型,我们建议选择启用了bitsandbytes量化的“GPU [1xlarge] – 1x Nvidia A100”或者“GPU [2xlarge] – 2x Nvidia A100”

注意:您可能需要通过电子邮件向[email protected]请求配额升级以访问A100

您可以在我们的博客中了解有关如何使用Hugging Face推理端点部署LLM的更多信息。该博客包括有关支持的超参数以及如何使用Python和Javascript流式传输响应的信息。

评估

代码语言模型通常在HumanEval等数据集上进行基准测试。它由编程挑战组成,其中模型被呈现一个函数签名和一个文档字符串,并被要求完成函数体。然后,通过运行一组预定义的单元测试来验证提议的解决方案。最后,报告一个通过率,描述了多少个解决方案通过了所有测试。pass@1率描述了模型在一次尝试时生成通过的解决方案的频率,而pass@10则描述了在10个候选解决方案中至少有一个解决方案通过的频率。

虽然HumanEval是一个Python基准测试,但已经有了将其翻译成更多编程语言的重要工作,从而实现了更全面的评估。MultiPL-E是这种方法之一,它将HumanEval翻译成十几种语言。我们在基于它的多语言代码排行榜上主办了一个多语言代码排行榜,以便社区可以比较不同语言的模型,评估哪个模型最适合他们的用例。

注意:上表中呈现的得分来自我们的代码排行榜,我们使用相同的设置评估所有模型。有关更多详细信息,请参阅排行榜。

其他资源

  • Hub上的模型
  • 论文页面
  • 官方元公告
  • 负责任使用指南
  • 演示