mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-11 17:26:57 +02:00
Raisonnement : corrections de relecture du lot 2 — un refus de gabarit reconnu sans faux positif
Avec REASONING_ECHO, tout 400/500 dont le corps contenait « thinking » passait pour un refus du raisonnement renvoyé, et ce test passe avant le filet des outils. Une erreur d'analyse d'appel d'outil cite le texte du modèle : s'il y écrivait « thinking », le tour était rejoué sans raisonnement et, si la relance passait par chance, la clé était coupée pour ce modèle jusqu'au redémarrage. - « Failed to parse input … » (appel d'outil mal formé) n'est jamais un refus du gabarit : le filet des outils s'en charge, comme sans la clé. - « thinking » ne compte que dans une erreur du gabarit (jinja, template) ; raise_exception et les messages invalides restent reconnus. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5f00b6f041
commit
568f344273
2 files changed
+32
-2
No files matched your search
@@ -244,12 +244,20 @@ func echoTemplateError(status int, body string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
low := strings.ToLower(body)
|
low := strings.ToLower(body)
|
||||||
for _, k := range []string{"raise_exception", "thinking", "expected 'content' or 'tool_calls'", "failed to parse messages"} {
|
// Appel d'outil mal formé (« Failed to parse input at pos N: … ») : le
|
||||||
|
// texte du modèle y est cité, il peut dire « thinking » sans que le gabarit
|
||||||
|
// y soit pour rien. Le filet des outils s'en charge, pas celui-ci — sinon
|
||||||
|
// une relance chanceuse ferait couper la clé pour ce modèle à tort.
|
||||||
|
if strings.Contains(low, "failed to parse input") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, k := range []string{"raise_exception", "expected 'content' or 'tool_calls'", "failed to parse messages"} {
|
||||||
if strings.Contains(low, k) {
|
if strings.Contains(low, k) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
// « thinking » seul ne dit rien : seulement dans une erreur du gabarit.
|
||||||
|
return strings.Contains(low, "thinking") && (strings.Contains(low, "jinja") || strings.Contains(low, "template"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReasoningEcho : raisonnement séparé de la complétion qui porte la réponse
|
// ReasoningEcho : raisonnement séparé de la complétion qui porte la réponse
|
||||||
|
|||||||
@@ -594,3 +594,25 @@ func TestBuilderAppliqueNewHistory(t *testing.T) {
|
|||||||
t.Fatalf("consigne présente %d fois, dernier message %q", fix, msgText(c.Messages[len(c.Messages)-1]))
|
t.Fatalf("consigne présente %d fois, dernier message %q", fix, msgText(c.Messages[len(c.Messages)-1]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Corrections de relecture du lot 2 : un refus de gabarit est reconnu, une
|
||||||
|
// erreur d'analyse d'appel d'outil qui cite le mot « thinking » ne l'est pas.
|
||||||
|
func TestEchoTemplateErrorEtroit(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
status int
|
||||||
|
body string
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{500, `{"error":{"message":"Jinja Exception: raise_exception('Cannot pass both content and thinking')"}}`, true},
|
||||||
|
{500, `{"error":{"message":"Error in template: thinking blocks not allowed here"}}`, true},
|
||||||
|
{400, `{"error":{"message":"Expected 'content' or 'tool_calls'"}}`, true},
|
||||||
|
{500, `{"error":{"message":"Failed to parse input at pos 12: <tool_call>{\"thinking\": 1}"}}`, false},
|
||||||
|
{500, `{"error":{"message":"the model kept thinking forever"}}`, false},
|
||||||
|
{502, `{"error":{"message":"raise_exception"}}`, false},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
if got := echoTemplateError(c.status, c.body); got != c.want {
|
||||||
|
t.Errorf("%d %s : %v", c.status, c.body, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user