mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-22 06:28:11 +02:00
Slots : SIDE_SLOT ouvre un second slot pour les travaux annexes, en opt-in
En --parallel 1, une vérification, un sous-agent, une tâche ou un bench prennent le slot de la discussion : son état part dans le cache RAM et en revient, ou se recalcule s'il n'y tient plus. Avec SIDE_SLOT=on (off par défaut), le moteur ouvre deux slots et la discussion garde le sien. Dimensionnement choisi pour qu'un débordement concurrent soit impossible par construction : cache KV NON unifié (--no-kv-unified) et -c 2×CTX, soit deux flux séparés de CTX jetons. Sous cache unifié, les deux slots partagent le pool et, plein, llama.cpp renvoie « Context size has been exceeded. » aux deux — que Loki prenait pour un débordement de la conversation. Chaque slot garde la fenêtre entière : ctxWindow et la compaction restent sur CTX, rien n'est raccourci. --cache-idle-slots ne vide les slots au repos que sous cache unifié : rien à régler. - lancement : refus (un slot, ligne d'avant, note au journal) si modèle + deux états dépassent 90 % de la VRAM, VRAM ou GGUF inconnus, poids sur CPU, moteur sans --no-kv-unified, PARALLEL≠2, ou -c/-np/-kvu/--no-kv-unified/ --kv-unified-per-slot/--cache-idle-slots dans EXTRA_ARGS (ou leurs LLAMA_ARG_*) ; note de VRAM en plus, avertissement si NGL imposé - routage id_slot seulement si /props annonce 2 slots d'au moins CTX jetons : 0 pour le tour, ses étapes, le préchauffage et le résumé en continuation ; 1 pour vérification, sous-agents, tâches, bench, résumé sur transcription - clients /v1 (proxy et relais) : corps réécrit en id_slot 1, quel qu'il soit - cohérence lot 1 : l'effacement de slot s'abstient (2 slots) ; une requête du slot 1 n'avance pas le numéro d'engineSlotHolds, la continuation de compaction reste possible après une vérification - « Context size has been exceeded. » sans nombre de jetons, deux slots en service : requête rejouée telle quelle, jamais compaction ni réduction - préchauffage permis sur les deux slots de SIDE_SLOT, vers le slot 0 - éditeur de preset : VRAM du second slot ou raison du refus - tests : ligne identique sans la clé, chaque conflit refuse sans changer la ligne, routage par nature, aucun id_slot sur un slot / preset externe / fenêtre partagée, rejeu sans compaction, proxy forcé, préchauffage Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c1d3757f23
commit
7a57322a62
18 files changed
+927
-16
No files matched your search
@@ -1312,6 +1312,8 @@ func runChatLoop(ctx context.Context, kt *keepImages, messages []Message, tools
|
||||
compactedRetry := false
|
||||
// Réductions forcées (shrinkToFit) quand le compactage n'a pas suffi.
|
||||
shrinkRetries := 0
|
||||
// Rejeux à l'identique après un cache KV plein en plein calcul (SIDE_SLOT).
|
||||
poolRetries := 0
|
||||
// Repli d'intensité de raisonnement (llm_effort.go) : une seule tentative par
|
||||
// tour, comme les autres filets.
|
||||
effortRetried := false
|
||||
@@ -1430,6 +1432,9 @@ func runChatLoop(ctx context.Context, kt *keepImages, messages []Message, tools
|
||||
tools: tools, disableTools: disableTools, toolChoiceNone: toolChoiceNone,
|
||||
effort: reasoningEffort, kwargs: reasoningKwargs,
|
||||
})
|
||||
// SIDE_SLOT (llm_sideslot.go) : le fil de la discussion sur le slot 0,
|
||||
// le reste sur le 1. Sans second slot en service, aucun id_slot.
|
||||
setEngineSlot(payload, engineSlotFor(ep, slotIsMain(ptag.kind)))
|
||||
body, _ := json.Marshal(payload)
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", ep.URL, bytes.NewReader(body))
|
||||
if err != nil {
|
||||
@@ -1450,7 +1455,7 @@ func runChatLoop(ctx context.Context, kt *keepImages, messages []Message, tools
|
||||
endReq := func() {}
|
||||
var reqSeq uint64
|
||||
if !ep.External {
|
||||
endReq, reqSeq = engineRequestBegin(prewarmKeeper(ptag.kind, sent, payload))
|
||||
endReq, reqSeq = engineRequestBeginSide(prewarmKeeper(ptag.kind, sent, payload), payloadOnSideSlot(payload))
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
@@ -1501,6 +1506,24 @@ func runChatLoop(ctx context.Context, kt *keepImages, messages []Message, tools
|
||||
continue
|
||||
}
|
||||
}
|
||||
// SIDE_SLOT : un cache KV à court de place en plein calcul n'est pas un
|
||||
// prompt trop long (llm_sideslot.go). Rejouée telle quelle, sans
|
||||
// compaction ni réduction — deux fois au plus, le temps que l'autre
|
||||
// slot finisse, puis l'erreur telle quelle : la conversation tenait
|
||||
// dans sa fenêtre, rien ne justifie d'en perdre un morceau. Sans
|
||||
// second slot en service, ce filet ne joue pas.
|
||||
if !ep.External && sideSlotPoolError(msg) && sideSlotLive(ep) {
|
||||
if poolRetries < 2 {
|
||||
poolRetries++
|
||||
logCtx("cache KV plein pendant le calcul (deux slots) : requête rejouée telle quelle, sans compaction")
|
||||
if werr := llmNetBackoff(ctx, poolRetries-1); werr == nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
err := fmt.Errorf("llama-server a renvoyé %d : %s", resp.StatusCode, msg)
|
||||
cb(StreamEvent{Err: err})
|
||||
return extra, err
|
||||
}
|
||||
// Gabarit qui refuse le raisonnement renvoyé (gpt-oss : « Cannot pass
|
||||
// both content and thinking », message assistant jugé invalide…) :
|
||||
// rejoué UNE fois sans lui, AVANT la coupure des outils et la consigne
|
||||
|
||||
Reference in new issue
Block a user