官网最新版telegram下载入口是什么

  随着『GPT4多模态/Microsoft 365 Copilot/Github Copilot X/ChatGPT插件』的推出,绝大部分公司的技术 产品 服务,以及绝大部分人的工作都将被革新一遍

  类似iPhone的诞生 大家面向iOS编程 有了App Store现在有了ChatGPT插件/GPT应用商店,以后很多公司 很多人面向GPT编程(很快技术人员分两种,一种懂GPT,一种不懂GPT)

  然ChatGPT/GPT4基本不可能开源了,而通过上篇文章《

  LLaMA的解读与其微调:Alpaca-LoRA/Vicuna/BELLE/中文LLaMA/姜子牙/LLaMA 2》可知,国内外各大公司、研究者推出了很多类ChatGPT开源项目,比如LLaMA、BLOOM

  1.1.1 GLM结构:微改transformer block且通过自定义attention mask兼容GPT BERT T5三种结构

  在2022年上半年,当时主流的预训练框架可以分为三种:

  autoregressive,自回归模型的代表是单向的GPT,本质上是一个从左到右的语言模型,常用于无条件生成任务(unconditional generation),缺点是无法利用到下文的信息autoencoding,自编码模型是通过某个降噪目标(如掩码语言模型,简单理解就是通过挖洞,训练模型做完形填空的能力)训练的语言编码器,如双向的BERT、ALBERT、RoBERTa、DeBERTa

  自编码模型擅长自然语言理解任务(natural language understanding tasks),常被用来生成句子的上下文表示,缺点是不适合生成任务encoder-decoder,则是一个完整的Transformer结构,包含一个编码器和一个解码器,以T5、BART为代表,常用于有条件的生成任务 (conditional generation)

  细致来说,T5的编码器中的注意力是双向,解码器中的注意力是单向的,因此可同时应用于自然语言理解任务和生成任务。但T5为了达到和RoBERTa和DeBERTa相似的性能,往往需要更多的参数量

  这三种预训练模型各自称霸一方,那么问题来了,可否结合三种预训练模型,以成天下之一统?这便是2022年5月发表的这篇论文《GLM: General Language Model Pretraining with Autoregressive Blank Infilling》的出发点,它提出了GLM架构

  首先,GLM框架在整体基于Transformer基础上,做了以下三点微小改动

  论文中说的是,重新排列了层归一化和残差连接的顺序

  we rearrangethe order of layer normalization and the resid-ual connection, which has been shown critical forlarge-scale language models to avoid numericalerrors (Shoeybi et al., 2019)

  但实际实现时,GLM用的post deepNorm,可以认为是对原始transformer用的post-norm的改进(GPT1和原始transformer都是先self-attention再LN,或先feed forward再LN,可称为post-norm,至于GPT2和GPT3等绝大部分模型则是LN层被放置在self-attention层和feed forward层之前,可称为pre-norm),如下图所示(图源: 第17页) 针对token的输出预测使用单一线性层用GeLU替换ReLU激活函数

  此外,关于GLM的结构,这个视频也可以看下:

  另,考虑到我讲的ChatGPT技术原理解析课群内,有同学对这块有疑问,所以再重点说下

  本质上,一个GLMblock其实就是在一个transformer block的基础上做了下结构上的微小改动而已

  至于实际模型时,这个block的数量或层数可以独立设置,比如设置24层(具体见下述代码第48行) GLM/arguments.py at 4b65bdb165ad323e28f91129a0ec053228d10566 · THUDM/GLM · GitHub

  比如,基于GLM框架的类ChatGPT开源项目「ChatGLM」便用了28个GLMBlock,类似gpt2 用的12-48个decoder-transformer block,BERT用的12-24个encoder-transformer block

   有些文章 包括我那篇Transformer笔记,为举例,便用的N=6的示例,相当于编码器模块 用的6个encoder-transformer block,解码器模块 也用的6个decoder-transformer block

  其次,考虑到三类预训练模型的训练目标

  GPT的训练目标是从左到右的文本生成BERT的训练目标是对文本进行随机掩码,然后预测被掩码的词T5则是接受一段文本,从左到右的生成另一段文本

  为了大一统,我们必须在结构和训练目标上兼容这三种预训练模型。如何实现呢?文章给出的解决方法是结构上,只需要GLM中同时存在单向注意力和双向注意力即可

  因为在原本的Transformer模型中,这两种注意力机制是通过修改attention mask实现的

  当attention_mask是全1矩阵的时候,这时注意力是双向的当attention_mask是三角矩阵的时候(如下图&#xfftelegram最新的中文版下载的网址在哪里09;,注意力就是单向

  

  类似地,GLM可以在只使用Transformer编码器的情况下&#xff精简版telegram下载地方在哪呢0c;自定义attention mask来兼容三种模型结构,使得

  前半部分互相之间能看到,等效于编码器(BERT)的效果,侧重于信息提炼后半部分只能看到自身之前的,等效于解码器(GPT)的效果,侧重于生成

  这样综合起来实现的效果就是,将提炼信息作为条件,进行有条件地生成(有条件生成就是编解码模型)

  其实,所谓编码解码,其本质就是mask的遮盖设计。举个例子,假设原始的文本序列为x_1,x_2,x_3,x_4,x_5,x_6,采样的两个文本片段为 x_3 和 x_5,x_6 ,那么掩码后的文本序列为 x_1,x_2,[M],x_4,[M](以下简称Part A),如上图所示,拆解图中的三块分别可得

  

  我们要根据第一个[M] 解码出 x_3 ,根据第二个[M]依次解码出 x_5,x_6 ,那怎么从 [M] 处解码出变长的序列吗?这就需要用到开始标记 [S] 和结束标记 [E] 了我们从开始标记 [S]开始依次解码出被掩码的文本片段,直至结束标记 [E] 。通过本博客内的Transformer笔记可知,Transformer中的位置信息是通过位置向量来记录的

  在GLM中,位置向量有两个,一个 用来记录Part A中的相对顺序,一个 用来记录被掩码的文本片段(简称为Part B)中的相对顺序此外,还需要通过自定义自注意掩码(attention mask)来达到以下目的:

  

  ightarrow  双向编码器Part A中的词彼此可见,即图(d)中蓝色框中的区域

  

  ightarrow  单向解码器Part B中的词单向可见,即图(d)黄色框的区域

  

  ightarrow  Part B可见Part A

  

  ightarrow  其余不可见,即图(d)中灰色的区域

  需要说明的是,Part B包含所有被掩码的文本片段,但是文本片段的相对顺序是随机打乱的

  1.1.2 GLM的预训练和微调

  训练目标上,GLM论文提出一个自回归空格填充的任务(Autoregressive Blank Infifilling),来兼容三种预训练目标

  自回归填充有些类似掩码语言模型,首先采样输入文本中部分片段,将其替换为[MASK]标记,然后预测[MASK]所对应的文本片段,与掩码语言模型不同的是,预测的过程是采用自回归的方式

  

  具体来说

  当被掩码的片段长度为1的时候,空格填充任务等价于掩码语言建模,类似BERT当将文本1和文本2拼接在一起,然后将文本2整体掩码掉,空格填充任务就等价于条件语言生成任务,类似T5/BART当全部的文本都被掩码时,空格填充任务就等价于无条件语言生成任务,类似GPT

  最终,作者使用了两个预训练目标来优化GLM,两个目标交替进行:

  文档级别的预测/生成:从文档中随机采样一个文本片段进行掩码,片段的长度为文档长度的50%-100%句子级别的预测/生成:从文档中随机掩码若干文本片段,每个文本片段必须为完整的句子,被掩码的词数量为整个文档长度的15%

  尽管GLM是BERT、GPT、T5三者的结合,但是在预训练时,为了适应预训练的目标,作者还是选择掩码较长的文本片段,以确保GLM的文本生成能力,并在微调的时候将自然语言理解任务也转化为生成任务,如情感分类任务转化为填充空白的任务

  输入:{Sentence},prompt:It is really [M] ,对应的标签为good和bad

  

  2022年8月,清华背景的智谱AI基于GLM框架,正式推出拥有1300亿参数的中英双语稠密模型 GLM-130B(论文地址、代码地址,论文解读之一,GLM-130B is trained on a cluster of 96 DGX-A100 GPU (8×40G) servers with a 60-day,可以较好的支持2048个token的上下文窗口)

  其在一些任务上的表现优于GPT3-175B,是国内与2020年5月的GPT3在综合能力上差不多的模型之一(即便放到23年年初也并不多),这是它的一些重要特点

  

  1.3.1 ChatGLM-6B的训练框架

  ChatGLM-6B(介绍页面、代码地址),是智谱 AI 开源、支持中英双语的对话语言模型,其

  基于General Language Model(GLM)架构,具有62亿参数,无量化下占用显存13G

  INT8量化级别下支持在单张11G显存的 2080Ti 上进行推理使用(因为INT8下占用显存8G)

  而INT4量化级别下部署的话最低只需 6GB显存(另基于 P-Tuning v2 的高效参数微调方法的话,在INT4 下最低只需 7GB 显存即可启动微调)

  量化等级最低 GPU 显存(部署/推理)最低 GPU 显存(高效参数微调)FP16(无量化)13 GB14 GBINT88 GB9 GBINT46 GB7 GB 这里需要解释下的是,INT8量化是一种将深度学习模型中的权重和激活值从32位浮点数(FP32)减少到8位整数(INT8)的技术。这种技术可以降低模型的内存占用和计算复杂度,从而减少计算资源需求,提高推理速度,同时降低能耗

  量化的过程通常包括以下几个步骤:

  1 量化范围选择:确定权重和激活值的最小值和最大值

  2 量化映射:根据范围将32位浮点数映射到8位整数

  3 反量化:将8位整数转换回浮点数,用于计算ChatGLM-6B参考了 ChatGPT 的训练思路,在千亿基座模型GLM-130B中注入了代码预训练,通过监督微调(Supervised Fine-Tuning)、反馈自助(Feedback Bootstrap)、人类反馈强化学习(Reinforcement Learning from Human Feedback)等方式等技术实现人类意图对齐,并针对中文问答和对话进行优化最终经过约 1T 标识符的中英双语训练,生成符合人类偏好的回答

  虽尚有很多不足(比如因为6B的大小限制,导致模型的记忆能力、编码、推理能力皆有限),但在6B这个参数量级下不错了,部署也非常简单,我七月在线的同事朝阳花了一两个小时即部署好了(主要时间花在模型下载上,实际的部署操作很快)

  

  1.3.2 ChatGLM-6B的部署步骤

  以下是具体的部署过程

  硬件配置

  本次实验用的七月的GPU服务器(专门为七月集/高/论文/VIP学员配置的),显存大小为16G的P100,具体配置如下:

  CPU&内存:28核(vCPU)112 GB

  操作系统:Ubuntu_64

  GPU:NVIDIA Tesla P100

  显存:16G配置环境

  建议最好自己新建一个conda环境

  pip install -r requirements.txt
最新官网的telegram下载的网址哪里有
  (ChatGLM-6B/requirements.txt at main · THUDM/ChatGLM-6B · GitHub)

  特别注意torch版本不低于1.10(这里安装的1.10),transformers为4.27.1

  torch的安装命令可以参考pytorch官网:https://pytorch.org/

  这里使用的pip命令安装的,命令如下

  pip install torch==1.10.0+cu102 torchvision==0.11.0+cu102 torchaudio==0下载项目仓库

  git clone https://github.com/THUDM/ChatGLM-6B

  cd ChatGLM-6B下载ChatGLM-6B模型文件

  文件可以从这里下载(点击中间的下载按钮即可):https://huggingface.co/THUDM/chatglm-6b

  

  注意,这里都下载在了/data/sim_chatgpt/chatglm-6b下,在后面执行代码的时候需要将文件中的模型文件路径改为自己的推理与部署

  可运行的方式有多种

  

  ightarrow  如果在本地运行,可以直接执行代码,或者使用命令行方式运行

  

  ightarrow  如果想让别人公网访问,可以用下面两种方式:一种是基于Gradio,一种是基于streamlit

  特别注意:运行代码前请检查模型文件路径是否正确,这里均改为了/data/chatglm-6b

  代码运行demo

  命令行 Demo

  运行仓库中 cli_demo.py:

  python cli_demo.py

  程序会在命令行中进行交互式的对话,在命令行中输入指示并回车即可生成回复,输入 clear 可以清空对话历史,输入 stop 终止程序

  基于Gradio的网页版demo

  运行web_demo.py即可(注意可以设置share=True,便于公网访问):python web_demo.py(注意运行前确认下模型文件路径)

  

  基于streamlit网页版 Demo

  pip install streamlit

  pip install streamlit-chat

  streamlit run web_demo2.py –server.port 6006(可以将6006端口放出,便于公网访问)

  默认情况下,模型以 FP16 精度加载,运行上述代码需要大概 13GB 显存。如果显存有限,还可以考虑模型量化,目前支持4/8 bit 量化

  此外,据介绍,GLM团队正在内测130B参数的ChatGLM,相信从6B到130B,效果应该能提升很多

  1.4.1 通过Stanford Alpaca的52K数据集基于LoRA(PEFT库)微调ChatGLM-6B

  从上文可知,Stanford Alpaca的52K数据集是通过Self Instruct方式提示GPT3对应的API产生的指令数据,然后通过这批指令数据微调Meta的LLaMA 7B

  而GitHub上的这个微调ChatGLM-6B项目(作者:mymusise),则基于Stanford Alpaca的52K数据集通过LoRA(low-rank adaptation)的方式微调ChatGLM-6B

  如上一篇文章所说,Huggingface公司推出的PEFT(Parameter-Efficient Fine-Tuning)库便封装了LoRA这个方法,具体而言,通过PEFT-LoRA微调ChatGLM-6B的具体步骤如下

  第一步,配置环境与准备

  先下载项目仓库

  git clone https://github.com/mymusise/ChatGLM-Tuning.git

  创建一个python3.8的环境

  conda create -n torch1.13 python==3.8

  conda activate torch1.13

  根据requirements.txt配置环境

  pip install bitsandbytes==0.37.1

  安装1.13,cuda11.6(torch官网命令)

  pip install torch==1.13.1+cu116 torchvision==0.14.1+cu116 torchaudio==0.13.1 –extra-index-url https://download.pytorch.org/whl/cu116

  安装其他的包

  遇到冲突问题:icetk 0.0.5 has requirement protobuf<3.19, but you have protobuf 3.19.5.

  最后装了3.18.3的protobuf,发现没有问题

  模型文件准备

  模型文件在前面基于ChatGLM-6B的部署中已经准备好了,注意路径修改正确即可第二步,数据准备

  项目中提供了数据,数据来源为 Stanford Alpaca 项目的用于微调模型的52K数据,数据生成过程可详见:https://github.com/tatsu-lab/stanford_alpaca#data-release

  alpaca_data.json,包含用于微调羊驼模型的 52K 指令数据,这个 JSON 文件是一个字典列表,每个字典包含以下字段:

  instruction: str,描述了模型应该执行的任务,52K 条指令中的每一条都是唯一的

  input: str,任务的可选上下文或输入。例如,当指令是“总结以下文章”时,输入就是文章,大约 40% 的示例有输入

  output: str,由 text-davinci-003 生成的指令的答案

  示例如下:

  第三步,数据处理

  运行 cover_alpaca2jsonl.py 文件

  python cover_alpaca2jsonl.py –data_path data/alpaca_data.json –save_path data/alpaca_data.jsonl

  处理后的文件示例如下:

  运行 tokenize_dataset_rows.py 文件,注意:修改tokenize_dataset_rows中的model_name为自己的文件路径 :/data/chatglm-6b

  第四步,微调过程

  ​​注意:运行前修改下finetune.py 文件中模型路径:/data/chatglm-6b

  这个finetune长啥样呢?

   其对应的完整代码为

  如遇Nvidia驱动报错(如没有可忽略)

  说明Nvidia驱动太老,需要更新驱动

  UserWarning: CUDA initialization: The NVIDIA driver on your system is too old (found version 10020). Please update your GPU driver by downloading and installing a new version from the URL: http://www.nvidia.com/Download/index.aspx Alternatively, go to: https://pytorch.org to install a PyTorch version that has been compiled with your version of the CUDA driver. (Triggered internally at https://blog.csdn.net/v_JULY_v/article/c10/cuda/CUDAFunctions.cpp:109.)

  解决:更新驱动即可,参考:Ubuntu 18.04 安装 NVIDIA 显卡驱动 – 知乎

  BUG REPORT报错

  参考:因为peft原因,cuda10.2报错 · Issue #108 · mymusise/ChatGLM-Tuning · GitHub

  CUDA SETUP: CUDA version lower than 11 are currently not supported for LLM.int8()

  考虑安装11以上的cudatooklit,参考下面链接,安装cudatooklit11.3(因为Ubuntu系统版本的原因,不能装11.6的)

  Ubuntu16.04 安装cuda11.3+cudnn8.2.1 – 知乎

  cudatooklit下载地址:

  CUDA Toolkit 11.3 Downloads | NVIDIA 开发者

  运行代码前先执行下面命令:

  内存不够,考虑将per_device_train_batch_size设为1

  报错:RuntimeError: expected scalar type Half but found Float

  https://github.com/mymusise/ChatGLM-Tuning/issues?q=is%3Aissue+is%3Aopen+RuntimeError%3A+expected+scalar+type+Half+but+found+Float

  解决方法:

  一种是,不启用fp16, load_in_8bit设为True,可以运行,但loss为0;

  一种是,启用fp16, load_in_8bit设为False,不行,应该还是显存不够的问题,至少需要24G左右的显存

  1.4.2 ChatGLM团队:通过ADGEN数据集基于P-Tuning v2微调ChatGLM-6B

  此外,ChatGLM团队自身也出了一个基于P-Tuning v2的方式微调ChatGLM-6B的项目:ChatGLM-6B 模型基于 P-Tuning v2 的微调

  P-Tuning v2(代码地址,论文地址)意义在于:将需要微调的参数量减少到原来的 0.1%,再通过模型量化、Gradient Checkpoint 等方法,最低只需要 7GB 显存即可运行

  

  那具体怎么通过P-Tuning v2微调ChatGLM-6B呢,具体步骤如下:

  第一步,配置环境与准备

  地址:ChatGLM-6B/ptuning at main · THUDM/ChatGLM-6B · GitHub

  安装以下包即可,这里直接在torch1.13的conda环境下安装的

  第二步,模型文件准备

  模型文件在前面基于ChatGLM-6B的部署中已经准备好了,注意路径修改正确即可

  特别注意:如果你是之前下载的可能会报错,下面有详细的错误及说明第三步,数据准备

  ADGEN数据集的任务为根据输入(content)生成一段广告词(summary)

  {

  "content": "类型#上衣*版型#宽松*版型#显瘦*图案#线条*衣样式#衬衫*衣袖型#泡泡袖*衣款式#抽绳",

  "summary": "这件衬衫的款式非常的宽松,利落的线条可以很好的隐藏身材上的小缺点,穿在身上有着很好的显瘦效果。领口装饰了一个可爱的抽绳,漂亮的绳结展现出了十足的个性,配合时尚的泡泡袖型,尽显女性甜美可爱的气息。"

  }

  从Google Drive 或者 Tsinghua Cloud 下载处理好的 ADGEN数据集,将解压后的AdvertiseGen目录放到本 ptuning 目录下即可第四步,微调过程

  修改train.sh文件

  去掉最后的 –quantization_bit 4

  注意修改模型路径,THUDM/chatglm-6b修改为/data/chatglm-6b

  如果你也是在云服务器上运行,建议可以加上nohup后台命令,以免断网引起训练中断的情况修改后train.sh文件如下:

  执行命令,开始微调

  bash train.sh

  如果报错:'ChatGLMModel' object has no attribute 'prefix_encoder'(如没有可忽略)

  解决方案:需要更新 THUDM/chatglm-6b at main 里面的几个py文件(重新下载下这几个文件就可以了)

   微调过程占用大约13G的显存

   微调过程loss变化情况

   微调完成后,output/adgen-chatglm-6b-pt-8-1e-2路径下会生成对应的模型文件,如下(这里生成了3个):

   第五步,推理过程

  只需要在加载模型的位置修改成微调后的路径即可

  将 evaluate.sh 中的 CHECKPOINT 更改为训练时保存的 checkpoint 名称,运行以下指令进行模型推理和评测:

  改这一行即可:–model_name_or_path https://blog.csdn.net/v_JULY_v/article/details/output/$CHECKPOINT/checkpoint-3000

  bash evaluate.sh

   评测指标为中文 Rouge score 和 BLEU-4,生成的结果保存在

  https://blog.csdn.net/v_JULY_v/article/details/output/adgen-chatglm-6b-pt-8-1e-2/generated_predictions.txt

   我们可以对比下微调前后的效果

  以命令行 Demo为例,只需修改cli_demo.py中的模型路径为:ptuning/out/adgen-chatglm-6b-pt-8-1e-2/checkpoint-3000,运行 cli_demo.py即可:

  python cli_demo.py

  用以下数据为例:

  Input: 类型#上衣*材质#牛仔布*颜色#白色*风格#简约*图案#刺绣*衣样式#外套*衣款式#破洞 Label: 简约而不简单的牛仔外套,白色的衣身十分百搭。衣身多处有做旧破洞设计,打破单调乏味,增加一丝造型看点。衣身后背处有趣味刺绣装饰,丰富层次感,彰显别样时尚。 这件上衣的材质是牛仔布,颜色是白色,风格是简约,图案是刺绣,衣样式是外套,衣款式是破洞。

  用户:根据输入生成一段广告词,输入为:类型#上衣*材质#牛仔布*颜色#白色*风格#简约*图案#刺绣*衣样式#外套*衣款式#破洞。

  Output[微调前]:

   Output[微调后]:

  

  总结:建议使用官方提供的基于P-Tuning v2微调ChatGLM-6B的方式对自己的数据进行微调

  此外,此文还介绍了如何通过Cursor一步一步生成一份微调ChatGLM的示例代码

  ChatGLM-6B(介绍页面),是智谱 AI 开源、支持中英双语的对话语言模型。

  话不多说,直接干,虽然6B的版本相比GPT3 175B 不算大,但毕竟不是一个小工程,本文就不一一贴所有代码了,更多针对某个文件夹下或某个链接下的代码进行整体分析/说明,以帮助大家更好、更快的理解ChatGLM-6B,从而加速大家的类ChatGPT复现之路

  其对应的Hugging Face上(THUDM/chatglm-6b · Hugging Face,详见下文的2.1 2.2 2.3节)

  存放的是chatglm-6b的模型文件,包含权重、配置文件、模型信息等等

  

  其中,pytorch_model-00001-of-00008.bin 到 pytorch_model-00008-of-00008.bin: 这些文件是PyTorch模型的权重文件,相当于一个大模型被分割成多个部分以方便下载和使用其对应的GitHub上(GitHub – THUDM/ChatGLM-6B: ChatGLM-6B: An Open Bilingual Dialogue Language Model | 开源双语对话语言模型,详见下文的2.4节)

  主要是ChatGLM-6B/ptuning,涉及对chatglm-6b进行推理、部署、微调的代码(就是如何使用的相关代码)

  2.1.1 导入相关库、编码器、GELU、旋转位置编码(第1-239行)

  首先,代码导入了许多需要的库,如torch、torch.nn.functional等,它们为模型实现提供了基本的功能。

  脚本中设置了一些标志,以便在运行时启用JIT(Just-In-Time)编译功能定义了InvalidScoreLogitsProcessor类,它继承自LogitsProcessor。该类用于处理可能出现的NaN和inf值,通过将它们替换为零来确保计算的稳定性load_tf_weights_in_chatglm_6b函数,用于从TensorFlow检查点加载权重到PyTorch模型中。这对于迁移学习和在PyTorch中使用预训练模型非常有用PrefixEncoder类是一个编码器,用于对输入的前缀进行编码。它根据配置使用一个两层的MLP(多层感知器)或者直接进行嵌入,输出维度为(batch_size, prefix_length, 2 * layers * hidden)gelu_impl函数是一个GELU(高斯误差线性单元)激活函数的实现,这是一个常用的激活函数,尤其在Transformer模型中

  RotaryEmbedding类实现了旋转位置编码(第177-239行)。旋转位置编码是一种新型的位置编码方法,相比于传统的位置编码,它在大序列长度和多头注意力上具有更好的性能

  

  ightarrow  _load_from_state_dict方法:这是一个空方法,用于从给定的状态字典加载模型参数。在这个代码段中,它没有实现任何功能

  

  ightarrow  forward方法:这是一个核心方法,实现了正向传播,输入为x和可选参数seq_dim和seq_len。这个方法首先计算序列长度,然后根据条件更新max_seq_len_cached。接着,它计算嵌入向量,并将其缓存。最后,它返回余弦和正弦缓存

  

  ightarrow  _apply方法:这个方法应用给定的函数(fn)到缓存的余弦和正弦值上,并调用父类的_apply方法

  

  ightarrow  rotate_half函数:这个函数将输入张量x在最后一个维度上分为两半,并将它们交换位置

  

  ightarrow  apply_rotary_pos_emb_index函数:这个函数应用了旋转位置嵌入索引,主要通过cos和sin将位置信息添加到输入张量q和k上

  2.1.2 SelfAttention的PyTorch模块:实现自注意力机制(第242-551行)

  定义了一个名为SelfAttention的PyTorch模块,它实现了自注意力机制。这个模块在许多自然语言处理任务中都被用作基本构建块。以下是代码中的关键部分:

  attention_fn方法:这个方法实现了自注意力的核心计算过程,包括计算注意力分数、注意力概率和上下文层。这些计算对于实现许多自然语言处理任务,如语言建模、命名实体识别等,都是非常重要的

  为方便大家更好、更快、更一目了然的理解

  一开始,我花了个把钟头,一如上面的 依然把下面每一行代码都逐行加上了注释,且关键的部分加了额外的解释说明

  再之后,在23年7.30日在七月在线类ChatGPT微调实战课 第6课上讲完本ChatGLM-6B的源码之后,又再次花了个把小时对下面整个函数attention_fn的注释做了全面改进,从而只要耐心梳理,都能看得懂  整个函数attention_fn对应的代码为

  default_init函数:这个函数是一个初始化辅助函数,用于创建类的实例

  SelfAttention类定义:这个类实现了自注意力机制,包括定义类的初始化方法和成员变量。类的初始化方法包括设置各种属性,如hidden_size,num_attention_heads,layer_id等。类还包含一个名为rotary_emb的RotaryEmbedding实例,用于处理位置编码。此外,query_key_value和dense是用于计算查询、键和值的线性层。

  attention_mask_func方法,将注意力掩码应用于Transformer模型中的注意力得分(到了第407行)

  split_tensor_along_last_dim 方法

  该方法沿着张量的最后一个维度将其分割成多个部分。参数包括输入张量 tensor、要将张量分割成的分区数 num_partitions,以及布尔值 contiguous_split_chunks,用于确定分割后的张量是否需要在内存中连续。函数首先计算最后一个维度的大小,然后使用torch.split将输入张量分割成多个子张量。如果需要连续的分割块,将每个子张量转换为连续张量SelfAttention 类的 forward 方法:

  该方法负责计算自注意力。它接收以下参数:hidden_states(输入序列的隐藏状态)、position_ids(位置编码)、attention_mask(注意力掩码)、layer_id(层ID)、layer_past(上一层的隐藏状态),以及use_cache(布尔值,表示是否使用缓存)和output_attentions(布尔值,表示是否输出注意力概率)。方法首先将隐藏状态传递给查询键值 (query, key, value) 层,然后将这些层分割成独立的张量。接下来,应用旋转位置编码,计算注意力概率,并得到上下文表示。最后,返回输出张量、隐藏状态以及注意力概率(如果需要的话)。

  2.1.3 GLMBlock类、ChatGLMPreTrainedModel类(第554-784行)

  GLMBlock 类:这是一个包含多个子模块的Transformer层,如层归一化 (LayerNorm)、自注意力 (SelfAttention) 和门控线性单元 (GLU)

  GLMBlock 类的 forward 方法接收与SelfAttention的forward方法类似的参数,如输入序列的隐藏状态、位置编码、注意力掩码等。在这个方法中

  首先应用层归一化然后计算自注意力,接着应用第二个层归一化,最后通过门控线性单元 (GLU) 计算输出。在每个步骤之间,都有残差连接来保留之前的信息最后,返回输出张量、隐藏状态以及注意力概率(如果需要的话)

  接下来第661-729行,定义了一个名为 ChatGLMPreTrainedModel 的类,它继承自 PreTrainedModel。这个类是用于处理权重初始化以及简化下载和加载预训练模型的接口。

  类变量包括:

  is_parallelizable:表示该模型是否可并行化,默认为 False

  supports_gradient_checkpointing:表示该模型是否支持梯度检查点,默认为 True

  config_class:模型配置类,这里使用了 ChatGLMConfig

  base_model_prefix:设置为 "transformer"

  _no_split_modules:一个包含 "GLMBlock" 的列表类方法包括:

  __init__:构造函数,调用父类的构造函数

  _init_weights:初始化权重的方法,这里没有具体实现

  get_masks:根据输入生成注意力掩码

  get_position_ids:根据输入和掩码位置生成位置编码,支持二维和非二维位置编码

  _set_gradient_checkpointing:根据给定的值(默认为False)设置梯度检查点。

  此外,还定义了一个名为 CHATGLM_6B_START_DOCSTRING 的变量,包含有关 ChatGLM6BConfig 的文档字符串,描述了如何使用这个 PyTorch 模型

  2.1.4 ChatGLMModel类(第785-1029行)

  定义了一个名为ChatGLMModel的类,它继承自ChatGLMPreTrainedModel。这是一个基于transformer的模型,能够作为编码器(仅使用自注意力机制)或解码器。解码器的情况下,会在自注意力层之间添加一个跨注意力层。模型的结构遵循论文Attention is all you need中描述的结构。

  ChatGLMModel类的forward方法负责执行模型的前向传播。这个方法接收一系列输入参数,如input_ids、attention_mask、past_key_values等。根据这些输入,方法将执行以下操作:

  如果没有提供inputs_embeds,使用word_embeddings将input_ids转换为嵌入向量如果没有提供past_key_values,使用get_prompt方法获取提示如果没有提供attention_mask,生成一个全零的张量如果没有提供position_ids,使用get_position_ids方法获取位置ID使用注意力掩码更新输入对于模型中的每个层,执行以下操作:

  更新隐藏状态

  如果需要,保存当前层的隐藏状态

  更新注意力权重对最后一层应用层归一化。如果需要,保存所有隐藏状态。如果需要,返回一个包含所有输出的元组,否则返回一个BaseModelOutputWithPast对象。

  这个模型的设计可以在序列到序列(Seq2Seq)任务中使用,这时需要将is_decoder和add_cross_attention参数设置为True,并在前向传播时提供encoder_hidden_states。

  2.1.5 ChatGLMForConditionalGeneration的类(第1031-1436行)

  定义了一个名为ChatGLMForConditionalGeneration的类,,它用于条件生成任务,如文本生成。这个类继承自ChatGLMPreTrainedModel,主要包括初始化方法、模型的前向传播逻辑以及生成过程中需要的输入预处理方法。

  主要部分的解释如下:

  __init__方法是类的构造函数,用于初始化该类的实例。它接受两个参数:config(一个ChatGLMConfig实例,包含模型的配置信息)和empty_init(一个布尔值,表示是否跳过模型参数的初始化)。构造函数首先调用父类的构造函数,然后根据empty_init的值选择初始化方法。接着,它初始化一些实例变量,例如max_sequence_length和position_encoding_2d。最后,它初始化transformer和lm_head两个关键组件get_output_embeddings和set_output_embeddings方法分别用于获取和设置lm_head的权重。_update_model_kwargs_for_generation方法用于在生成过程中更新模型的关键字参数,包括更新past_key_values、attention_mask和position_ids。prepare_inputs_for_generation方法在生成过程中准备模型的输入,包括input_ids、past_key_values、attention_mask和position_ids等。此外,该方法还处理了遮罩位置和gmask的使用。forward方法实现了模型的前向传播逻辑。它接受一系列可选参数,例如input_ids、position_ids、attention_mask、past_key_values等,并根据这些输入调用transformer模块。接着,它将hidden_states传递给lm_head,并计算lm_logits。如果提供了标签(labels),则计算损失函数。最后,根据return_dict的值,返回一个包含损失、logits、隐藏状态等信息的元组或字典。此时到了1231行_reorder_cache 方法:在执行束搜索 (beam search) 或者束采样 (beam sample) 时用于重新排序 past_key_values 缓存,以便将 past_key_values 与正确的 beam_idx 匹配。process_response 方法:处理模型生成的回应,将其中的训练时间替换为 "2023年",同时将英文标点符号替换为中文标点符号。chat 方法:根据给定的查询和聊天历史生成回应。通过 tokenizer 对查询和聊天历史进行编码,并将其输入到模型中。然后,对模型生成的回应进行解码和处理,最后将新的回应添加到聊天历史中并返回。stream_chat 方法:与 chat 方法类似,但使用生成器函数 (generator function) 以流式方式生成回应。stream_generate 方法:一个生成器函数,用于生成回应。它首先将输入的 query 和聊天历史进行编码,然后根据生成配置 (generation_config) 进行一系列的准备工作。接着,在满足停止条件之前,通过模型的多次迭代来生成回应。quantize 方法:量化模型的权重,以减少模型的内存占用和计算资源。这对于在资源有限的设备上部署模型非常有用。

  该类中还包括一些辅助方法,例如 _get_logits_processor, _get_stopping_criteria, _get_logits_warper, prepare_inputs_for_generation, 和 _update_model_kwargs_for_generation,这些方法用于处理生成过程中的各种设置和参数。

  2.2.1 处理文本和词条之间的转换

  :这个类主要处理文本和词条之间的转换,包括将文本转化为词条列表的分词(),将词条列表转化为文本的解码(),以及获取词条的ID和从ID获取词条(, )等操作。此外,它还包含了处理特殊词条和填充的功能

  这些处理是许多自然语言处理(NLP)任务,如文本分类、命名实体识别、问答系统、机器翻译等的基础步骤

  还依赖下面的进行文本的分词和解码操作,而将复杂的操作封装在了自己的接口之下,同时添加了对特殊词条和填充的处理。

  2.2.2 包装了SentencePiece库的分词器

  :这个类是一个包装了SentencePiece库的分词器。SentencePiece是一个开源的自然语言处理库,用于神经网络模型的不规则文本分词,这个类主要提供了一些接口来利用SentencePiece库进行分词、解码等操作

  2.2.3 字节级字节对编码(Byte-Pair Encoding,BPE)分词器类

  下面这段代码定义了一个ChatGLM的字节级字节对编码(Byte-Pair Encoding,BPE)分词器类,包含了一些分词器的基础操作,例如文本预处理、分词、词条解码、填充等

  具体而言,以下的代码包括了对输入文本的预处理,将文本转化为词条序列的分词,以及将词条序列转化为文本的解码,等一系列分词器常用的操作。同时,这个分词器还支持添加特殊词条,以及在分词器的左边或右边进行填充,以满足模型输入的需要

  跟分词相关的还有一个:这个文件通常包含分词器的配置信息,例如预训练模型使用的特殊令牌(如[CLS],[SEP]等)

  quantization.py: 这是一个Python脚本,可能包含了对模型进行量化的代码,量化是一种减小模型大小和推理时间的技术​

  2.3.1 compress_int4_weight等类

  2.3.2 QuantizedLinear

  // 待更..

  2.4.1 模型的训练/微调/推理

  仓库实现了对于 ChatGLM-6B 模型基于 P-Tuning v2 的微调。P-Tuning v2 将需要微调的参数量减少到原来的 0.1%,再通过模型量化、Gradient Checkpoint 等方法,最低只需要 7GB 显存即可运行

  运行微调需要4.27.1版本的,且除 ChatGLM-6B 的依赖之外,还需要安装以下依赖

  下面以 ADGEN (广告生成) 数据集为例介绍代码的使用方法

  ADGEN 数据集任务为根据输入(content)生成一段广告词(summary)

  {

  "content": "类型#上衣*版型#宽松*版型#显瘦*图案#线条*衣样式#衬衫*衣袖型#泡泡袖*衣款式#抽绳",

  "summary": "这件衬衫的款式非常的宽松,利落的线条可以很好的隐藏身材上的小缺点,穿在身上有着很好的显瘦效果。领口装饰了一个可爱的抽绳,漂亮的绳结展现出了十足的个性,配合时尚的泡泡袖型,尽显女性甜美可爱的气息。"

  }

  从 Google Drive 或者 Tsinghua Cloud 下载处理好的 ADGEN 数据集,将解压后的  目录放到本目录下

  训练

  运行以下指令进行训练:bash train.sh

  train.sh 中的 PRE_SEQ_LEN 和 LR 分别是 soft prompt 长度和训练的学习率,可以进行调节以取得最佳的效果。P-Tuning-v2 方法会冻结全部的模型参数,可通过调整 quantization_bit 来被原始模型的量化等级,不加此选项则为 FP16 精度加载在默认配置 quantization_bit=4、per_device_train_batch_size=1、gradient_accumulation_steps=16 下,INT4 的模型参数被冻结,一次训练迭代会以 1 的批处理大小进行 16 次累加的前后向传播,等效为 16 的总批处理大小,此时最低只需 6.7G 显存

  若想在同等批处理大小下提升训练效率,可在二者乘积不变的情况下,加大 per_device_train_batch_size 的值,但也会带来更多的显存消耗,请根据实际情况酌情调整如果你想要从本地加载模型,可以将 train.sh 中的 THUDM/chatglm-6b 改为你本地的模型路径

  Finetune

  如果需要进行全参数的 Finetune,需要安装 Deepspeed,然后运行以下指令:bash ds_train_finetune.sh

  其中的main.py引入了from trainer_seq2seq import Seq2SeqTrainer,而trainer_seq2seq.py又引入了from trainer import Trainer,而Trainer.py则来自https://github.com/huggingface/transformers/blob/main/src/transformers/trainer.py

  关于这个有着3800多行的traner.py的分析详见此文《》4.1节逐行解读:3858行的transformers/src/transformers/trainer.py

  推理

  在 P-tuning v2 训练时模型只保存 PrefixEncoder 部分的参数,所以在推理时需要同时加载原 ChatGLM-6B 模型以及 PrefixEncoder 的权重,因此需要指定  中的参数:

  仍然兼容旧版全参保存的 Checkpoint,只需要跟之前一样设定 model_name_or_path:

  评测指标为中文 Rouge score 和 BLEU-4。生成的结果保存在 https://blog.csdn.net/v_JULY_v/article/details/output/adgen-chatglm-6b-pt-8-1e-2/generated_predictions.txt

  2.4.2 使用自己的数据集与多轮对话

  使用自己的数据集

  修改 train.sh 和 evaluate.sh 中的 train_file、validation_file和test_file为你自己的 JSON 格式数据集路径,并将 prompt_column 和 response_column 改为 JSON 文件中输入文本和输出文本对应的 KEY。可能还需要增大 max_source_length 和 max_target_length 来匹配你自己的数据集中的最大输入输出长度

  对话数据集

  如需要使用多轮对话数据对模型进行微调,可以提供聊天历史,例如以下是一个三轮对话的训练数据:

  训练时需要指定 –history_column 为数据中聊天历史的 key(在此例子中是 history),将自动把聊天历史拼接。要注意超过输入长度 max_source_length 的内容会被截断。

  可以参考以下指令:

  bash train_chat.sh

  至于模型的部署请见:https://github.com/THUDM/ChatGLM-6B/blob/main/ptuning/README.md

  2.4.3 广告词创作的示例数据集data_sample

  这个示例数据集总计有100条,以下是前三条的示例

  // 待更..

  ChatGLM2-6B(GitHub项目地址、HuggingFace地址)是开源中英双语对话模型 ChatGLM-6B 的第二代版本,相比第一代,第二点引入了如下新特性:

  数据集上

  经过了 1.4T 中英标识符的预训练与人类偏好对齐训练更长的上下文:FlashAttention

  基于 FlashAttention 技术(关于什么是FlashAttention,详见),将基座模型的上下文长度(Context Length)由 ChatGLM-6B 的 2K 扩展到了 32K,并在对话阶段使用 8K 的上下文长度训练,允许更多轮次的对话

  (当前版本的 ChatGLM2-6B 对单轮超长文档的理解能力有限,会在后续迭代升级中着重进行优化)更高效的推理:基于多查询注意力(Multi-Query Attention)

  基于 Multi-Query Attention 技术,ChatGLM2-6B 有更高效的推理速度和更低的显存占用:在官方的模型实现下,推理速度相比初代提升了 42%,INT4 量化下,6G 显存支持的对话长度由 1K 提升到了 8K模型架构:从encoder架构变成了decoder only架构

  chatglm还是encoder架构,但是到了chatglm2 变成了decoder only的架构(这点很少有资料会提及到),何以见得呢?

  如七月黄老师所说,chatglm2仓库的modeling用了新版pytorch的这个函数:context_layer

  context_layer 这个函数实现了attention机制的计算,入参 is_causal=True 表示遮后看前的mask(这种类型的注意力通常用在transformer的decoder部分,以确保当前位置只能关注到之前的位置,俗称“看不见未来”,从而使模型可以进行自回归预测 )

  ​ 允许商业使用准确性不足

  尽管模型在训练的各个阶段都尽力确保数据的合规性和准确性,但由于 ChatGLM2-6B 模型规模较小,且模型受概率随机性因素影响,无法保证输出内容的准确性,且模型易被误导

  3.1.1 FlashAttention的原理与实现

  请参见《》

  3.1.2 多查询注意力(Muti Query Attention):各自Query矩阵,但共享Key 和 Value 矩阵

  多查询注意力(Muti Query Attention)是 19 年Google一研究者提出的一种新的 Attention 机制(对应论文为:Fast Transformer Decoding: One Write-Head is All You Need、这是其解读之一),其能够在保证模型效果的同时加快 decoder 生成 token 的速度

  那其与17年 Google提出的transformer中多头注意力机制(简称MHA)有啥本质区别呢?有意思的是,区别在于:

  我们知道MHA的每个头都各自有一份不同的Key、Query、Value矩阵而MQA 让所有的头之间 共享 同一份 Key 和 Value 矩阵,每个头只单独保留了一份 Query 参数,从而大大减少 Key 和 Value 矩阵的参数量

  总之,MQA 实际上是将 head 中的 key 和 value 矩阵抽出来单独存为一份共享参数,而 query 则是依旧保留在原来的 head 中,每个 head 有一份自己独有的 query 参数

  下图对比了多头注意力(Multi-Head Attention)、LLaMA2中分组查询注意力(Grouped-Query Attention)、多查询注意力(Muti Query Attention)的差别

  总之,MHA 和 MQA 之间的区别只在于建立 Wqkv Layer 上

  更多请参见:《》

  3.2.1 模型的使用/部署

  首先需要下载本仓库:

  然后使用 pip 安装依赖:

  其中 transformers 库版本推荐为 , 推荐使用 2.0 及以上的版本,以获得最佳的推理性能代码调用

  可以通过如下代码调用 ChatGLM2-6B 模型来生成对话:

  你好👋!我是人工智能助手 ChatGLM2-6B,很高兴见到你,欢迎问我任何问题。

  晚上睡不着可能会让你感到焦虑或不舒服,但以下是一些可以帮助你入睡的方法:

  1. 制定规律的睡眠时间表:保持规律的睡眠时间表可以帮助你建立健康的睡眠习惯,使你更容易入睡。尽量在每天的相同时间上床,并在同一时间起床。官方最新版的telegram的下载地方哪里有

  2. 创造一个舒适的睡眠环境:确保睡眠环境舒适,安静,黑暗且温度适宜。可以使用舒适的床上用品,并保持房间通风。

  3. 放松身心:在睡前做些放松的活动,例如泡个热水澡,听些轻柔的音乐,阅读一些有趣的书籍等,有助于缓解紧张和焦虑,使你更容易入睡。

  4. 避免饮用含有咖啡因的饮料:咖啡因是一种刺激性物质,会影响你的睡眠质量。尽量避免在睡前饮用含有咖啡因的饮料,例如咖啡,茶和可乐。

  5. 避免在床上做与睡眠无关的事情:在床上做些与睡眠无关的事情,例如看电影,玩游戏或工作等,可能会干扰你的睡眠。

  6. 尝试呼吸技巧:深呼吸是一种放松技巧,可以帮助你缓解紧张和焦虑,使你更容易入睡。试着慢慢吸气,保持几秒钟,然后缓慢呼气。

  如果这些方法无法帮助你入睡,你可以考虑咨询医生或睡眠专家,寻求进一步的建议

  从本地加载模型

  以上代码会由 transformers 自动下载模型实现和参数

  完整的模型实现在 Hugging Face Hub。如果你的网络环境较差,下载模型参数可能会花费较长时间甚至失败。此时可以先将模型下载到本地,然后从本地加载。

  从 Hugging Face Hub 下载模型需要先安装Git LFS,然后运行

  如果你从 Hugging Face Hub 上下载 checkpoint 的速度较慢,可以只下载模型实现

  GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/THUDM/chatglm2-6b

  然后从这里手动下载模型参数文件,并将下载的文件替换到本地的  目录下

  将模型下载到本地之后,将以上代码中的  替换为你本地的  文件夹的路径,即可从本地加载模型。

  模型的实现仍然处在变动中。如果希望固定使用的模型实现以保证兼容性,可以在  的调用中增加  参数。 是当前最新的版本号,完整的版本列表参见 Change Log

  最后,可以通过以下命令启动基于 Gradio 的网页版 demo:

  ​3.2.2 基于 P-Tuning v2 的微调(官方)

  P-Tuning v2 将需要微调的参数量减少到原来的 0.1%,再通过模型量化、Gradient Checkpoint 等方法,最低只需要 7GB 显存即可运行(当然,我司杜老师也会在七月类ChatGPT微调实战课上录一个ChatGLM2-6B的微调视频)

  环境配置

  在原chatglm-6b的环境中安装以下依赖

  pip install rouge_chinese nltk jieba datasets微调数据准备

  ADGEN 数据集任务为根据输入(content)生成一段广告词(summary)

  从 Google Drive 或者 Tsinghua Cloud 下载处理好的 ADGEN 数据集,将解压后的 AdvertiseGen 目录放到本 ptuning 目录下即可微调

  修改train.sh文件

  去掉最后的 –quantization_bit 4( 去掉后为FP16 精度加载)

  修改模型路径,THUDM/chatglm-6b修改为/data/sim_chatgpt/chatglm2-6b

  目前专业级GPU Tesla P100也不支持INT4或8量化

  执行train.sh文件

  如遇报错:

  wandb.errors.UsageError: api_key not configured (no-tty). call wandb.login(k…

  解决方法:

  在main.py文件中加入下面两行,禁用wandb即可import os

  os.environ["WANDB_DISABLED"] = "true"

  其中,train.sh 中的 PRE_SEQ_LEN 和 LR 分别是 soft prompt 长度和训练的学习率,可以进行调节以取得最佳的效果。

  微调过程显存使用情况如下:

  ​微调完成后,在https://blog.csdn.net/v_JULY_v/article/details/output/adgen-chatglm2-6b-pt-128-2e-2 下回生成微调好的模型文件。

  我们可以对比下微调前后的效果

  以命令行 Demo为例,只需修改ptuning路径下web_demo.sh中的模型路径为/data/sim_chatgpt/chatglm2-6b,运行 web_demo.py即可:

  Input:

  类型#上衣材质#牛仔布颜色#白色风格#简约图案#刺绣衣样式#外套衣款式#破洞

  Label:

  简约而不简单的牛仔外套,白色的衣身十分百搭。衣身多处有做旧破洞设计,打破单调乏味,增加一丝造型看点。衣身后背处有趣味刺绣装饰,丰富层次感,彰显别样时尚。

  Output[微调前]:

  ​Output[微调后]:

  ​更多,咱们《》上见