mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-20 15:33:54 +00:00
fix(insights): include auxiliary usage in overview token totals (#65603)
The overview's total_input/output/cache token counts summed only the sessions counters (main-loop usage), while the per-model breakdown already included auxiliary usage rows (task dimension from #65537) and reconciled residuals. Result: hermes insights top-line totals undercounted aux spend (compression summarizer, vision, titles) and disagreed with the per-model table below them — the symptom reported in #58592 and requested in #9979. When the per-model breakdown is available, derive the overview token totals from it (same pattern total_cost already used). Verified no double-count across incremental CLI deltas, gateway absolute overwrites, and aux rows.
This commit is contained in:
parent
07e537d8ea
commit
21dedb8586
2 changed files with 58 additions and 0 deletions
|
|
@ -439,6 +439,18 @@ class InsightsEngine:
|
|||
|
||||
if models:
|
||||
total_cost = sum(float(m.get("cost") or 0.0) for m in models)
|
||||
# Token totals likewise: the per-model breakdown includes
|
||||
# auxiliary usage rows (vision/compression/titles — task
|
||||
# dimension in session_model_usage, #23270) plus reconciled
|
||||
# residuals, while the sessions counters carry main-loop usage
|
||||
# only. Summing the breakdown keeps overview totals consistent
|
||||
# with the per-model table and stops `hermes insights`
|
||||
# undercounting aux spend (#58592, #9979).
|
||||
total_input = sum(int(m.get("input_tokens") or 0) for m in models)
|
||||
total_output = sum(int(m.get("output_tokens") or 0) for m in models)
|
||||
total_cache_read = sum(int(m.get("cache_read_tokens") or 0) for m in models)
|
||||
total_cache_write = sum(int(m.get("cache_write_tokens") or 0) for m in models)
|
||||
total_tokens = total_input + total_output + total_cache_read + total_cache_write
|
||||
|
||||
# Session duration stats (guard against negative durations from clock drift)
|
||||
durations = []
|
||||
|
|
|
|||
|
|
@ -340,3 +340,49 @@ class TestAnalyticsAuxRows:
|
|||
|
||||
tasks = _aux_task_summary(aux)
|
||||
assert {t["task"] for t in tasks} == {"vision", "compression"}
|
||||
|
||||
|
||||
class TestInsightsAuxTotals:
|
||||
def test_overview_totals_include_aux_usage(self, db):
|
||||
"""`hermes insights` overview must count aux tokens, not just the
|
||||
sessions counters (issues #58592, #9979)."""
|
||||
from agent.insights import InsightsEngine
|
||||
|
||||
db.create_session("s1", source="cli")
|
||||
db.update_token_counts(
|
||||
"s1", input_tokens=1000, output_tokens=100,
|
||||
model="main-model", billing_provider="nous", api_call_count=1,
|
||||
)
|
||||
db.record_auxiliary_usage(
|
||||
"s1", "compression", model="glm-5",
|
||||
billing_provider="openrouter", input_tokens=5000, output_tokens=500,
|
||||
)
|
||||
report = InsightsEngine(db).generate(days=30)
|
||||
ov = report["overview"]
|
||||
assert ov["total_input_tokens"] == 6000
|
||||
assert ov["total_output_tokens"] == 600
|
||||
models = {m["model"] for m in report["models"]}
|
||||
assert {"main-model", "glm-5"} <= models
|
||||
|
||||
def test_overview_totals_not_double_counted_with_absolute_updates(self, db):
|
||||
"""Gateway absolute overwrites + aux rows must not inflate totals."""
|
||||
from agent.insights import InsightsEngine
|
||||
|
||||
db.create_session("s2", source="telegram")
|
||||
db.update_token_counts(
|
||||
"s2", input_tokens=2000, output_tokens=200,
|
||||
model="main-model", billing_provider="nous", api_call_count=1,
|
||||
)
|
||||
db.update_token_counts(
|
||||
"s2", input_tokens=2000, output_tokens=200,
|
||||
model="main-model", billing_provider="nous",
|
||||
absolute=True, api_call_count=1,
|
||||
)
|
||||
db.record_auxiliary_usage(
|
||||
"s2", "title_generation", model="main-model",
|
||||
billing_provider="nous", input_tokens=40, output_tokens=8,
|
||||
)
|
||||
report = InsightsEngine(db).generate(days=30)
|
||||
ov = report["overview"]
|
||||
assert ov["total_input_tokens"] == 2040
|
||||
assert ov["total_output_tokens"] == 208
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue