mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-19 21:18:20 +02:00
Lot 23 : sonde de gabarit en Rust (avec LOKI_CHAT=rust)
Port de chat_tplprobe.go : la façade sonde le gabarit du moteur après ses complétions (/health, /props, /apply-template), avec les verdicts preserves_history, prefix_stable et renders_reasoning, le cache par build/modèle/gabarit/forme et la relance bornée. - l'écho du raisonnement suit le verdict de la sonde (echo_policy_for) ; - NUDGE_IN_TOOL ne garde plus la conversation au Go : le rappel de budget va dans le dernier résultat d'outil quand le préfixe n'est pas stable ; - le Go lit le verdict de la façade (/internal/facade/v1/chat/tpl) quand elle tient la conversation. Parité : parity_tplprobe_test.go tire du Go un journal d'échanges rejoué octet pour octet par tests/tplprobe.rs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
This commit is contained in:
17 files changed
+5006
-22
No files matched your search
@@ -298,7 +298,7 @@ func TestFacadeReglageQuiGardeLaConversation(t *testing.T) {
|
||||
t.Fatalf("remis à la façade malgré le réglage : %q %v", rec.Body.String(), f.recu())
|
||||
}
|
||||
for k, want := range map[string]string{
|
||||
"PROJ_SNAPSHOT": "PROJ_SNAPSHOT", "NUDGE_IN_TOOL": "NUDGE_IN_TOOL", "SIDE_SLOT": "SIDE_SLOT",
|
||||
"PROJ_SNAPSHOT": "PROJ_SNAPSHOT", "NUDGE_IN_TOOL": "", "SIDE_SLOT": "SIDE_SLOT",
|
||||
"SLOT_PERSIST": "SLOT_PERSIST", "PREWARM": "PREWARM",
|
||||
} {
|
||||
if got := facadeChatBlocker(map[string]string{k: "on"}); got != want {
|
||||
@@ -1064,3 +1064,41 @@ func TestFacadeBackends(t *testing.T) {
|
||||
}
|
||||
lcAppend("perdue") // tracée, sans panique
|
||||
}
|
||||
|
||||
// Lot 23 : quand la façade tient la conversation, c'est elle qui sonde le
|
||||
// gabarit ; le résumé des performances relit son verdict.
|
||||
func TestFacadeSondeDeGabarit(t *testing.T) {
|
||||
testHome(t)
|
||||
freshTplProbe(t)
|
||||
oublierDecisionFacade(t)
|
||||
verdict := `{"ok":true,"result":{"preserves_history":"no","prefix_stable":"no","renders_reasoning":"yes","model":"m1.gguf","tools":2,"at":"2026-10-15T20:00:00.5Z"}}`
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get(internalTokenHeader) != jetonTest || r.URL.Path != "/internal/facade/v1/chat/tpl" {
|
||||
w.WriteHeader(404)
|
||||
return
|
||||
}
|
||||
io.WriteString(w, verdict)
|
||||
}))
|
||||
defer srv.Close()
|
||||
t.Setenv(internalTokenEnv, jetonTest)
|
||||
t.Setenv(facadeAddrEnv, strings.TrimPrefix(srv.URL, "http://"))
|
||||
t.Setenv(facadeChatEnv, "rust")
|
||||
r, ok := tplCapsCurrent()
|
||||
if !ok || r.PrefixStable != tplNo || r.Model != "m1.gguf" || r.Tools != 2 || r.At.IsZero() {
|
||||
t.Fatalf("verdict de la façade : %+v %v", r, ok)
|
||||
}
|
||||
rec := httptest.NewRecorder()
|
||||
handlePerfSummary(rec, httptest.NewRequest(http.MethodGet, "/api/perf/summary", nil))
|
||||
if !strings.Contains(rec.Body.String(), `"prefix_stable":"no"`) {
|
||||
t.Fatalf("résumé : %s", rec.Body.String())
|
||||
}
|
||||
// Aucun verdict encore, ou façade injoignable : rien.
|
||||
verdict = `{"ok":false}`
|
||||
if _, ok := tplCapsCurrent(); ok {
|
||||
t.Fatal("verdict inventé")
|
||||
}
|
||||
t.Setenv(facadeAddrEnv, "127.0.0.1:1")
|
||||
if _, ok := tplCapsCurrent(); ok {
|
||||
t.Fatal("verdict sans façade")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user