tokenator 0.1.10__py3-none-any.whl → 0.1.12__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -71,7 +71,6 @@ def _create_usage_callback(execution_id, log_usage_fn):
71
71
  usage_data.usage.prompt_tokens += chunk.message.usage.input_tokens
72
72
  usage_data.usage.completion_tokens += chunk.message.usage.output_tokens
73
73
  elif isinstance(chunk, RawMessageDeltaEvent):
74
- usage_data.usage.prompt_tokens += chunk.usage.input_tokens
75
74
  usage_data.usage.completion_tokens += chunk.usage.output_tokens
76
75
 
77
76
  usage_data.usage.total_tokens = usage_data.usage.prompt_tokens + usage_data.usage.completion_tokens
tokenator/base_wrapper.py CHANGED
@@ -47,7 +47,7 @@ class BaseWrapper:
47
47
  total_tokens=token_usage_stats.usage.total_tokens,
48
48
  )
49
49
  session.add(token_usage)
50
- logger.info(
50
+ logger.debug(
51
51
  "Logged token usage: model=%s, total_tokens=%d",
52
52
  token_usage_stats.model,
53
53
  token_usage_stats.usage.total_tokens,
@@ -14,7 +14,9 @@ logger = logging.getLogger(__name__)
14
14
 
15
15
 
16
16
  class BaseOpenAIWrapper(BaseWrapper):
17
- provider = "openai"
17
+ def __init__(self, client, db_path=None, provider: str = "openai"):
18
+ super().__init__(client, db_path)
19
+ self.provider = provider
18
20
 
19
21
  def _process_response_usage(
20
22
  self, response: ResponseType
@@ -134,6 +136,7 @@ class AsyncOpenAIWrapper(BaseOpenAIWrapper):
134
136
  def tokenator_openai(
135
137
  client: OpenAI,
136
138
  db_path: Optional[str] = None,
139
+ provider: str = "openai",
137
140
  ) -> OpenAIWrapper: ...
138
141
 
139
142
 
@@ -141,23 +144,26 @@ def tokenator_openai(
141
144
  def tokenator_openai(
142
145
  client: AsyncOpenAI,
143
146
  db_path: Optional[str] = None,
147
+ provider: str = "openai",
144
148
  ) -> AsyncOpenAIWrapper: ...
145
149
 
146
150
 
147
151
  def tokenator_openai(
148
152
  client: Union[OpenAI, AsyncOpenAI],
149
153
  db_path: Optional[str] = None,
154
+ provider: str = "openai",
150
155
  ) -> Union[OpenAIWrapper, AsyncOpenAIWrapper]:
151
156
  """Create a token-tracking wrapper for an OpenAI client.
152
157
 
153
158
  Args:
154
159
  client: OpenAI or AsyncOpenAI client instance
155
160
  db_path: Optional path to SQLite database for token tracking
161
+ provider: Provider name, defaults to "openai"
156
162
  """
157
163
  if isinstance(client, OpenAI):
158
- return OpenAIWrapper(client=client, db_path=db_path)
164
+ return OpenAIWrapper(client=client, db_path=db_path, provider=provider)
159
165
 
160
166
  if isinstance(client, AsyncOpenAI):
161
- return AsyncOpenAIWrapper(client=client, db_path=db_path)
167
+ return AsyncOpenAIWrapper(client=client, db_path=db_path, provider=provider)
162
168
 
163
169
  raise ValueError("Client must be an instance of OpenAI or AsyncOpenAI")
@@ -0,0 +1,240 @@
1
+ Metadata-Version: 2.3
2
+ Name: tokenator
3
+ Version: 0.1.12
4
+ Summary: Token usage tracking wrapper for LLMs
5
+ License: MIT
6
+ Author: Ujjwal Maheshwari
7
+ Author-email: your.email@example.com
8
+ Requires-Python: >=3.9,<4.0
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Requires-Dist: alembic (>=1.13.0,<2.0.0)
17
+ Requires-Dist: anthropic (>=0.40.0,<0.41.0)
18
+ Requires-Dist: openai (>=1.57.0,<2.0.0)
19
+ Requires-Dist: requests (>=2.32.3,<3.0.0)
20
+ Requires-Dist: sqlalchemy (>=2.0.0,<3.0.0)
21
+ Description-Content-Type: text/markdown
22
+
23
+ # Tokenator : Track and analyze LLM token usage and cost
24
+
25
+ Have you ever wondered about :
26
+ - How many tokens does your AI agent consume?
27
+ - How much does it cost to do run a complex AI workflow with multiple LLM providers?
28
+ - How much money/tokens did you spend today on developing with LLMs?
29
+
30
+ Afraid not, tokenator is here! With tokenator's easy to use API, you can start tracking LLM usage in a matter of minutes.
31
+
32
+ Get started with just 3 lines of code!
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ pip install tokenator
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ ### OpenAI
43
+
44
+ ```python
45
+ from openai import OpenAI
46
+ from tokenator import tokenator_openai
47
+
48
+ openai_client = OpenAI(api_key="your-api-key")
49
+
50
+ # Wrap it with Tokenator
51
+ client = tokenator_openai(openai_client)
52
+
53
+ # Use it exactly like the OpenAI client
54
+ response = client.chat.completions.create(
55
+ model="gpt-4o",
56
+ messages=[{"role": "user", "content": "Hello!"}]
57
+ )
58
+ ```
59
+
60
+ Works with AsyncOpenAI and `streaming=True` as well!
61
+ Note : When streaming, don't forget to add `stream_options={"include_usage": True}` to the `create()` call!
62
+
63
+ ### Cost Analysis
64
+
65
+ ```python
66
+ from tokenator import usage
67
+
68
+ # Get usage for different time periods
69
+ usage.last_hour()
70
+ usage.last_day()
71
+ usage.last_week()
72
+ usage.last_month()
73
+
74
+ # Custom date range
75
+ usage.between("2024-03-01", "2024-03-15")
76
+
77
+ # Get usage for different LLM providers
78
+ usage.last_day("openai")
79
+ usage.last_day("anthropic")
80
+ usage.last_day("google")
81
+ ```
82
+
83
+ ### Example `usage` object
84
+
85
+ ```python
86
+ print(cost.last_hour().model_dump_json(indent=4))
87
+ ```
88
+
89
+ ```json
90
+ {
91
+ "total_cost": 0.0004,
92
+ "total_tokens": 79,
93
+ "prompt_tokens": 52,
94
+ "completion_tokens": 27,
95
+ "providers": [
96
+ {
97
+ "total_cost": 0.0004,
98
+ "total_tokens": 79,
99
+ "prompt_tokens": 52,
100
+ "completion_tokens": 27,
101
+ "provider": "openai",
102
+ "models": [
103
+ {
104
+ "total_cost": 0.0004,
105
+ "total_tokens": 79,
106
+ "prompt_tokens": 52,
107
+ "completion_tokens": 27,
108
+ "model": "gpt-4o-2024-08-06"
109
+ }
110
+ ]
111
+ }
112
+ ]
113
+ }
114
+ ```
115
+
116
+ ## Features
117
+
118
+ - Drop-in replacement for OpenAI, Anthropic client
119
+ - Automatic token usage tracking
120
+ - Cost analysis for different time periods
121
+ - SQLite storage with zero configuration
122
+ - Thread-safe operations
123
+ - Minimal memory footprint
124
+ - Minimal latency footprint
125
+
126
+ ### Anthropic
127
+
128
+ ```python
129
+ from anthropic import Anthropic, AsyncAnthropic
130
+ from tokenator import tokenator_anthropic
131
+
132
+ anthropic_client = AsyncAnthropic(api_key="your-api-key")
133
+
134
+ # Wrap it with Tokenator
135
+ client = tokenator_anthropic(anthropic_client)
136
+
137
+ # Use it exactly like the Anthropic client
138
+ response = await client.messages.create(
139
+ model="claude-3-5-haiku-20241022",
140
+ messages=[{"role": "user", "content": "hello how are you"}],
141
+ max_tokens=20,
142
+ )
143
+
144
+ print(response)
145
+
146
+ print(usage.last_execution().model_dump_json(indent=4))
147
+ """
148
+ {
149
+ "total_cost": 0.0001,
150
+ "total_tokens": 23,
151
+ "prompt_tokens": 10,
152
+ "completion_tokens": 13,
153
+ "providers": [
154
+ {
155
+ "total_cost": 0.0001,
156
+ "total_tokens": 23,
157
+ "prompt_tokens": 10,
158
+ "completion_tokens": 13,
159
+ "provider": "anthropic",
160
+ "models": [
161
+ {
162
+ "total_cost": 0.0004,
163
+ "total_tokens": 79,
164
+ "prompt_tokens": 52,
165
+ "completion_tokens": 27,
166
+ "model": "claude-3-5-haiku-20241022"
167
+ }
168
+ ]
169
+ }
170
+ ]
171
+ }
172
+ """
173
+ ```
174
+
175
+ ### xAI
176
+
177
+ You can use xAI models through the `openai` SDK and track usage using `provider` parameter in `tokenator`.
178
+
179
+ ```python
180
+ from openai import OpenAI
181
+ from tokenator import tokenator_openai
182
+
183
+ xai_client = OpenAI(
184
+ api_key=os.getenv("XAI_API_KEY"),
185
+ base_url="https://api.x.ai/v1"
186
+ )
187
+
188
+ # Wrap it with Tokenator
189
+ client = tokenator_openai(client, db_path=temp_db, provider="xai")
190
+
191
+ # Use it exactly like the OpenAI client but with xAI models
192
+ response = client.chat.completions.create(
193
+ model="grok-2-latest",
194
+ messages=[{"role": "user", "content": "Hello!"}]
195
+ )
196
+
197
+ print(response)
198
+
199
+ print(usage.last_execution())
200
+ ```
201
+
202
+ ### Other AI model providers through openai SDKs
203
+
204
+ Today, a variety of AI companies have made their APIs compatible to the `openai` SDK.
205
+ You can track usage of any such AI models using `tokenator`'s `provider` parameter.
206
+
207
+ For example, let's see how we can track usage of `perplexity` tokens.
208
+
209
+ ```python
210
+ from openai import OpenAI
211
+ from tokenator import tokenator_openai
212
+
213
+ xai_client = OpenAI(
214
+ api_key=os.getenv("PERPLEXITY_API_KEY"),
215
+ base_url="https://api.perplexity.ai"
216
+ )
217
+
218
+ # Wrap it with Tokenator
219
+ client = tokenator_openai(client, db_path=temp_db, provider="perplexity")
220
+
221
+ # Use it exactly like the OpenAI client but with xAI models
222
+ response = client.chat.completions.create(
223
+ model="grok-2-latest",
224
+ messages=[{"role": "user", "content": "Hello!"}]
225
+ )
226
+
227
+ print(response)
228
+
229
+ print(usage.last_execution())
230
+
231
+ print(usage.provider("perplexity"))
232
+ ```
233
+
234
+ ---
235
+
236
+ Most importantly, none of your data is ever sent to any server.
237
+
238
+ ## License
239
+
240
+ MIT
@@ -1,19 +1,19 @@
1
1
  tokenator/__init__.py,sha256=bIAPyGAvWreS2i_5tzxJEyX9JlZgAUNxzVk1iHNUhvU,593
2
- tokenator/anthropic/client_anthropic.py,sha256=fcKxGsLex99II-WD9SVNI5QVzH0IEWRmVLjyvZd9wKs,5936
2
+ tokenator/anthropic/client_anthropic.py,sha256=fnjWz_Kf8D0GUTudkZNeSmH9ueCGFLDSBDz1U8Jri3Y,5861
3
3
  tokenator/anthropic/stream_interceptors.py,sha256=4VHC_-WkG3Pa10YizmFLrHcbz0Tm2MR_YB5-uohKp5A,5221
4
- tokenator/base_wrapper.py,sha256=VYSkQB1MEudgzBX60T-VAMsNg4fFx7IRzpadzjm4klE,2466
4
+ tokenator/base_wrapper.py,sha256=IO344KWbRswQy4vG_pBxWPR7Wp7K-4mlgmS3SCYGep8,2467
5
5
  tokenator/create_migrations.py,sha256=k9IHiGK21dLTA8MYNsuhO0-kUVIcMSViMFYtY4WU2Rw,730
6
6
  tokenator/migrations/env.py,sha256=JoF5MJ4ae0wJW5kdBHuFlG3ZqeCCDvbMcU8fNA_a6hM,1396
7
7
  tokenator/migrations/script.py.mako,sha256=nJL-tbLQE0Qy4P9S4r4ntNAcikPtoFUlvXe6xvm9ot8,635
8
8
  tokenator/migrations/versions/f6f1f2437513_initial_migration.py,sha256=4cveHkwSxs-hxOPCm81YfvGZTkJJ2ClAFmyL98-1VCo,1910
9
9
  tokenator/migrations.py,sha256=YAf9gZmDzAq36PWWXPtdUQoJFYPXtIDzflC79H6gcJg,1114
10
10
  tokenator/models.py,sha256=MhYwCvmqposUNDRxFZNAVnzCqBTHxNL3Hp0MNFXM5ck,1201
11
- tokenator/openai/client_openai.py,sha256=Umfxha3BhBFU_JebPjyuaUZEZuPqJWQo1xTCuAy3R24,5691
11
+ tokenator/openai/client_openai.py,sha256=Ffa3ujLh5PuPe1W8KSISGH3NonZ_AC6ZpKhO6kTupTU,5996
12
12
  tokenator/openai/stream_interceptors.py,sha256=ez1MnjRZW_rEalv2SIPAvrU9oMD6OJoD9vht-057fDM,5243
13
13
  tokenator/schemas.py,sha256=Ye8hqZlrm3Gh2FyvOVX-hWCpKynWxS58QQRQMfDtIAQ,2114
14
14
  tokenator/usage.py,sha256=eTWfcRrTLop-30FmwHpi7_GwCJxU6Qfji374hG1Qptw,8476
15
15
  tokenator/utils.py,sha256=xg9l2GV1yJL1BlxKL1r8CboABWDslf3G5rGQEJSjFrE,1973
16
- tokenator-0.1.10.dist-info/LICENSE,sha256=wdG-B6-ODk8RQ4jq5uXSn0w1UWTzCH_MMyvh7AwtGns,1074
17
- tokenator-0.1.10.dist-info/METADATA,sha256=ryILkOYlq8V8219sVmK0xUeEEw51msw_FCoF_3VJ_k8,3108
18
- tokenator-0.1.10.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
19
- tokenator-0.1.10.dist-info/RECORD,,
16
+ tokenator-0.1.12.dist-info/LICENSE,sha256=wdG-B6-ODk8RQ4jq5uXSn0w1UWTzCH_MMyvh7AwtGns,1074
17
+ tokenator-0.1.12.dist-info/METADATA,sha256=VdJVlwESY2_QbiterwI1lH9dng4r4WwWYd6MwXlT9V4,5969
18
+ tokenator-0.1.12.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
19
+ tokenator-0.1.12.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.1
2
+ Generator: poetry-core 2.0.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,127 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: tokenator
3
- Version: 0.1.10
4
- Summary: Token usage tracking wrapper for LLMs
5
- License: MIT
6
- Author: Ujjwal Maheshwari
7
- Author-email: your.email@example.com
8
- Requires-Python: >=3.9,<4.0
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.9
12
- Classifier: Programming Language :: Python :: 3.10
13
- Classifier: Programming Language :: Python :: 3.11
14
- Classifier: Programming Language :: Python :: 3.12
15
- Classifier: Programming Language :: Python :: 3.13
16
- Requires-Dist: alembic (>=1.13.0,<2.0.0)
17
- Requires-Dist: anthropic (>=0.40.0,<0.41.0)
18
- Requires-Dist: openai (>=1.57.0,<2.0.0)
19
- Requires-Dist: requests (>=2.32.3,<3.0.0)
20
- Requires-Dist: sqlalchemy (>=2.0.0,<3.0.0)
21
- Description-Content-Type: text/markdown
22
-
23
- # Tokenator : Easiest way to track and analyze LLM token usage and cost
24
-
25
- Have you ever wondered about :
26
- - How many tokens does your AI agent consume?
27
- - How much does it cost to do run a complex AI workflow with multiple LLM providers?
28
- - How much money did I spent today on development?
29
-
30
- Afraid not, tokenator is here! With tokenator's easy to use API, you can start tracking LLM usage in a matter of minutes.
31
-
32
- Get started with just 3 lines of code!
33
-
34
- ## Installation
35
-
36
- ```bash
37
- pip install tokenator
38
- ```
39
-
40
- ## Usage
41
-
42
- ### OpenAI
43
-
44
- ```python
45
- from openai import OpenAI
46
- from tokenator import tokenator_openai
47
-
48
- openai_client = OpenAI(api_key="your-api-key")
49
-
50
- # Wrap it with Tokenator
51
- client = tokenator_openai(openai_client)
52
-
53
- # Use it exactly like the OpenAI client
54
- response = client.chat.completions.create(
55
- model="gpt-4o",
56
- messages=[{"role": "user", "content": "Hello!"}]
57
- )
58
- ```
59
-
60
- ### Cost Analysis
61
-
62
- ```python
63
- from tokenator import usage
64
-
65
- # Get usage for different time periods
66
- usage.last_hour()
67
- usage.last_day()
68
- usage.last_week()
69
- usage.last_month()
70
-
71
- # Custom date range
72
- usage.between("2024-03-01", "2024-03-15")
73
-
74
- # Get usage for different LLM providers
75
- usage.last_day("openai")
76
- usage.last_day("anthropic")
77
- usage.last_day("google")
78
- ```
79
-
80
- ### Example `usage` object
81
-
82
- ```python
83
- print(cost.last_hour().model_dump_json(indent=4))
84
- ```
85
-
86
- ```json
87
- {
88
- "total_cost": 0.0004,
89
- "total_tokens": 79,
90
- "prompt_tokens": 52,
91
- "completion_tokens": 27,
92
- "providers": [
93
- {
94
- "total_cost": 0.0004,
95
- "total_tokens": 79,
96
- "prompt_tokens": 52,
97
- "completion_tokens": 27,
98
- "provider": "openai",
99
- "models": [
100
- {
101
- "total_cost": 0.0004,
102
- "total_tokens": 79,
103
- "prompt_tokens": 52,
104
- "completion_tokens": 27,
105
- "model": "gpt-4o-2024-08-06"
106
- }
107
- ]
108
- }
109
- ]
110
- }
111
- ```
112
-
113
- ## Features
114
-
115
- - Drop-in replacement for OpenAI, Anthropic client
116
- - Automatic token usage tracking
117
- - Cost analysis for different time periods
118
- - SQLite storage with zero configuration
119
- - Thread-safe operations
120
- - Minimal memory footprint
121
- - Minimal latency footprint
122
-
123
- Most importantly, none of your data is ever sent to any server.
124
-
125
- ## License
126
-
127
- MIT