Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] Introducing mlc4j and app packaging #2305

Merged
merged 1 commit into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions android/MLCChat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# MLC-LLM Android

Checkout [Documentation page](https://llm.mlc.ai/docs/deploy/android.html) for more information.

- run `mlc_llm package`
- open this `MLCChat/` folder as a project in Android Studio
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ android {
}

dependencies {
implementation project(":library")
implementation project(":mlc4j")
implementation 'androidx.core:core-ktx:1.10.1'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1'
implementation 'androidx.activity:activity-compose:1.7.1'
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class AppViewModel(application: Application) : AndroidViewModel(application) {
private val modelIdSet = emptySet<String>().toMutableSet()

companion object {
const val AppConfigFilename = "app-config.json"
const val AppConfigFilename = "mlc-app-config.json"
const val ModelConfigFilename = "mlc-chat-config.json"
const val ParamsConfigFilename = "ndarray-cache.json"
const val ModelUrlSuffix = "resolve/main/"
Expand Down
File renamed without changes.
65 changes: 65 additions & 0 deletions android/MLCChat/bundle_weight.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import argparse
import os
import subprocess
from pathlib import Path

from mlc_llm.support import logging

logging.enable_logging()
logger = logging.getLogger(__name__)


def main(apk_path: Path, package_output_path: Path):
"""Push weights to the android device with adb"""
# - Install the apk on device.
logger.info('Install apk "%s" to device', str(apk_path.absolute()))
subprocess.run(["adb", "install", str(apk_path)], check=True, env=os.environ)
# - Create the weight directory for the app.
device_weihgt_dir = "/storage/emulated/0/Android/data/ai.mlc.mlcchat/files/"
logger.info('Creating directory "%s" on device', device_weihgt_dir)
subprocess.run(
["adb", "shell", "mkdir", "-p", device_weihgt_dir],
check=True,
env=os.environ,
)
for model_weight_dir in (package_output_path / "bundle").iterdir():
if model_weight_dir.is_dir():
src_path = str(model_weight_dir.absolute())
dst_path = "/data/local/tmp/" + model_weight_dir.name
logger.info('Pushing local weights "%s" to device location "%s"', src_path, dst_path)
subprocess.run(["adb", "push", src_path, dst_path], check=True, env=os.environ)

src_path = dst_path
dst_path = "/storage/emulated/0/Android/data/ai.mlc.mlcchat/files/"
logger.info('Move weights from "%s" to "%s"', src_path, dst_path)
subprocess.run(["adb", "shell", "mv", src_path, dst_path], check=True, env=os.environ)
logger.info("All finished.")


if __name__ == "__main__":
parser = argparse.ArgumentParser("MLC LLM Android Weight Bundle")

def _parse_apk_path(path: str) -> Path:
path = Path(path)
if not path.exists():
raise ValueError(
f"Path {str(path)} is expected to be an apk file, but the file does not exist."
)
if not path.is_file():
raise ValueError(f"Path {str(path)} is expected to be an apk file.")
return path

parser.add_argument(
"--apk-path",
type=_parse_apk_path,
default="app/release/app-release.apk",
help="The path to generated MLCChat apk file.",
)
parser.add_argument(
"--package-output-path",
type=Path,
default="dist",
help='The path to the output directory of "mlc_llm package".',
)
args = parser.parse_args()
main(args.apk_path, args.package_output_path)
File renamed without changes.
File renamed without changes.
File renamed without changes.
38 changes: 38 additions & 0 deletions android/MLCChat/mlc-package-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"device": "android",
"model_list": [
{
"model": "HF://mlc-ai/gemma-2b-it-q4f16_1-MLC",
"model_id": "gemma-2b-q4f16_1",
"estimated_vram_bytes": 3000000000
},
{
"model": "HF://mlc-ai/Llama-2-7b-chat-hf-q4f16_1-MLC",
"estimated_vram_bytes": 4348727787,
"model_id": "Llama-2-7b-chat-hf-q4f16_1",
"overrides": {
"context_window_size": 768,
"prefill_chunk_size": 256
}
},
{
"model": "HF://mlc-ai/RedPajama-INCITE-Chat-3B-v1-q4f16_1-MLC",
"estimated_vram_bytes": 1948348579,
"model_id": "RedPajama-INCITE-Chat-3B-v1-q4f16_1"
},
{
"model": "HF://mlc-ai/Mistral-7B-Instruct-v0.2-q4f16_1-MLC",
"estimated_vram_bytes": 4275453296,
"model_id": "Mistral-7B-Instruct-v0.2-q4f16_1",
"overrides": {
"sliding_window_size": 768,
"prefill_chunk_size": 256
}
},
{
"model": "HF://mlc-ai/phi-2-q4f16_1-MLC",
"estimated_vram_bytes": 2036816936,
"model_id": "phi-2-q4f16_1"
}
]
}
3 changes: 2 additions & 1 deletion android/settings.gradle → android/MLCChat/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ dependencyResolutionManagement {
}
rootProject.name = "MLCChat"
include ':app'
include ':library'
include ':mlc4j'
project(':mlc4j').projectDir = file('dist/lib/mlc4j')
34 changes: 0 additions & 34 deletions android/library/prepare_libs.sh

This file was deleted.

79 changes: 0 additions & 79 deletions android/library/prepare_model_lib.py

This file was deleted.

41 changes: 0 additions & 41 deletions android/library/src/main/assets/app-config.json

This file was deleted.

File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ add_custom_command(
)

add_library(model_android STATIC IMPORTED)
set_target_properties(model_android PROPERTIES IMPORTED_LOCATION ${ANDROID_BIN_DIR}/model_lib/libmodel_android.a)
set_target_properties(model_android PROPERTIES IMPORTED_LOCATION ${ANDROID_BIN_DIR}/lib/libmodel_android.a)

add_library(tvm4j_runtime_packed SHARED ${TVM_HOME}/jvm/native/src/main/native/org_apache_tvm_native_c_api.cc)

Expand Down
4 changes: 2 additions & 2 deletions android/library/build.gradle → android/mlc4j/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ android {
}
sourceSets {
main {
jniLibs.srcDirs = ['build/output']
jniLibs.srcDirs = ['output']
}
}
}

dependencies {
implementation fileTree(dir: 'build/output', include: ['*.jar'])
implementation fileTree(dir: 'output', include: ['*.jar'])
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.10.0'
Expand Down
Loading
Loading