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
|
||||
}
|
||||
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) {
|
||||
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
|
||||
|
||||
@@ -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]))
|
||||
}
|
||||
}
|
||||
|
||||
// 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