下面是官方原话, 选择他的原因完全是因为可以消费级电脑上使用,更强的130B模型看https://github.com/THUDM/GLM-130B
ChatGLM-6B 是一个开源的、支持中英双语的对话语言模型,基于 General Language Model (GLM) 架构,具有62亿参数。结合模型量化技术,用户可以在消费级的显卡上进行本地部署(INT4 量化级别下最低只需 6GB 显存)。 ChatGLM-6B 使用了和 ChatGPT 相似的技术,针对中文问答和对话进行了优化。经过约 1T 标识符的中英双语训练,辅以监督微调、反馈自助、人类反馈强化学习等技术的加持,62 亿参数的 ChatGLM-6B 已经能生成相当符合人类偏好的回答,更多信息请参考我们的博客。
为了方便下游开发者针对自己的应用场景定制模型,我们同时实现了基于 P-Tuning v2 的高效参数微调方法 (使用指南) ,INT4 量化级别下最低只需 7GB 显存即可启动微调。
不过,由于 ChatGLM-6B 的规模较小,目前已知其具有相当多的局限性,如事实性/数学逻辑错误,可能生成有害/有偏见内容,较弱的上下文能力,自我认知混乱,以及对英文指示生成与中文指示完全矛盾的内容。请大家在使用前了解这些问题,以免产生误解。更大的基于 1300 亿参数 GLM-130B 的 ChatGLM 正在内测开发中。
为与社区一起更好地推动大模型技术的发展,我们同时开源 ChatGLM-6B 模型。ChatGLM-6B 是一个具有62亿参数的中英双语语言模型。通过使用与 ChatGLM(chatglm.cn)相同的技术,ChatGLM-6B 初具中文问答和对话功能,并支持在单张 2080Ti 上进行推理使用。具体来说,ChatGLM-6B 有如下特点:
安装日期:2023-04-08
THUDM/ChatGLM-6B github
备用但是仓库代码
zero_nlp 这个项目入门应该不错,涉及知识点比较多
git clone https://github.com/THUDM/ChatGLM-6B.git
(venv) [root@VM-245-24-centos ~]# cd ChatGLM-6B
python3.9 -m venv venv
source venv/bin/activate
pip3.9 install -r requirements.txt
pip3.9 install accelerate
pip3.9 install streamlit streamlit_chat
模型模型数据准备阶段
mkdir THUDM
cd THUDM
# 注意此时是没有大模型文件(比如pytorch_model-00001-of-00008.bin这种IFS文件)
git clone https://huggingface.co/THUDM/chatglm-6b
# 去清华大学镜像站下载文件
# 这里建议看这个文章中的python自动爬虫下载,亲测有效 https://aistudio.baidu.com/aistudio/projectdetail/5741753?channelType=0&channel=0
附:下载大文件的的python代码
# 文件1pytorch_model 8个文件下载----------------------------------------------------------------------------------------------------------
import requests
url1='https://cloud.tsinghua.edu.cn/d/fb9f16d6dc8f482596c2/files/?p=%2Fpytorch_model-0000'
url2='-of-00008.bin&dl=1'
save_path1='pytorch_model-0000'
save_path2='-of-00008.bin'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'}
# 循环获取models,总共有8个基础模型
for i in range(8):
url=url1+str(i+1)+url2
save_path=save_path1+str(i+1)+save_path2
res = requests.get(url,headers=headers)
file1 =open(save_path,'wb')
file1.write(res.content)
file1.close()
print("第{}个模型下载已完成".format(i+1))
# 文件2 ice_text 个文件下载---------------------------------------------------------------------------------------------------------------------------------
# 一开始想用wget命令抓取清华镜像的预训练模型,但一直不成功只能用爬虫方法进行get获取了
# 获取网页信息
import requests
url='https://cloud.tsinghua.edu.cn/d/fb9f16d6dc8f482596c2/files/?p=%2Fice_text.model&dl=1'
save_path='ice_text.model'
# 设置header
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'}
# 获取文件并写入
res = requests.get(url,headers=headers)
file1 =open(save_path,'wb')
file1.write(res.content)
file1.close()
运行Demo测试
# web_demo 的前端资源有些是google的,可能会页面打不开,推荐第二个
python3.9 web_demo.py
或者
streamlit run web_demo2.py
注意确认demo中模型路径和实际路径是否相同
THUDM/ChatGLM-6B ptuning 微调官方教程
微调代码就在THUDM/ChatGLM-6B的ptuning目录下
进入目录
[root@VM-245-24-centos ChatGLM-6B]# cd ptuning
防止包冲突我这里重新初始化了
venv环境
python3.9 -m venv venv
source venv/bin/activate
pip3.9 install rouge_chinese nltk jieba datasets transformers torch icetk cpm_kernels
官方示例的数据太久了(目瞪口呆,54M数据居然要11个小时),放弃了,我们准备自己的数据集
改一下train.sh的内容
PRE_SEQ_LEN=8
LR=1e-2
CUDA_VISIBLE_DEVICES=0 python3.9 main.py \
--do_train \
--train_file mydata/train.json \
--validation_file mydata/dev.json \
--prompt_column content \
--response_column summary \
--overwrite_cache \
--model_name_or_path ../THUDM/chatglm-6b \
--output_dir output/adgen-chatglm-6b-pt-$PRE_SEQ_LEN-$LR \
--overwrite_output_dir \
--max_source_length 64 \
--max_target_length 64 \
--per_device_train_batch_size 1 \
--per_device_eval_batch_size 1 \
--gradient_accumulation_steps 16 \
--predict_with_generate \
--max_steps 3000 \
--logging_steps 10 \
--save_steps 1000 \
--learning_rate $LR \
--pre_seq_len $PRE_SEQ_LEN
# --quantization_bit 4
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 的值,但也会带来更多的显存消耗,请根据实际情况酌情调整。
修改如下
# 我的python版本是3.9
python3 -> python3.9
# 训练文件变了,后面会创建,先改
--train_file mydata/train.json \
--validation_file mydata/dev.json \
# 修改模型的路径,模型此时已经在父目录,我们修改一下即可
--model_name_or_path THUDM/chatglm-6b \ -> --model_name_or_path ../THUDM/chatglm-6b \
# 关闭quantization_bit ,我的显卡是够的,而且quantization_bit为4我这里反而报错,所以索性关闭了,不加此选项则为 FP16 精度加载
--pre_seq_len $PRE_SEQ_LEN \ -> --pre_seq_len $PRE_SEQ_LEN
--quantization_bit 4 -> #--quantization_bit 4
目前这个过程是自己造数据,属于
有监督学习,一问一答类型,后面研究要开始关注无监督 文字接龙 teacher forcing,Self instruction,few-shot
经过前面的折腾,我们知道格式是{“content”:"","summary":""}(看教程广告数据训练都是这个结构),一个是input,一个是output, 我们按照这个格式造数据即可(经过zy网友指导,这里对于同一个input要做到同义句泛化,要使用大量同义句,微调的效果才好)
提前准备一下泛化数据(懒得泛化的,可以直接手写自己的数据
{“content”:"","summary":""}格式大概是这样),Self instruction 这个貌似要单独学习一下,基于GPT自动泛化,作为新手这里暂时就手动自己造数据好了
mkdir mydata
vim mydata/dev.json
vim mydata/train.json
训练数据写入到dev.json(随便一条),train.json(全部)
{"content": "你叫什么名字?","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "你可以告诉我你的名字吗?","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "你是GPT吗","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "你能告诉我你的名字吗?","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "你是机器人吗?","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "你能告诉我你的名字吗?","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "你知道我叫啥名字吗?","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "介绍一下你自己","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "介绍自己","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "你是ChatGPT吗","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "自我介绍一下","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "你是?","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "你知道我叫啥名字吗?","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "你是谁","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "你是","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "你可以告诉我你的名字吗","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "你是哪位","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "你叫啥","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "你叫什么","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
{"content": "你是谁","summary":"你好,我是小君,很高兴认识你,有什么可以帮你?"}
开始运行训练啦,(*^▽^*)
bash train.sh
这个时候才发现和训练数据的大小无关,自定义20条数据一样也是预计11个小时( ̄ェ ̄;)

整个训练过程大概11个小时

训练后的数据大小39G左右
du -sh output/
39G output/
依然修改一下evaluate.sh, 我需要修改的是python版本和关闭quantization_bit
PRE_SEQ_LEN=8
CHECKPOINT=adgen-chatglm-6b-pt-8-1e-2
STEP=3000
CUDA_VISIBLE_DEVICES=0 python3.9 main.py \
--do_predict \
--validation_file mydata/dev.json \
--test_file mydata/dev.json \
--overwrite_cache \
--prompt_column content \
--response_column summary \
--model_name_or_path ./output/$CHECKPOINT/checkpoint-$STEP \
--output_dir ./output/$CHECKPOINT \
--overwrite_output_dir \
--max_source_length 64 \
--max_target_length 64 \
--per_device_eval_batch_size 1 \
--predict_with_generate \
--pre_seq_len $PRE_SEQ_LEN
#--quantization_bit 4
开始推理,这次速度很快就结束
bash evaluate.sh

将对应的demo或代码中的 THUDM/chatglm-6b 换成经过 P-Tuning 微调之后 checkpoint 的地址(在示例中为 ptuning/output/adgen-chatglm-6b-pt-8-1e-2/checkpoint-3000)。注意,目前的微调还不支持多轮数据,所以只有对话第一轮的回复是经过微调的。
我们修改一下web_demo2.py启动文件,使用训练后的模型,需要重新指定模型路径ptuning/output/adgen-chatglm-6b-pt-8-1e-2
# 返回ChatGLM-6B目录
cd ../
# 切换环境
source venv/bin/activate
# 修改模型 路径 THUDM/chatglm-6b --> ptuning/output/adgen-chatglm-6b-pt-8-1e-2/checkpoint-3000
vim web_demo2.py
# 启动模型
streamlit run web_demo2.py
效果展示

问题探讨,ISSUE542有提及https://github.com/THUDM/ChatGLM-6B/issues/542
随着对ptuning理解加深,可以发现,我很容易改变了几人的认知,但是其他知识似乎都忘记了(回答变得很奇怪了),而且还容易出现复读现象。所以在技术落地方面,我同意用来做特点的任务场景比较适合(意图识别,信息抽取等),然后再结合传统NLP技术落地应用即可。
另外,LoRA相关微调,听说也很优秀,后面再实践。
属于有监督训练
貌似这种方法是有点过时的,主流好像是利用ChatGPT做Self instruction,不过需要gpt key,这是另外一个故事了,后面再看看这个怎么玩,现在先学习理解这个过程为主
苏神的科学空间:https://spaces.ac.cn/
simbert:https://spaces.ac.cn/archives/7427
simbertv2:https://spaces.ac.cn/archives/8454
这个项目有点久没更新了,不要混着GLM在一起使用同一个环境,包依赖是会冲突的,已经踩坑了
这里要注意,不要使用太高版本的python(不是3.9,也不可以是3.6)版本,这里我用了python3.7(点击我下载),附上安装教程, 清华大学开源软件镜像站
[root@VM-245-24-centos ~]# git clone https://github.com/425776024/nlpcda.git
[root@VM-245-24-centos ~]# cd nlpcda/
python3.7 -m venv venv
source venv/bin/activate
pip3.7 install -r requirements.txt
pip3.7 install nlpcda keras==2.3.1 bert4keras==0.7.7 tensorflow==1.13.1 tensorflow-gpu==1.13.1
pip install 'protobuf~=3.19.0'
根据教程https://github.com/425776024/nlpcda下载simbert的模型, 如下图

报错

把函数名字给换一下
vim nlpcda/tools/simbert/generator.py
第46行
@AutoRegressiveDecoder.set_rtype('probas')
通过上面的百度网盘我下载了tiny的模型文件,准备下test.py
from nlpcda.tools.Simbert import Simbert
config = {
'model_path': 'chinese_simbert_L-4_H-312_A-12',
'CUDA_VISIBLE_DEVICES': '0',
'max_len': 32,
'seed': 1
}
simbert = Simbert(config=config)
sent = '把我的一个亿存银行安全吗'
synonyms = simbert.replace(sent=sent, create_num=5)
print(synonyms)
SimBERT属于有监督训练,训练语料是自行收集到的相似句对,通过一句来预测另一句的相似句生成任务来构建Seq2Seq部分,然后前面也提到过[CLS]的向量事实上就代表着输入的句向量,所以可以同时用它来训练一个检索任务。

深入学习参数使用
https://kexue.fm/archives/7427
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我有一些非常大的模型,我必须将它们迁移到最新版本的Rails。这些模型有相当多的验证(User有大约50个验证)。是否可以将所有这些验证移动到另一个文件中?说app/models/validations/user_validations.rb。如果可以,有人可以提供示例吗? 最佳答案 您可以为此使用关注点:#app/models/validations/user_validations.rbrequire'active_support/concern'moduleUserValidationsextendActiveSupport:
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs
我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案
我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie