CodeLlama
概述
Code Llama模型由Baptiste Rozière、Jonas Gehring、Fabian Gloeckle、Sten Sootla、Itai Gat、Xiaoqing Ellen Tan、Yossi Adi、Jingyu Liu、Tal Remez、Jérémy Rapin、Artyom Kozhevnikov、Ivan Evtimov、Joanna Bitton、Manish Bhatt、Cristian Canton Ferrer、Aaron Grattafiori、Wenhan Xiong、Alexandre Défossez、Jade Copet、Faisal Azhar、Hugo Touvron、Louis Martin、Nicolas Usunier、Thomas Scialom、Gabriel Synnaeve在Code Llama: Open Foundation Models for Code中提出。
论文的摘要如下:
我们发布了Code Llama,这是一个基于Llama 2的代码大语言模型家族,提供了开源模型中最先进的性能、填充能力、对大输入上下文的支持以及编程任务的零样本指令跟随能力。我们提供了多种版本以覆盖广泛的应用场景:基础模型(Code Llama)、Python专用模型(Code Llama - Python)和指令跟随模型(Code Llama - Instruct),每个模型都有7B、13B和34B参数。所有模型都在16k个标记的序列上进行训练,并在最多100k个标记的输入上显示出改进。7B和13B的Code Llama和Code Llama - Instruct变体支持基于周围内容的填充。Code Llama在多个代码基准测试中达到了开源模型的最先进性能,在HumanEval和MBPP上的得分分别高达53%和55%。值得注意的是,Code Llama - Python 7B在HumanEval和MBPP上优于Llama 2 70B,并且我们所有的模型在MultiPL-E上都优于其他所有公开可用的模型。我们在一个允许研究和商业使用的宽松许可下发布了Code Llama。
查看所有Code Llama模型检查点 这里 以及官方发布的在 Meta Llama 组织 中的模型。
该模型由ArthurZucker贡献。作者的原始代码可以在这里找到。
使用技巧和示例
Code Llama 所基于的 Llama2
系列模型是使用 bfloat16
进行训练的,但原始推理使用的是 float16
。让我们来看看不同的精度:
float32
: PyTorch 在模型初始化时的惯例是使用float32
加载模型,无论模型权重是以哪种dtype
存储的。transformers
也遵循这一惯例,以保持与 PyTorch 的一致性。默认情况下会使用这一设置。如果你希望AutoModel
API 以存储权重类型加载检查点,你必须指定torch_dtype="auto"
,例如model = AutoModelForCausalLM.from_pretrained("path", torch_dtype = "auto")
。bfloat16
: Code Llama 是用这种精度训练的,因此我们建议在进一步训练或微调时使用它。float16
: 我们建议使用这种精度进行推理,因为它通常比bfloat16
更快,并且评估指标显示相对于bfloat16
没有明显的退化。你也可以使用bfloat16
进行推理,我们建议你在微调后检查float16
和bfloat16
的推理结果。
如上所述,存储权重的dtype
大多无关紧要,除非你在初始化模型时使用torch_dtype="auto"
。原因是模型会首先被下载(使用在线检查点的dtype
),然后会被转换为torch
的默认dtype
(变为torch.float32
)。如果有指定的torch_dtype
,则会使用该指定的dtype
。
提示:
- 填充任务开箱即用。您应该在希望填充输入的地方使用
tokenizer.fill_token
。 - 模型转换脚本与
Llama2
系列相同:
这是一个示例用法:
python src/transformers/models/llama/convert_llama_weights_to_hf.py \ --input_dir /path/to/downloaded/llama/weights --model_size 7B --output_dir /output/path
请注意,执行脚本需要足够的CPU内存来以float16精度托管整个模型(即使最大的版本分为多个检查点,每个检查点都包含模型每个权重的一部分,因此我们需要将它们全部加载到内存中)。
转换后,可以通过以下方式加载模型和分词器:
>>> from transformers import LlamaForCausalLM, CodeLlamaTokenizer
>>> tokenizer = CodeLlamaTokenizer.from_pretrained("meta-llama/CodeLlama-7b-hf")
>>> model = LlamaForCausalLM.from_pretrained("meta-llama/CodeLlama-7b-hf")
>>> PROMPT = '''def remove_non_ascii(s: str) -> str:
... """ <FILL_ME>
... return result
... '''
>>> input_ids = tokenizer(PROMPT, return_tensors="pt")["input_ids"]
>>> generated_ids = model.generate(input_ids, max_new_tokens=128)
>>> filling = tokenizer.batch_decode(generated_ids[:, input_ids.shape[1]:], skip_special_tokens = True)[0]
>>> print(PROMPT.replace("<FILL_ME>", filling))
def remove_non_ascii(s: str) -> str:
""" Remove non-ASCII characters from a string.
<BLANKLINE>
Args:
s: The string to remove non-ASCII characters from.
<BLANKLINE>
Returns:
The string with non-ASCII characters removed.
"""
result = ""
for c in s:
if ord(c) < 128:
result += c
return result
<BLANKLINE>
如果你只想要填充的部分:
>>> from transformers import pipeline
>>> import torch
>>> generator = pipeline("text-generation",model="meta-llama/CodeLlama-7b-hf",torch_dtype=torch.float16, device_map="auto")
>>> generator('def remove_non_ascii(s: str) -> str:\n """ <FILL_ME>\n return result', max_new_tokens = 128)
[{'generated_text': 'def remove_non_ascii(s: str) -> str:\n """ <FILL_ME>\n return resultRemove non-ASCII characters from a string. """\n result = ""\n for c in s:\n if ord(c) < 128:\n result += c'}]
在底层,分词器自动通过
进行分割,以创建一个遵循原始训练模式的格式化输入字符串。这比自己准备模式更稳健:它避免了诸如标记粘合等非常难以调试的问题。要查看此模型或其他模型所需的CPU和GPU内存量,请尝试此计算器,它可以帮助确定该值。
LLaMA 分词器是一个基于 sentencepiece 的 BPE 模型。sentencepiece 的一个特点是,当解码一个序列时,如果第一个标记是单词的开头(例如“Banana”),分词器不会在字符串前添加前缀空格。
Code Llama 具有与 Llama2
模型相同的架构,请参考 Llama2 的文档页面 获取 API 参考。
以下是 Code Llama 分词器的参考。
CodeLlamaTokenizer
类 transformers.CodeLlamaTokenizer
< source >( vocab_file unk_token = '' eos_token = '' prefix_token = '▁
'middle_token = '▁
参数
- vocab_file (
str
) — 词汇表文件的路径。 - unk_token (
str
, 可选, 默认为"
) — 未知标记。不在词汇表中的标记无法转换为ID,而是设置为这个标记。" - bos_token (
str
, optional, defaults to"
) — 在预训练期间使用的序列开始标记。可以用作序列分类器标记。" - eos_token (
str
, optional, defaults to"</s>"
) — The end of sequence token.在使用特殊标记构建序列时,这不是用于序列结束的标记。 使用的标记是
sep_token
。 - prefix_token (
str
, optional, defaults to"▁
) — 用于填充的前缀标记。"
- middle_token (
str
, 可选, 默认为"▁
) — 用于填充的中间标记。" - suffix_token (
str
, optional, defaults to"▁
) — 用于填充的后缀标记。" - eot_token (
str
, 可选, 默认为"▁
) — 用于填充的文本结束标记。" - fill_token (
str
, optional, defaults to"
) — 用于在输入的前缀和后缀之间进行分割的标记。" - suffix_first (
bool
, 可选, 默认为False
) — 输入提示和后缀是否应以后缀优先的格式进行格式化。 - sp_model_kwargs (
dict
, optional) — Will be passed to theSentencePieceProcessor.__init__()
method. The Python wrapper for SentencePiece can be used, among other things, to set:-
enable_sampling
: 启用子词正则化。 -
nbest_size
: 用于unigram的采样参数。对于BPE-Dropout无效。nbest_size = {0,1}
: No sampling is performed.nbest_size > 1
: samples from the nbest_size results.nbest_size < 0
: assuming that nbest_size is infinite and samples from the all hypothesis (lattice) using forward-filtering-and-backward-sampling algorithm.
-
alpha
: 用于单字采样的平滑参数,以及BPE-dropout的合并操作丢弃概率。
-
- add_bos_token (
bool
, optional, defaults toTrue
) — 是否在序列的开头添加一个序列开始标记。 - add_eos_token (
bool
, optional, defaults toFalse
) — 是否在序列的末尾添加一个序列结束标记。 - clean_up_tokenization_spaces (
bool
, optional, defaults toFalse
) — 是否清理分词后的空格。 - additional_special_tokens (
List[str]
, optional) — 分词器使用的额外特殊标记。 - use_default_system_prompt (
bool
, optional, 默认为False
) — 是否应使用Llama的默认系统提示。
构建一个CodeLlama分词器。基于字节级别的字节对编码。默认的填充标记未设置,因为原始模型中没有填充标记。
默认配置与 codellama/CodeLlama-7b-Instruct-hf 相匹配,支持提示填充。
get_special_tokens_mask
< source >( token_ids_0: typing.List[int] token_ids_1: typing.Optional[typing.List[int]] = None already_has_special_tokens: bool = False ) → List[int]
从没有添加特殊标记的标记列表中检索序列ID。当使用标记器的prepare_for_model
方法添加特殊标记时,会调用此方法。
create_token_type_ids_from_sequences
< source >( token_ids_0: typing.List[int] token_ids_1: typing.Optional[typing.List[int]] = None ) → List[int]
从传递给序列对分类任务的两个序列中创建一个掩码。一个ALBERT
如果 token_ids_1 为 None,则只返回掩码的第一部分(0s)。
保存词汇表
< source >( save_directory filename_prefix: typing.Optional[str] = None ) → Tuple(str)
将词汇表和特殊标记文件保存到一个目录中。
CodeLlamaTokenizerFast
类 transformers.CodeLlamaTokenizerFast
< source >( vocab_file = None tokenizer_file = None clean_up_tokenization_spaces = False unk_token = '' eos_token = '' prefix_token = '▁
'middle_token = '▁
参数
- vocab_file (
str
, 可选) — SentencePiece 文件(通常具有 .model 扩展名),包含实例化分词器所需的词汇表。 - tokenizer_file (
str
, 可选) — tokenizers 文件(通常具有 .json 扩展名),包含加载分词器所需的所有内容。 - clean_up_tokenization_spaces (
str
, optional, defaults toFalse
) — 是否在解码后清理空格,清理包括移除潜在的额外空格等可能的痕迹。 - unk_token (
str
, optional, defaults to"
) — 未知标记。不在词汇表中的标记无法转换为ID,而是设置为这个标记。" - bos_token (
str
, optional, defaults to"
) — 在预训练期间使用的序列开始标记。可以用作序列分类器标记。" - eos_token (
str
, optional, defaults to""
) — 序列结束标记。 - prefix_token (
str
, optional, defaults to"▁
) — 用于填充的前缀标记。"
- middle_token (
str
, 可选, 默认为"▁
) — 用于填充的中间标记。" - suffix_token (
str
, 可选, 默认为"▁
) — 用于填充的后缀标记。" - eot_token (
str
, optional, defaults to"▁
) — 用于填充的文本结束标记。" - fill_token (
str
, optional, defaults to"
) — 用于在输入的前缀和后缀之间进行分割的标记。" - additional_special_tokens (
List[str]
, optional) — 分词器使用的额外特殊标记。 - add_bos_token (
bool
, optional, defaults toTrue
) — 是否在序列的开头添加一个序列开始标记。 - add_eos_token (
bool
, optional, defaults toFalse
) — 是否在序列的末尾添加一个序列结束标记。 - use_default_system_prompt (
bool
, optional, 默认为False
) — 是否应使用Llama的默认系统提示。
构建一个Llama分词器。基于字节级的字节对编码。
这主要使用了ByteFallback并且没有进行标准化。
>>> from transformers import CodeLlamaTokenizerFast
>>> tokenizer = CodeLlamaTokenizerFast.from_pretrained("hf-internal-testing/llama-tokenizer")
>>> tokenizer.encode("Hello this is a test")
[1, 15043, 445, 338, 263, 1243]
如果你想更改bos_token
或eos_token
,请确保在初始化模型时指定它们,或者调用tokenizer.update_post_processor()
以确保后处理正确完成(否则编码序列的第一个标记和最后一个标记的值将不正确)。更多详情,请查看[后处理器] (https://huggingface.co/docs/tokenizers/api/post-processors) 文档。
这个分词器继承自PreTrainedTokenizerFast,其中包含了大部分主要方法。用户应参考这个超类以获取有关这些方法的更多信息。默认配置与meta-llama/CodeLlama-7b-Instruct-hf匹配,支持提示填充。
build_inputs_with_special_tokens
< source >( token_ids_0: typing.List[int] token_ids_1: typing.Optional[typing.List[int]] = None ) → List[int]
通过连接和添加特殊标记,从序列或序列对构建序列分类任务的模型输入。特殊标记取决于调用set_lang。
一个NLLB序列具有以下格式,其中X
代表序列:
input_ids
(用于编码器)X [eos, src_lang_code]
decoder_input_ids
: (用于解码器)X [eos, tgt_lang_code]
BOS 从未被使用。序列对不是预期的使用场景,但它们将在没有分隔符的情况下处理。
get_special_tokens_mask
< source >( token_ids_0: typing.List[int] token_ids_1: typing.Optional[typing.List[int]] = None already_has_special_tokens: bool = False ) → 一个在范围 [0, 1] 内的整数列表
从没有添加特殊标记的标记列表中检索序列ID。当使用标记器的prepare_for_model
或encode_plus
方法添加特殊标记时,会调用此方法。
create_token_type_ids_from_sequences
< source >( token_ids_0: typing.List[int] token_ids_1: typing.Optional[typing.List[int]] = None ) → List[int]
创建与传递的序列相对应的令牌类型ID。什么是令牌类型ID?
如果模型有特殊的构建方式,应该在子类中重写。
使用当前的bos_token
和eos_token
更新底层后处理器。