23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
데보션에 이미 여러 분들이 Gemma에 관한 포스팅을 해주셨습니다.
Gemma에 관해 생소하시다면 아래 포스팅들을 먼저 읽어보시면 좋을 것 같습니다. 여기서는 기존에 다루지 않은 On-Device 상에서 Gemma 모델을 실행하는 방법에 대해서 다루겠습니다.
ChatGPT 같이 이미 거대하고 성능이 좋은 모델들이 많이 출시된 상황인데 On-Device로 LLM 모델(LLM를 작게 줄여서 sLLM이라고도 함)을 사용해야 할 필요가 있을까 하는 생각이 들 수도 있습니다.
하지만 On-Device에서 동작하는 경우엔 다음과 같은 장점들을 갖추고 있습니다.
민감한 개인정보를 서버에 전송할 필요가 없습니다.
인터넷이 연결되지 않은 환경에서도 사용할 수 있습니다.
따로 서버 운영 비용을 감당하지 않아도 됩니다.
더불어 특정 용도에 맞게 적절히 파인튜닝시키면 거대한 LLM 모델과 비슷하거나 더 좋은 성능을 낼 수 있다고도 합니다.
디바이스 성능은 지속적으로 향상되고 있고 On-Device로 LLM 모델을 돌리기 위한 노력들도 계속되고 있기 때문에 앞으로 더욱 발전할 것으로 기대되는 분야입니다.
MediaPipe는 구글에서 개발된 AI/ML 관련 라이브러리로 올해 초 생성형 AI 기능들이 추가되었고 Gemma 같은 LLM 모델들을 실행시킬 수 있게 되었습니다.
여기서는 MediaPipe를 통해 Gemma 모델을 한번 실행해 보겠습니다.
MediaPipe GenAI의 minSDK는 Android 7.0(API Level 24)이고 디바이스에 대한 최소 요구 사항은 명시되어 있지 않지만 개인적으로 확인했을 때는 Galaxy S10에서도 원활하게 동작하였습니다.
샘플 소스 코드를 다운로드합니다.
git clone https://github.com/google-ai-edge/mediapipe-samplesAndroid Studio에서 examples/llm_inference/android 프로젝트를 오픈합니다.
app/build.gradle.kts에서 com.google.mediapipe:tasks-genai 라이브러리를 확인합니다.
현시점 최신 버전은 0.10.14 이지만 긴 프롬프트에 대해선 이상한 응답을 생성해내고 있어서 0.10.11 사용을 권장합니다.
dependencies {
implementation 'com.google.mediapipe:tasks-genai:0.10.14' // 최신 버전에서 문제 있을 시 0.10.11 버전 사용 권장
}https://www.kaggle.com/models/google/gemma/tfLite에 접속하여 TensorFlow Lite용으로 변환되어 있는 Gemma 모델을 다운로드 받습니다.
추천하는 모델은 gemma-1.1-2b-it-gpu-int4.bin 입니다.
디바이스에 임의의 디렉토리를 생성하고 다운로드 받은 모델을 복사합니다.
adb shell mkdir -p /data/local/tmp/llm/
adb push gemma-1.1-2b-it-gpu-int4.bin /data/local/tmp/llm/gemma-1.1-2b-it-gpu-int4.binInference.kt 파일에 llmInference 생성 부분이 있는데 아래와 같은 형식으로 사용할 수 있습니다.
val options = LlmInferenceOptions.builder()
.setModelPath("/data/local/tmp/llm/gemma-1.1-2b-it-gpu-int4.bin")
.setMaxTokens(1000)
.setTopK(40)
.setTemperature(0.8)
.setRandomSeed(101)
.setResultListener { partialResult, done ->
_partialResults.tryEmit(partialResult to done)
}
.build()
llmInference = LlmInference.createFromOptions(context, options)modelPath는 모델의 위치입니다.
maxTokens는 최대 토큰(입력+ 출력) 길이입니다. 만약 maxTokens를 1000으로 설정한 상태에서 입력토큰이 700개 들어오면 최대 300개 토큰을 출력으로 생성해냅니다.
topK는 토큰을 생성하는 단계에서 사용되는 값으로서 가능성 높은 k개의 토큰중에서 하나를 선택하게 됩니다. setRandomSeed와 함께 사용됩니다.
temperature는 값이 클 수록 무작위성이 증가하면서 좀 더 창의적인 결과가 나오고 값이 작을 수록 좀 더 일관성 있는 결과들이 나옵니다. setRandomSeed와 함께 사용됩니다.
randomSeed는 토큰을 선택할 때 사용하는 시드값입니다.
resultListener는 생성된 결과를 전달 받을 리스너입니다. 비동기적으로 결과를 전달 받을 때 사용되는데 partialResult는 String형으로 새로 추가되는 결과를, done은 boolean형으로 마지막(프롬프트에 대한 응답의 끝)인지 여부를 나타냅니다.
마지막으로 텍스트 생성 호출은 다음과 같이 수행합니다.
val result = llmInference.generateResponseAsync(inputPrompt)참고로 입력창의 문자열을 전달할때 화면상에서 표시는 안되지만 실제로는 대화형 형식에 맞춰서 앞 뒤에 아래와 같이 토큰들이 덧붙여져서 전달됩니다.
<start_of_turn>user
입력메시지<end_of_turn>이전 대화 이력이 있다면 아래와 같이 전달됩니다.
<start_of_turn>user
입력메시지1<end_of_turn>
<start_of_turn>model
응답메시지1<end_of_turn>
<start_of_turn>user
입력메시지2<end_of_turn>질문을 한번 해 보겠습니다. Gemma 모델은 다국어 데이터셋을 통해 학습되었기 때문에 한글로 질문해도 답변을 곧잘 해냅니다.
다만, 영어로 질문했을 때보다는 정확도가 떨어지는 답변을 하는 경우가 많습니다.
최근 기존 Gemma 보다 성능이 더욱 좋아진 Gemma2가 발표되었습니다.
현재 MediaPipe를 통해서 Gemma2 모델을 실행시킬 수는 없습니다.
여기선 MLC LLM라는 엔진을 통해서 Gemma2 모델을 안드로이드에서 실행시켜 보겠습니다.
MLC LLM 샘플 앱의 minSDK는 Android 8.0(API Level 26)이고 Galaxy S23 같은 최신폰에서 테스트되었다고 나와 있습니다.
개인적으로 Galaxy S10에서 실행해 보니 출력속도가 MediaPipe에서 Gemma1 모델을 실행할때 보다는 많이 느렸습니다. (짧은 질문에도 첫 출력에 20~30초 정도 소요)
참고: 빌드없이 단순히 실행만 해보고 싶으시면 https://github.com/mlc-ai/binary-mlc-llm-libs/releases/ 에서 apk를 받으셔도 됩니다.
아래 명령어로 Rust를 설치합니다.
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh설치 후에는 PATH 환경 변수를 다시 불러오도록 shell을 다시 시작합니다.
Android Studio의 SDK Manager를 통해 NDK 및 Cmake 최신 버전을 설치하고 아래 환경 변수를 설정합니다.
export ANDROID_NDK=~/Library/Android/sdk/ndk/27.0.12077973
export TVM_NDK_CC=$ANDROID_NDK/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android24-clang빌드 중 cmake 명령어를 찾지 못하는 경우가 있어서 아래와 같이 cmake 위치를 PATH에 추가해줍니다.
export PATH=$PATH:~/Library/Android/sdk/cmake/3.22.1/binJAVA_HOME이 설정되어 있지 않은 경우 JDK(17이상) 위치를 JAVA_HOME에 설정합니다
export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jbr/Contents/HomeMLC LLM Python 패키지를 설치합니다. (conda 환경에서 설치하는 것을 권장합니다.)
python -m pip install --pre -U -f https://mlc.ai/wheels mlc-llm-nightly mlc-ai-nightly소스 코드를 다운로드합니다.
git clone https://github.com/mlc-ai/mlc-llm.git
cd mlc-llm
git submodule update --init --recursive런타임 라이브러리를 빌드합니다.
cd android/MLCChat
export MLC_LLM_SOURCE_DIR=$PWD/../../ # mlc-llm에 대한 경로
export TVM_SOURCE_DIR=$MLC_LLM_SOURCE_DIR/3rdparty/tvm
mlc_llm packagedist/lib/mlc4j/output에 tvm4j_core.jar와 arm64-v8a/libtvm4j_runtime_packed.so 파일이 생성된 것을 확인합니다.
Android Studio에서 android/MLCChat 프로젝트를 열어서 실행을 시킵니다.
실행하면 사용할 수 있는 모델 리스트가 나오는데 여기선 gemma-2-2b-it-q4f16_1-MLC 모델을 다운로드 한 후 선택합니다.
앞에서 했던 질문을 다시 해 보겠습니다. Gemma2 모델은 기본 Gemma 모델보다 더 좋은 품질의 결과가 나오는 것을 확인할 수 있습니다.
지금까지 안드로이드에서 Gemma1 및 Gemma2 모델을 실행하는 법에 대해서 알아 보았습니다.
파인튜닝과 MediaPipe용 모델변환은 구글에서 제공하는 변환 스크립트의 오류를 좀 더 검토한 뒤에 다음 포스팅에서 추가로 다룰 예정입니다.
On-Device로 LLM 모델을 실행시킨다는 것이 아직은 부족한 점이 있지만 미리 한번 경험해보셔도 좋을 것 같습니다.
MediaPipe LLM Inference guide for Android - https://ai.google.dev/edge/mediapipe/solutions/genai/llm_inference/android
MediaPipe LLM Inference Android Demo Github - https://github.com/google-ai-edge/mediapipe-samples/tree/main/examples/llm_inference/android
MLC LLM Docs Android - https://llm.mlc.ai/docs/deploy/android.html
MLC LLM Github - https://github.com/mlc-ai/mlc-llm
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.