十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CodeBERT实战:从代码搜索到代码补全

CodeBERT实战:从代码搜索到代码补全 CodeBERT实战从代码搜索到代码补全【免费下载链接】CodeBERTCodeBERT项目地址: https://gitcode.com/gh_mirrors/co/CodeBERT凌晨接手一个三年没人动的遗留库第二天评审要你用自然语言回答“哪些函数会改全局配置”grep 只认字符串而 CodeBERT——微软开源的代码预训练模型系列主打代码搜索、代码补全与代码摘要——正是为这类 NL-PL自然语言-编程语言任务设计的。它适合做代码检索系统、NL2Code 原型、遗留代码问答的开发者。30秒速览六个模型各管一摊这个仓库是微软 6 个代码预训练模型的官方实验代码CodeBERTEMNLP 2020、GraphCodeBERTICLR 2021、UniXcoderACL 2022、CodeReviewerFSE 2022、CodeExecutorACL 2023、LongCoderICML 2023。它们解决同一个问题代码和自然语言活在两个世界——所有模型都在 CodeSearchNet 的 NL-PL 对上预训练覆盖 Python、Java、JavaScript、PHP、Ruby、Go 六种语言无需你自训模型就能直接拿嵌入和生成能力。模型架构形态能干什么上下文长度CodeBERT双向 EncoderNL-PL 嵌入、代码搜索、克隆检测512GraphCodeBERTEncoder 数据流图代码搜索/翻译/重构/克隆检测512UniXcoderEnc / Dec / Enc-Dec 三模式搜索、补全、摘要、函数名与 API 推荐512LongCoder稀疏长程 Transformer长上下文代码补全LCC3968CodeExecutorEncoder-Decoder预测代码执行轨迹需多卡1024它是怎么跑起来的先当翻译再当电路工可以把 RoBERTa 想象成只读过中文小说的翻译而 CodeBERT 是拿「文档 对应代码」的双语语料把他练出来的——所以输入序列长这样自然语言[SEP]代码。预训练用两个任务MLM随机掩码猜 token和 RTDReplaced Token Detection随机替换若干 token让模型判断哪些被换过。RTD 逼着模型盯住和、和这种细粒度差异这正是嵌入能力强的原因。反直觉的点codebert-base是 RTD 路线官方明确说它不适合 mask 预测补全/填空必须换codebert-base-mlm两个 checkpoint 不通用。GraphCodeBERT 在此基础上多走一步用 tree-sitter 把代码解析成数据流图DFG图中节点如变量定义的向量由它覆盖的所有 token 嵌入归一化平均得到——GraphCodeBERT/codesearch/model.py里核心就几行 einsum。类比一下普通模型读代码像读逐字稿GraphCodeBERT 像看电路图知道数据从哪流到哪。效果在官方过滤版数据集中代码搜索整体 MRR 0.713CodeBERT 是 0.693纯 RoBERTa 只有 0.617。跟着做从跑通到玩起来先拿到仓库和依赖git clone https://gitcode.com/gh_mirrors/co/CodeBERT pip install torch transformers最小可运行示例给一段自然语言和一段代码各算一个向量看余弦相似度。取[CLS]位表示作为整段语义向量并做归一化import torch from transformers import AutoTokenizer, AutoModel device torch.device(cuda if torch.cuda.is_available() else cpu) tokenizer AutoTokenizer.from_pretrained(microsoft/codebert-base) model AutoModel.from_pretrained(microsoft/codebert-base).to(device) def encode(text): ids tokenizer(text, return_tensorspt, max_length512).to(device) with torch.no_grad(): # 推理期省显存关掉反向图 emb model(**ids).last_hidden_state[:, 0] return torch.nn.functional.normalize(emb, dim1) nl encode(return the maximum value) code encode(def max(a,b): if ab: return a else return b) print(torch.cosine_similarity(nl, code, dim1))预期输出是一个标量这对语义匹配的 NL-PL 得分会明显高于「return the maximum value」配上一个求最小值的函数。仓库 README 里还有一个 token 级嵌入的完整示例可对照验证。拿到向量后最顺手的组合玩法是代码检索把代码库按函数切块、批量 encode、灌进 FAISS 或 pgvector查询走自然语言。想省内存就按批 encode 再释放。进阶填空式代码修复。换 MLM 版 checkpoint用 pipeline 三行搞定from transformers import RobertaForMaskedLM, RobertaTokenizer, pipeline model RobertaForMaskedLM.from_pretrained(microsoft/codebert-base-mlm) tokenizer RobertaTokenizer.from_pretrained(microsoft/codebert-base-mlm) fill_mask pipeline(fill-mask, modelmodel, tokenizertokenizer) print(fill_mask(if (x is not None) mask (x1)))预期输出官方示例的真实分数候选依次为and0.6049、or0.3068、if0.0213……and高出一大截说明模型真的理解了条件句逻辑而不是在做词频猜测。补全和摘要这类生成任务CodeBERT 系列交给 UniXcoder它的 decoder-only 模式开箱即用import torch from unixcoder import UniXcoder # 仓库 UniXcoder/ 目录下的封装类 device torch.device(cuda if torch.cuda.is_available() else cpu) model UniXcoder(microsoft/unixcoder-base).to(device) context def f(data,file_path): # write json data into file_path in python language tokens_ids model.tokenize([context], max_length512, modedecoder-only) source_ids torch.tensor(tokens_ids).to(device) predictions model.decode(model.generate( source_ids, decoder_onlyTrue, beam_size3, max_length128)) print(context predictions[0][0])预期输出官方示例def f(data,file_path): # write json data into file_path in python language data json.dumps(data) with open(file_path, w) as f: f.write(data)encoder-decoder 模式还能预测函数名write_json/write_file和推荐 APIjson.dumps排第一。想在自己的语料上复现代码搜索微调CodeBERT/codesearch/目录给了完整流程先process_data.py处理数据再用run_classifier.py微调关键参数照抄官方学习率 1e-5、8 个 epoch、序列长 200官方在 2 卡 P100 上完成训练最后用mrr.py评测。和谁比系列内部先选型这六个模型同仓同源均为 MIT 协议、HF 上可一键加载差异在形态而非生态真正的选型是「任务匹配」维度codebert-basegraphcodebert-baseunixcoder-base上手难度低一行 HF 加载中需 tree-sitter 依赖低需仓库内封装类适用场景NL-PL 嵌入、检索、克隆检测结构化代码理解检索 MRR 更高理解 生成一体补全/摘要/命名上下文512512512许可证MITMITMIT明确建议只要嵌入做代码搜索选 codebert-base最轻要生成代码、写摘要选 UniXcoderCodeBERT 本体是纯 encoder没有解码头搜索 MRR 想抠出那 2 个点选 GraphCodeBERT函数超过 512 token选 LongCoder源长 3968想学执行轨迹预训练看 CodeExecutor但它默认 8 卡分布式单机基本跑不动。踩坑实录推理与微调常见问题症状fill_mask输出全是垃圾词 →根因base 版是 RTD 预训练不是 MLM →解法换microsoft/codebert-base-mlm。症状对 base 版调model.generate()得到乱码 →根因纯 encoder 没有语言模型头 →解法生成任务改用 UniXcoder 或 -mlm 版。症状my-languages.so加载崩溃或 tree-sitter 报错 →根因预编译产物与本地 tree-sitter 版本不匹配 →解法进parser/目录执行bash build.sh重编译。症状长函数嵌入相似度不稳定 →根因超过 512 token 被截断语义被砍半 →解法按 AST 切块嵌入或换 LongCoder。症状代码搜索微调 MRR 远低于论文值 →根因学习率、epoch、序列长偏离官方配置 →解法照抄 lr 1e-5 / 8 epochs / max_seq_length 200 再谈超参。症状CodeExecutor 预训练 OOM →根因官方配置是 8 卡 block_size 1024 →解法调小per_gpu_train_batch_size用gradient_accumulation_steps补有效批量。症状同一函数的 NL-PL 相似度意外偏低 →根因代码里注释、链接、特殊字符没清洗 →解法先remove_comments并保证代码可被 AST 解析这是 GraphCodeBERT 数据清洗的四条规则之一。部署建议CPU 上批量算嵌入务必torch.no_grad() 分批推理能上 CUDA 就上 CUDAfp16 可再省一半显存嵌入结果建议 L2 归一化后直接存查询侧省一次 normalize。收个尾CodeBERT 系列给你一双代码的「双语眼睛」嵌入用 CodeBERT生成用 UniXcoder长上下文用 LongCoder。下一步把上面第一段嵌入代码跑起来亲眼看看一个函数和它的文档向量靠得多近。【免费下载链接】CodeBERTCodeBERT项目地址: https://gitcode.com/gh_mirrors/co/CodeBERT创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表