Skip to content

Commit ef862d7

Browse files
fix(usage): Handle None values in token details when adding usage
The Usage.add() method was failing when token detail fields (cached_tokens, reasoning_tokens) were None. This occurs when using providers like Ollama that don't provide these optional fields. Added defensive handling to treat None as 0, matching the pattern used elsewhere in the codebase (openai_chatcompletions.py, litellm_model.py, chatcmpl_stream_handler.py). Signed-off-by: Adrian Cole <[email protected]>
1 parent 0c4f2b9 commit ef862d7

File tree

3 files changed

+32
-4
lines changed

3 files changed

+32
-4
lines changed

examples/financial_research_agent/agents/model.py

Whitespace-only changes.

src/agents/usage.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,13 @@ def add(self, other: "Usage") -> None:
7373
self.output_tokens += other.output_tokens if other.output_tokens else 0
7474
self.total_tokens += other.total_tokens if other.total_tokens else 0
7575
self.input_tokens_details = InputTokensDetails(
76-
cached_tokens=self.input_tokens_details.cached_tokens
77-
+ other.input_tokens_details.cached_tokens
76+
cached_tokens=(self.input_tokens_details.cached_tokens or 0)
77+
+ (other.input_tokens_details.cached_tokens or 0)
7878
)
7979

8080
self.output_tokens_details = OutputTokensDetails(
81-
reasoning_tokens=self.output_tokens_details.reasoning_tokens
82-
+ other.output_tokens_details.reasoning_tokens
81+
reasoning_tokens=(self.output_tokens_details.reasoning_tokens or 0)
82+
+ (other.output_tokens_details.reasoning_tokens or 0)
8383
)
8484

8585
# Automatically preserve request_usage_entries.

tests/test_usage.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,31 @@ def test_anthropic_cost_calculation_scenario():
267267
for req in usage.request_usage_entries:
268268
assert req.input_tokens < 200_000
269269
assert req.output_tokens < 200_000
270+
271+
272+
def test_usage_add_handles_none_token_details():
273+
u1 = Usage(
274+
requests=1,
275+
input_tokens=10,
276+
input_tokens_details=InputTokensDetails(cached_tokens=3),
277+
output_tokens=20,
278+
output_tokens_details=OutputTokensDetails(reasoning_tokens=5),
279+
total_tokens=30,
280+
)
281+
u2 = Usage(
282+
requests=2,
283+
input_tokens=15,
284+
output_tokens=25,
285+
total_tokens=40,
286+
)
287+
u2.input_tokens_details.cached_tokens = None
288+
u2.output_tokens_details.reasoning_tokens = None
289+
290+
u1.add(u2)
291+
292+
assert u1.requests == 3
293+
assert u1.input_tokens == 25
294+
assert u1.output_tokens == 45
295+
assert u1.total_tokens == 70
296+
assert u1.input_tokens_details.cached_tokens == 3
297+
assert u1.output_tokens_details.reasoning_tokens == 5

0 commit comments

Comments
 (0)