diff options
Diffstat (limited to 'llama.cpp/examples/llama.android/app')
32 files changed, 846 insertions, 0 deletions
diff --git a/llama.cpp/examples/llama.android/app/.gitignore b/llama.cpp/examples/llama.android/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/llama.cpp/examples/llama.android/app/.gitignore | |||
| @@ -0,0 +1 @@ | |||
| /build | |||
diff --git a/llama.cpp/examples/llama.android/app/build.gradle.kts b/llama.cpp/examples/llama.android/app/build.gradle.kts new file mode 100644 index 0000000..2edfe98 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/build.gradle.kts | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | plugins { | ||
| 2 | alias(libs.plugins.android.application) | ||
| 3 | alias(libs.plugins.jetbrains.kotlin.android) | ||
| 4 | } | ||
| 5 | |||
| 6 | android { | ||
| 7 | namespace = "com.example.llama" | ||
| 8 | compileSdk = 36 | ||
| 9 | |||
| 10 | defaultConfig { | ||
| 11 | applicationId = "com.example.llama.aichat" | ||
| 12 | |||
| 13 | minSdk = 33 | ||
| 14 | targetSdk = 36 | ||
| 15 | |||
| 16 | versionCode = 1 | ||
| 17 | versionName = "1.0" | ||
| 18 | |||
| 19 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" | ||
| 20 | vectorDrawables { | ||
| 21 | useSupportLibrary = true | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | buildTypes { | ||
| 26 | debug { | ||
| 27 | isMinifyEnabled = true | ||
| 28 | isShrinkResources = true | ||
| 29 | proguardFiles( | ||
| 30 | getDefaultProguardFile("proguard-android.txt"), | ||
| 31 | "proguard-rules.pro" | ||
| 32 | ) | ||
| 33 | } | ||
| 34 | release { | ||
| 35 | isMinifyEnabled = true | ||
| 36 | isShrinkResources = true | ||
| 37 | proguardFiles( | ||
| 38 | getDefaultProguardFile("proguard-android-optimize.txt"), | ||
| 39 | "proguard-rules.pro" | ||
| 40 | ) | ||
| 41 | } | ||
| 42 | } | ||
| 43 | compileOptions { | ||
| 44 | sourceCompatibility = JavaVersion.VERSION_17 | ||
| 45 | targetCompatibility = JavaVersion.VERSION_17 | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | dependencies { | ||
| 50 | implementation(libs.bundles.androidx) | ||
| 51 | implementation(libs.material) | ||
| 52 | |||
| 53 | implementation(project(":lib")) | ||
| 54 | |||
| 55 | testImplementation(libs.junit) | ||
| 56 | androidTestImplementation(libs.androidx.junit) | ||
| 57 | androidTestImplementation(libs.androidx.espresso.core) | ||
| 58 | } | ||
diff --git a/llama.cpp/examples/llama.android/app/proguard-rules.pro b/llama.cpp/examples/llama.android/app/proguard-rules.pro new file mode 100644 index 0000000..358020d --- /dev/null +++ b/llama.cpp/examples/llama.android/app/proguard-rules.pro | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | # Add project specific ProGuard rules here. | ||
| 2 | # You can control the set of applied configuration files using the | ||
| 3 | # proguardFiles setting in build.gradle. | ||
| 4 | # | ||
| 5 | # For more details, see | ||
| 6 | # http://developer.android.com/guide/developing/tools/proguard.html | ||
| 7 | |||
| 8 | # If your project uses WebView with JS, uncomment the following | ||
| 9 | # and specify the fully qualified class name to the JavaScript interface | ||
| 10 | # class: | ||
| 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||
| 12 | # public *; | ||
| 13 | #} | ||
| 14 | |||
| 15 | # Uncomment this to preserve the line number information for | ||
| 16 | # debugging stack traces. | ||
| 17 | #-keepattributes SourceFile,LineNumberTable | ||
| 18 | |||
| 19 | # If you keep the line number information, uncomment this to | ||
| 20 | # hide the original source file name. | ||
| 21 | #-renamesourcefileattribute SourceFile | ||
| 22 | |||
| 23 | -keep class com.arm.aichat.* { *; } | ||
| 24 | -keep class com.arm.aichat.gguf.* { *; } | ||
| 25 | |||
| 26 | -assumenosideeffects class android.util.Log { | ||
| 27 | public static int v(...); | ||
| 28 | public static int d(...); | ||
| 29 | } | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/AndroidManifest.xml b/llama.cpp/examples/llama.android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..8f7c606 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/AndroidManifest.xml | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <manifest xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 3 | |||
| 4 | <application | ||
| 5 | android:allowBackup="true" | ||
| 6 | android:dataExtractionRules="@xml/data_extraction_rules" | ||
| 7 | android:extractNativeLibs="true" | ||
| 8 | android:fullBackupContent="@xml/backup_rules" | ||
| 9 | android:icon="@mipmap/ic_launcher_round" | ||
| 10 | android:label="@string/app_name" | ||
| 11 | android:roundIcon="@mipmap/ic_launcher_round" | ||
| 12 | android:supportsRtl="true" | ||
| 13 | android:theme="@style/Theme.AiChatSample" | ||
| 14 | > | ||
| 15 | |||
| 16 | <activity | ||
| 17 | android:name=".MainActivity" | ||
| 18 | android:exported="true"> | ||
| 19 | <intent-filter> | ||
| 20 | <action android:name="android.intent.action.MAIN" /> | ||
| 21 | |||
| 22 | <category android:name="android.intent.category.LAUNCHER" /> | ||
| 23 | </intent-filter> | ||
| 24 | </activity> | ||
| 25 | </application> | ||
| 26 | |||
| 27 | </manifest> | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/java/com/example/llama/MainActivity.kt b/llama.cpp/examples/llama.android/app/src/main/java/com/example/llama/MainActivity.kt new file mode 100644 index 0000000..872ec2b --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/java/com/example/llama/MainActivity.kt | |||
| @@ -0,0 +1,275 @@ | |||
| 1 | package com.example.llama | ||
| 2 | |||
| 3 | import android.net.Uri | ||
| 4 | import android.os.Bundle | ||
| 5 | import android.util.Log | ||
| 6 | import android.widget.EditText | ||
| 7 | import android.widget.TextView | ||
| 8 | import android.widget.Toast | ||
| 9 | import androidx.activity.addCallback | ||
| 10 | import androidx.activity.enableEdgeToEdge | ||
| 11 | import androidx.activity.result.contract.ActivityResultContracts | ||
| 12 | import androidx.appcompat.app.AppCompatActivity | ||
| 13 | import androidx.lifecycle.lifecycleScope | ||
| 14 | import androidx.recyclerview.widget.LinearLayoutManager | ||
| 15 | import androidx.recyclerview.widget.RecyclerView | ||
| 16 | import com.arm.aichat.AiChat | ||
| 17 | import com.arm.aichat.InferenceEngine | ||
| 18 | import com.arm.aichat.gguf.GgufMetadata | ||
| 19 | import com.arm.aichat.gguf.GgufMetadataReader | ||
| 20 | import com.google.android.material.floatingactionbutton.FloatingActionButton | ||
| 21 | import kotlinx.coroutines.Dispatchers | ||
| 22 | import kotlinx.coroutines.Job | ||
| 23 | import kotlinx.coroutines.flow.onCompletion | ||
| 24 | import kotlinx.coroutines.launch | ||
| 25 | import kotlinx.coroutines.withContext | ||
| 26 | import java.io.File | ||
| 27 | import java.io.FileOutputStream | ||
| 28 | import java.io.InputStream | ||
| 29 | import java.util.UUID | ||
| 30 | |||
| 31 | class MainActivity : AppCompatActivity() { | ||
| 32 | |||
| 33 | // Android views | ||
| 34 | private lateinit var ggufTv: TextView | ||
| 35 | private lateinit var messagesRv: RecyclerView | ||
| 36 | private lateinit var userInputEt: EditText | ||
| 37 | private lateinit var userActionFab: FloatingActionButton | ||
| 38 | |||
| 39 | // Arm AI Chat inference engine | ||
| 40 | private lateinit var engine: InferenceEngine | ||
| 41 | private var generationJob: Job? = null | ||
| 42 | |||
| 43 | // Conversation states | ||
| 44 | private var isModelReady = false | ||
| 45 | private val messages = mutableListOf<Message>() | ||
| 46 | private val lastAssistantMsg = StringBuilder() | ||
| 47 | private val messageAdapter = MessageAdapter(messages) | ||
| 48 | |||
| 49 | override fun onCreate(savedInstanceState: Bundle?) { | ||
| 50 | super.onCreate(savedInstanceState) | ||
| 51 | enableEdgeToEdge() | ||
| 52 | setContentView(R.layout.activity_main) | ||
| 53 | // View model boilerplate and state management is out of this basic sample's scope | ||
| 54 | onBackPressedDispatcher.addCallback { Log.w(TAG, "Ignore back press for simplicity") } | ||
| 55 | |||
| 56 | // Find views | ||
| 57 | ggufTv = findViewById(R.id.gguf) | ||
| 58 | messagesRv = findViewById(R.id.messages) | ||
| 59 | messagesRv.layoutManager = LinearLayoutManager(this).apply { stackFromEnd = true } | ||
| 60 | messagesRv.adapter = messageAdapter | ||
| 61 | userInputEt = findViewById(R.id.user_input) | ||
| 62 | userActionFab = findViewById(R.id.fab) | ||
| 63 | |||
| 64 | // Arm AI Chat initialization | ||
| 65 | lifecycleScope.launch(Dispatchers.Default) { | ||
| 66 | engine = AiChat.getInferenceEngine(applicationContext) | ||
| 67 | } | ||
| 68 | |||
| 69 | // Upon CTA button tapped | ||
| 70 | userActionFab.setOnClickListener { | ||
| 71 | if (isModelReady) { | ||
| 72 | // If model is ready, validate input and send to engine | ||
| 73 | handleUserInput() | ||
| 74 | } else { | ||
| 75 | // Otherwise, prompt user to select a GGUF metadata on the device | ||
| 76 | getContent.launch(arrayOf("*/*")) | ||
| 77 | } | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | private val getContent = registerForActivityResult( | ||
| 82 | ActivityResultContracts.OpenDocument() | ||
| 83 | ) { uri -> | ||
| 84 | Log.i(TAG, "Selected file uri:\n $uri") | ||
| 85 | uri?.let { handleSelectedModel(it) } | ||
| 86 | } | ||
| 87 | |||
| 88 | /** | ||
| 89 | * Handles the file Uri from [getContent] result | ||
| 90 | */ | ||
| 91 | private fun handleSelectedModel(uri: Uri) { | ||
| 92 | // Update UI states | ||
| 93 | userActionFab.isEnabled = false | ||
| 94 | userInputEt.hint = "Parsing GGUF..." | ||
| 95 | ggufTv.text = "Parsing metadata from selected file \n$uri" | ||
| 96 | |||
| 97 | lifecycleScope.launch(Dispatchers.IO) { | ||
| 98 | // Parse GGUF metadata | ||
| 99 | Log.i(TAG, "Parsing GGUF metadata...") | ||
| 100 | contentResolver.openInputStream(uri)?.use { | ||
| 101 | GgufMetadataReader.create().readStructuredMetadata(it) | ||
| 102 | }?.let { metadata -> | ||
| 103 | // Update UI to show GGUF metadata to user | ||
| 104 | Log.i(TAG, "GGUF parsed: \n$metadata") | ||
| 105 | withContext(Dispatchers.Main) { | ||
| 106 | ggufTv.text = metadata.toString() | ||
| 107 | } | ||
| 108 | |||
| 109 | // Ensure the model file is available | ||
| 110 | val modelName = metadata.filename() + FILE_EXTENSION_GGUF | ||
| 111 | contentResolver.openInputStream(uri)?.use { input -> | ||
| 112 | ensureModelFile(modelName, input) | ||
| 113 | }?.let { modelFile -> | ||
| 114 | loadModel(modelName, modelFile) | ||
| 115 | |||
| 116 | withContext(Dispatchers.Main) { | ||
| 117 | isModelReady = true | ||
| 118 | userInputEt.hint = "Type and send a message!" | ||
| 119 | userInputEt.isEnabled = true | ||
| 120 | userActionFab.setImageResource(R.drawable.outline_send_24) | ||
| 121 | userActionFab.isEnabled = true | ||
| 122 | } | ||
| 123 | } | ||
| 124 | } | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | /** | ||
| 129 | * Prepare the model file within app's private storage | ||
| 130 | */ | ||
| 131 | private suspend fun ensureModelFile(modelName: String, input: InputStream) = | ||
| 132 | withContext(Dispatchers.IO) { | ||
| 133 | File(ensureModelsDirectory(), modelName).also { file -> | ||
| 134 | // Copy the file into local storage if not yet done | ||
| 135 | if (!file.exists()) { | ||
| 136 | Log.i(TAG, "Start copying file to $modelName") | ||
| 137 | withContext(Dispatchers.Main) { | ||
| 138 | userInputEt.hint = "Copying file..." | ||
| 139 | } | ||
| 140 | |||
| 141 | FileOutputStream(file).use { input.copyTo(it) } | ||
| 142 | Log.i(TAG, "Finished copying file to $modelName") | ||
| 143 | } else { | ||
| 144 | Log.i(TAG, "File already exists $modelName") | ||
| 145 | } | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | /** | ||
| 150 | * Load the model file from the app private storage | ||
| 151 | */ | ||
| 152 | private suspend fun loadModel(modelName: String, modelFile: File) = | ||
| 153 | withContext(Dispatchers.IO) { | ||
| 154 | Log.i(TAG, "Loading model $modelName") | ||
| 155 | withContext(Dispatchers.Main) { | ||
| 156 | userInputEt.hint = "Loading model..." | ||
| 157 | } | ||
| 158 | engine.loadModel(modelFile.path) | ||
| 159 | } | ||
| 160 | |||
| 161 | /** | ||
| 162 | * Validate and send the user message into [InferenceEngine] | ||
| 163 | */ | ||
| 164 | private fun handleUserInput() { | ||
| 165 | userInputEt.text.toString().also { userMsg -> | ||
| 166 | if (userMsg.isEmpty()) { | ||
| 167 | Toast.makeText(this, "Input message is empty!", Toast.LENGTH_SHORT).show() | ||
| 168 | } else { | ||
| 169 | userInputEt.text = null | ||
| 170 | userInputEt.isEnabled = false | ||
| 171 | userActionFab.isEnabled = false | ||
| 172 | |||
| 173 | // Update message states | ||
| 174 | messages.add(Message(UUID.randomUUID().toString(), userMsg, true)) | ||
| 175 | lastAssistantMsg.clear() | ||
| 176 | messages.add(Message(UUID.randomUUID().toString(), lastAssistantMsg.toString(), false)) | ||
| 177 | |||
| 178 | generationJob = lifecycleScope.launch(Dispatchers.Default) { | ||
| 179 | engine.sendUserPrompt(userMsg) | ||
| 180 | .onCompletion { | ||
| 181 | withContext(Dispatchers.Main) { | ||
| 182 | userInputEt.isEnabled = true | ||
| 183 | userActionFab.isEnabled = true | ||
| 184 | } | ||
| 185 | }.collect { token -> | ||
| 186 | withContext(Dispatchers.Main) { | ||
| 187 | val messageCount = messages.size | ||
| 188 | check(messageCount > 0 && !messages[messageCount - 1].isUser) | ||
| 189 | |||
| 190 | messages.removeAt(messageCount - 1).copy( | ||
| 191 | content = lastAssistantMsg.append(token).toString() | ||
| 192 | ).let { messages.add(it) } | ||
| 193 | |||
| 194 | messageAdapter.notifyItemChanged(messages.size - 1) | ||
| 195 | } | ||
| 196 | } | ||
| 197 | } | ||
| 198 | } | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | /** | ||
| 203 | * Run a benchmark with the model file | ||
| 204 | */ | ||
| 205 | @Deprecated("This benchmark doesn't accurately indicate GUI performance expected by app developers") | ||
| 206 | private suspend fun runBenchmark(modelName: String, modelFile: File) = | ||
| 207 | withContext(Dispatchers.Default) { | ||
| 208 | Log.i(TAG, "Starts benchmarking $modelName") | ||
| 209 | withContext(Dispatchers.Main) { | ||
| 210 | userInputEt.hint = "Running benchmark..." | ||
| 211 | } | ||
| 212 | engine.bench( | ||
| 213 | pp=BENCH_PROMPT_PROCESSING_TOKENS, | ||
| 214 | tg=BENCH_TOKEN_GENERATION_TOKENS, | ||
| 215 | pl=BENCH_SEQUENCE, | ||
| 216 | nr=BENCH_REPETITION | ||
| 217 | ).let { result -> | ||
| 218 | messages.add(Message(UUID.randomUUID().toString(), result, false)) | ||
| 219 | withContext(Dispatchers.Main) { | ||
| 220 | messageAdapter.notifyItemChanged(messages.size - 1) | ||
| 221 | } | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | /** | ||
| 226 | * Create the `models` directory if not exist. | ||
| 227 | */ | ||
| 228 | private fun ensureModelsDirectory() = | ||
| 229 | File(filesDir, DIRECTORY_MODELS).also { | ||
| 230 | if (it.exists() && !it.isDirectory) { it.delete() } | ||
| 231 | if (!it.exists()) { it.mkdir() } | ||
| 232 | } | ||
| 233 | |||
| 234 | override fun onStop() { | ||
| 235 | generationJob?.cancel() | ||
| 236 | super.onStop() | ||
| 237 | } | ||
| 238 | |||
| 239 | override fun onDestroy() { | ||
| 240 | engine.destroy() | ||
| 241 | super.onDestroy() | ||
| 242 | } | ||
| 243 | |||
| 244 | companion object { | ||
| 245 | private val TAG = MainActivity::class.java.simpleName | ||
| 246 | |||
| 247 | private const val DIRECTORY_MODELS = "models" | ||
| 248 | private const val FILE_EXTENSION_GGUF = ".gguf" | ||
| 249 | |||
| 250 | private const val BENCH_PROMPT_PROCESSING_TOKENS = 512 | ||
| 251 | private const val BENCH_TOKEN_GENERATION_TOKENS = 128 | ||
| 252 | private const val BENCH_SEQUENCE = 1 | ||
| 253 | private const val BENCH_REPETITION = 3 | ||
| 254 | } | ||
| 255 | } | ||
| 256 | |||
| 257 | fun GgufMetadata.filename() = when { | ||
| 258 | basic.name != null -> { | ||
| 259 | basic.name?.let { name -> | ||
| 260 | basic.sizeLabel?.let { size -> | ||
| 261 | "$name-$size" | ||
| 262 | } ?: name | ||
| 263 | } | ||
| 264 | } | ||
| 265 | architecture?.architecture != null -> { | ||
| 266 | architecture?.architecture?.let { arch -> | ||
| 267 | basic.uuid?.let { uuid -> | ||
| 268 | "$arch-$uuid" | ||
| 269 | } ?: "$arch-${System.currentTimeMillis()}" | ||
| 270 | } | ||
| 271 | } | ||
| 272 | else -> { | ||
| 273 | "model-${System.currentTimeMillis().toHexString()}" | ||
| 274 | } | ||
| 275 | } | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/java/com/example/llama/MessageAdapter.kt b/llama.cpp/examples/llama.android/app/src/main/java/com/example/llama/MessageAdapter.kt new file mode 100644 index 0000000..0439f96 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/java/com/example/llama/MessageAdapter.kt | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | package com.example.llama | ||
| 2 | |||
| 3 | import android.view.LayoutInflater | ||
| 4 | import android.view.View | ||
| 5 | import android.view.ViewGroup | ||
| 6 | import android.widget.TextView | ||
| 7 | import androidx.recyclerview.widget.RecyclerView | ||
| 8 | |||
| 9 | data class Message( | ||
| 10 | val id: String, | ||
| 11 | val content: String, | ||
| 12 | val isUser: Boolean | ||
| 13 | ) | ||
| 14 | |||
| 15 | class MessageAdapter( | ||
| 16 | private val messages: List<Message> | ||
| 17 | ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { | ||
| 18 | |||
| 19 | companion object { | ||
| 20 | private const val VIEW_TYPE_USER = 1 | ||
| 21 | private const val VIEW_TYPE_ASSISTANT = 2 | ||
| 22 | } | ||
| 23 | |||
| 24 | override fun getItemViewType(position: Int): Int { | ||
| 25 | return if (messages[position].isUser) VIEW_TYPE_USER else VIEW_TYPE_ASSISTANT | ||
| 26 | } | ||
| 27 | |||
| 28 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { | ||
| 29 | val layoutInflater = LayoutInflater.from(parent.context) | ||
| 30 | return if (viewType == VIEW_TYPE_USER) { | ||
| 31 | val view = layoutInflater.inflate(R.layout.item_message_user, parent, false) | ||
| 32 | UserMessageViewHolder(view) | ||
| 33 | } else { | ||
| 34 | val view = layoutInflater.inflate(R.layout.item_message_assistant, parent, false) | ||
| 35 | AssistantMessageViewHolder(view) | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { | ||
| 40 | val message = messages[position] | ||
| 41 | if (holder is UserMessageViewHolder || holder is AssistantMessageViewHolder) { | ||
| 42 | val textView = holder.itemView.findViewById<TextView>(R.id.msg_content) | ||
| 43 | textView.text = message.content | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | override fun getItemCount(): Int = messages.size | ||
| 48 | |||
| 49 | class UserMessageViewHolder(view: View) : RecyclerView.ViewHolder(view) | ||
| 50 | class AssistantMessageViewHolder(view: View) : RecyclerView.ViewHolder(view) | ||
| 51 | } | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/drawable/bg_assistant_message.xml b/llama.cpp/examples/llama.android/app/src/main/res/drawable/bg_assistant_message.xml new file mode 100644 index 0000000..f90c3db --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/drawable/bg_assistant_message.xml | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> | ||
| 2 | <solid android:color="#E5E5EA" /> | ||
| 3 | <corners android:radius="16dp" /> | ||
| 4 | </shape> | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/drawable/bg_user_message.xml b/llama.cpp/examples/llama.android/app/src/main/res/drawable/bg_user_message.xml new file mode 100644 index 0000000..3ca7dae --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/drawable/bg_user_message.xml | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> | ||
| 2 | <solid android:color="#4285F4" /> | ||
| 3 | <corners android:radius="16dp" /> | ||
| 4 | </shape> | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/drawable/ic_launcher_background.xml b/llama.cpp/examples/llama.android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/drawable/ic_launcher_background.xml | |||
| @@ -0,0 +1,170 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | android:width="108dp" | ||
| 4 | android:height="108dp" | ||
| 5 | android:viewportWidth="108" | ||
| 6 | android:viewportHeight="108"> | ||
| 7 | <path | ||
| 8 | android:fillColor="#3DDC84" | ||
| 9 | android:pathData="M0,0h108v108h-108z" /> | ||
| 10 | <path | ||
| 11 | android:fillColor="#00000000" | ||
| 12 | android:pathData="M9,0L9,108" | ||
| 13 | android:strokeWidth="0.8" | ||
| 14 | android:strokeColor="#33FFFFFF" /> | ||
| 15 | <path | ||
| 16 | android:fillColor="#00000000" | ||
| 17 | android:pathData="M19,0L19,108" | ||
| 18 | android:strokeWidth="0.8" | ||
| 19 | android:strokeColor="#33FFFFFF" /> | ||
| 20 | <path | ||
| 21 | android:fillColor="#00000000" | ||
| 22 | android:pathData="M29,0L29,108" | ||
| 23 | android:strokeWidth="0.8" | ||
| 24 | android:strokeColor="#33FFFFFF" /> | ||
| 25 | <path | ||
| 26 | android:fillColor="#00000000" | ||
| 27 | android:pathData="M39,0L39,108" | ||
| 28 | android:strokeWidth="0.8" | ||
| 29 | android:strokeColor="#33FFFFFF" /> | ||
| 30 | <path | ||
| 31 | android:fillColor="#00000000" | ||
| 32 | android:pathData="M49,0L49,108" | ||
| 33 | android:strokeWidth="0.8" | ||
| 34 | android:strokeColor="#33FFFFFF" /> | ||
| 35 | <path | ||
| 36 | android:fillColor="#00000000" | ||
| 37 | android:pathData="M59,0L59,108" | ||
| 38 | android:strokeWidth="0.8" | ||
| 39 | android:strokeColor="#33FFFFFF" /> | ||
| 40 | <path | ||
| 41 | android:fillColor="#00000000" | ||
| 42 | android:pathData="M69,0L69,108" | ||
| 43 | android:strokeWidth="0.8" | ||
| 44 | android:strokeColor="#33FFFFFF" /> | ||
| 45 | <path | ||
| 46 | android:fillColor="#00000000" | ||
| 47 | android:pathData="M79,0L79,108" | ||
| 48 | android:strokeWidth="0.8" | ||
| 49 | android:strokeColor="#33FFFFFF" /> | ||
| 50 | <path | ||
| 51 | android:fillColor="#00000000" | ||
| 52 | android:pathData="M89,0L89,108" | ||
| 53 | android:strokeWidth="0.8" | ||
| 54 | android:strokeColor="#33FFFFFF" /> | ||
| 55 | <path | ||
| 56 | android:fillColor="#00000000" | ||
| 57 | android:pathData="M99,0L99,108" | ||
| 58 | android:strokeWidth="0.8" | ||
| 59 | android:strokeColor="#33FFFFFF" /> | ||
| 60 | <path | ||
| 61 | android:fillColor="#00000000" | ||
| 62 | android:pathData="M0,9L108,9" | ||
| 63 | android:strokeWidth="0.8" | ||
| 64 | android:strokeColor="#33FFFFFF" /> | ||
| 65 | <path | ||
| 66 | android:fillColor="#00000000" | ||
| 67 | android:pathData="M0,19L108,19" | ||
| 68 | android:strokeWidth="0.8" | ||
| 69 | android:strokeColor="#33FFFFFF" /> | ||
| 70 | <path | ||
| 71 | android:fillColor="#00000000" | ||
| 72 | android:pathData="M0,29L108,29" | ||
| 73 | android:strokeWidth="0.8" | ||
| 74 | android:strokeColor="#33FFFFFF" /> | ||
| 75 | <path | ||
| 76 | android:fillColor="#00000000" | ||
| 77 | android:pathData="M0,39L108,39" | ||
| 78 | android:strokeWidth="0.8" | ||
| 79 | android:strokeColor="#33FFFFFF" /> | ||
| 80 | <path | ||
| 81 | android:fillColor="#00000000" | ||
| 82 | android:pathData="M0,49L108,49" | ||
| 83 | android:strokeWidth="0.8" | ||
| 84 | android:strokeColor="#33FFFFFF" /> | ||
| 85 | <path | ||
| 86 | android:fillColor="#00000000" | ||
| 87 | android:pathData="M0,59L108,59" | ||
| 88 | android:strokeWidth="0.8" | ||
| 89 | android:strokeColor="#33FFFFFF" /> | ||
| 90 | <path | ||
| 91 | android:fillColor="#00000000" | ||
| 92 | android:pathData="M0,69L108,69" | ||
| 93 | android:strokeWidth="0.8" | ||
| 94 | android:strokeColor="#33FFFFFF" /> | ||
| 95 | <path | ||
| 96 | android:fillColor="#00000000" | ||
| 97 | android:pathData="M0,79L108,79" | ||
| 98 | android:strokeWidth="0.8" | ||
| 99 | android:strokeColor="#33FFFFFF" /> | ||
| 100 | <path | ||
| 101 | android:fillColor="#00000000" | ||
| 102 | android:pathData="M0,89L108,89" | ||
| 103 | android:strokeWidth="0.8" | ||
| 104 | android:strokeColor="#33FFFFFF" /> | ||
| 105 | <path | ||
| 106 | android:fillColor="#00000000" | ||
| 107 | android:pathData="M0,99L108,99" | ||
| 108 | android:strokeWidth="0.8" | ||
| 109 | android:strokeColor="#33FFFFFF" /> | ||
| 110 | <path | ||
| 111 | android:fillColor="#00000000" | ||
| 112 | android:pathData="M19,29L89,29" | ||
| 113 | android:strokeWidth="0.8" | ||
| 114 | android:strokeColor="#33FFFFFF" /> | ||
| 115 | <path | ||
| 116 | android:fillColor="#00000000" | ||
| 117 | android:pathData="M19,39L89,39" | ||
| 118 | android:strokeWidth="0.8" | ||
| 119 | android:strokeColor="#33FFFFFF" /> | ||
| 120 | <path | ||
| 121 | android:fillColor="#00000000" | ||
| 122 | android:pathData="M19,49L89,49" | ||
| 123 | android:strokeWidth="0.8" | ||
| 124 | android:strokeColor="#33FFFFFF" /> | ||
| 125 | <path | ||
| 126 | android:fillColor="#00000000" | ||
| 127 | android:pathData="M19,59L89,59" | ||
| 128 | android:strokeWidth="0.8" | ||
| 129 | android:strokeColor="#33FFFFFF" /> | ||
| 130 | <path | ||
| 131 | android:fillColor="#00000000" | ||
| 132 | android:pathData="M19,69L89,69" | ||
| 133 | android:strokeWidth="0.8" | ||
| 134 | android:strokeColor="#33FFFFFF" /> | ||
| 135 | <path | ||
| 136 | android:fillColor="#00000000" | ||
| 137 | android:pathData="M19,79L89,79" | ||
| 138 | android:strokeWidth="0.8" | ||
| 139 | android:strokeColor="#33FFFFFF" /> | ||
| 140 | <path | ||
| 141 | android:fillColor="#00000000" | ||
| 142 | android:pathData="M29,19L29,89" | ||
| 143 | android:strokeWidth="0.8" | ||
| 144 | android:strokeColor="#33FFFFFF" /> | ||
| 145 | <path | ||
| 146 | android:fillColor="#00000000" | ||
| 147 | android:pathData="M39,19L39,89" | ||
| 148 | android:strokeWidth="0.8" | ||
| 149 | android:strokeColor="#33FFFFFF" /> | ||
| 150 | <path | ||
| 151 | android:fillColor="#00000000" | ||
| 152 | android:pathData="M49,19L49,89" | ||
| 153 | android:strokeWidth="0.8" | ||
| 154 | android:strokeColor="#33FFFFFF" /> | ||
| 155 | <path | ||
| 156 | android:fillColor="#00000000" | ||
| 157 | android:pathData="M59,19L59,89" | ||
| 158 | android:strokeWidth="0.8" | ||
| 159 | android:strokeColor="#33FFFFFF" /> | ||
| 160 | <path | ||
| 161 | android:fillColor="#00000000" | ||
| 162 | android:pathData="M69,19L69,89" | ||
| 163 | android:strokeWidth="0.8" | ||
| 164 | android:strokeColor="#33FFFFFF" /> | ||
| 165 | <path | ||
| 166 | android:fillColor="#00000000" | ||
| 167 | android:pathData="M79,19L79,89" | ||
| 168 | android:strokeWidth="0.8" | ||
| 169 | android:strokeColor="#33FFFFFF" /> | ||
| 170 | </vector> | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/drawable/ic_launcher_foreground.xml b/llama.cpp/examples/llama.android/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..7706ab9 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/drawable/ic_launcher_foreground.xml | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 2 | xmlns:aapt="http://schemas.android.com/aapt" | ||
| 3 | android:width="108dp" | ||
| 4 | android:height="108dp" | ||
| 5 | android:viewportWidth="108" | ||
| 6 | android:viewportHeight="108"> | ||
| 7 | <path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z"> | ||
| 8 | <aapt:attr name="android:fillColor"> | ||
| 9 | <gradient | ||
| 10 | android:endX="85.84757" | ||
| 11 | android:endY="92.4963" | ||
| 12 | android:startX="42.9492" | ||
| 13 | android:startY="49.59793" | ||
| 14 | android:type="linear"> | ||
| 15 | <item | ||
| 16 | android:color="#44000000" | ||
| 17 | android:offset="0.0" /> | ||
| 18 | <item | ||
| 19 | android:color="#00000000" | ||
| 20 | android:offset="1.0" /> | ||
| 21 | </gradient> | ||
| 22 | </aapt:attr> | ||
| 23 | </path> | ||
| 24 | <path | ||
| 25 | android:fillColor="#FFFFFF" | ||
| 26 | android:fillType="nonZero" | ||
| 27 | android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z" | ||
| 28 | android:strokeWidth="1" | ||
| 29 | android:strokeColor="#00000000" /> | ||
| 30 | </vector> | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/drawable/outline_folder_open_24.xml b/llama.cpp/examples/llama.android/app/src/main/res/drawable/outline_folder_open_24.xml new file mode 100644 index 0000000..f58b501 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/drawable/outline_folder_open_24.xml | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 2 | android:width="24dp" | ||
| 3 | android:height="24dp" | ||
| 4 | android:viewportWidth="24" | ||
| 5 | android:viewportHeight="24" | ||
| 6 | android:tint="?attr/colorControlNormal"> | ||
| 7 | <path | ||
| 8 | android:fillColor="@android:color/white" | ||
| 9 | android:pathData="M20,6h-8l-2,-2L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,8c0,-1.1 -0.9,-2 -2,-2zM20,18L4,18L4,8h16v10z"/> | ||
| 10 | </vector> | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/drawable/outline_send_24.xml b/llama.cpp/examples/llama.android/app/src/main/res/drawable/outline_send_24.xml new file mode 100644 index 0000000..712adc0 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/drawable/outline_send_24.xml | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 2 | android:width="24dp" | ||
| 3 | android:height="24dp" | ||
| 4 | android:viewportWidth="24" | ||
| 5 | android:viewportHeight="24" | ||
| 6 | android:tint="?attr/colorControlNormal" | ||
| 7 | android:autoMirrored="true"> | ||
| 8 | <path | ||
| 9 | android:fillColor="@android:color/white" | ||
| 10 | android:pathData="M4.01,6.03l7.51,3.22 -7.52,-1 0.01,-2.22m7.5,8.72L4,17.97v-2.22l7.51,-1M2.01,3L2,10l15,2 -15,2 0.01,7L23,12 2.01,3z"/> | ||
| 11 | </vector> | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/layout/activity_main.xml b/llama.cpp/examples/llama.android/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..d15772b --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/layout/activity_main.xml | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | xmlns:app="http://schemas.android.com/apk/res-auto" | ||
| 4 | xmlns:tools="http://schemas.android.com/tools" | ||
| 5 | android:id="@+id/main" | ||
| 6 | android:layout_height="match_parent" | ||
| 7 | android:layout_width="match_parent"> | ||
| 8 | |||
| 9 | <LinearLayout | ||
| 10 | android:fitsSystemWindows="true" | ||
| 11 | android:layout_width="match_parent" | ||
| 12 | android:layout_height="match_parent" | ||
| 13 | android:orientation="vertical" | ||
| 14 | android:layout_marginEnd="4dp" | ||
| 15 | tools:context=".MainActivity"> | ||
| 16 | |||
| 17 | <ScrollView | ||
| 18 | android:layout_width="match_parent" | ||
| 19 | android:layout_height="0dp" | ||
| 20 | android:layout_weight="1" | ||
| 21 | android:fadeScrollbars="false"> | ||
| 22 | |||
| 23 | <TextView | ||
| 24 | android:id="@+id/gguf" | ||
| 25 | android:layout_width="match_parent" | ||
| 26 | android:layout_height="wrap_content" | ||
| 27 | android:padding="16dp" | ||
| 28 | android:text="Selected GGUF model's metadata will show here." | ||
| 29 | style="@style/TextAppearance.MaterialComponents.Body2" /> | ||
| 30 | |||
| 31 | </ScrollView> | ||
| 32 | |||
| 33 | <com.google.android.material.divider.MaterialDivider | ||
| 34 | android:layout_width="match_parent" | ||
| 35 | android:layout_height="2dp" | ||
| 36 | android:layout_marginHorizontal="16dp" /> | ||
| 37 | |||
| 38 | <androidx.recyclerview.widget.RecyclerView | ||
| 39 | android:id="@+id/messages" | ||
| 40 | android:layout_width="match_parent" | ||
| 41 | android:layout_height="0dp" | ||
| 42 | android:layout_weight="4" | ||
| 43 | android:fadeScrollbars="false" | ||
| 44 | android:scrollbars="vertical" | ||
| 45 | app:reverseLayout="true" | ||
| 46 | tools:listitem="@layout/item_message_assistant"/> | ||
| 47 | |||
| 48 | <LinearLayout | ||
| 49 | android:layout_width="match_parent" | ||
| 50 | android:layout_height="wrap_content" | ||
| 51 | android:orientation="horizontal" | ||
| 52 | android:paddingStart="16dp" | ||
| 53 | android:paddingEnd="4dp"> | ||
| 54 | |||
| 55 | <EditText | ||
| 56 | android:id="@+id/user_input" | ||
| 57 | android:enabled="false" | ||
| 58 | android:layout_width="0dp" | ||
| 59 | android:layout_weight="1" | ||
| 60 | android:layout_height="match_parent" | ||
| 61 | android:padding="8dp" | ||
| 62 | style="@style/TextAppearance.MaterialComponents.Body2" | ||
| 63 | android:hint="Please first pick a GGUF model file to import." /> | ||
| 64 | |||
| 65 | <com.google.android.material.floatingactionbutton.FloatingActionButton | ||
| 66 | android:id="@+id/fab" | ||
| 67 | android:enabled="true" | ||
| 68 | style="@style/Widget.Material3.FloatingActionButton.Primary" | ||
| 69 | android:layout_width="wrap_content" | ||
| 70 | android:layout_height="wrap_content" | ||
| 71 | android:layout_margin="12dp" | ||
| 72 | android:src="@drawable/outline_folder_open_24" /> | ||
| 73 | |||
| 74 | </LinearLayout> | ||
| 75 | |||
| 76 | </LinearLayout> | ||
| 77 | </androidx.constraintlayout.widget.ConstraintLayout> | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/layout/item_message_assistant.xml b/llama.cpp/examples/llama.android/app/src/main/res/layout/item_message_assistant.xml new file mode 100644 index 0000000..2c8e4bc --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/layout/item_message_assistant.xml | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | android:layout_width="match_parent" | ||
| 4 | android:layout_height="wrap_content" | ||
| 5 | android:layout_marginHorizontal="16dp" | ||
| 6 | android:layout_marginVertical="8dp" | ||
| 7 | android:gravity="start"> | ||
| 8 | |||
| 9 | <TextView | ||
| 10 | android:id="@+id/msg_content" | ||
| 11 | android:layout_width="wrap_content" | ||
| 12 | android:layout_height="wrap_content" | ||
| 13 | android:background="@drawable/bg_assistant_message" | ||
| 14 | android:padding="12dp" | ||
| 15 | android:textColor="@android:color/black" /> | ||
| 16 | </LinearLayout> | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/layout/item_message_user.xml b/llama.cpp/examples/llama.android/app/src/main/res/layout/item_message_user.xml new file mode 100644 index 0000000..5aa79f2 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/layout/item_message_user.xml | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | android:layout_width="match_parent" | ||
| 4 | android:layout_height="wrap_content" | ||
| 5 | android:layout_marginHorizontal="16dp" | ||
| 6 | android:layout_marginVertical="8dp" | ||
| 7 | android:gravity="end"> | ||
| 8 | |||
| 9 | <TextView | ||
| 10 | android:id="@+id/msg_content" | ||
| 11 | android:layout_width="wrap_content" | ||
| 12 | android:layout_height="wrap_content" | ||
| 13 | android:background="@drawable/bg_user_message" | ||
| 14 | android:padding="12dp" | ||
| 15 | android:textColor="@android:color/white" /> | ||
| 16 | </LinearLayout> | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/mipmap-anydpi/ic_launcher.xml b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-anydpi/ic_launcher.xml new file mode 100644 index 0000000..b3e26b4 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-anydpi/ic_launcher.xml | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 3 | <background android:drawable="@drawable/ic_launcher_background" /> | ||
| 4 | <foreground android:drawable="@drawable/ic_launcher_foreground" /> | ||
| 5 | <monochrome android:drawable="@drawable/ic_launcher_foreground" /> | ||
| 6 | </adaptive-icon> | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml new file mode 100644 index 0000000..b3e26b4 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 3 | <background android:drawable="@drawable/ic_launcher_background" /> | ||
| 4 | <foreground android:drawable="@drawable/ic_launcher_foreground" /> | ||
| 5 | <monochrome android:drawable="@drawable/ic_launcher_foreground" /> | ||
| 6 | </adaptive-icon> | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-hdpi/ic_launcher.webp | |||
| Binary files differ | |||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp | |||
| Binary files differ | |||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-mdpi/ic_launcher.webp | |||
| Binary files differ | |||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp | |||
| Binary files differ | |||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp | |||
| Binary files differ | |||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp | |||
| Binary files differ | |||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp | |||
| Binary files differ | |||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp | |||
| Binary files differ | |||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp | |||
| Binary files differ | |||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp | |||
| Binary files differ | |||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/values/colors.xml b/llama.cpp/examples/llama.android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..ca1931b --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/values/colors.xml | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <resources> | ||
| 3 | <color name="purple_200">#FFBB86FC</color> | ||
| 4 | <color name="purple_500">#FF6200EE</color> | ||
| 5 | <color name="purple_700">#FF3700B3</color> | ||
| 6 | <color name="teal_200">#FF03DAC5</color> | ||
| 7 | <color name="teal_700">#FF018786</color> | ||
| 8 | <color name="black">#FF000000</color> | ||
| 9 | <color name="white">#FFFFFFFF</color> | ||
| 10 | </resources> | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/values/strings.xml b/llama.cpp/examples/llama.android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..36059fc --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/values/strings.xml | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | <resources> | ||
| 2 | <string name="app_name">AI Chat basic sample</string> | ||
| 3 | </resources> | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/values/themes.xml b/llama.cpp/examples/llama.android/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..2e4fdad --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/values/themes.xml | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <resources> | ||
| 3 | |||
| 4 | <style name="Base.Theme.AiChatSample" parent="Theme.Material3.DayNight.NoActionBar"> | ||
| 5 | <!-- Customize your light theme here. --> | ||
| 6 | <!-- <item name="colorPrimary">@color/my_light_primary</item> --> | ||
| 7 | </style> | ||
| 8 | |||
| 9 | <style name="Theme.AiChatSample" parent="Base.Theme.AiChatSample" /> | ||
| 10 | </resources> | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/xml/backup_rules.xml b/llama.cpp/examples/llama.android/app/src/main/res/xml/backup_rules.xml new file mode 100644 index 0000000..148c18b --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/xml/backup_rules.xml | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?><!-- | ||
| 2 | Sample backup rules file; uncomment and customize as necessary. | ||
| 3 | See https://developer.android.com/guide/topics/data/autobackup | ||
| 4 | for details. | ||
| 5 | Note: This file is ignored for devices older that API 31 | ||
| 6 | See https://developer.android.com/about/versions/12/backup-restore | ||
| 7 | --> | ||
| 8 | <full-backup-content> | ||
| 9 | <!-- | ||
| 10 | <include domain="sharedpref" path="."/> | ||
| 11 | <exclude domain="sharedpref" path="device.xml"/> | ||
| 12 | --> | ||
| 13 | </full-backup-content> | ||
diff --git a/llama.cpp/examples/llama.android/app/src/main/res/xml/data_extraction_rules.xml b/llama.cpp/examples/llama.android/app/src/main/res/xml/data_extraction_rules.xml new file mode 100644 index 0000000..0c4f95c --- /dev/null +++ b/llama.cpp/examples/llama.android/app/src/main/res/xml/data_extraction_rules.xml | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?><!-- | ||
| 2 | Sample data extraction rules file; uncomment and customize as necessary. | ||
| 3 | See https://developer.android.com/about/versions/12/backup-restore#xml-changes | ||
| 4 | for details. | ||
| 5 | --> | ||
| 6 | <data-extraction-rules> | ||
| 7 | <cloud-backup> | ||
| 8 | <!-- TODO: Use <include> and <exclude> to control what is backed up. | ||
| 9 | <include .../> | ||
| 10 | <exclude .../> | ||
| 11 | --> | ||
| 12 | </cloud-backup> | ||
| 13 | <!-- | ||
| 14 | <device-transfer> | ||
| 15 | <include .../> | ||
| 16 | <exclude .../> | ||
| 17 | </device-transfer> | ||
| 18 | --> | ||
| 19 | </data-extraction-rules> | ||
