blaze-android-app / BonsaiInference.kt
MR-CODESPIKE's picture
Upload folder using huggingface_hub
38cf36c verified
Raw
History Blame Contribute Delete
2.52 kB
package com.blaze.agent.ai
import android.content.Context
import android.util.Log
import kotlinx.coroutines.*
class BonsaiInference(private val context: Context) {
companion object {
private const val TAG = "BlazeBonsai"
private const val LIB_NAME = "blaze_llama"
private const val N_CTX = 512
private const val N_THREADS = 4
private const val MAX_TOKENS = 512
private const val UNLOAD_TIMEOUT_MS = 30_000L
private var libLoaded = false
fun tryLoadLibrary(): Boolean {
if (libLoaded) return true
return try { System.loadLibrary(LIB_NAME); libLoaded = true; true }
catch (e: UnsatisfiedLinkError) { false }
}
}
private val inferenceDispatcher = Dispatchers.IO.limitedParallelism(1)
private val scope = CoroutineScope(inferenceDispatcher + SupervisorJob())
private var unloadJob: Job? = null
private var modelPath: String? = null
private external fun loadModel(modelPath: String, nCtx: Int, nThreads: Int): Int
private external fun complete(prompt: String, maxTokens: Int): String
private external fun unloadModel()
private external fun isLoaded(): Boolean
suspend fun complete(prompt: String): String = withContext(inferenceDispatcher) {
if (!tryLoadLibrary()) throw IllegalStateException("Bonsai native library not loaded")
ensureModelLoaded()
scheduleUnload()
Log.d(TAG, "Running Bonsai inference (${prompt.length} chars)")
complete(prompt, MAX_TOKENS)
}
fun preloadIfReady() {
if (BonsaiDownloader.modelExists && tryLoadLibrary()) {
scope.launch { ensureModelLoaded(); scheduleUnload() }
}
}
fun forceUnload() {
scope.launch { if (libLoaded && isLoaded()) { unloadModel(); Log.d(TAG, "Force unloaded") } }
}
private fun ensureModelLoaded() {
if (!libLoaded || isLoaded()) return
val path = BonsaiDownloader.getModelFile(context).absolutePath
val result = loadModel(path, N_CTX, N_THREADS)
if (result != 1) throw IllegalStateException("Failed to load Bonsai model (JNI=$result)")
modelPath = path
Log.d(TAG, "Bonsai model loaded into memory")
}
private fun scheduleUnload() {
unloadJob?.cancel()
unloadJob = scope.launch {
delay(UNLOAD_TIMEOUT_MS)
if (libLoaded && isLoaded()) { Log.d(TAG, "Unloading Bonsai after inactivity"); unloadModel() }
}
}
}