本文目录
近期,清华开源了其中文对话大模型的小参数量版本 ChatGLM-6B(GitHub地址:https://github.com/THUDM/ChatGLM-6B)。其不仅可以单卡部署在个人电脑上,甚至 INT4 量化还可以最低部署到 6G 显存的电脑上,当然 CPU 也可以。
随着大语言模型的通用对话热潮展开,庞大的参数量也使得这些模型只能在大公司自己平台上在线部署或者提供 api 接口。所以 ChatGLM-6B 的开源和部署在个人电脑上,都具有重要的意义。
博主测试后发现,对比 huggingface 上其他同参数量的模型来说,ChatGLM-6B 的效果已经是很好的了,更何况它还有 130B 的版本,官网说明(官方博客:https://chatglm.cn/blog)是优于 GPT-3.5 效果的(130B 版本正在内测,博主没有拿到测试资格,所以无法确认)。所以把 ChatGLM-6B 部署在个人电脑或者服务器上还是很好玩的,这个参数量还要什么自行车。
【最新更新】ChatGLM-6B 在 2023/03/19 更新增加了量化后的 INT4 模型,官方直接针对性的量化模型后提供下载。对比原版自己设置量化效果好一些,而且模型大小只有 4G,极大地加快了下载速度。 对于只有 CPU 或者只有 6G 显存的同学,可以直接选择量化后的模型下载和部署,本文单独更新了 ChatGLM-6B-int4 版本的部署教程,在第四章,需要部署的可以直接跳转到第四章,忽略前面的内容。huggingface 地址:https://huggingface.co/THUDM/chatglm-6b-int4

把模型部署在本地,需要在 Python 环境下安装影响的库,此外还需要针对 GPU 安装相应版本的 cuda 和对应的 Pytorch。之后修改 demo 文件就可以启动运行了。
pip install -r requirements.txt上述三个步骤完成后,部署的环境就搭建完成了。下面仅需要稍微修改 demo 的代码,或者自己根据 demo 编写程序,就可以开始使用 ChatGLM-6B 了!
在 …/ChatGLM/ 目录下有两个 demo 代码:(1)cli_demo.py,直接在命令行中输入进行问答;(2)web_demo.py,利用 gradio 库生成问答网页。
第一个 demo 方便,还可以清除历史记录,但是在命令行(尤其是 Linux 命令行)中容易输入一些奇怪的字符,这会使得程序意外停止;第二个 demo 界面简单,但是不能清除记录,而且如果在没有图形界面的 Linux 系统服务器中使用,需要端口映射到本地电脑,再打开浏览器访问。个人建议,如果有能力,可以自己综合二者的有点自己编写,比如使用 jupyter 就可以很好结合二者,还可以以 markdown 渲染输出,使得代码或者公式更好看。
# 6G 显存可以 4 bit 量化
model = AutoModel.from_pretrained("model", trust_remote_code=True).half().quantize(4).cuda()
# 10G 显存可以 8 bit 量化
model = AutoModel.from_pretrained("model", trust_remote_code=True).half().quantize(8).cuda()
python cli_demo.pypip install gradio# 6G 显存可以 4 bit 量化
model = AutoModel.from_pretrained("model", trust_remote_code=True).half().quantize(4).cuda()
# 10G 显存可以 8 bit 量化
model = AutoModel.from_pretrained("model", trust_remote_code=True).half().quantize(8).cuda()
python web_demo.pyChatGLM-6B-INT4 是 ChatGLM-6B 量化后的模型权重。具体的,ChatGLM-6B-INT4 对 ChatGLM-6B 中的 28 个 GLM Block 进行了 INT4 量化,没有对 Embedding 和 LM Head 进行量化。量化后的模型理论上 6G 显存(使用 CPU 即内存) 即可推理,具有在 嵌入式设备(如树莓派)上运行的可能。
pip install -r requirements.txt本节内容与 3.2 节内容基本相同,参考 3.2 节的部分内容即可,这里不再赘述。请注意:↓↓↓
与 3.2 节不同的是,3.2.1 的步骤 2 和 3.2.2 的步骤 3 直接忽略即可,因为模型已经量化过,不需要重复量化。
虽然 ChatGLM-6B-int4 模型只需要 6G 内存或显存,但是可能对一些想尝试的同学还是有一定困难。所以这里推荐华为云 ModelArts 平台下的 CodeLab,类似于谷歌的 colab,提供免费的最高 64G 内存 + 16G 显存。
打开 ModelArts 控制台页面,注册账号并登陆。网址:https://console.huaweicloud.com/modelarts/?region=cn-north-4#/dashboard
找到控制台页面【总览】下方的【开发工具】,点击 CodeLab 下方的【立即体验】。随后会跳转到 CodeLab 页面并开始加载资源。
导入 ChatGLM-6B 相关代码文件:在加载好的 CodeLab 上方点击【Git】-【Clone a Repository】,在弹出的窗口中输入 https://github.com/THUDM/ChatGLM-6B.git,则 demo 等代码文件就克隆到 CodeLab 了。可以看到在左侧文件管理中多出了 ChatGLM-6B 的文件夹。
下载 ChatGLM-6B-int4 模型:打开 Huggingface 模型文件页面(https://huggingface.co/THUDM/chatglm-6b-int4/tree/main),分别复制每个文件的下载地址,在 ChatGLM-6B 文件夹下新建 model 文件夹,利用 wget 下载地址 在命令行终端分别把模型文件下载到 model 文件夹中。
安装相关依赖:命令行中输入指令 pip install protobuf==3.20.0 transformers==4.26.1 icetk cpm_kernels ,即可完成安装。
运行 demo 代码:双击打开编辑 ChatGLM-6B 文件夹下的 cli_demo.py 文件,把第 5、6 行改为如下形式:
tokenizer = AutoTokenizer.from_pretrained("model", trust_remote_code=True)
model = AutoModel.from_pretrained("model", trust_remote_code=True).float()
随后,在 ChatGLM-6B 下命令行输入 python cli_demo.py 即可运行 demo 程序。
经过一段时间对 ChatGLM-6B、文心一言和 ChatGPT 的使用后,前二者在文字对话上与 ChatGPT 差距已经不大了,在代码生成能力上还有一定差距,但是都好过 GPT-3.5。
文心一言在大部分情况下比 ChatGLM-6B 好一些,不过要注意 ChatGLM-6B 只有 60 亿参数,而且可以单卡部署,这已经是很大的进步了,所以我对 ChatGLM 的发展还是非常看好的,官方也说过除了 int4 量化,还会进一步压缩模型。
总的来说,ChatGLM-6B 在同参数量下可以碾压其他对话模型,而且可以部署到个人电脑上,或者用华为的免费 GPU。通过几天的体验,ChatGLM-6B 是对话模型里非常让人惊喜的了,所以推荐大家可以部署玩玩。甚至可以考虑给嵌入式设备部署一波,也期待官方的进一步极致压缩!
最后也祝 ChatGLM 和 文心一言可以进一步加油,最近的体验也感受到官方每天的更新和进步了,说明态度还是非常积极的。
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我需要从一个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我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案
ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序
我正在使用Rails3.1并在一个论坛上工作。我有一个名为Topic的模型,每个模型都有许多Post。当用户创建新主题时,他们也应该创建第一个Post。但是,我不确定如何以相同的形式执行此操作。这是我的代码:classTopic:destroyaccepts_nested_attributes_for:postsvalidates_presence_of:titleendclassPost...但这似乎不起作用。有什么想法吗?谢谢! 最佳答案 @Pablo的回答似乎有你需要的一切。但更具体地说...首先改变你View中的这一行对此#