Skip to content

Commit d082cbf

Browse files
committed
fix: correct token usage accounting
1 parent f7231d1 commit d082cbf

2 files changed

Lines changed: 13 additions & 5 deletions

File tree

backend/open_webui/models/chat_messages.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from sqlalchemy import select, delete, func, cast, Integer, distinct
77
from sqlalchemy.ext.asyncio import AsyncSession
88
from open_webui.internal.db import Base, get_async_db_context
9-
from open_webui.utils.response import merge_usage, normalize_usage
9+
from open_webui.utils.response import normalize_usage
1010
from pydantic import BaseModel, ConfigDict
1111
from sqlalchemy import (
1212
JSON,
@@ -200,11 +200,14 @@ async def upsert_message(
200200
existing.error = data.get('error')
201201
if 'context_summary' in data or 'contextSummary' in data:
202202
existing.context_summary = data.get('context_summary') or data.get('contextSummary')
203-
# Extract and normalize usage
203+
# Usage is monotonic per message; keep the largest snapshot so
204+
# idempotent re-saves dedupe instead of double-counting.
204205
usage = get_usage(data)
205206
if usage:
206-
existing_usage = normalize_usage(existing.usage or {}) if existing.usage else {}
207-
existing.usage = existing_usage if usage == existing_usage else merge_usage(existing_usage, usage)
207+
new_total = normalize_usage(usage).get('total_tokens', 0)
208+
existing_total = normalize_usage(existing.usage or {}).get('total_tokens', 0)
209+
if existing.usage is None or new_total >= existing_total:
210+
existing.usage = usage
208211
existing.updated_at = now
209212
await db.commit()
210213
await db.refresh(existing)

backend/open_webui/utils/middleware.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4018,7 +4018,12 @@ def set_last_text(out, text):
40184018
else:
40194019
output = []
40204020

4021-
usage = None
4021+
# Continue re-sends prior context as prompt; input_tokens is cumulative across calls, not a double-count.
4022+
usage = (
4023+
normalize_usage(message['usage'])
4024+
if existing_output and message and message.get('usage')
4025+
else None
4026+
)
40224027
prior_output = []
40234028
last_response_id = None
40244029

0 commit comments

Comments
 (0)