1
1
from dataclasses import dataclass
2
+ from typing import TypeVar
3
+
4
+ from openai .types .responses .response_usage import InputTokensDetails , OutputTokensDetails
5
+
6
+ T = TypeVar ("T" , bound = "InputTokensDetails | OutputTokensDetails" )
7
+
8
+
9
+ def add_numeric_fields (current : T , other : T ) -> None :
10
+ for field in current .__dataclass_fields__ :
11
+ v1 = getattr (current , field , 0 )
12
+ v2 = getattr (other , field , 0 )
13
+ if isinstance (v1 , (int , float )) and isinstance (v2 , (int , float )):
14
+ setattr (current , field , (v1 or 0 ) + (v2 or 0 ))
2
15
3
16
4
17
@dataclass
@@ -9,9 +22,13 @@ class Usage:
9
22
input_tokens : int = 0
10
23
"""Total input tokens sent, across all requests."""
11
24
25
+ input_tokens_details : InputTokensDetails = InputTokensDetails (cached_tokens = 0 )
26
+
12
27
output_tokens : int = 0
13
28
"""Total output tokens received, across all requests."""
14
29
30
+ output_tokens_details : OutputTokensDetails = OutputTokensDetails (reasoning_tokens = 0 )
31
+
15
32
total_tokens : int = 0
16
33
"""Total tokens sent and received, across all requests."""
17
34
@@ -20,3 +37,5 @@ def add(self, other: "Usage") -> None:
20
37
self .input_tokens += other .input_tokens if other .input_tokens else 0
21
38
self .output_tokens += other .output_tokens if other .output_tokens else 0
22
39
self .total_tokens += other .total_tokens if other .total_tokens else 0
40
+ add_numeric_fields (self .input_tokens_details , other .input_tokens_details )
41
+ add_numeric_fields (self .output_tokens_details , other .output_tokens_details )
0 commit comments