Compare commits

...

8 Commits

Author SHA1 Message Date
Yu FranzKafka d4eb5b7e74
Merge fad7396a0a into 6ed0ea9bf3 2025-07-29 14:58:00 +08:00
jxt1234 6ed0ea9bf3
Merge pull request #3738 from jules-ai/set_hint_support_sequence
pymnn-linux / pymnn_linux_buil_test (push) Has been cancelled Details
pymnn-macos / pymnn_macos_buil_test (push) Has been cancelled Details
pymnn-windows / pymnn_windows_buil_test (push) Has been cancelled Details
update pymnn set_hint support list/tuple as value
2025-07-28 14:31:28 +08:00
Yu FranzKafka fad7396a0a
Merge branch 'master' into develop 2025-07-24 21:44:24 +08:00
franzkafkayu bf63541e58 rename build variable to MNN_BUILD_LLM_FROM_PREBUILT 2025-07-24 18:19:14 +08:00
franzkafkayu 737c766fd4 keep old build method if we want build MnnLlmChat with prebuilt libMNN 2025-07-24 17:57:16 +08:00
Jules bd59e631c2 update pymnn set_hint with seq 2025-07-21 09:44:30 +00:00
franzkafkayu 7b9854b4af upda README 2025-07-18 12:04:11 +08:00
franzkafkayu 8d39cdf685 optimze MnnLlmChat compile progress,no need to execute shell script 2025-07-17 22:44:55 +08:00
7 changed files with 172 additions and 61 deletions

View File

@ -35,28 +35,38 @@ This is our full multimodal language model (LLM) Android app
# Development
+ Prepare
+ Android Studio
+ NDK(21 recommended)
+ `export ANDROID_NDK=${YOUR_NDK_ROOT}`
## Windows
Using `Android Studio` IDE for building:
+ Clone the repository
```shell
git clone https://github.com/alibaba/MNN.git
```
+ In `Android Studio`, go to the top-left corner and click File → Open, then select the project. After that, click Build and choose either Make Project or Build Bundle(s) / APK(s) to generate the APK.
+ If you need to integrate a prebuilt `libMNN.so` library, please place the prebuilt `libMNN.so` in `project\android\build_64\lib`, and modify the `gradle.properties` file in the `MnnLlmChat` project to configure `MNN_BUILD_LLM_FROM_PREBUILT=ON`.
## Linux
+ Clone the repository:
```shell
git clone https://github.com/alibaba/MNN.git
git clone https://github.com/alibaba/MNN.git
```
+ Build library:
```shell
+ Configure Android SDK NDK
```
#here we use sdkmanager to install SDK/NDK tools
sudo sdkmanager "platforms;android-35"
sudo sdkmanager "build-tools;33.0.1"
```
+ Compile&Build
```
#build debug version with preebuilt libMNN
cd project/android
mkdir build_64
cd build_64
../build_64.sh "-DMNN_LOW_MEMORY=true -DMNN_CPU_WEIGHT_DEQUANT_GEMM=true -DMNN_BUILD_LLM=true -DMNN_SUPPORT_TRANSFORMER_FUSE=true -DMNN_ARM82=true -DMNN_USE_LOGCAT=true -DMNN_OPENCL=true -DLLM_SUPPORT_VISION=true -DMNN_BUILD_OPENCV=true -DMNN_IMGCODECS=true -DLLM_SUPPORT_AUDIO=true -DMNN_BUILD_AUDIO=true -DMNN_BUILD_DIFFUSION=ON -DMNN_SEP_BUILD=OFF -DCMAKE_SHARED_LINKER_FLAGS='-Wl,-z,max-page-size=16384' -DCMAKE_INSTALL_PREFIX=."
make install
```
+ build android app project and install
```shell
cd ../../../apps/Android/MnnLlmChat
./gradlew installDebug
```
./gradlew assembleDebug -PMNN_BUILD_LLM_FROM_PREBUILT=ON
#build debug verion from current MNN source
./gradlew assembleDebug
```
# Releases
## Version 0.5.1.2

View File

@ -34,23 +34,40 @@
!!!warning!!! 此版本目前仅在 OnePlus 13 和 小米 14 Ultra 上进行了测试。由于大型语言模型LLM对设备性能要求较高许多低配置设备可能会遇到以下问题推理速度缓慢、应用不稳定甚至无法运行。对于其他设备的稳定性无法保证。如果您在使用过程中遇到问题请随时提交问题以获取帮助。
# 开发
# 开发
## Windows
基于`AndroidStuido` IDE进行构建:
+ 克隆代码库:
```shell
git clone https://github.com/alibaba/MNN.git
git clone https://github.com/alibaba/MNN.git
```
+ 构建库:
+ `AndroidStuido`左上角File->Open,选择该工程,点击`Build`,选择`Make Project`或者`Build App Bundle(s)/APK(s)`,即可生成APK
+ 如果需要以预编译`libMNN.so`库的形式集成,请将预编译好的`libMNN.so`放置于`project\android\build_64\lib`,并修改`MnnLlmChat`工程内的`gradle.properties`文件,配置`MNN_BUILD_LLM_FROM_PREBUILT=ON`
## Linux
+ 克隆代码库:
```shell
git clone https://github.com/alibaba/MNN.git
```
+ 配置Android SDK与NDK
```shell
#here we use sdkmanager to install SDK/NDK tools
sudo sdkmanager "platforms;android-35"
sudo sdkmanager "build-tools;33.0.1"
```
+ 编译构建
```shell
#集成预编译好的libMNN.so,打包debug版本的APK
cd project/android
mkdir build_64
cd build_64
../build_64.sh "-DMNN_LOW_MEMORY=true -DMNN_CPU_WEIGHT_DEQUANT_GEMM=true -DMNN_BUILD_LLM=true -DMNN_SUPPORT_TRANSFORMER_FUSE=true -DMNN_ARM82=true -DMNN_USE_LOGCAT=true -DMNN_OPENCL=true -DLLM_SUPPORT_VISION=true -DMNN_BUILD_OPENCV=true -DMNN_IMGCODECS=true -DLLM_SUPPORT_AUDIO=true -DMNN_BUILD_AUDIO=true -DMNN_BUILD_DIFFUSION=ON -DMNN_SEP_BUILD=OFF -DCMAKE_INSTALL_PREFIX=."
make install
```
+ 构建 Android 应用项目并安装:
```shell
cd ../../../apps/Android/MnnLlmChat
./gradlew installDebug
```
./gradlew assembleDebug -PMNN_BUILD_LLM_FROM_PREBUILT=ON
#以当前仓库内的源码进行编译生成libMNN.so,打包debug版本的APK
./gradlew assembleDebug
```
# Releases

View File

@ -5,6 +5,9 @@ plugins {
}
// if BUILT_FROM_PREBUILT passed, use its value,or will use default value "OFF"
def builtFromPrebuilt = project.hasProperty('MNN_BUILD_LLM_FROM_PREBUILT') ? project.MNN_BUILD_LLM_FROM_PREBUILT : "OFF"
android {
namespace 'com.alibaba.mnnllm.android'
compileSdk 35
@ -23,8 +26,34 @@ android {
externalNativeBuild {
cmake {
cppFlags '-std=c++17'
// Enable 16KB page size support for NDK r27
arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
if (builtFromPrebuilt == "OFF") {
arguments "-DMNN_USE_SSE=OFF",
"-DMNN_BUILD_TEST=ON",
"-DANDROID_STL=c++_static",
"-DMNN_BUILD_BENCHMARK=ON",
"-DANDROID_NATIVE_API_LEVEL=android-21",
"-DMNN_BUILD_FOR_ANDROID_COMMAND=true",
"-DMNN_LOW_MEMORY=true",
"-DMNN_CPU_WEIGHT_DEQUANT_GEMM=true",
"-DMNN_BUILD_LLM=true",
"-DMNN_SUPPORT_TRANSFORMER_FUSE=true",
"-DMNN_ARM82=true",
"-DMNN_USE_LOGCAT=true",
"-DMNN_OPENCL=true",
"-DLLM_SUPPORT_VISION=true",
"-DMNN_BUILD_OPENCV=true",
"-DMNN_IMGCODECS=true",
"-DLLM_SUPPORT_AUDIO=true",
"-DMNN_BUILD_AUDIO=true",
"-DMNN_BUILD_DIFFUSION=ON",
"-DMNN_SEP_BUILD=OFF",
"-DMNN_BUILD_LLM_FROM_PREBUILT=OFF"
} else {
arguments "-DMNN_BUILD_LLM_FROM_PREBUILT=ON"
}
}
}
@ -191,7 +220,8 @@ dependencies {
//
implementation "com.jakewharton.timber:timber:5.0.1"
// implementation(name: 'android_device_names', ext: 'aar')
//implementation(name: 'android_device_names', ext: 'aar')
implementation 'com.github.Juude:AndroidDeviceNames:0.0.1'
testImplementation 'androidx.test:core:1.5.0'
testImplementation 'junit:junit:4.13.2'

View File

@ -11,6 +11,11 @@ cmake_minimum_required(VERSION 3.22.1)
# build script scope).
project("mnnllmapp")
# 使MNN
option(MNN_BUILD_LLM_FROM_PREBUILT "use prebuilt MNN library" OFF)
message(INFO "MNN_BUILD_LLM_FROM_PREBUILT: ${MNN_BUILD_LLM_FROM_PREBUILT}")
add_library(${CMAKE_PROJECT_NAME} SHARED
# List C/C++ source files with relative paths to this CMakeLists.txt.
llm_mnn_jni.cpp
@ -20,21 +25,18 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
crash_util.cpp
)
# Add 16KB page size support (required for Android 15+ devices)
target_link_options(${CMAKE_PROJECT_NAME} PRIVATE "-Wl,-z,max-page-size=16384")
#mnn
set (MNN_SOURCE_ROOT "${CMAKE_SOURCE_DIR}/../../../../../../../")
set(MNN_SOURCE_ROOT "${CMAKE_SOURCE_DIR}/../../../../../../../")
#set (MNN_SOURCE_ROOT "/Users/songjinde/git/DAI/AliNNPrivate")
set (MNN_INSTALL_ROOT "${MNN_SOURCE_ROOT}/project/android/build_64")
# set (MNN_INSTALL_ROOT "/Users/songjinde/MNN/project/android/build_64")
#set (MNN_ROOT "${CMAKE_SOURCE_DIR}/../../../../../../../")
message(INFO "MNN_SOURCE_ROOT: ${MNN_SOURCE_ROOT}")
message(INFO "MNN_INSTALL_ROOT: ${MNN_INSTALL_ROOT}")
include_directories("${MNN_SOURCE_ROOT}/include/")
#diffusion
include_directories("${MNN_SOURCE_ROOT}/transformers/diffusion/engine/include/")
@ -45,31 +47,37 @@ include_directories("${MNN_SOURCE_ROOT}/transformers/llm/engine/include")
#audio
include_directories("${MNN_SOURCE_ROOT}/tools/audio/include")
include_directories("${CMAKE_SOURCE_DIR}/third_party")
# Add library paths
set(LIB_PATH "${MNN_INSTALL_ROOT}/lib")
# Link the shared library
if (MNN_BUILD_LLM_FROM_PREBUILT)
#use prebuilt mnn library,use build_64.sh to build
set(MNN_INSTALL_ROOT "${MNN_SOURCE_ROOT}/project/android/build_64")
# Add library paths
set(LIB_PATH "${MNN_INSTALL_ROOT}/lib")
# Link the shared library
add_library(MNN SHARED IMPORTED)
set_target_properties(MNN PROPERTIES IMPORTED_LOCATION "${LIB_PATH}/libMNN.so")
add_library(MNN SHARED IMPORTED)
set_target_properties(MNN PROPERTIES IMPORTED_LOCATION "${LIB_PATH}/libMNN.so")
#add_library(llm SHARED IMPORTED)
#set_target_properties(llm PROPERTIES IMPORTED_LOCATION "${LIB_PATH}/libllm.so")
#add_library(llm SHARED IMPORTED)
#set_target_properties(llm PROPERTIES IMPORTED_LOCATION "${LIB_PATH}/libllm.so")
#
#add_library(diffusion SHARED IMPORTED)
#set_target_properties(diffusion PROPERTIES IMPORTED_LOCATION "${LIB_PATH}/libdiffusion.so")
#
#add_library(mnn_cl SHARED IMPORTED)
#set_target_properties(mnn_cl PROPERTIES IMPORTED_LOCATION "${LIB_PATH}/libMNN_CL.so")
#
#add_library(mnn_audio SHARED IMPORTED)
#set_target_properties(mnn_audio PROPERTIES IMPORTED_LOCATION "${LIB_PATH}/libMNNAudio.so")
#
#add_library(mnn_cv SHARED IMPORTED)
#set_target_properties(mnn_cv PROPERTIES IMPORTED_LOCATION "${LIB_PATH}/libMNNOpenCV.so")
#
#add_library(mnn_Express SHARED IMPORTED)
#set_target_properties(mnn_Express PROPERTIES IMPORTED_LOCATION "${LIB_PATH}/libMNN_Express.so")
#add_library(diffusion SHARED IMPORTED)
#set_target_properties(diffusion PROPERTIES IMPORTED_LOCATION "${LIB_PATH}/libdiffusion.so")
#add_library(mnn_cl SHARED IMPORTED)
#set_target_properties(mnn_cl PROPERTIES IMPORTED_LOCATION "${LIB_PATH}/libMNN_CL.so")
#add_library(mnn_audio SHARED IMPORTED)
#set_target_properties(mnn_audio PROPERTIES IMPORTED_LOCATION "${LIB_PATH}/libMNNAudio.so")
#add_library(mnn_cv SHARED IMPORTED)
#set_target_properties(mnn_cv PROPERTIES IMPORTED_LOCATION "${LIB_PATH}/libMNNOpenCV.so")
#add_library(mnn_Express SHARED IMPORTED)
#set_target_properties(mnn_Express PROPERTIES IMPORTED_LOCATION "${LIB_PATH}/libMNN_Express.so")
else ()
#load local mnn,output dir will changed to .cxx
add_subdirectory(../../../../../../../ build-mnn)
endif ()
# Link your native library with the `.so` file
@ -82,4 +90,4 @@ target_link_libraries(${CMAKE_PROJECT_NAME}
android
log
MNN
)
)

View File

@ -19,4 +19,6 @@ android.useAndroidX=true
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
android.suppressUnsupportedCompileSdk=35
android.suppressUnsupportedCompileSdk=35
#control whether use prebuilt library
MNN_BUILD_LLM_FROM_PREBUILT=OFF

View File

@ -824,15 +824,37 @@ static PyObject* PyMNNInterpreter_setSessionMode(PyMNNInterpreter *self, PyObjec
}
static PyObject* PyMNNInterpreter_setSessionHint(PyMNNInterpreter *self, PyObject *args) {
int type_val = 0;
int num_val = 0;
if (!PyArg_ParseTuple(args, "ii", &type_val, &num_val)) {
PyObject* num_val = nullptr;
if (!PyArg_ParseTuple(args, "iO", &type_val, &num_val)) {
PyErr_SetString(PyExc_Exception,
"PyMNNInterpreter_setSessionHint: Not interger input and interger input");
return NULL;
"PyMNNInterpreter_setSessionHint: Not interger input and interger/list/tuple input");
return nullptr;
}
auto type = (MNN::Interpreter::HintMode)type_val;
self->interpreter->setSessionHint(type, num_val);
if (PyList_Check(num_val)) {
size_t size = PyList_Size(num_val);
int* list = new int[size];
for (int i = 0; i < size; i++) {
list[i] = static_cast<int>(PyLong_AsLong(PyList_GetItem(num_val, i)));
}
self->interpreter->setSessionHint(type, list, size);
delete[] list;
} else if (PyTuple_Check(num_val)) {
size_t size = PyTuple_Size(num_val);
int* list = new int[size];
for (int i = 0; i < size; i++) {
list[i] = static_cast<int>(PyLong_AsLong(PyTuple_GetItem(num_val, i)));
}
self->interpreter->setSessionHint(type, list, size);
delete[] list;
} else if (PyLong_Check(num_val)) {
self->interpreter->setSessionHint(type, static_cast<int>(PyLong_AsLong(num_val)));
} else {
PyErr_SetString(PyExc_Exception,
"PyMNNInterpreter_setSessionHint: num_val must be a list, tuple or int");
return nullptr;
}
Py_RETURN_NONE;
}
static PyObject* PyMNNInterpreter_runSession(PyMNNInterpreter *self, PyObject *args) {

View File

@ -345,15 +345,37 @@ static PyObject* PyMNNRuntimeManager_set_mode(PyMNNRuntimeManager *self, PyObjec
}
static PyObject* PyMNNRuntimeManager_set_hint(PyMNNRuntimeManager *self, PyObject *args) {
int type_val = 0;
int num_val = 0;
if (!PyArg_ParseTuple(args, "ii", &type_val, &num_val)) {
PyObject* num_val = nullptr;
if (!PyArg_ParseTuple(args, "iO", &type_val, &num_val)) {
PyErr_SetString(PyExc_Exception,
"PyMNNRuntimeManager_set_hint: Not interger input and interger input");
return NULL;
"PyMNNRuntimeManager_set_hint: Not interger input and interger/list/tuple input");
return nullptr;
}
auto type = (MNN::Interpreter::HintMode)type_val;
(*(self->ptr))->setHint(type, num_val);
if (PyList_Check(num_val)) {
size_t size = PyList_Size(num_val);
int* list = new int[size];
for (int i = 0; i < size; i++) {
list[i] = static_cast<int>(PyLong_AsLong(PyList_GetItem(num_val, i)));
}
(*(self->ptr))->setHint(type, list, size);
delete[] list;
} else if (PyTuple_Check(num_val)) {
size_t size = PyTuple_Size(num_val);
int* list = new int[size];
for (int i = 0; i < size; i++) {
list[i] = static_cast<int>(PyLong_AsLong(PyTuple_GetItem(num_val, i)));
}
(*(self->ptr))->setHint(type, list, size);
delete[] list;
} else if (PyLong_Check(num_val)) {
(*(self->ptr))->setHint(type, static_cast<int>(PyLong_AsLong(num_val)));
} else {
PyErr_SetString(PyExc_Exception,
"PyMNNRuntimeManager_set_hint: num_val must be a list, tuple or int");
return nullptr;
}
Py_RETURN_NONE;
}