mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-11 17:26:57 +02:00
Repris d'AJEAN 0.17.5. Sur une fenêtre de 65k, un tour qui lit plusieurs gros fichiers d'un coup passait de 60 % à plus de 130 % sans jamais compacter, et l'erreur remontait telle quelle. - Le test de compactage en cours de tour compte aussi les résultats d'outils de l'étape, que le moteur n'a pas encore vus. Sans usage côté serveur, l'estimation porte toujours sur tout l'historique. - Tout résultat d'outil est borné à 30 000 caractères dans la vue du modèle, avec une mention qui l'invite à cibler. L'interface garde le résultat complet (« voir plus »). - Dernier recours quand le moteur refuse encore le prompt et que le compactage n'a rien pu faire : shrinkToFit tronque les gros résultats d'outils puis retire les plus vieux échanges, vers 60 % de la fenêtre corrigés par la taille réelle lue dans l'erreur. Deux essais au plus. - Tâches planifiées : la note de tâche passe en tête du message utilisateur au lieu du système. Le préfixe reste celui du chat et le cache de prompt de llama-server sert aux deux (l'amont mesurait 12 s de recalcul pour un « salut » après une tâche). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
70 lines
2.4 KiB
Go
70 lines
2.4 KiB
Go
package loki
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// Le compactage de secours ne doit se déclencher que sur un vrai débordement de
|
|
// contexte, pas sur n'importe quel refus du moteur.
|
|
func TestContextOverflow(t *testing.T) {
|
|
small := []Message{{Role: "user", Content: "salut"}}
|
|
yes := []string{
|
|
`{"error":{"code":400,"message":"request (70000 tokens) exceeds the available context size (65536 tokens), try increasing it","type":"exceed_context_size_error"}}`,
|
|
`{"error":{"message":"This model's maximum context length is 8192 tokens","code":"context_length_exceeded"}}`,
|
|
}
|
|
no := []string{
|
|
`{"error":{"code":500,"message":"Failed to parse tool call arguments as JSON","type":"server_error"}}`,
|
|
`{"error":{"code":503,"message":"Loading model","type":"unavailable_error"}}`,
|
|
`Unable to generate parser for this template`,
|
|
}
|
|
for _, m := range yes {
|
|
if !contextOverflow(m, small) {
|
|
t.Errorf("débordement non reconnu : %s", m)
|
|
}
|
|
}
|
|
for _, m := range no {
|
|
if contextOverflow(m, small) {
|
|
t.Errorf("faux débordement (déclencherait un compactage) : %s", m)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Le dernier recours ramène sous la fenêtre même quand tout est dans un seul
|
|
// tour (AJEAN 0.17.5).
|
|
func TestShrinkToFit(t *testing.T) {
|
|
testHome(t)
|
|
big := strings.Repeat("x", 200000)
|
|
msgs := []Message{
|
|
{Role: "system", Content: "ctx"},
|
|
{Role: "user", Content: "vieux"},
|
|
{Role: "assistant", Content: "ok"},
|
|
{Role: "user", Content: "lis tout"},
|
|
{Role: "assistant", Content: "", ToolCalls: []ToolCall{{ID: "a"}}},
|
|
{Role: "tool", ToolCallID: "a", Content: big},
|
|
{Role: "tool", ToolCallID: "b", Content: big},
|
|
}
|
|
out, changed := shrinkToFit(msgs, 132291)
|
|
if !changed || out[0].Role != "system" {
|
|
t.Fatalf("pas réduit : %v", changed)
|
|
}
|
|
if est := estimateTokens(out); est > int(float64(ctxWindow())*0.6) {
|
|
t.Fatalf("encore trop gros : %d", est)
|
|
}
|
|
if overflowTokens(`{"message":"request (132291 tokens) exceeds"}`) != 132291 {
|
|
t.Fatal("taille réelle non lue")
|
|
}
|
|
}
|
|
|
|
// Un résultat d'outil géant est borné pour le modèle, avec une mention qui dit
|
|
// au modèle de cibler plus précisément.
|
|
func TestCapToolResult(t *testing.T) {
|
|
if got := capToolResult("court"); got != "court" {
|
|
t.Fatalf("résultat court modifié : %q", got)
|
|
}
|
|
got := capToolResult(strings.Repeat("é", toolResultMax+500))
|
|
if r := []rune(got); len(r) > toolResultMax+200 || !strings.Contains(got, "tronqué") {
|
|
t.Fatalf("résultat géant mal borné (%d runes)", len(r))
|
|
}
|
|
}
|