To run an LLM on the NPU using Qualcomm AI Engine Direct, use LlmWrapper.builder() with LlmCreateInput.
Configuration Requirements:
runtime_id must be set to "qairt".compute_unit must be null (this selects the NPU, which is the only option for Qualcomm AI Engine Direct).- Important: Do not attempt to set
nGpuLayers or nCtx (context length), as these are fixed at compile time in the AI Hub bundle. Setting them will result in a PARAM_NOT_SUPPORTED error. Use max_tokens and enable_thinking within ModelConfig instead.
To generate text, first call applyChatTemplate to format the chat history, then pass the resulting formattedText to generateStreamFlow.
val paths = ModelManagerWrapper.getPaths("ai-hub-models/Qwen3-4B-Instruct-2507")
?: error("Model not downloaded")
LlmWrapper.builder()
.llmCreateInput(
LlmCreateInput(
model_name = paths.model_name,
model_path = paths.model_path,
config = ModelConfig(max_tokens = 2048, enable_thinking = false),
runtime_id = "qairt",
compute_unit = null, // null → NPU (only option for Qualcomm AI Engine Direct)
)
)
.build()
.onSuccess { llmWrapper = it }
.onFailure { println("Error: ${it.message}") }
val chat = arrayListOf(ChatMessage("user", "What is AI?"))
llmWrapper.applyChatTemplate(chat.toTypedArray(), null, false).onSuccess { t ->
llmWrapper.generateStreamFlow(t.formattedText, GenerationConfig()).collect { result ->
when (result) {
is LlmStreamResult.Token -> print(result.text)
is LlmStreamResult.Completed -> println("\nDone")
is LlmStreamResult.Error -> println("Error: ${result.throwable}")
}
}
}