当争议和流量都消失后,或许现在是个合适的时间点,来抛开情绪、客观的聊聊这个 34B 模型本身,尤其是实践应用相关的一些细节。来近距离看看这个模型在各种实际使用场景中的真实表现和对硬件的性能要求。
或许,这会对也想在本地私有化部署和运行模型的你有帮助,本篇是第一篇相关内容。
前几周,我曾经写过一篇,如何使用 CPU、CPU & GPU 来本地运行零一万物 34B 模型:《》。随后社区里出现了一些和我一样因为吃瓜关注到零一,因为实际使用被惊艳(finetune 版),而对其持续关注的同学。
距离之前的争议事件已经过去了两周,目前最具公信力的 HuggingFace 榜单中,包括 Yi-34B 在内,排在它前面的模型只有 26 个,但是其中 48% (14个)都是 Yi-34B 和 Yi-34B 200K 的变体模型,其中第一名是来自社区用户 fblgit 的 “LLaMa Yi 34B” ,比之前因为数据污染而被取消榜单资格的 TigerBot 的 70B 的效果还要好一些,千问憋出的大招 QWen 72B 暂居第二;而原本被 70B 霸占的头部榜单里,还剩包括 QWen 72B 在内和 Llama2 变体模型的一共 8 个模型。
一时间,34B 和 34B 200K 蔚然成风。
如果你对上面详细的模型的血缘关系和基础模型分类感兴趣,可以移步文章结尾中的“其他”小节。
在之前文章里,我们使用的是来自社区的 finetune 和量化版本,这次,我们来陆续测试和使用下官方的模型吧。
当然,本篇文章也会聊聊之前漏了的 GGUF 模型量化,希望对你有帮助。
想要折腾零一万物的模型,依旧是需要准备两件前置材料:模型运行软件环境、模型程序文件、运行模型的设备。
模型运行的软件环境
在上一篇文章中,我再次提到了 Docker 环境。当然,如果你实在不喜欢 Docker ,我们也可以不用 Docker,撸起袖子直接干。
如果你选择 Docker 路线,不论你的设备是否有显卡,都可以根据自己的操作系统喜好,参考这两篇来完成基础环境的配置《》、《》。当然,使用 Docker 之后,你还可以做很多事情,比如:,在此就不赘述啦。
关于 Yi-34B 的通用容器环境,你可以在上篇文章的“”小节找到,相关程序保存在开源项目 中,可以自取。
如果你选择 Bare metal 路线,可以用这篇文章中“准备工作”小节中提到的“”来完成基础环境的初始化:
在上篇文章中,我详细的介绍了如何使用 HuggingFace CLI 和新工具 HF transfer 下载模型,如果你感兴趣,可以,这里我们就不再赘述,只提基础操作:
使用上面的命令,我们就能够从 HuggingFace 社区拽下来 Yi-34B 两个基础模型到本地啦。(非常期待国内不论是爱好者还是开源组织能够提供一个快速下载的方式,每次下载模型的过程都太痛苦了)
下载完毕,我们将能够得到两个模型目录:
当然,为了节约空间,你可以删除下载模型中的某一个模型版本,只保留一种( PyTorch 原版的 或者 HF 推荐的 )整理完之后,每个模型目录,大概会分别占用 65GB:
在上一篇文章中,我使用的是一台能打游戏的台式机:13900KF + 4090。
在实际测试过程中,如果你按照我提供的方法来运行。并不需要 4090 24G的显卡,我们将显存需求卸载到 CPU 和内存上,显卡只要能装载,最少 13G,最多 21 GB 的程序即可。(虽然不推荐魔改显卡,但是如果你恰好有魔改的 22GB 显卡的话,也不妨一试)
这次,我使用的是一台 A800 的 Docker 虚拟机,这个规格对于 34B 来说,显存容量怎么都有些“超纲”了:
但是足够的冗余资源,正好让我们更好的测试和验证 34B 的模型(不再会 Out Of Memory),只有知道模型到底“多费电”,“多吃”显卡,心里有数才能做好优化,用好它不是?
下面我们先使用一个“相对简单”的任务,来进行模型的基础使用。
其中我要求程序输出的内容,因为笔误,导致要求多了一个无意义的 ,正好也借此来看看模型对于额外的干扰的反应。
随意的加载和使用模型(不进行正确参数设置)
迄今为止,市面上的开源模型也好,OpenAI 的闭源模型也罢,没有不喜欢“戴高帽”的,我们先随便写一段脚本,来调用模型,测试和感受下模型的基础生成能力(不特别设置参数,直接调用模型):
我们将上面的程序保存为 ,然后执行 后。稍等片刻,模型程序运行完毕后。
我得到了一个“嘴硬”、“不听话”且“会偷懒的”模型回复(假装已经干完活儿的人工智能…):
随便运行几次,还能够得到乱七八糟的,带有重复内容输出内容,或者完全不听话的结果:
或者是重复的内容:
或者是有些感觉,但是文本控制和细节把握并不好的结果。
在内容生成的过程中,我们如果观察显卡的运行状态,会发现默认参数调用的情况下,GPU 大概一共会消耗 76GB,每张卡的使用率其实都不算高,只有 8%~15%。
但其实,我也曾得到过非常有趣的结果(如果没有那段代码生成,就更好了):
那么,这就是 Yi-34B 的能力吗?不,我们并没有设置好参数,上面的活动只是热身。
进行相对合理的模型参数设置
通过上面直接调用模型的方式,我们大概知道了一些很基础的事情:如果我们不进行任何参数的设置,直接进行模型调用,虽然模型具备生成能力,能够“听一些话”,但是整体上会生成“重复的内容”、“思维一会死板、一会跳跃”,“生成内容上下文的控制能力并不是那么好”。
那么,我们来参考官方仓库中的参数,来对模型调用进行一些调整:
这里对一个参数()进行了调整,并细粒度的设置了四个新的参数 、、、。
简单来解释下为什么这样设置,当我们将 设置为大于 1 的数值后,能够避免程序输出太多的重复内容(对重复内容进行生成惩罚);当我们将 设置为某个整数时,模型在生成的时候,会杜绝连续生成相同的或者连续的 5 个重复词组;当我们将 设置为小于 1 的数值,模型的输出会变的相对稳定,如同吃了镇定剂(但不要喂太多了);当我们设置了 ,能够更加科学的选择没有出现过的词汇,让整理内容的重复度更加少,内容质量更高。因为我们想生成故事,所以,可以相对调大 的数值,让模型生成每个词的时候,能够从更大的范围来选择。
当我们再次执行程序的时候,稍等片刻,这次生成的内容是不是感觉就对路子啦。
图中的文本内容如下:
因为我们调整了参数,实际的运行的资源消耗,从 76G 涨到了 85GB。显卡资源利用率也从 8~15% 提升到了 10%~15%。
错误的 Yi-34B 200K 模型使用方式
简单使用 Yi-34B 基础模型后,我们来看在开源榜单中热火朝天的另外一个 Yi-34B 生态,200K 超长文本内容模型:Yi-34B 200K。
有了上面的经验后,我想,你一定会这样使用 200K 的 34B。比如对上面的程序进行一些直觉上的内容参数调整:
但是,如果你这样做,你很可能会得到一个如同上文中出现过的“嘴硬”加“偷懒” 2.0 版本的人工智能式的回答:
图片中的生成文本,如下:
尝试在 Yi-34B 200K 使用处理超长的文本内容
对于 200K 的模型,或许最合适和最让人心动的用法是让模型加载大量数据并进行内容续写或分析。
比如,下面的 Python 程序中,我们实现了一个读取 文件(可以放一本你喜欢的小说),并截断文件的前 19 万字符的功能:
对上文中的程序进行调整,我们可以得到类似下面的程序:
但是,倘若你直接运行,恐怕会得到类似下面的结果。(社区里有用户反馈无法运行 200K 的模型,多半也是因为这个原因)。
想要运行 200K 模型,我们有很多种方式,但是想要“单机多卡”运行这个原版模型,并保持 200K 长文本窗口,目前还是比较困难的。
我这边尝试了三种方案,最终都因为显存不足而被迫中止(或许后面有时间再试):
如果你有多台机器,或许可以用下面的代码试试看:
当然,如果我们没有那么多显存,还是想运行官方的原版模型,其实也是行的。重点是:不要贪心,把 Token 数量缩小一些。
我们依旧以上面的代码为例,我将上面代码中的 改成了 “2万”到“3万”,然后同时调整了输入的文本的大小,把《天龙八部》一书中从序言到第一章结束的完整内容(3万余字)贴到 中,将上面的代码保存为 ,使用 运行程序。
等待模型被加载完毕后,不需要太长时间,我们就能够看到模型在进行内容的仿写。虽然模型忘记了,我给的最初的任务目标是“摘要”。但是有一说一,仿写的还真有一些金庸的文风:
当然,这种文风并没有坚持太久,毕竟我们使用的是 “base model” 这个毛坯房。 想要提升效果,我们需要更换基于基础模型训练出的对话模型,或者进行一些轻量的 finetune。关于这里的效果提升,后面的文章里,我们再展开聊。
和 Yi 34B 基础模型相比,200K 上下文,轻轻松松吃光所有的资源。
量化模型相比原版模型最直观的差别是“模型尺寸”会得到显著的减少、模型的运行速度通常会有明显的提升。如果你采用了合适的量化方案,在大模型的场景下,通常模型的性能影响是可以接受的。
在《》和《》这两篇文章中,我提到了“使用 Transformers 对 LLaMA2 进行量化”,同样的,如果你想在加载过程中动态的对 Yi-34B 进行量化,或者一次性转换 Yi-34B 原版模型为量化模型,可以考虑参考这两篇文章中的操作。
在《》,我提到了如何将模型量化为 GGML 格式。但随着时间的推移,Llama.cpp 项目中和开源社区里,有一种新的格式逐渐取代了 GGML:它就是 GGUF 格式。
通用模型格式:GGUF
GGUF (GGML Universal File)是 llama.cpp 团队在今年的 8 月 21 日推出的新的模型存储格式,替代之前的存储格式 GGML(此外还有两个变体版本 GGMF、GGJT)。
GGUF 是一种新的模型二进制文件,设计的目标是为了快速的加载和存储模型,并方便程序加载和使用。我们可以通过分发和执行这个独立的执行文件,来完成模型的部署,不需要之前的模型仓库里的一堆元信息文件。
GGUF 能够随意控制模型的多少层由 GPU 加载,而剩下的部分全部交给 CPU 和内存,使用方法比之前的几行 Python 代码还要简单。GGUF 还支持多种不同的量化方式,并能够稳定的保存 4 位量化版本的模型程序。
说了这么多,我们如何制作 Yi-34B 的量化模型呢?
制作 GGUF 量化模型
量化模型其实非常简单,因为这个 GGUF 格式发起之处是 llama.cpp 生态的产品的一部分,所以我们需要下载 llama.cpp 的项目代码,使用其中的工具来进行模型转换。
为了验证转换后的模型是可用的,我们还需要编译 llama.cpp 的执行文件:
进入目录后,手动执行下面的命令,等待程序运行完毕后,我们就能够得到“会轻微造成效果降低”的 8位量化的 GGUF模型啦。
在执行的过程中,我们将看到类似下面的日志滚动:
上面日志中最后出现的 文件,就是我们转换生成的 8 位量化的 GGUF 模型文件啦。
为了能够运行和实践这个程序,我们还需要构建 llama.cpp 中的可执行程序:
当构建执行完毕之后,我们可以在项目目录中找到 可执行文件,我们可以使用下面的命令执行这个程序,来启动一个轻量、快速的 ChatBot 服务:
命令执行完毕,我们将能够看到类似下面的日志输出:
在上面的日志中,我们能够清晰的看到当前运行程序的环境(有多少张卡、每张卡有多少显存、模型的每一层的具体参数、数据量、文件大小、模型文件的基础信息、模型加载所实际消耗的内存和显存资源等等。
相比较上文中的 PyTorch 模型,是不是“可解释性”强了非常多呢?
当我们访问上面日志中最后一行输出的地址 ,就能够看到 llama.cpp 的默认界面啦。
在上文中,我们详细的配置过 Yi-34B 的程序。所以,在使用这个 Web 界面开始聊天之前。我们还是先进行一些配置和调整。
聪明的你,一定会发现,我再次使用了上文中带有“笔误”的 prompt 内容,并且尽可能的将模型参数配置和上文中调整到一样。但是,默认的 llama.cpp 程序中,还是和上文中的参数有一些不同:
当我们点击按钮进行提交后,将会发现模型的输出效率相比之前直接加载官方模型,速度快了许多倍。
当然,最直观以及和推理成本最相关的显存需求,也得到了明显下降:从原本需要 70~80GB 的显存,降低到了 46GB。
或许你会说,这不是还是一张卡的水平嘛,其实不然。一来即使都是使用 80GB 显存的硬件,前者 70~80GB,已经接近显卡最大容量,一旦程序数据量激增,很容易发生 OOM,导致程序 Crash。而后者还留有几十 GB 的“冗余”。二来,46GB 是我们将模型全部都加载到显卡中啦。其实,我们也可以根据自己的实际情况,将模型层中的一半或者更多都卸载到内存中,这样对显卡的显存需求就能够有质的下降 啦。
比如,我们可以将执行加载模型的命令进行调整,将其中的 调整为模型的一半尺寸 。此时在看模型的显存消耗也就降低到了一半,就只需要 26GB 了,相比较最初的官方版本,显存立省 2/3:
除了资源消耗外,我们还需要关注模型的输出效果。
在这个例子中,模型的输出的结果怎么说呢?前 1241 个字,还是在讲故事,后面发现能偷懒了,就和我们在玩“从前有座山、山上有座庙、庙里有个小和尚…”的循环把戏了。
不过,你还记得前文提到的“毛胚房”概念嘛?想要追求效果,还是要“精装修一下”的。
我将目前 HuggingFace 社区中排名较高的前 30 个模型项目进行了梳理和分类,希望对你有帮助 :D
随着明年大概率推理成本的进一步降低、算法的效率的进一步提升,相信上面的榜单,一定还会有更大的变化。
我们一起拭目以待。
两周前在知乎和大家一起 “吃过” 零一万物开源模型的瓜时,当时我也在知乎也回答了,包含了我对于这件事的看法和一些推测。
当天晚上,第一天上班即背锅的社区负责人(苦主)找到了我,非常客气的希望交个朋友,以及非常诚恳地邀请我测试和再未来开放测试的时候使用零一万物的在线版的开源模型,反馈一些来自开源社区的建议和意见。
其实,一方面是朋友圈褒贬不一的评价,另一方面是当时帖子里非常多的回答都是基于情绪,而非真实的运行和使用过模型。加上这位新加到我好友的同学,底气十足的向我保证他们正在找不同的律师,以及提交相关的数据材料,证明模型没有问题。
更加勾起了我对这个模型的兴趣,于是当天晚上我就使用 Colab 在云上跑了一把社区的 Finetune 版本的 Yi-34B,发现好像真没有那么扯。
于是,就有了上一篇文章。
这篇文章记录和梳理了 Yi 34B 的基础使用,和常见踩坑点。以及分享了如何进行基础的 INT8 GGUF 模型的生成转换。
接下来相关的内容里,我们来聊聊 Yi 34B 的性能、效果优化,社区里的开源模型到底能做到什么程度吧。
--EOF
本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。
本文作者: 苏洋
创建时间: 2023年12月10日
统计字数: 24119字
阅读时间: 49分钟阅读