赞
踩
本文精讲代码生成的发展史与其背后的技术原理,总计4个部分
我们在这篇文章《ChatGPT技术原理解析:从RL之PPO算法、RLHF到GPT4、instructGPT》中的2.5节有提到,“2021 年7月,OpenAI发布Codex的论文《Evaluating Large Language Models Trained on Code》,其中初始的Codex是根据120亿参数的GPT-3变体进行微调的,且通过对159GB的Python代码进行代码训练,后来这个120 亿参数的模型演变成OpenAI API中的code-cushman-001,具备较强的代码/推理能力”
接下来,我们来看下Codex背后的原理到底是怎样的,即其是如何一步一步训练出来的
为了准确地对Codex进行基准测试,OpenAI创建了一个包含164个原始编程问题的数据集,并进行了单元测试
为了解决该测试集中的一个个编程问题,让Codex生成了多个答案,并检查其中是否有通过单元测试的样本
当然,如果对于某个编程问题,让Codex生成100个答案的话,那Codex-S能够为77.5%的问题生成至少一个正确的答案,这一结果表明,可以通过启发式排序来选择准确的代码样本,而不是充分评估每个样本(This result suggests that accurate code samples can be selected via heuristic ranking instead of fully evaluating each sample)
事实上,我们发现对数概率均值最高的样本通过了44.5%问题的单元测试(Indeed, we find that the sample with highest mean log-probability passes unit tests for 44.5% of the problems)
代码的生成模型主要通过与参考解决方案匹配样本来进行基准测试,其中匹配可以是精确的或模糊的(如BLEU分数)。然而Ren等人(2020)发现BLEU在捕获特定于代码的语义特征方面存在问题,并建议对分数进行一些语义修改,说白了,BLEU在基于匹配的代码指标方面存在缺陷
为方便大家对上述pass@k的计算过程有更好的理解,故我还是推导下其计算公式
通过最后的式子可知,式子中第二项的分子有2n-c-k项相乘,其分母也有2n-c-k项相乘,很容易导致相乘的结果超出整数所能表示的范围
下面单独分析一下这个式子
然后把上式拆成两项,可得
最后的结果相当于便是论文中的写法,即,从而也就与论文中给出的稳定版的代码一致了
def pass_at_k(n, c, k): """ :param n: total number of samples :param c: number of correct samples :param k: k in pass@$k$ """ if n - c < k: return 1.0 return 1.0 - np.prod(1.0 - k / np.arange(n - c + 1, n + 1))
因为GPT3只能解决一些相对简单的代码问题(因为其训练数据中并没有特别多的代码),但解决不了相对复杂的代码问题,故Codex通过对12B参数大小的GPT3进行微调
其训练数据集是在2020年5月从GitHub上托管的5400万个公共软件库中收集的,一开始有179 GB的Python代码,但随着过滤掉了可能是自动生成的文件,平均行长度大于100,最大行长度大于1000,或者包含一小部分字母数字字符,最终数据集大小为159 GB
Codex使用与GPT模型相同的学习率,具有175步线性热身和余弦学习率衰减。我们使用具有β1= 0.9,β2= 0.95,=10−8,权重衰减系数为0.1的Adam优化器,对总共1000亿个token进行训练「We train Codex using the same learning rate as the corre-sponding GPT model, with a 175 step linear warmup andcosine learning rate decay. We train for a total of 100 billiontokens, using the Adam optimizer with β1 = 0.9, β2 = 0.95, = 10−8 , and a weight decay coefficient of 0.1.」
之后,有个问题是在预测当前序列的最后一个词时,可以选取概率最大的词(softmax最高的值),但没法全局最优且不具备多样性(因为每次局部最优不代表最终全局最优,且每次都是取概率最大的词,则无论采样多少次,答案都是唯一没有多样性),对此
据GitHub copilot官方介绍的页面称
GitHub Copilot通过OpenAI的Codex演变而来,在大量公共源代码上进行了培训。它既擅长编写自然语言,也擅长编写代码,因此实际上它可以为您完成注释。在下面的例子中,我们首先让它不全我们的注释,然后,一行一行地,完成注释所要求的的功能
GitHub Copilot的一个重要用例是减少编写单元测试的一些苦差事。比如当我们实现了一个计算两个列表的公共前缀的代码后(we already have an implementation of a function that computes the common prefix of two lists),我们想要测试它
为此,我们导入单元测试包,然后我们开始编写一个测试函数,让Copilot生成asserts,我们只需按Tab键就可以接受这些断言
比如我们还可以通过GitHub Copilot把嵌入式SQL生成Go(只需将模式显示为CREATE TABLE语句),具体如下图
// 待更
Code Llama 基于特定的代码数据集在Llama 2上进一步微调训练而成,可以根据代码和自然语言提示生成代码,它还可帮助用户进行代码补全和调试代码
且Code Llama 的开源协议与 Llama 2 一样,免费用于研究以及商用目的, 其对应的论文为《Code Llama: Open Foundation Models for Code》,此为其GitHub 地址
下表为 Code Llama、Code Llama-Python 的训练数据集
对长序列的有效处理是基于transformer的语言建模的一个主要研究课题(Vaswani et al., 2017)。基本的建模挑战是外推,即在训练时间以外的序列长度上进行操作,以及有利于在短到中等长度输入上进行训练的注意力传递的二次复杂度(Effective handling of long sequences is a major topic of research in transformer-based language model-ing (Vaswani et al., 2017). The fundamental modeling challenges are extrapolation, i.e., operating on sequencelengths beyond those seen at training time, and the quadratic complexity of attention passes which favors training on short-to-medium length inputs.)
具体来说,在旋转嵌入中,位置n的query和key向量xn受到线性变换RΘd,n xn,其中RΘd,n是一个分块对角矩阵,其形式为(Specifically, with rotary embeddings, the query and key vectors xn at position n are subject to a linear transformation RΘd,n xn, where RΘd,nis a blockdiagonal matrix with entries of the form)
而d表示嵌入维数。旋转频率计算为θi=θ−2i/d,为了进行微调,我们将基准周期θ从10000增加到1,000,000。这种增加允许处理更大的序列,并减少对短距离注意力的偏差「d denotes the embedding dimension. Rotation frequencies are computed as θi = θ−2i/d , and we increasethe base period θfrom 10,000 to 1,000,000 for fine-tuning. This increase allows for processing much largersequences and reduces bias towards short-distance attention (see Appendix F.1 for further discussion).」
我们的实验证实,Code Llama模型不仅在微调期间使用的增加的序列长度内有效,而且进一步显示外推能力,不仅提供了多达 100000 个上下文 token 的稳定生成,所有模型的训练 token 序列也高达 16000「Ourexperiments confirm that Code Llama models are not only effective within the increased sequence lengthused during fine-tuning, but further show extrapolation capabilities and exhibit stable behavior on very longsequences of up to 100,000 tokens (Section 3.3).」
// 待更
Meta 使用了 HumanEval 和 MBPP(Mostly Basic Python Programming)两个编码基准进行测试。我们已经知道,HumanEval 测试模型基于文档字符串(docstrings)完成代码的能力,而MBPP 则测试模型基于描述编写代码的能力,具体而言
// 待更
关于大型预训练代码模型,除了OpenAI的Codex,还包括
很快,推出了ChatGLM的智谱AI发布了CodeGeeX,参数规模为13B,在23种编程语言的大型代码语料库上进行了预训练,且支持集成到Visual Studio Code、JetBrains等编译器里
与最近的预训练模型(如GPT-3 (Brown等人,2020)、PaLM (Chowdhery等人,2022)和Codex (Chen等人,2021)类似,CodeGeeX遵循生成式预训练(GPT)架构(Radford等人,2018),采用自回归(编程)语言建模的解码器风格
CodeGeeX的核心架构是一个39层的transformer解码器
此外,通过采用GPT范式,我们在大量未标记的代码数据上训练模型。其原理是迭代地将代码token作为输入,预测下一个token,并将其与ground truth进行比较,具体来说
原始的GPT模型使用pooler function来获得最终输出。我们在所有其他transformer层之上使用一个额外的查询层(Zeng et al., 2021),通过attention获得最终的嵌入(如上图所示,he input of the top query layer replaces the query input by the query embedding of position n + 1)。最后的输出再乘以词嵌入矩阵的转置,得到输出概率(The final output is multiplied by the transpose of word embedding matrix to get the output probability)
对于解码策略,CodeGeeX支持贪婪、温度采样、top-k采样、top-p采样和束搜索(greedy, temperature sampling, top-k sampling, top-p sampling, and beam search)
最后,detokenization的操作再将把选中的token ID变成一个实际的单词
训练语料库包含两部分
为提高训练效率
据CodeGeeX2的GitHub页面所称,其是多语言代码生成模型 CodeGeeX (KDD’23) 的第二代模型。不同于一代 CodeGeeX(完全在国产华为昇腾芯片平台训练)
更多特性包括:
我们开发了支持 VS Code、 IntelliJ IDEA、PyCharm、GoLand、WebStorm、Android Studio 等IDE的 CodeGeeX 插件。在插件中,可以更直接地体验到 CodeGeeX2 模型在代码生成与补全、添加注释、代码翻译及技术问答方面的能力为开发效率带来的提升。欢迎在IDE中下载 CodeGeeX 插件获得更加全面的AI编程体验,详情见CodeGeeX主页
transformers
快速调用CodeGeeX2-6B- from transformers import AutoTokenizer, AutoModel
- tokenizer = AutoTokenizer.from_pretrained("THUDM/codegeex2-6b", trust_remote_code=True)
- model = AutoModel.from_pretrained("THUDM/codegeex2-6b", trust_remote_code=True, device='cuda')
- model = model.eval()
-
- # remember adding a language tag for better performance
- prompt = "# language: Python\n# write a bubble sort function\n"
- inputs = tokenizer.encode(prompt, return_tensors="pt").to(model.device)
- outputs = model.generate(inputs, max_length=256, top_k=1)
- response = tokenizer.decode(outputs[0])
-
- >>> print(response)
- # language: Python
- # write a bubble sort function
-
-
- def bubble_sort(list):
- for i in range(len(list) - 1):
- for j in range(len(list) - 1):
- if list[j] > list[j + 1]:
- list[j], list[j + 1] = list[j + 1], list[j]
- return list
-
-
- print(bubble_sort([5, 2, 1, 8, 4]))
- python ./demo/run_demo.py
-
- usage: run_demo.py [-h] [--model-path MODEL_PATH] [--example-path EXAMPLE_PATH] [--quantize QUANTIZE]
- [--chatglm-cpp] [--fastllm] [--n-gpus N_GPUS] [--gpu GPU] [--cpu] [--auth] [--username yourname]
- [--password yourpassword]
- [--port PORT] [--listen ADDRESS]
-
- # 若要启用身份验证,请先启用--auth,然后定义--username与--password,如:
- python run_demo.py --auth --username user --password password # 若要监听所有地址请指定 --listen 0.0.0.0
支持使用 ChatGLM.cpp 量化推理加速:
python ./demo/run_demo.py --quantize 4 --chatglm-cpp
- python ./demo/fastapicpu.py
- usage: fastapicpu.py [-h] [--model-path MODEL_PATH] [--listen ADDRESS] [--port PORT] [--workders NUM] [--cpu] [--half] [--quantize QUANTIZE] [--chatglm-cpp]
- # --cpu启用cpu --half启用.half()
支持使用 ChatGLM.cpp 量化推理加速,同样添加 --quantize 4 --chatglm-cpp
参数即可。
- curl -X POST "http://127.0.0.1:7860" \
- -H 'Content-Type: application/json' \
- -d '{"lang": "Python", "prompt": "# Write a quick sort function"}'
// 待更
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。