mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-23 23:18:13 +02:00
Rebaptise AJEAN en Loki (fork, lignée conservée)
- module github.com/R0m1k3/Loki, cmd/loki, internal/loki (package loki) - LOKI_HOME, LOKI_MODEL_DIRS, LOKI_SERVICE, LOKI_DL_CONNS ; /etc/loki ; units loki-engine / loki-ui ; binaire et aide CLI - updateRepo pointe sur R0m1k3/Loki (l'auto-update ne tirera plus les binaires AJEAN amont) Conservé à l'identique : le domaine ajean.link (service de tunnel amont), les littéraux de migration 0.7.x (migrate_07.go), RELEASE_NOTES.md et LICENSE (historique et licence de l'amont). go build/vet/test : verts.
This commit is contained in:
157 files changed
+928
-928
No files matched your search
@@ -0,0 +1,65 @@
|
||||
package loki
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Budget du préambule envoyé À CHAQUE TOUR : prompt système + schémas des outils.
|
||||
// Il est payé sur toute la conversation et sort du contexte utile.
|
||||
//
|
||||
// Ce test existe pour empêcher le regonflement. Le prompt a déjà été raccourci
|
||||
// une fois pour une raison de comportement (un préambule verbeux fait
|
||||
// sur-raisonner les modèles à reasoning, qui finissent leur tour sans appeler
|
||||
// d'outil), puis une seconde fois pour le coût. Les deux fois, il avait
|
||||
// regrossi ligne par ligne, chacune paraissant anodine.
|
||||
//
|
||||
// Approximation 1 tok ≈ 4 caractères : suffisante pour une alerte, et sans
|
||||
// dépendance à un tokenizer.
|
||||
const promptCharBudget = 7500 // ~1875 tokens, tout allumé
|
||||
|
||||
func TestSystemPromptStaysLean(t *testing.T) {
|
||||
caps := Caps{Agent: true, Internet: true, Mem: MemAlways}
|
||||
sp := baseSystemPrompt(caps)
|
||||
tb, err := json.Marshal(EnabledTools(caps))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
total := len(sp) + len(tb)
|
||||
t.Logf("prompt %d car (~%d tok) + outils %d car (~%d tok) = ~%d tok",
|
||||
len(sp), len(sp)/4, len(tb), len(tb)/4, total/4)
|
||||
if total > promptCharBudget {
|
||||
t.Fatalf("préambule à %d car (~%d tok), budget %d car (~%d tok).\n"+
|
||||
"Avant de relever le budget : les schémas d'outils pèsent le double du prompt,\n"+
|
||||
"et une consigne écrite dans un schéma n'a pas à être répétée dans le prompt.",
|
||||
total, total/4, promptCharBudget, promptCharBudget/4)
|
||||
}
|
||||
}
|
||||
|
||||
// Le prompt ne doit pas redevenir un catalogue d'outils : leurs schémas partent
|
||||
// dans la MÊME requête et les décrivent déjà un par un.
|
||||
func TestSystemPromptDoesNotRelistTools(t *testing.T) {
|
||||
sp := baseSystemPrompt(Caps{Agent: true, Internet: true, Mem: MemAlways})
|
||||
for _, line := range strings.Split(sp, "\n") {
|
||||
l := strings.TrimSpace(line)
|
||||
if !strings.HasPrefix(l, "- ") {
|
||||
continue
|
||||
}
|
||||
// Une puce qui commence par un nom d'outil = un catalogue qui revient.
|
||||
for _, tool := range []string{"bash ", "write ", "edit ", "mem_", "web_"} {
|
||||
if strings.HasPrefix(l[2:], tool) {
|
||||
t.Fatalf("le prompt réénumère un outil : %q", l)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sans agent ni mémoire, aucun préambule : un modèle de chat simple à qui on
|
||||
// ordonne d'appeler des outils invente des appels textuels qui fuient dans la
|
||||
// réponse.
|
||||
func TestSystemPromptEmptyWithoutTools(t *testing.T) {
|
||||
if sp := baseSystemPrompt(Caps{Mem: MemOff}); sp != "" {
|
||||
t.Fatalf("préambule non vide sans outils : %q", sp)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user