94 lines
4.1 KiB
Markdown
94 lines
4.1 KiB
Markdown
# Spec — API d'échantillonnage natif (kazeia-engine) pour les presets Kazeia
|
|
|
|
**Date** : 2026-06-18
|
|
**Demandeur** : app Kazeia (refonte presets admin)
|
|
**Cible** : `kazeia-engine` (lib `libkazeia_engine`, JNI `EngineJni`)
|
|
|
|
## Contexte
|
|
|
|
L'app admin permet désormais de régler, par modèle (Speaker / Thinker) et via des
|
|
**presets** nommés, les paramètres d'échantillonnage : `temperature`, `top_p`,
|
|
`top_k`, `repeat_penalty`, `presence_penalty`, `frequency_penalty`, `max_tokens`.
|
|
|
|
Côté app, ces valeurs sont **persistées et transmises** jusqu'au pont JNI
|
|
(`UnifiedLlmAdapter` → `EngineLlmEngine`/`LlmSession`). **MAIS le JNI actuel
|
|
n'expose que `maxTok`** :
|
|
|
|
```kotlin
|
|
external fun generate(h: Long, sys: String, usr: String, maxTok: Int): String
|
|
external fun sessionAsk(h: Long, usr: String, maxTok: Int, cb: TokenCallback)
|
|
external fun generateStream(h: Long, sys: String, usr: String, maxTok: Int, cb: TokenCallback)
|
|
```
|
|
|
|
Donc aujourd'hui **seul `max_tokens` agit** ; température/top-p/k/pénalités sont
|
|
inertes (l'app l'indique honnêtement dans l'UI : « effectif après MAJ moteur »).
|
|
|
|
## Demande — exposer le sampling au JNI
|
|
|
|
Ajouter une **variante échantillonnée** des entrées de génération (sans casser les
|
|
signatures existantes), qui prend une struct de sampling et la câble sur la chaîne
|
|
de samplers llama.cpp. Le GGUF Qwen3.5-4B (Speaker par défaut) est la cible
|
|
prioritaire.
|
|
|
|
### Signatures proposées
|
|
|
|
```kotlin
|
|
// Struct portée côté natif (ou 7 args primitifs si plus simple en JNI) :
|
|
// temperature: Float, topP: Float, topK: Int,
|
|
// repeatPenalty: Float, presencePenalty: Float, frequencyPenalty: Float, maxTokens: Int
|
|
external fun generateSampled(
|
|
h: Long, sys: String, usr: String,
|
|
maxTokens: Int, temperature: Float, topP: Float, topK: Int,
|
|
repeatPenalty: Float, presencePenalty: Float, frequencyPenalty: Float,
|
|
cb: TokenCallback
|
|
)
|
|
external fun sessionAskSampled(
|
|
h: Long, usr: String,
|
|
maxTokens: Int, temperature: Float, topP: Float, topK: Int,
|
|
repeatPenalty: Float, presencePenalty: Float, frequencyPenalty: Float,
|
|
cb: TokenCallback
|
|
)
|
|
```
|
|
|
|
### Mapping llama.cpp (sampler chain)
|
|
|
|
Construire la chaîne par requête (ou réutiliser un `llama_sampler` reconfiguré) :
|
|
|
|
```c
|
|
auto * chain = llama_sampler_chain_init(llama_sampler_chain_default_params());
|
|
llama_sampler_chain_add(chain, llama_sampler_init_top_k(top_k));
|
|
llama_sampler_chain_add(chain, llama_sampler_init_top_p(top_p, 1));
|
|
llama_sampler_chain_add(chain, llama_sampler_init_penalties(
|
|
/*penalty_last_n*/ 64, repeat_penalty, frequency_penalty, presence_penalty));
|
|
llama_sampler_chain_add(chain, llama_sampler_init_temp(temperature));
|
|
llama_sampler_chain_add(chain, llama_sampler_init_dist(/*seed*/ LLAMA_DEFAULT_SEED));
|
|
```
|
|
|
|
- `temperature <= 0` ⇒ greedy (`llama_sampler_init_greedy`), ignorer les autres.
|
|
- Conserver le **thinking-off** et le template ChatML actuels inchangés.
|
|
- `presence/frequency_penalty = 0` ⇒ no-op (comportement neutre).
|
|
|
|
### Comportement attendu
|
|
|
|
- Valeurs de référence (preset « Kaz chaleureux ») : temp 0.4, top_p 0.85, top_k 40,
|
|
repeat 1.05, presence 0.2, frequency 0.2, max 256 — doit produire des sorties
|
|
visiblement moins répétitives / plus chaleureuses que le greedy actuel.
|
|
- Déterminisme : exposer un `seed` optionnel plus tard si besoin (pas requis v1).
|
|
|
|
### `.pte` (NPU) — hors scope v1
|
|
|
|
Le runner ExecuTorch `.pte` décode **greedy**. Le sampling y est une évolution
|
|
distincte (échantillonnage post-logits côté runner). Pour l'instant les presets
|
|
n'affectent que le chemin GGUF ; documenter la limite suffit.
|
|
|
|
## Côté app — déjà prêt
|
|
|
|
- `SamplingParams` (com.kazeia.core) porte les 7 knobs.
|
|
- `UnifiedLlmAdapter.generateWithSystem` reçoit les params ; il suffira de router
|
|
vers `*Sampled` au lieu de `ask(max)` / `generateStream(max)` quand le JNI existe.
|
|
- `ConfigStore.ModelConfig` + presets persistent les valeurs ; l'admin les édite.
|
|
|
|
Quand le JNI échantillonné est livré : ~10 lignes à changer côté `UnifiedLlmAdapter`
|
|
(brancher `sessionAskSampled` / `generateSampled`) et retirer la mention
|
|
« effectif après MAJ moteur » de l'UI admin.
|