使用MLC-LLM将RWKV 3B模型跑在Android手机上

news2025/1/14 18:03:46

0x0. 前言

这篇文章主要是填一下 MLC-LLM 部署RWKV World系列模型实战(3B模型Mac M2解码可达26tokens/s) 这里留下来的坑,这篇文章里面介绍了如何使用 MLC-LLM 在A100/Mac M2上部署 RWKV 模型。但是探索在Android端部署一个RWKV对话模型的app时却碰到了诸多问题,解决的周期也很长,之前留了issue在MLC-LLM的repo,这周@chentianqi大佬回复说之前编译出的app会在模型初始化阶段卡住的问题已经解决了,所以我又重新开始踩了一些坑最终完成了在手机上运行RWKV World4 3B模型的目的。这里把踩的坑和Android编译方法都描述一下。

我这里编译了一个RWKV4 World 3B模型的权重int4量化版本的apk,地址为:https://github.com/BBuf/run-rwkv-world-4-in-mlc-llm/releases/download/v1.0.0/app-debug.apk 。感兴趣的小伙伴可以下载这个apk到android手机上来运行,需要注意的是由于要在线拉取HuggingFace的权重,所以手机上需要可以访问HuggingFace需要代理。

在我的Redmik50手机上进行测试,效果和速度如下:在这里插入图片描述

每一秒大概可以解码8个token,我感觉速度勉强够用了。由于RWKV5迭代到了第5个版本,后续希望能支持RWKV5的模型,当然也可以寻求新的优化机会提升解码速度。

0x1. 踩坑

之前写这篇文章 MLC-LLM 部署RWKV World系列模型实战(3B模型Mac M2解码可达26tokens/s) 的时候发现android app在初始化的时候一直会卡住,即使换成官方编译的app也是如此,所以提了issue之后就放弃了。现在这个bug被修复了,不过我没有找到具体的改动pr是什么,但我在mlc-llm的android部分没有发现相关改动,所以大概率是relax本身的bug,就不深究了。

这次仍然是按照之前的方法进行编译,但是也踩了几个坑,具体体现在下方的改动:

在这里插入图片描述这个改动只是为了在本地可以编译出RWKV的android app,有坑的地方体现在下面的2个改动:

在这里插入图片描述
第一个坑是在dump_mlc_chat_config的时候,对于RWKV World模型应该使用工程下面的tokenzier_model文件作为tokenzie的文件,但是之前没考虑这个问题(dump出的config中tokenizer_files字段为空)就会导致编译出的app在初始化阶段报错:

在这里插入图片描述
经过上面的修改之后重新在mlc-llm下面pip install .,然后编译模型就可以得到可以正常初始化的config了。这个问题是通过在Android Studio里面通过Device Explore查看下载的文件夹发现的,我发现少了一个tokenizer_model文件才注意的。

第二个坑是初始化完成之后聊天的时候不出字,我在mac上去复现了这个错误,然后发现是因为在RWKV里面把max_window_size这个属性设置成了1。

在这里插入图片描述然后在mlc_chat.cc里面通过max_window_size判断结束符时没有考虑-1,所以第一个token生成之后程序就终止了。所以在这里加一个特判进行了修复。在这里插入图片描述

解决了上面2个问题,编译出新的apk之后就可以正常运行了。

0x2. 详细教程

下面是编译出apk的详细教程。在这之前请阅读:MLC-LLM 部署RWKV World系列模型实战(3B模型Mac M2解码可达26tokens/s) ,这是前置内容。

对于Android,你可以按照https://mlc.ai/mlc-llm/docs/deploy/android.html的教程在你的手机上编译apk。

根据官方教程,这里有一些需要修改的地方:

  1. 修改这个文件。更新的内容应该是:
{
  "model_libs": [
    "RWKV-4-World-3B-q4f16_1"
  ],
  "model_list": [
    {
      "model_url": "https://huggingface.co/BBuf/RWKV-4-World-3B-q4f16_1/",
      "local_id": "RWKV-4-World-3B-q4f16_1"
    }
  ],
  "add_model_samples": []
}
  1. 将代码的这个部分修改为:
compileOptions {
    sourceCompatibility JavaVersion.VERSION_17
    targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
    jvmTarget = '17'
}
  1. 如果你遇到错误:“Android Gradle插件要求运行Java 17。你目前使用的是Java 11”,请按照https://stackoverflow.com/questions/76362800/android-gradle-plugin-requires-java-17-to-run-you-are-currently-using-java-11 的方法清除缓存并重新编译。

一旦你完成了APK的编译,你可以在你的手机上启用开发者模式并安装APK以供使用。

以小米手机为例,你可以按照下面的教程启用开发者模式并将APK传输到你的手机上。

  • 第一步:在手机上启用USB调试

    • 首先,前往你的手机的"设置 -> 我的设备 -> 所有规格 -> MIUI版本",连续点击"MIUI版本"七次以进入开发者模式。
    • 接下来,导航至"设置 -> 额外设置 -> 开发者选项",打开"USB调试"和"USB安装"。
  • 第二步:配置Android Studio

    • 打开你的Android Studio项目,前往"运行 -> 编辑配置",如下图所示,选择"打开选择部署目标对话框"。这将在每次你调试时提示设备选择对话框。注意:如果你直接选择"USB设备",你可能无法在调试过程中检测到你的手机。
  • 第三步:在线调试

    • 通过USB将你的手机连接到电脑。通常会自动安装必要的驱动程序。当你运行程序时,将出现设备选择对话框。选择你的手机,APK将自动安装并运行。

一个编译好的apk: https://github.com/BBuf/run-rwkv-world-4-in-mlc-llm/releases/download/v1.0.0/app-debug.apk

0x3. 总结

这篇文章分享了一下使用MLC-LLM将RWKV模型跑在Android手机上遭遇的坑以及编译的详细教程,接下来也会尝试一下RWKV5。想在andorid手机上本地运行开源大模型的伙伴们可以考虑一下MLC-LLM,他们的社区还是比较活跃的,如果你提出一些问题一般都会有快速的回复或者解决方法。

0x4. 相关link

  • https://github.com/mlc-ai/tokenizers-cpp/pull/14
  • https://github.com/mlc-ai/mlc-llm/pull/1136
  • https://github.com/mlc-ai/mlc-llm/pull/848
  • https://mlc.ai/mlc-llm/docs/
  • StarRing2022/RWKV-4-World-1.5B
  • StarRing2022/RWKV-4-World-3B
  • StarRing2022/RWKV-4-World-7B
  • https://github.com/mlc-ai/mlc-llm/issues/862
  • https://github.com/mlc-ai/mlc-llm/issues/859

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1146340.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

宇信科技:强势行业加速融入AIGC,同时做深做细

【科技明说 | 重磅专题】 大家可能没有想到,一向对外低调行事的宇信科技,在AIGC方面2023年就已经训练出了适配金融场景的垂直模型,并应用到了各产品线上,同时结合通用大模型预研了宇信金融系统编程大模型。宇信金融系…

IOC课程整理-15 Spring 类型转换

1. Spring 类型转换的实现 2. 使用场景 3. 基于 JavaBeans 接口的类型转换 4. Spring 內建 PropertyEditor 扩展 5. 自定义 PropertyEditor 扩展 6. Spring PropertyEditor 的设计缺陷 7. Spring 3 通用类型转换接口 8. Spring 內建类型转换器 9. Converter 接口的局限性 10. G…

Azure - 机器学习:使用 Apache Spark 进行交互式数据整理

目录 本文内容先决条件使用 Apache Spark 进行交互式数据整理Azure 机器学习笔记本中的无服务器 Spark 计算从 Azure Data Lake Storage (ADLS) Gen 2 导入和整理数据从 Azure Blob 存储导入和处理数据从 Azure 机器学习数据存储导入和整理数据 关注TechLead,分享AI…

深入理解Linux网络笔记(五):深度理解本机网络IO

本文为《深入理解Linux网络》学习笔记,使用的Linux源码版本是3.10,网卡驱动默认采用的都是Intel的igb网卡驱动 Linux源码在线阅读:https://elixir.bootlin.com/linux/v3.10/source 4、深度理解本机网络IO 1)、跨机网络通信过程 …

快速排序——及其改进

hoare版本(原始版本): 思想:树的遍历思想,先把数组第一个数作为KEY,然后left从左到右,right从右到左一起走,当left找到比key大的值时停下来,当right找到比key小的值时停下来&#xf…

通讯网关软件030——利用CommGate X2Modbus实现Modbus RTU访问Mysql服务器

本文介绍利用CommGate X2Modbus实现Modbus RTU访问Mysql数据库。CommGate X2MODBUS是宁波科安网信开发的网关软件,软件可以登录到网信智汇(http://wangxinzhihui.com)下载。 【案例】如下图所示,实现上位机通过Modbus RTU来获取Mysql数据库的数据。 【解…

IOC课程整理-16

1. Java 泛型基础 Java中的泛型擦除(Type Erasure)是Java编译器为了兼容之前的非泛型代码而采用的一种机制。在编译过程中,Java编译器会将泛型类型转换为原始类型,并在必要时插入强制类型转换。 泛型擦除有以下几个主要特点&…

深度学习_1 介绍;安装环境

深度学习 学习自李沐老师的课程。笔记主要以总结老师所讲解的内容以及我个人的想法为主,侵删! 课程链接:课程安排 - 动手学深度学习课程 (d2l.ai) 介绍 AI地图: 我们以前写的非 AI 类程序基本都是人自己去想会遇到什么样的问题…

【PyQt学习篇 · ③】:QObject - 神奇的对象管理工具

文章目录 QObject类型判定常用的API应用场景:过滤筛选控件 QObject定时器常用API应用场景 QObject类型判定 常用的API isWidgetType()方法: 使用方式:obj.isWidgetType()作用:判断一个对象是否为QWidget及其子类的实例。QWidget…

4.5 final修饰符

在Java中,final修饰符可以修饰类、属性和方法,final有“最终”、“不可更改”的含义,所以在使用final关键字时需要注意以下几点: 使用final修饰类,则该类就为最终类,最终类不能被继承。 使用final修饰方法…

C++----模板进阶

文章目录 非类型模板参数STL知识补充 类模板的特化函数模板特化类模板特化偏特化 模板的分离编译模板总结 非类型模板参数 模板参数分为类型形参与非类型形参。 类型形参:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。 非类型形参…

Vue性能优化:加速你的应用

目录 1. 使用虚拟DOM 2. 合理使用计算属性和侦听器 3. 懒加载组件 4. 合理使用v-if和v-show 5. 使用Key管理列表渲染 6. 避免不必要的Watcher 7. 缓存响应式数据 8. 使用异步组件 9. 使用Webpack进行代码优化 10. 监控性能并进行优化 Vue.js是一款流行的JavaScript框…

东软集团:看似低调,却有了19年的AI坚持

【科技明说 | 重磅专题】 在AI领域的专注与研究,东软集团是一个低调的存在。 可能很多人不太了解东软集团对于AI的专心与专注以及专业。三专可以简单概括东软集团的AI雄心壮志。 专注在于,早在2004年,东软就开始启动人工智能技…

【Apache Flink】流式分析的多种应用场景

文章目录 0. 前言1. 数据处理架构的演进2. 传统数据处理架构3. 事务型处理4. 分析型处理用于数据分析的传统数据仓架构 状态化流处理5. 事件驱动型应用什么是事件驱动型应用? 6. 数据管道什么是数据管道?Flink 如何支持数据管道应用?典型的数…

二叉树三种遍历的递归与非递归写法

目录 ​编辑 一,前序遍历 题目接口: 递归解法: 非递归解法: 二,中序遍历 题目接口: 递归解法: 非递归写法: 三,后序遍历 题目接口: 递归解法&…

IOC课程整理-17 Spring事件

1. Java 事件/监听器编程模型 2. 面向接口的事件/监听器设计模式 3. 面向注解的事件/监听器设计模式 4. Spring 标准事件-ApplicationEvent 5. 基于接口的 Spring 事件监听器 6. 基于注解的 Spring 事件监听器 7. 注册 Spring ApplicationListener 8. Spring 事件发布器 9. Spr…

基于VectorGrid加载GeoServer发布的矢量瓦片实例

目录 前言 一、关于VectorGrid 1、开源地址 2、本地示例 二、与LeafLet集成 1、新建html页面 2、地图初始化 3、pbf瓦片地址配置 4、pbf初始化 三、GeoServer跨域问题 1、web.xml配置 2、重启tomcat 总结 前言 回望10月,发生了一些变动,面向未…

状态机图和活动图

在面向对象软件分析过程中,状态机图和活动图用于建立软件的动态模型,主要描述系统随时间变化的行为。 1.状态图 1.1概念 状态图用来描述对象状态和事件之间的关系,强调一个实体基于事件反应的动态行为。状态图适合用于表述在不同用例之间的…

C语言#error和#line

C语言#error和#line #error #error用于生成一个编译错误消息,并停止编译 示例: 随便找了一个工程测试下#error 看图中我圈起来的部分,编译器提示warning和error。看我的程序如果没有定义TEST_#ERROR这个宏,编译器会报错You di…

我是如何快速从python小白达到20k?

前言 首先说一下我自己的情况,我之前是学JAVA的,JAVA亡了只好转行python 很多新手就在好奇自己明明都认认真真的学习了python,但就是感觉很杂很乱,按照我这个流程,至少可以省一大半时间,完整的知识体系很重…