mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-23 06:58:14 +02:00
Bench : une mesure honnête à profondeur réelle, en tâche de fond
L'ancien bench ne lisait pas le statut HTTP, inventait un partage 15/85 du temps quand les timings manquaient (et l'enregistrait comme mesuré), tuilait un petit corpus qu'un brouillon recopiait, et ne disait rien du prefill à 30k ni du chemin où le cache est repris. Synchrone, il était coupé par les proxys (60-100 s) pendant que le moteur continuait, et un simple GET suffisait à le lancer. - Tâche de fond : POST /api/bench (202, 405 sur GET, 409 si occupé), /api/bench/status pour la progression, /api/bench/cancel ; chaque requête au moteur porte le contexte annulable. - Verrou de génération tenu pendant toute la mesure : chat, tâches et compaction reçoivent un refus clair ; les clients /v1 un 503 avec Retry-After ; /slots occupé (client externe, CLI) refuse aussi. - Mode rapide par défaut : préchauffage jeté + la ligne courte, sur le chat avec gabarit, raisonnement et échantillonnage du preset, seed fixe. - Mode complet (bouton « bench complet », loki bench --full) : prefill à froid à D = min(CTX/2, 32k, ce qui laisse tenir les tours), 16k si des poids tournent sur CPU, puis 3 tours user → assistant → user de code jamais vu. Reprise du cache lue dans cache_n, jamais supposée ; note pour les hybrides (points de contrôle). Pas d'ignore_eos. - Rien n'est enregistré sans réponses 200 et timings réels, ni pour un résultat partiel (budget de 6 min par requête, contexte plein). - Empreinte enregistrée (configuration + CUDA_VISIBLE_DEVICES + protocole) ; les anciennes mesures retombent sur le nom du modèle. Types de cache KV et build du moteur affichés, KV quantifié signalé (zone grise). - Linux : indication « possible thrash » (read_bytes, VmRSS), jamais enregistrée. - Effacement du slot en fin de bench inchangé (engineSideJob, différé : il tourne aussi sur erreur et annulation). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9f6bd725e6
commit
cf83f5f629
17 files changed
+1904
-245
No files matched your search
@@ -77,6 +77,9 @@ type Conversation struct {
|
||||
// à une génération fantôme dans la discussion ouverte.
|
||||
runningTaskID string
|
||||
runningTaskName string
|
||||
// benching : le verrou est tenu par un benchmark (llm_bench_job.go). Même
|
||||
// logique que la tâche : l'interface et les refus disent qui occupe le moteur.
|
||||
benching bool
|
||||
|
||||
// File d'attente des messages envoyés PENDANT une génération (AJEAN
|
||||
// 0.14.0). Ils sont injectés dans le tour en cours à la prochaine frontière
|
||||
@@ -443,8 +446,11 @@ var ErrBusy = fmt.Errorf("génération en cours")
|
||||
// nomme la tâche et on dit comment reprendre la main.
|
||||
func (c *Conversation) busyReason() error {
|
||||
c.mu.Lock()
|
||||
name := c.runningTaskName
|
||||
name, bench := c.runningTaskName, c.benching
|
||||
c.mu.Unlock()
|
||||
if bench {
|
||||
return errBenchBusy
|
||||
}
|
||||
if name == "" {
|
||||
return ErrBusy
|
||||
}
|
||||
@@ -550,8 +556,8 @@ func (c *Conversation) seenCIDLocked(cid string) bool {
|
||||
// EnqueueOrStart démarre un tour tout de suite si le moteur est libre, sinon
|
||||
// MET EN FILE le message (AJEAN 0.14.0) — au lieu du 409 d'avant, qui obligeait
|
||||
// à arrêter la réponse pour ajouter une précision. Seul un tour de CHAT accepte
|
||||
// une file : une tâche planifiée qui occupe le modèle garde le refus
|
||||
// (busyReason), sa fin ne dépile rien. cid = identifiant de l'envoi (voir
|
||||
// une file : une tâche planifiée ou un benchmark qui occupe le modèle garde le
|
||||
// refus (busyReason), sa fin ne dépile rien. cid = identifiant de l'envoi (voir
|
||||
// recentCIDs) ; un doublon renvoie ErrDupSend.
|
||||
func (c *Conversation) EnqueueOrStart(cid, text string, files []attachInfo, caps Caps, temperature float64) (bool, error) {
|
||||
c.mu.Lock()
|
||||
@@ -559,7 +565,7 @@ func (c *Conversation) EnqueueOrStart(cid, text string, files []attachInfo, caps
|
||||
c.mu.Unlock()
|
||||
return false, ErrDupSend
|
||||
}
|
||||
if c.Generating && c.runningTaskName == "" {
|
||||
if c.Generating && c.runningTaskName == "" && !c.benching {
|
||||
c.queued = append(c.queued, queuedMsg{text: text, files: files, caps: caps, temp: temperature})
|
||||
c.mu.Unlock()
|
||||
return true, nil
|
||||
@@ -571,7 +577,7 @@ func (c *Conversation) EnqueueOrStart(cid, text string, files []attachInfo, caps
|
||||
// appareils qui envoient en même temps) : en file plutôt qu'un refus
|
||||
// (AJEAN 0.17.4). Une tâche planifiée garde le refus : sa fin ne dépile rien.
|
||||
c.mu.Lock()
|
||||
if c.Generating && c.runningTaskName == "" {
|
||||
if c.Generating && c.runningTaskName == "" && !c.benching {
|
||||
c.queued = append(c.queued, queuedMsg{text: text, files: files, caps: caps, temp: temperature})
|
||||
c.mu.Unlock()
|
||||
// Ce tour a pu finir entre-temps : sans relance, le message attendrait
|
||||
|
||||
Reference in new issue
Block a user