Skip to content

Commit 1f852ad

Browse files
Add detailed LiteRT file-attempt logging and fallback
1 parent 6861939 commit 1f852ad

1 file changed

Lines changed: 61 additions & 24 deletions

File tree

app/src/main/kotlin/com/google/ai/sample/feature/multimodal/PhotoReasoningViewModel.kt

Lines changed: 61 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager
4848
import kotlinx.coroutines.delay
4949
import kotlinx.coroutines.launch
5050
import kotlinx.coroutines.withContext
51+
import java.io.File
5152
import java.io.IOException
5253
import java.util.concurrent.atomic.AtomicBoolean
5354

@@ -331,8 +332,8 @@ class PhotoReasoningViewModel(
331332
if (missingFiles.isNotEmpty()) {
332333
return "Offline model files missing: ${missingFiles.joinToString(", ")}. Please redownload the model package."
333334
}
334-
val modelFile = ModelDownloadManager.getModelFile(context, currentModel)
335-
if (modelFile != null && modelFile.exists()) {
335+
val selectedModelFile = ModelDownloadManager.getModelFile(context, currentModel)
336+
if (selectedModelFile != null && selectedModelFile.exists()) {
336337
// Load backend preference
337338
GenerativeAiViewModelFactory.loadBackendPreference(context)
338339
val backend = GenerativeAiViewModelFactory.getBackend()
@@ -342,41 +343,77 @@ class PhotoReasoningViewModel(
342343
if (!isLiteRtAbiSupported()) {
343344
return "Offline LiteRT models are only supported on arm64-v8a or x86_64 devices."
344345
}
346+
347+
val externalFilesDir = context.getExternalFilesDir(null)
348+
val candidateNames = linkedSetOf<String>().apply {
349+
add(selectedModelFile.name)
350+
currentModel.offlineModelFilename?.let { add(it) }
351+
addAll(currentModel.offlineAlternateModelFilenames)
352+
}
353+
val candidateFiles = candidateNames
354+
.mapNotNull { name -> externalFilesDir?.let { File(it, name) } }
355+
.filter { it.exists() && it.length() > 0L }
356+
345357
Log.i(
346358
TAG,
347359
"Initializing LiteRT engine for ${currentModel.displayName}. preferredBackend=$backend, " +
348360
"abis=${Build.SUPPORTED_ABIS?.joinToString() ?: "unknown"}, " +
349-
"modelPath=${modelFile.absolutePath}, modelSizeBytes=${modelFile.length()}"
361+
"candidateFiles=${candidateFiles.joinToString { "${it.name}(${it.length()}B)" }}"
350362
)
363+
351364
if (liteRtEngine == null) {
352365
val preferredBackend = if (backend == InferenceBackend.GPU) Backend.GPU() else Backend.CPU()
353-
val useVisionBackend = currentModel.requiresVisionBackend &&
354-
modelFile.name.contains("multimodal", ignoreCase = true)
355-
val preferredVisionBackend = if (useVisionBackend) {
356-
if (backend == InferenceBackend.GPU) Backend.GPU() else Backend.CPU()
357-
} else {
358-
null
359-
}
360-
val audioBackend = null
361-
val cacheDir =
362-
if (modelFile.absolutePath.startsWith("/data/local/tmp")) {
363-
context.getExternalFilesDir(null)?.absolutePath
364-
} else {
365-
null
366+
367+
val attempts = if (candidateFiles.isNotEmpty()) candidateFiles else listOf(selectedModelFile)
368+
val failureDetails = StringBuilder()
369+
370+
attempts.forEachIndexed { index, modelFile ->
371+
try {
372+
val useVisionBackend = currentModel.requiresVisionBackend &&
373+
modelFile.name.contains("multimodal", ignoreCase = true)
374+
val preferredVisionBackend = if (useVisionBackend) {
375+
if (backend == InferenceBackend.GPU) Backend.GPU() else Backend.CPU()
376+
} else {
377+
null
378+
}
379+
val audioBackend = null
380+
val cacheDir =
381+
if (modelFile.absolutePath.startsWith("/data/local/tmp")) {
382+
context.getExternalFilesDir(null)?.absolutePath
383+
} else {
384+
null
385+
}
386+
387+
Log.i(
388+
TAG,
389+
"LiteRT model file attempt ${index + 1}/${attempts.size}: " +
390+
"modelFile=${modelFile.absolutePath}, size=${modelFile.length()}, useVision=$useVisionBackend"
391+
)
392+
393+
liteRtEngine = createLiteRtEngineWithFallbacks(
394+
modelPath = modelFile.absolutePath,
395+
preferredBackend = preferredBackend,
396+
preferredVisionBackend = preferredVisionBackend,
397+
audioBackend = audioBackend,
398+
cacheDir = cacheDir
399+
)
400+
Log.d(TAG, "Offline model initialized with LiteRT-LM Engine using ${modelFile.name}")
401+
return null
402+
} catch (e: Exception) {
403+
val msg = e.message ?: e.toString()
404+
failureDetails.append("${modelFile.name}: $msg\n")
405+
Log.e(TAG, "LiteRT file attempt failed for ${modelFile.name}", e)
366406
}
367-
liteRtEngine = createLiteRtEngineWithFallbacks(
368-
modelPath = modelFile.absolutePath,
369-
preferredBackend = preferredBackend,
370-
preferredVisionBackend = preferredVisionBackend,
371-
audioBackend = audioBackend,
372-
cacheDir = cacheDir
407+
}
408+
409+
throw IllegalStateException(
410+
"All model-file attempts failed for ${currentModel.displayName}.\n$failureDetails"
373411
)
374-
Log.d(TAG, "Offline model initialized with LiteRT-LM Engine")
375412
}
376413
} else {
377414
if (llmInference == null) {
378415
val optionsBuilder = LlmInference.LlmInferenceOptions.builder()
379-
.setModelPath(modelFile.absolutePath)
416+
.setModelPath(selectedModelFile.absolutePath)
380417
.setMaxTokens(4096)
381418

382419
// Set preferred backend (CPU or GPU)

0 commit comments

Comments
 (0)