49 lines
2.2 KiB
Kotlin
49 lines
2.2 KiB
Kotlin
package com.kazeia.llm
|
|
// Remplace ExecuTorchLlmEngine. Option C: prefill HTP / decode CPU (géré côté natif).
|
|
// Mono-tour: generate(sys, usr). Multi-tour: ChatSession (gère l'historique + le template ChatML).
|
|
|
|
class EngineJni {
|
|
external fun load(ggufPath: String, nCtx: Int): Long
|
|
external fun generate(h: Long, sys: String, usr: String, maxTok: Int): String
|
|
external fun generateRaw(h: Long, prompt: String, maxTok: Int): String // prompt complet déjà formaté
|
|
external fun reset(h: Long)
|
|
external fun free(h: Long)
|
|
companion object { init { System.loadLibrary("kazeia_engine") } }
|
|
}
|
|
|
|
class EngineLlmEngine(model: String, ctx: Int = 4096) {
|
|
private val jni = EngineJni()
|
|
private val h = jni.load(model, ctx)
|
|
init { require(h != 0L) { "Kazeia-Engine: échec du chargement du modèle ($model)" } }
|
|
|
|
// Mono-tour : system + un message user.
|
|
fun generate(sys: String, usr: String, max: Int = 96) = jni.generate(h, sys, usr, max)
|
|
// Multi-tour : prompt complet pré-formaté (voir ChatSession).
|
|
fun generateRaw(prompt: String, max: Int = 96) = jni.generateRaw(h, prompt, max)
|
|
|
|
fun newChat(system: String) = ChatSession(this, system)
|
|
fun reset() = jni.reset(h)
|
|
fun release() = jni.free(h)
|
|
}
|
|
|
|
// Conversation multi-tour : accumule l'historique et construit le ChatML Qwen3.5 + thinking-off.
|
|
// Structure identique à celle validée (jni/dual_ctx_mt.cpp) : mémoire conversationnelle correcte.
|
|
class ChatSession(private val engine: EngineLlmEngine, private val system: String) {
|
|
private val turns = StringBuilder() // "<|im_start|>role\ntext<|im_end|>\n" accumulés
|
|
|
|
fun ask(user: String, max: Int = 96): String {
|
|
val prompt = buildString {
|
|
append("<|im_start|>system\n").append(system).append("<|im_end|>\n")
|
|
append(turns)
|
|
append("<|im_start|>user\n").append(user).append("<|im_end|>\n")
|
|
append("<|im_start|>assistant\n<think>\n\n</think>\n\n") // thinking OFF déterministe
|
|
}
|
|
val resp = engine.generateRaw(prompt, max)
|
|
turns.append("<|im_start|>user\n").append(user).append("<|im_end|>\n")
|
|
.append("<|im_start|>assistant\n").append(resp).append("<|im_end|>\n")
|
|
return resp
|
|
}
|
|
|
|
fun clear() { turns.setLength(0) }
|
|
}
|