lib: replace the factory pattern for deprecated tiered lib loading with single instance pattern
This commit is contained in:
parent
63e5bd0771
commit
6dfdc2c105
|
|
@ -76,8 +76,7 @@ internal abstract class AppModule {
|
|||
return if (USE_STUB_ENGINE) {
|
||||
StubInferenceEngine()
|
||||
} else {
|
||||
KleidiLlama.createInferenceEngine(context)
|
||||
?: throw InstantiationException("Cannot instantiate InferenceEngine!")
|
||||
KleidiLlama.getInferenceEngine(context)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package android.llama.cpp
|
||||
|
||||
import android.content.Context
|
||||
import android.llama.cpp.internal.InferenceEngineFactory
|
||||
import android.llama.cpp.internal.InferenceEngineImpl
|
||||
import android.llama.cpp.internal.TierDetectionImpl
|
||||
|
||||
/**
|
||||
|
|
@ -10,12 +10,12 @@ import android.llama.cpp.internal.TierDetectionImpl
|
|||
*/
|
||||
object KleidiLlama {
|
||||
/**
|
||||
* Create an inference engine instance with automatic tier detection.
|
||||
* Get the inference engine single instance.
|
||||
*/
|
||||
fun createInferenceEngine(context: Context) = InferenceEngineFactory.getInstance(context)
|
||||
fun getInferenceEngine(context: Context) = InferenceEngineImpl.getInstance(context)
|
||||
|
||||
/**
|
||||
* Get tier detection information for debugging/settings.
|
||||
* Get tier detection single instance.
|
||||
*/
|
||||
fun getTierDetection(context: Context): TierDetection = TierDetectionImpl(context)
|
||||
fun getTierDetection(context: Context): TierDetection = TierDetectionImpl.getInstance(context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,45 +0,0 @@
|
|||
package android.llama.cpp.internal
|
||||
|
||||
import android.content.Context
|
||||
import android.llama.cpp.InferenceEngine
|
||||
import android.llama.cpp.TierDetection
|
||||
import android.util.Log
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
/**
|
||||
* Internal factory to create [InferenceEngine] and [TierDetection]
|
||||
*/
|
||||
internal object InferenceEngineFactory {
|
||||
private val TAG = InferenceEngineFactory::class.simpleName
|
||||
|
||||
private var _cachedInstance: InferenceEngineImpl? = null
|
||||
|
||||
/**
|
||||
* Factory method to get a configured [InferenceEngineImpl] instance.
|
||||
* Handles tier detection, caching, and library loading automatically.
|
||||
*/
|
||||
@Synchronized
|
||||
fun getInstance(context: Context): InferenceEngine? {
|
||||
// Return cached instance if available
|
||||
_cachedInstance?.let { return it }
|
||||
|
||||
return runBlocking {
|
||||
try {
|
||||
// Create and cache the inference engine instance
|
||||
InferenceEngineImpl.create(context).also {
|
||||
_cachedInstance = it
|
||||
Log.i(TAG, "Successfully instantiated Inference Engine")
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error instantiating Inference Engine", e)
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun clearCache() {
|
||||
_cachedInstance = null
|
||||
Log.i(TAG, "Cleared cached instance of InferenceEngine")
|
||||
}
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ import java.io.IOException
|
|||
* with the underlying C++ native code.
|
||||
*
|
||||
* The typical usage flow is:
|
||||
* 1. Get instance via [instance]
|
||||
* 1. Get instance via [getInstance]
|
||||
* 2. Load a model with [loadModel]
|
||||
* 3. Send prompts with [sendUserPrompt]
|
||||
* 4. Generate responses as token streams
|
||||
|
|
@ -47,30 +47,29 @@ internal class InferenceEngineImpl private constructor(
|
|||
companion object {
|
||||
private val TAG = InferenceEngineImpl::class.java.simpleName
|
||||
|
||||
private var initialized = false
|
||||
@Volatile
|
||||
private var instance: InferenceEngine? = null
|
||||
|
||||
/**
|
||||
* Create [InferenceEngineImpl] instance at runtime
|
||||
* Create or obtain [InferenceEngineImpl]'s single instance.
|
||||
*
|
||||
* @param Context for obtaining native library directory
|
||||
* @throws IllegalArgumentException if native library path is invalid
|
||||
* @throws UnsatisfiedLinkError if library failed to load
|
||||
*/
|
||||
internal fun create(context: Context): InferenceEngineImpl {
|
||||
assert(!initialized) { "Inference Engine has already been initialized!" }
|
||||
internal fun getInstance(context: Context) =
|
||||
instance ?: synchronized(this) {
|
||||
val nativeLibDir = context.applicationInfo.nativeLibraryDir
|
||||
require(nativeLibDir.isNotBlank()) { "Expected a valid native library path!" }
|
||||
|
||||
val nativeLibDir = context.applicationInfo.nativeLibraryDir
|
||||
require(nativeLibDir.isNotBlank()) { "Expected native library" }
|
||||
|
||||
return try {
|
||||
Log.i(TAG, "Instantiating InferenceEngineImpl,,,")
|
||||
InferenceEngineImpl(nativeLibDir).also { initialized = true }
|
||||
|
||||
} catch (e: UnsatisfiedLinkError) {
|
||||
Log.e(TAG, "Failed to load native library from $nativeLibDir", e)
|
||||
throw e
|
||||
try {
|
||||
Log.i(TAG, "Instantiating InferenceEngineImpl,,,")
|
||||
InferenceEngineImpl(nativeLibDir).also { instance = it }
|
||||
} catch (e: UnsatisfiedLinkError) {
|
||||
Log.e(TAG, "Failed to load native library from $nativeLibDir", e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import kotlinx.coroutines.runBlocking
|
|||
/**
|
||||
* Internal [LLamaTier] detection implementation
|
||||
*/
|
||||
internal class TierDetectionImpl(
|
||||
internal class TierDetectionImpl private constructor(
|
||||
private val context: Context
|
||||
): TierDetection {
|
||||
|
||||
|
|
@ -30,6 +30,19 @@ internal class TierDetectionImpl(
|
|||
|
||||
private val DETECTION_VERSION = intPreferencesKey("detection_version")
|
||||
private val DETECTED_TIER = intPreferencesKey("detected_tier")
|
||||
|
||||
@Volatile
|
||||
private var instance: TierDetection? = null
|
||||
|
||||
/**
|
||||
* Create or obtain [TierDetectionImpl]'s single instance.
|
||||
*
|
||||
* @param Context for obtaining the data store
|
||||
*/
|
||||
internal fun getInstance(context: Context) =
|
||||
instance ?: synchronized(this) {
|
||||
instance ?: TierDetectionImpl(context).also { instance = it }
|
||||
}
|
||||
}
|
||||
|
||||
private external fun getOptimalTier(): Int
|
||||
|
|
|
|||
Loading…
Reference in New Issue