diff --git a/llm/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/AppSettings.kt b/llm/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/AppSettings.kt index 75cdc79c..f82f734c 100644 --- a/llm/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/AppSettings.kt +++ b/llm/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/AppSettings.kt @@ -13,5 +13,10 @@ package com.example.executorchllamademo */ data class AppSettings( val appearanceMode: AppearanceMode = AppearanceMode.SYSTEM, - val saveChatHistory: Boolean = false -) + val saveChatHistory: Boolean = false, + val maxSeqLen: Int = DEFAULT_MAX_SEQ_LEN +) { + companion object { + const val DEFAULT_MAX_SEQ_LEN = 768 + } +} diff --git a/llm/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/ui/screens/AppSettingsScreen.kt b/llm/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/ui/screens/AppSettingsScreen.kt index 0c89f0d5..b0aa3665 100644 --- a/llm/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/ui/screens/AppSettingsScreen.kt +++ b/llm/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/ui/screens/AppSettingsScreen.kt @@ -9,6 +9,7 @@ package com.example.executorchllamademo.ui.screens import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -20,6 +21,8 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack @@ -43,8 +46,11 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.example.executorchllamademo.AppSettings @@ -68,11 +74,13 @@ fun AppSettingsScreen( var moduleSettings by remember { mutableStateOf(ModuleSettings()) } var showAppearanceDialog by remember { mutableStateOf(false) } var showClearChatDialog by remember { mutableStateOf(false) } + var maxSeqLenText by remember { mutableStateOf("") } LaunchedEffect(Unit) { val prefs = DemoSharedPreferences(context) appSettings = prefs.getAppSettings() moduleSettings = prefs.getModuleSettings() + maxSeqLenText = appSettings.maxSeqLen.toString() } Column( @@ -133,6 +141,77 @@ fun AppSettingsScreen( Spacer(modifier = Modifier.height(24.dp)) + // Model Configuration section header + Text( + text = "Model Configuration", + fontSize = 16.sp, + fontWeight = FontWeight.Bold, + color = appColors.settingsText + ) + + Spacer(modifier = Modifier.height(8.dp)) + + // Max Seq Len input field + Column( + modifier = Modifier + .fillMaxWidth() + .background(appColors.settingsRowBackground, RoundedCornerShape(8.dp)) + .padding(horizontal = 16.dp, vertical = 12.dp) + ) { + Text( + text = "Max Sequence Length", + fontSize = 14.sp, + color = appColors.settingsText, + fontWeight = FontWeight.Medium + ) + Spacer(modifier = Modifier.height(8.dp)) + BasicTextField( + value = maxSeqLenText, + onValueChange = { newValue -> + maxSeqLenText = newValue + val newMaxSeqLen = newValue.toIntOrNull() + if (newMaxSeqLen != null && newMaxSeqLen > 0) { + appSettings = appSettings.copy(maxSeqLen = newMaxSeqLen) + val prefs = DemoSharedPreferences(context) + prefs.saveAppSettings(appSettings) + } + }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + singleLine = true, + textStyle = TextStyle( + color = appColors.settingsText, + fontSize = 16.sp + ), + cursorBrush = SolidColor(appColors.settingsText), + modifier = Modifier.fillMaxWidth(), + decorationBox = { innerTextField -> + Row( + modifier = Modifier + .fillMaxWidth() + .border(1.dp, appColors.settingsText.copy(alpha = 0.5f), RoundedCornerShape(4.dp)) + .padding(horizontal = 12.dp, vertical = 14.dp) + ) { + if (maxSeqLenText.isEmpty()) { + Text( + text = "Enter max sequence length", + color = appColors.settingsText.copy(alpha = 0.5f), + fontSize = 16.sp + ) + } + innerTextField() + } + } + ) + Text( + text = "Maximum number of tokens to generate (default: ${AppSettings.DEFAULT_MAX_SEQ_LEN})", + fontSize = 12.sp, + color = appColors.settingsText.copy(alpha = 0.6f), + modifier = Modifier.padding(top = 4.dp) + ) + } + + Spacer(modifier = Modifier.height(24.dp)) + // Conversation section header Text( text = "Conversation", diff --git a/llm/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/ui/viewmodel/ChatViewModel.kt b/llm/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/ui/viewmodel/ChatViewModel.kt index e046df61..a9e7c89c 100644 --- a/llm/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/ui/viewmodel/ChatViewModel.kt +++ b/llm/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/ui/viewmodel/ChatViewModel.kt @@ -19,6 +19,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.AndroidViewModel import com.example.executorchllamademo.BackendType +import com.example.executorchllamademo.AppSettings import com.example.executorchllamademo.DemoSharedPreferences import com.example.executorchllamademo.ETImage import com.example.executorchllamademo.ETLogging @@ -85,6 +86,7 @@ class ChatViewModel(application: Application) : AndroidViewModel(application), L private var resultMessage: Message? = null private val demoSharedPreferences = DemoSharedPreferences(application) private var currentSettingsFields = ModuleSettings() + private var appSettings = AppSettings() private var promptID = 0 private var sawStartHeaderId = false private var audioFileToPrefill: String? = null @@ -96,6 +98,7 @@ class ChatViewModel(application: Application) : AndroidViewModel(application), L init { // Check for clear chat history flag BEFORE loading saved messages val moduleSettings = demoSharedPreferences.getModuleSettings() + appSettings = demoSharedPreferences.getAppSettings() if (moduleSettings.isClearChatHistory) { // Clear the flag and don't load messages // Keep isLoadModel flag so model still loads in checkAndLoadSettings() @@ -144,6 +147,7 @@ class ChatViewModel(application: Application) : AndroidViewModel(application), L fun checkAndLoadSettings() { val updatedSettingsFields = demoSharedPreferences.getModuleSettings() + appSettings = demoSharedPreferences.getAppSettings() val isUpdated = currentSettingsFields != updatedSettingsFields val isLoadModel = updatedSettingsFields.isLoadModel @@ -662,10 +666,10 @@ class ChatViewModel(application: Application) : AndroidViewModel(application), L prefillVoxtralAudio(audioFileToPrefill!!, finalPrompt) audioFileToPrefill = null ETLogging.getInstance().log("Running vision model inference.. prompt=(empty after audio prefill)") - module?.generate("", ModelUtils.VISION_MODEL_SEQ_LEN, this, false) + module?.generate("", appSettings.maxSeqLen, this, false) } else { ETLogging.getInstance().log("Running vision model inference.. prompt=$finalPrompt") - module?.generate(finalPrompt, ModelUtils.VISION_MODEL_SEQ_LEN, this, false) + module?.generate(finalPrompt, appSettings.maxSeqLen, this, false) } } else if (currentSettingsFields.modelType == ModelType.LLAMA_GUARD_3) { val llamaGuardPromptForClassification = @@ -679,7 +683,7 @@ class ChatViewModel(application: Application) : AndroidViewModel(application), L ) } else { ETLogging.getInstance().log("Running inference.. prompt=$finalPrompt") - module?.generate(finalPrompt, ModelUtils.TEXT_MODEL_SEQ_LEN, this, false) + module?.generate(finalPrompt, appSettings.maxSeqLen, this, false) } val generateDuration = System.currentTimeMillis() - generateStartTime