added correct reasoning token stats
This commit is contained in:
@@ -2848,3 +2848,77 @@ func TestToolsDir(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TestContextStatsCountReasoning verifies that reasoning tokens which are resent
|
||||
// as part of the context are counted in the context window statistics. The
|
||||
// provider may under-report prompt_tokens (omitting the reasoning_content we
|
||||
// echo back), so the statistics must never drop below a local estimate of the
|
||||
// messages we actually send, which includes the reasoning content.
|
||||
func TestContextStatsCountReasoning(t *testing.T) {
|
||||
msgs := []Message{
|
||||
{Role: "system", Content: strp("sys")},
|
||||
{Role: "user", Content: strp("question")},
|
||||
{Role: "assistant", Content: strp("answer"), ReasoningContent: "long chain of thought that consumes many tokens"},
|
||||
}
|
||||
// Local estimate of the context, including the reasoning content above.
|
||||
est := estTokens(msgs)
|
||||
if est <= estTokens([]Message{msgs[0], msgs[1], {Role: "assistant", Content: strp("answer")}}) {
|
||||
t.Fatalf("estTokens should grow when reasoning content is present (got %d)", est)
|
||||
}
|
||||
|
||||
// Simulate a provider that reports prompt_tokens WITHOUT the reasoning tokens.
|
||||
underReported := Usage{PromptTokens: est - 40, CompletionTokens: 10, ContextTokens: est}
|
||||
if got := ctxTokens(underReported); got != est {
|
||||
t.Errorf("ctxTokens = %d, want %d (reasoning must be counted)", got, est)
|
||||
}
|
||||
|
||||
// Simulate an accurate provider that already counts reasoning in prompt_tokens.
|
||||
accurate := Usage{PromptTokens: est, CompletionTokens: 10, ContextTokens: est}
|
||||
if got := ctxTokens(accurate); got != est {
|
||||
t.Errorf("ctxTokens = %d, want %d", got, est)
|
||||
}
|
||||
|
||||
// The displayed context numerator must reflect the reasoning-inclusive count.
|
||||
s := formatUsage(underReported, 200000)
|
||||
want := fmt.Sprintf("[%d prompt + 10 completion | context: %d/200000 (%.1f%%)]", underReported.PromptTokens, est, float64(est)*100.0/200000)
|
||||
if s != want {
|
||||
t.Errorf("formatUsage under-reported =\n %q\nwant\n %q", s, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestLLMContextTokensIncludesReasoning verifies that llm() populates
|
||||
// ContextTokens with a local estimate that includes any reasoning_content we
|
||||
// resend, even when the provider omits usage entirely (the fallback path).
|
||||
func TestLLMContextTokensIncludesReasoning(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// No usage block: forces the local-estimate fallback path.
|
||||
w.Write([]byte(`{"choices":[{"message":{"role":"assistant","content":"hi","reasoning_content":"think hard about this for a while"}}]}`))
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
cfg := defCfg
|
||||
cfg.Endpoint = srv.URL
|
||||
cfg.Stream = false
|
||||
msgs := []Message{
|
||||
{Role: "user", Content: strp("hi")},
|
||||
{Role: "assistant", Content: strp("prev"), ReasoningContent: "prior reasoning that is resent as context"},
|
||||
}
|
||||
m, u, err := llm(context.Background(), &cfg, msgs, TOOLS)
|
||||
if err != nil {
|
||||
t.Fatalf("llm: %v", err)
|
||||
}
|
||||
if m.ReasoningContent != "think hard about this for a while" {
|
||||
t.Errorf("reasoning not parsed: %q", m.ReasoningContent)
|
||||
}
|
||||
if u.ContextTokens <= 0 {
|
||||
t.Fatalf("ContextTokens not populated, got %d", u.ContextTokens)
|
||||
}
|
||||
// ContextTokens must include the resent reasoning content.
|
||||
withoutReasoning := estTokens([]Message{{Role: "user", Content: strp("hi")}, {Role: "assistant", Content: strp("prev")}})
|
||||
if u.ContextTokens <= withoutReasoning {
|
||||
t.Errorf("ContextTokens=%d should exceed estimate without reasoning=%d", u.ContextTokens, withoutReasoning)
|
||||
}
|
||||
if ctxTokens(u) != u.ContextTokens {
|
||||
t.Errorf("ctxTokens=%d should equal ContextTokens=%d when prompt_tokens is absent", ctxTokens(u), u.ContextTokens)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user