Stop the router repetition loop
Route now sets RepeatPenalty on the request, and the grammar's string rule is capped at 120 characters. Two of 76 fixture cases looped one sentence inside the text field until MaxTokens, which cut the JSON in half. Reviewers: the new constant and the grammar string rule. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CGeSZxh1DCtRxmFVSYVGvJ
This commit is contained in:
@@ -13,9 +13,35 @@ import (
|
||||
type mockLLM struct {
|
||||
out string
|
||||
err error
|
||||
got *llm.Req // last request, when the test wants to inspect it
|
||||
}
|
||||
|
||||
func (m mockLLM) Complete(_ context.Context, _ llm.Req) (string, error) { return m.out, m.err }
|
||||
func (m mockLLM) Complete(_ context.Context, r llm.Req) (string, error) {
|
||||
if m.got != nil {
|
||||
*m.got = r
|
||||
}
|
||||
return m.out, m.err
|
||||
}
|
||||
|
||||
// Without a repeat penalty the model loops inside the text field until MaxTokens
|
||||
// and the truncated JSON fails to parse.
|
||||
func TestLLMRouterSetsRepeatPenalty(t *testing.T) {
|
||||
var got llm.Req
|
||||
lr := NewLLMRouter(mockLLM{out: `{"intent":"chat","text":"привет"}`, got: &got})
|
||||
if _, _, err := lr.Route(context.Background(), "привет", time.Now()); err != nil {
|
||||
t.Fatalf("route: %v", err)
|
||||
}
|
||||
if got.RepeatPenalty <= 1 {
|
||||
t.Fatalf("want repeat penalty above 1, got %v", got.RepeatPenalty)
|
||||
}
|
||||
}
|
||||
|
||||
// An unbounded string rule lets one field eat the whole token budget.
|
||||
func TestRouteGrammarBoundsStrings(t *testing.T) {
|
||||
if !strings.Contains(routeGrammar, `string ::= "\"" ([^"\\] | "\\" .){0,120} "\""`) {
|
||||
t.Fatal("grammar string rule lost its length bound")
|
||||
}
|
||||
}
|
||||
|
||||
// A question naming a fact key used to be stored as a fact because the fact rule
|
||||
// was tested first. Keep the query rule above it.
|
||||
|
||||
Reference in New Issue
Block a user