MLC-LLM 支持RWKV-5推理以及对RWKV-5的一些思考
自从2023年3月左右,chatgpt火热起来之后,我把关注的一些知乎帖子都记录到了这个markdown里面,:https://github.com/BBuf/how-to-optim-algorithm-in-cuda/tree/master/large-language-model-note ,从2023年3月左右到现在保持了持续动态更新整理,有关于LLM基础知识,LLM训练,LLM推理等各个方面的知乎文章链接,感兴趣的读者可以看一下。
0x0. 前言
继续填 使用MLC-LLM将RWKV 3B模型跑在Android手机上(redmi k50每s可解码8个token 这篇文章留下的坑。由于上面这篇文章支持的是RWKV4模型,不支持最近RWKV社区正在训练的RWKV5模型,所以利用业余时间在MLC-LLM里面支持了最新的RWKV5模型的推理,同时也可以带大家看一下RWKV5的3B模型表现是否有惊艳之处。目前我跑通了Metal和Android平台的RWKV5推理(包含1.5B和3B),并且也编译出了一个3B int8模式的apk提供给android用户使用,地址为:https://github.com/BBuf/run-rwkv-world-4-in-mlc-llm/releases/download/v1.0.0/rwkv5-3b-int8.apk 。大家可以下载这个apk来体验最新的RWKV-5-3B模型。
另外,我在测试RWKV-5-3B的时候也发现了RWKV4的表现和HuggingFace版本的表现相差比较多,也修复了这个bug。总的来说,在MLC-LLM里面适配一个新的RWKV5模型是比较麻烦的,我前后肝了几个周末,并且在Hzfengsy的热心帮助下解决了一个关键的TIR实现问题后。这篇文章我会分享一下适配过程中的主要问题是什么,给想使用MLC-LLM适配其它不支持的模型的读者一个踩坑经验。
关于RWKV模型的更多信息大家可以关注bo的两篇博客:
- RWKV-5 的训练进展,与 SOTA GPT 模型的性能对比:https://zhuanlan.zhihu.com/p/659872347
- RWKV-5 的训练进展(之二),与 SotA GPT 模型的性能对比:https://zhuanlan.zhihu.com/p/664079347
再次感谢@Hzfengsy 在适配RWKV-5过程中的指导。
本文涉及到的工程代码体现在下面的2个PR:
- https://github.com/mlc-ai/mlc-llm/pull/1275 (MLC-LLM中支持RWKV5)
- https://github.com/mlc-ai/tokenizers-cpp/pull/19 (对RWKV World Tokenzier的bug修复,也提升了RWKV-4-World系列模型的效果)
另外,目前MLC-LLM支持RWKV-5在Metal和Android的推理,但是在nvidia gpu上因为一个已知的tvm bug导致编译失败,如果要在Nvidia GPU上部署RWKV-5-World模型需要等官方完成这个bug fix,具体请关注 https://github.com/mlc-ai/mlc-llm/pull/1275 进展。
0x1. 笔者为何关注RWKV
对LLM的理解比较有限,从代码实现的角度来说,RWKV的状态和KV Cache不同,不依赖序列长度,这让RWKV模型在各种长度下运行内存和运行速度都是趋于稳定的,所以我感觉工程价值是比基于Transformer架构比如Llama更好的,部署的性价比会天然更优。这个特点让他在更长的序列比如100K长度下的推理也更有前景吧。
但是,RWKV是否可以取得和Transformer主流架构相同的效果呢?我个人感觉还是需要等待时间的检验,目前最新的RWKV5模型最多scale up到7B,并且数据也是很有限只有1.12TB,这个信息我是从HuggingFace的项目看到的,如下图所示。(这里的v2就是最新的RWKV5架构,内部小版本命名稍显混乱,这一点也可以从ChatRWKV的model.py看出)。
所以如果RWKV架构真的可以取得和Transformer开源SOTA架构一样的效果,前景是很好的。RWKV-5 的训练进展(之二),与 SotA GPT 模型的性能对比:https://zhuanlan.zhihu.com/p/664079347 这里已经贴出一些BenchMark结果:
从作者这里选取的一些数据集来看,RWKV-5-World 7B目前仅训练30%的checkpoint的效果已经和Baichuan2-7B-Base非常接近了,还是值得期待一下的。
不过,这里存在的问题是这里的这些测试的数据集可能需要使用一些更加有说服力的,比如MMLU/CMMLU/HummanEval/MBPP/CMRC2018等等。这个属于开源大模型评测的知识,大家应该能找到很多榜单,RWKV官方是否考虑去opencompass打一下榜,更全面的做个对比。
因为这里有个明显的疑问就是,按照官方的说法,为什么使用1.12T数据训练30%之后在上面的任务里面就可以几乎持平使用2.6T数据进行全量预训练的Baichuan2-7B-Base模型的效果呢?所以我个人感觉这里需要更多的榜单数据来看效果。
0x2. RWKV-5-3B模型在Mac上的一些文创和代码生成效果演示
我个人感觉7B模型和3B模型就是为了手机上离线运行而生的尺寸,所以我这里使用上面编译的Apk来演示一下使用MLC-LLM推理的RWKV-5-3B模型的一些文创效果和代码生成效果。下面演示的文创问题大多数来自昆仑天工的Skywork-13B例子(https://github.com/SkyworkAI/Skywork),感谢。下面的User是我问的问题,Assistant是RWKV-5-3B模型的回答,运行环境为Mac M2 FP16模式。由于这个模型是基础模型,所以对话效果会受到上下文多轮对话干扰,所以在测试不同种类的问题时,可以使用/reset
来重置对话。
概念介绍
广告文案
作文生成
演讲稿生成
心得体会
科技文稿
记录文
评论评语
问题生成
起名字
简单代码
总的来说,对于大多数文学创作问题,RWKV-5-3B的回答还算像那回事,不过也可以明显感觉到一些瑕疵以及指令跟随的能力很有限,比如对数字非常不敏感,让他说5个字他似乎不明白意思。此外,3b模型拥有了一定的代码能力,可以写有限的简单代码。
最后,我比较期待7b最终训练完之后的效果,希望RWKV可以在opencompass榜单上证明自己。
0x3. MLC-LLM支持RWKV-5步骤
这一节可能会写得流水账一点。模型实现文件:https://github.com/mlc-ai/mlc-llm/pull/1275 里的 rwkv5.py
首先,由于MLC-LLM已经支持了RWKV4架构,所以我们大体上是可以使用RWKV4的实现的,然后把RWKV5的改动加上去。
我们可以从ChatRWKV的rwkv4/rwkv5模型实现(https://github.com/BlinkDL/ChatRWKV/blob/main/rwkv_pip_package/src/rwkv/model.py)看出rwkv4和rwkv5的不同之处主要在于RWKV5引入了多头的线性Attention,代码上体现为对Attention部分的重写,包括state的个数也从5个变成了3个。从MLC-LLM的模型实现代码上来看,如果要在同一个实现中进行兼容会相当麻烦,所以我使用了一个新的文件来实现RWKV5,接下来就是对着ChatRWKV修改代码把RWKV5的初版本改上去。在RWKV5的prefill阶段,会调用一个新的CUDA Kernel:https://github.com/BlinkDL/ChatRWKV/blob/main/rwkv_pip_package/src/rwkv/model.py#L465-L497 。而这个Kernel的原始实现则对应这里的Python公式:https://github.com/BlinkDL/RWKV-CUDA/blob/main/wkv5/run.py#L67-L87
但需要注意的是,在真正的模型实现中,这里的state是需要更新的全局变量而非local的。由于这个函数有一个循环会在T的维度上进行迭代,而T是序列长度是可变的,所以这里需要类似于RWKV4的实现写一个TIR来模拟这个python程序的逻辑,在冯博的帮助下得到了一版初始的TIR实现:
这个实现过程中也帮助发现一个DLight的bug,由@Hzfengsy在tvm里面进行了修复。https://github.com/apache/tvm/pull/16124
解决了上面的TIR问题之后就可以在MLC-LLM里面编译RWKV5模型了,然后使用TVM的dump ir工具和ChatRWKV来对比精度,这里需要固定输入的Tensor才行,为了方便我将输入固定为一个全1的十个元素的ids。然后在对比精度的实现发现,上面实现的TIR的输入的所有值都是可以对上的,但是TIR的输出out却是错误的。仍旧是冯博帮我解决了这个bug,原因是因为上面的版本中对于state来说T不应该是spatial的而是reduction。修复后的正确版本长这样:
接着又从dump的结果观察到attention部分的groupnorm的结果无法对上,但输入都是可以对上的,然后我手动实现了一下groupnorm的过程(下面的237-247行)发现结果竟然是可以对上的。
后面经Hzfengsy提醒确认是开始的groupnorm调用参数写错了,修复之后继续下一步。这一下attention和ffn的结果是可以对上了。
然后开始使用mlc chat程序尝试进行对话,发现输出会乱码。又怀疑中间某个地方精度没对齐,所以继续完整模拟了一遍prefill+decode,发现prefill+第一轮decode的结果完全能对上,想摆烂了。。
然后我使用相同的问题问了一下ChatRWKV,发现ChatRWKV的结果也是乱码。。。直觉告诉我一定是乌龙了,由于我这里对比的ChatRWKV是我自己fork的,可能不小心改了bug。我重新拉官方的ChatRWKV一一对比,找到了问题所在。是因为我的代码里错误的去掉一个transpose op,我也忘记了为什么要这么做,但是这个transpose op去transpose的两个维度的大小是相同的,所以输出shape也是相同的,导致了对精度浪费了很多时间。
解决这个问题之后,发现输出就是正常的了。但,真的正常吗?
我在尝试一些问题时发现输出非常奇怪:
感觉这里一定还有bug,既然模型精度方面没有bug,要么就是prompt技巧,tokenizer,sampling。sampling是比较正常并且经过众多模型检验的,应该问题不大。然后恰好想起daquexian的faster-rwkv里面更新过tokenzier,之前的实现应该有bug:
接下来就是更新tokenzier的代码修复bug,最后在review 初始化prompt的时候也发现了一个bug,将其修复。
最终获得的代码效果就是0x2节展示的了,这些prompt的输出和ChatRWKV相差不大,理论上来说应该是完成了正确的适配。
0x4. 总结
本文记录了笔者使用 MLC-LLM 支持RWKV-5推理的过程以及对RWKV-5的一些思考,谢谢。
相关文章:

MLC-LLM 支持RWKV-5推理以及对RWKV-5的一些思考
自从2023年3月左右,chatgpt火热起来之后,我把关注的一些知乎帖子都记录到了这个markdown里面,:https://github.com/BBuf/how-to-optim-algorithm-in-cuda/tree/master/large-language-model-note ,从2023年3月左右到现…...

WPF中行为与触发器的概念及用法
完全来源于十月的寒流,感谢大佬讲解 一、行为 (Behaviors) behaviors的简单测试 <Window x:Class"Test_05.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winf…...

2023-2024华为ICT大赛-计算赛道-广东省省赛初赛-高职组-部分赛题分析【2023.11.18】
2023-2024华为ICT大赛 计算赛道 广东省 省赛 初赛 高职组 部分赛题 分析【2023.11.18】 文章目录 单选题tpcds模式中存在表customer,不能成功删除tpcds模式是( )以下哪个函数将圆转换成矩形( )下列哪个选项表示依赖该D…...

『 MySQL数据库 』数据库之表的约束
文章目录 前言 💻空属性约束(非空约束) 🔖default约束(默认值约束,缺省) 🔖列描述comment 🔖数字类型长度zerofill 🔖主键primary key 🔖📍 追加主键 📍📍 删除主键 &…...

flink 8081 web页面无法被局域网内其他机器访问
实现 http://localhost:8081/#/overview 可以被局域网其他机器访问...

零基础安装分布式数据服务注册系统
一、先安装VM虚拟机,安装最新的ubuntu22系统, 先安装mysql, sudo apt install mysql-server sudo mysql_secure_installation 根据自己需求选择 密码安全级别时,选择n 删除匿名用户?(按y|Y表示是&…...

2023最新最全【OpenMV】 入门教程
1. 什么是OpenMV OpenMV 是一个开源,低成本,功能强大的 机器视觉模块。 OpenMV上的机器视觉算法包括 寻找色块、人脸检测、眼球跟踪、边缘检测、标志跟踪 等。 以STM32F427CPU为核心,集成了OV7725摄像头芯片,在小巧的硬件模块上&a…...

【Java并发编程三】线程的基本使用一
基本使用一 将类继承Runnable,创建Thread,然后调用Thread的start方法启动: package myTest;public class myTest implements Runnable {public static void main(String[] args) throws InterruptedException {myTest test new myTest();Th…...

企业邮箱认证指南:安全与高效的邮箱认证方法
企业邮箱是专门为企业提供的电子邮件服务,安全性和专业性更高。在开始使用企业邮箱之前,很多人会有一些问题,比如企业邮箱需要认证吗、如何开通企业邮箱,以及哪款企业邮箱好。 1、企业邮箱在使用前需要认证吗? 答案是肯…...

Django(八、如何开启事务、介绍长见的字段类型和参数)
文章目录 ORM事务操作开启事务 常见的字段类型和参数ORM还支持用户自定义字段类型ORM常用字段参数外键相关参数 ORM事务操作 引入事务 1.事务的四大特性原子性、一致性、隔离性、持久性 2.相关SQL关键字start transaction;rollback;commit;savapoint; 3.相关重要概念脏读、幻…...

机器学习第5天:多项式回归与学习曲线
文章目录 多项式回归介绍 方法与代码 方法描述 分离多项式 学习曲线的作用 场景 学习曲线介绍 欠拟合曲线 示例 结论 过拟合曲线 示例 结论 多项式回归介绍 当数据不是线性时我们该如何处理呢,考虑如下数据 import matplotlib.pyplot as plt impo…...

MSYS2介绍及工具安装
0 Preface/Foreword 1 MSYS2 官网:MSYS2...

Swift开发中:非逃逸闭包、逃逸闭包、自动闭包的区别
1. 非逃逸闭包(Non-Escaping Closure) 定义:默认情况下,在 Swift 中闭包是非逃逸的。这意味着闭包在函数结束之前被调用并完成,它不会“逃逸”出函数的范围。内存管理:由于闭包在函数返回前被调用…...

栈结构应用-进制转换-辗转相除法
// 定义类class Stack{// #items [] 前边加#变为私有 外部不能随意修改 内部使用也要加#items []pop(){return this.items.pop()}push(data){this.items.push(data)}peek(){return this.items[this.items.length-1]}isEmpty(){return this.items.length 0}size(){return th…...

【Azure 架构师学习笔记】-Azure Storage Account(6)- File Layer
本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Storage Account】系列。 接上文 【Azure 架构师学习笔记】-Azure Storage Account(5)- Data Lake layers 前言 上一文介绍了存储帐户的概述,还有container的一些配置,在…...

idea 环境搭建及运行java后端源码
1、 idea 历史版本下载及安装 建议下载和我一样的版本,2020.3 https://www.jetbrains.com/idea/download/other.html,idea分为专业版本(Ultimate)和社区版本(Community),前期可以下载专业版本…...

掌握Shell:从新手到编程大师的Linux之旅
1 shell介绍 1.1 shell脚本的意义 1.记录命令执行的过程和执行逻辑,以便以后重复执行 2.脚本可以批量处理主机 3.脚本可以定时处理主机 1.2 脚本的创建 #!/bin/bash # 运行脚本时候执行的环境1.3 自动添加脚本说明信息 /etc/vimrc # vim主配置文件 ~/.vimrc # 该…...

有重复元素的快速排序
当涉及到处理重复元素的快速排序时,可以使用荷兰国旗问题的方法,也就是三路划分。下面是使用 Java 实现的示例代码: import java.util.Arrays;public class QuickSort {public static void quickSort(int[] arr, int low, int high) {if (lo…...

Bert浅谈
优点 首先,bert的创新点在于利用了双向transformer,这就跟openai的gpt有区别,gpt是采用单向的transformer,而作者认为双向transformer更能够融合上下文的信息。这里双向和单向的区别在于,单向只跟当前位置之前的tocke…...

产品运营的场景和运营策略
一、启动屏 1.概念 启动屏,特指 APP 产品启动时即显示的界面,这个界面一般会停留几秒钟时间,在这个时间内 APP 会在后台加载服务框架、启动各种服务 SDK 、获取用户地理位置、判断有无新版本、判断用户账户状态以及其他系统级别的…...

C#异常捕获try catch详细介绍
在C#中,异常处理是通过try、catch、finally和throw语句来实现的,它们提供了一种结构化和可预测的方法来处理运行时错误。 C#异常基本用法 try块 异常处理以try块开始,try块包含可能会引发异常的代码。如果在try块中的代码执行过程中发生了…...

切换阿里云ES方式及故障应急处理方案
一、阿里云es服务相关问题及答解 1.1 ES7.10扩容节点时间 增加节点数量需要节点拉起和数据Rebalance两步,拉起时间7.16及以上的新版本大概10分钟以内,7.16以前大概一小时,数据迁移的时间就看数据量了,一般整体在半小时以内 (需进行相关测试验证) 1.2 ES7.10扩容数据节点…...

CTFhub-RCE-过滤空格
1. 查看当前目录:127.0.0.1|ls 2. 查看 flag_890277429145.php 127.0.0.1|cat flag_890277429145.php 根据题目可以知道空格被过滤掉了 3.空格可以用以下字符代替: < 、>、<>、%20(space)、%09(tab)、$IFS$9、 ${IFS}、$IFS等 $IFS在li…...

无需添加udid,ios企业证书的自助生成方法
我们开发uniapp的app的时候,需要苹果证书去打包。 假如申请的是个人或company类型的苹果开发者账号,必须上架才能安装,异常的麻烦,但是有一些app,比如企业内部使用的app,是不需要上架苹果应用市场的。 假…...

【PTA题目】6-20 使用函数判断完全平方数 分数 10
6-20 使用函数判断完全平方数 分数 10 全屏浏览题目 切换布局 作者 张高燕 单位 浙大城市学院 本题要求实现一个判断整数是否为完全平方数的简单函数。 函数接口定义: int IsSquare( int n ); 其中n是用户传入的参数,在长整型范围内。如果n是完全…...

Nas搭建webdav服务器并同步Zotero科研文献
无需云盘,不限流量实现Zotero跨平台同步:内网穿透私有WebDAV服务器 文章目录 无需云盘,不限流量实现Zotero跨平台同步:内网穿透私有WebDAV服务器一、Zotero安装教程二、群晖NAS WebDAV设置三、Zotero设置四、使用公网地址同步Zote…...

一句话总结敏捷实践中不同方法
敏捷实践是指一组优先考虑灵活性、协作和客户满意度的软件开发和项目管理原则和方法。 不同方法论的敏捷实践: 1、敏捷: Sprints:限时迭代(通常 2-4 周),在此期间创建潜在的可交付产品增量。每日站立会议…...

【数据结构】线段树(点修区查)
数据结构-线段树(点修区查) 前置知识 分治递归二叉树 思路 我们需要维护一个支持单点修改,区间查询的数据结构,并且要求在线,一般使用线段树解决。 线段树是一个二叉树形的数据结构。 线段树的思想很简单,…...

Ansys Lumerical | 用于增强现实系统的表面浮雕光栅
在本示例中,我们使用 RCWA 求解器设计了一个斜面浮雕光栅 (SRG),它将用于将光线耦合到单色增强现实 (AR) 系统的波导中。光栅的几何形状经过优化,可将正常入射光导入-1 光栅阶次。 然后我们将光栅特性导出为 Lumerical Sub-Wavelength Model …...

QT day3作业
1.思维导图 2、 完善对话框,点击登录对话框,如果账号和密码匹配,则弹出信息对话框,给出提示”登录成功“,提供一个Ok按钮,用户点击Ok后,关闭登录界面,跳转到其他界面 如果账号和密…...