llm-cost-guard 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. llm_cost_guard-0.1.0/.github/workflows/ci.yml +72 -0
  2. llm_cost_guard-0.1.0/.github/workflows/publish.yml +54 -0
  3. llm_cost_guard-0.1.0/.gitignore +82 -0
  4. llm_cost_guard-0.1.0/LICENSE +21 -0
  5. llm_cost_guard-0.1.0/PKG-INFO +357 -0
  6. llm_cost_guard-0.1.0/README.md +295 -0
  7. llm_cost_guard-0.1.0/examples/bedrock_example.py +203 -0
  8. llm_cost_guard-0.1.0/examples/budget_alerts.py +196 -0
  9. llm_cost_guard-0.1.0/examples/distributed_tracking.py +246 -0
  10. llm_cost_guard-0.1.0/examples/langchain_rag.py +186 -0
  11. llm_cost_guard-0.1.0/examples/quickstart.py +151 -0
  12. llm_cost_guard-0.1.0/examples/streaming_example.py +156 -0
  13. llm_cost_guard-0.1.0/llm_cost_guard/__init__.py +39 -0
  14. llm_cost_guard-0.1.0/llm_cost_guard/backends/__init__.py +52 -0
  15. llm_cost_guard-0.1.0/llm_cost_guard/backends/base.py +121 -0
  16. llm_cost_guard-0.1.0/llm_cost_guard/backends/memory.py +265 -0
  17. llm_cost_guard-0.1.0/llm_cost_guard/backends/sqlite.py +425 -0
  18. llm_cost_guard-0.1.0/llm_cost_guard/budget.py +306 -0
  19. llm_cost_guard-0.1.0/llm_cost_guard/cli.py +464 -0
  20. llm_cost_guard-0.1.0/llm_cost_guard/clients/__init__.py +11 -0
  21. llm_cost_guard-0.1.0/llm_cost_guard/clients/anthropic.py +231 -0
  22. llm_cost_guard-0.1.0/llm_cost_guard/clients/openai.py +262 -0
  23. llm_cost_guard-0.1.0/llm_cost_guard/exceptions.py +71 -0
  24. llm_cost_guard-0.1.0/llm_cost_guard/integrations/__init__.py +12 -0
  25. llm_cost_guard-0.1.0/llm_cost_guard/integrations/cache.py +189 -0
  26. llm_cost_guard-0.1.0/llm_cost_guard/integrations/langchain.py +257 -0
  27. llm_cost_guard-0.1.0/llm_cost_guard/models.py +123 -0
  28. llm_cost_guard-0.1.0/llm_cost_guard/pricing/__init__.py +7 -0
  29. llm_cost_guard-0.1.0/llm_cost_guard/pricing/anthropic.yaml +88 -0
  30. llm_cost_guard-0.1.0/llm_cost_guard/pricing/bedrock.yaml +215 -0
  31. llm_cost_guard-0.1.0/llm_cost_guard/pricing/loader.py +221 -0
  32. llm_cost_guard-0.1.0/llm_cost_guard/pricing/openai.yaml +148 -0
  33. llm_cost_guard-0.1.0/llm_cost_guard/pricing/vertex.yaml +133 -0
  34. llm_cost_guard-0.1.0/llm_cost_guard/providers/__init__.py +69 -0
  35. llm_cost_guard-0.1.0/llm_cost_guard/providers/anthropic.py +115 -0
  36. llm_cost_guard-0.1.0/llm_cost_guard/providers/base.py +72 -0
  37. llm_cost_guard-0.1.0/llm_cost_guard/providers/bedrock.py +135 -0
  38. llm_cost_guard-0.1.0/llm_cost_guard/providers/openai.py +110 -0
  39. llm_cost_guard-0.1.0/llm_cost_guard/rate_limit.py +233 -0
  40. llm_cost_guard-0.1.0/llm_cost_guard/span.py +143 -0
  41. llm_cost_guard-0.1.0/llm_cost_guard/tokenizers/__init__.py +7 -0
  42. llm_cost_guard-0.1.0/llm_cost_guard/tokenizers/base.py +207 -0
  43. llm_cost_guard-0.1.0/llm_cost_guard/tracker.py +718 -0
  44. llm_cost_guard-0.1.0/pyproject.toml +93 -0
  45. llm_cost_guard-0.1.0/tests/__init__.py +3 -0
  46. llm_cost_guard-0.1.0/tests/conftest.py +116 -0
  47. llm_cost_guard-0.1.0/tests/integration/__init__.py +3 -0
  48. llm_cost_guard-0.1.0/tests/integration/test_e2e.py +537 -0
  49. llm_cost_guard-0.1.0/tests/unit/__init__.py +3 -0
  50. llm_cost_guard-0.1.0/tests/unit/test_backends.py +306 -0
  51. llm_cost_guard-0.1.0/tests/unit/test_budget.py +241 -0
  52. llm_cost_guard-0.1.0/tests/unit/test_pricing.py +194 -0
  53. llm_cost_guard-0.1.0/tests/unit/test_providers.py +212 -0
  54. llm_cost_guard-0.1.0/tests/unit/test_rate_limit.py +196 -0
  55. llm_cost_guard-0.1.0/tests/unit/test_span.py +115 -0
  56. llm_cost_guard-0.1.0/tests/unit/test_tracker.py +274 -0
@@ -0,0 +1,72 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, develop]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ['3.9', '3.10', '3.11', '3.12']
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python ${{ matrix.python-version }}
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+
24
+ - name: Install dependencies
25
+ run: |
26
+ python -m pip install --upgrade pip
27
+ pip install -e ".[dev]"
28
+
29
+ - name: Lint with ruff
30
+ run: ruff check llm_cost_guard/
31
+
32
+ - name: Type check with mypy
33
+ run: mypy llm_cost_guard/ --ignore-missing-imports
34
+ continue-on-error: true
35
+
36
+ - name: Security check with bandit
37
+ run: bandit -r llm_cost_guard/ -ll
38
+ continue-on-error: true
39
+
40
+ - name: Run tests
41
+ run: pytest tests/ -v --cov=llm_cost_guard --cov-report=xml
42
+
43
+ - name: Upload coverage
44
+ uses: codecov/codecov-action@v4
45
+ if: matrix.python-version == '3.11'
46
+ with:
47
+ files: coverage.xml
48
+ fail_ci_if_error: false
49
+
50
+ build:
51
+ needs: test
52
+ runs-on: ubuntu-latest
53
+
54
+ steps:
55
+ - uses: actions/checkout@v4
56
+
57
+ - name: Set up Python
58
+ uses: actions/setup-python@v5
59
+ with:
60
+ python-version: '3.11'
61
+
62
+ - name: Install build tools
63
+ run: pip install build
64
+
65
+ - name: Build package
66
+ run: python -m build
67
+
68
+ - name: Upload artifacts
69
+ uses: actions/upload-artifact@v4
70
+ with:
71
+ name: dist
72
+ path: dist/
@@ -0,0 +1,54 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ matrix:
12
+ python-version: ['3.9', '3.10', '3.11', '3.12']
13
+
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Set up Python ${{ matrix.python-version }}
18
+ uses: actions/setup-python@v5
19
+ with:
20
+ python-version: ${{ matrix.python-version }}
21
+
22
+ - name: Install dependencies
23
+ run: |
24
+ python -m pip install --upgrade pip
25
+ pip install -e ".[dev]"
26
+
27
+ - name: Run tests
28
+ run: pytest tests/ -v --cov=llm_cost_guard
29
+
30
+ publish:
31
+ needs: test
32
+ runs-on: ubuntu-latest
33
+
34
+ steps:
35
+ - uses: actions/checkout@v4
36
+
37
+ - name: Set up Python
38
+ uses: actions/setup-python@v5
39
+ with:
40
+ python-version: '3.11'
41
+
42
+ - name: Install build tools
43
+ run: |
44
+ python -m pip install --upgrade pip
45
+ pip install build twine
46
+
47
+ - name: Build package
48
+ run: python -m build
49
+
50
+ - name: Publish to PyPI
51
+ env:
52
+ TWINE_USERNAME: __token__
53
+ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
54
+ run: twine upload dist/*
@@ -0,0 +1,82 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ *.egg-info/
24
+ .installed.cfg
25
+ *.egg
26
+
27
+ # PyInstaller
28
+ *.manifest
29
+ *.spec
30
+
31
+ # Installer logs
32
+ pip-log.txt
33
+ pip-delete-this-directory.txt
34
+
35
+ # Unit test / coverage reports
36
+ htmlcov/
37
+ .tox/
38
+ .nox/
39
+ .coverage
40
+ .coverage.*
41
+ .cache
42
+ nosetests.xml
43
+ coverage.xml
44
+ *.cover
45
+ *.py,cover
46
+ .hypothesis/
47
+ .pytest_cache/
48
+
49
+ # Translations
50
+ *.mo
51
+ *.pot
52
+
53
+ # Environments
54
+ .env
55
+ .venv
56
+ env/
57
+ venv/
58
+ ENV/
59
+ env.bak/
60
+ venv.bak/
61
+
62
+ # IDEs
63
+ .idea/
64
+ .vscode/
65
+ *.swp
66
+ *.swo
67
+ *~
68
+
69
+ # Jupyter Notebook
70
+ .ipynb_checkpoints
71
+
72
+ # mypy
73
+ .mypy_cache/
74
+ .dmypy.json
75
+ dmypy.json
76
+
77
+ # Ruff
78
+ .ruff_cache/
79
+
80
+ # OS
81
+ .DS_Store
82
+ Thumbs.db
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Prashant Dudami
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,357 @@
1
+ Metadata-Version: 2.4
2
+ Name: llm-cost-guard
3
+ Version: 0.1.0
4
+ Summary: Real-time cost tracking, budget enforcement, and usage analytics for LLM applications
5
+ Project-URL: Homepage, https://github.com/prashantdudami/llm-cost-guard
6
+ Project-URL: Documentation, https://github.com/prashantdudami/llm-cost-guard#readme
7
+ Project-URL: Repository, https://github.com/prashantdudami/llm-cost-guard
8
+ Project-URL: Issues, https://github.com/prashantdudami/llm-cost-guard/issues
9
+ Author: Prashant Dudami
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: anthropic,bedrock,budget,cost-tracking,langchain,llm,openai
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Requires-Python: >=3.9
24
+ Requires-Dist: httpx>=0.24.0
25
+ Requires-Dist: pyyaml>=6.0
26
+ Requires-Dist: tiktoken>=0.5.0
27
+ Provides-Extra: all
28
+ Requires-Dist: anthropic>=0.18.0; extra == 'all'
29
+ Requires-Dist: boto3>=1.28.0; extra == 'all'
30
+ Requires-Dist: langchain-core>=0.1.0; extra == 'all'
31
+ Requires-Dist: langchain>=0.1.0; extra == 'all'
32
+ Requires-Dist: opentelemetry-api>=1.20.0; extra == 'all'
33
+ Requires-Dist: opentelemetry-sdk>=1.20.0; extra == 'all'
34
+ Requires-Dist: prometheus-client>=0.17.0; extra == 'all'
35
+ Requires-Dist: redis>=4.5.0; extra == 'all'
36
+ Requires-Dist: sqlalchemy>=2.0.0; extra == 'all'
37
+ Provides-Extra: anthropic
38
+ Requires-Dist: anthropic>=0.18.0; extra == 'anthropic'
39
+ Provides-Extra: bedrock
40
+ Requires-Dist: boto3>=1.28.0; extra == 'bedrock'
41
+ Provides-Extra: dev
42
+ Requires-Dist: bandit>=1.7.0; extra == 'dev'
43
+ Requires-Dist: moto>=4.2.0; extra == 'dev'
44
+ Requires-Dist: mypy>=1.5.0; extra == 'dev'
45
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
46
+ Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
47
+ Requires-Dist: pytest>=7.4.0; extra == 'dev'
48
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
49
+ Provides-Extra: langchain
50
+ Requires-Dist: langchain-core>=0.1.0; extra == 'langchain'
51
+ Requires-Dist: langchain>=0.1.0; extra == 'langchain'
52
+ Provides-Extra: otel
53
+ Requires-Dist: opentelemetry-api>=1.20.0; extra == 'otel'
54
+ Requires-Dist: opentelemetry-sdk>=1.20.0; extra == 'otel'
55
+ Provides-Extra: prometheus
56
+ Requires-Dist: prometheus-client>=0.17.0; extra == 'prometheus'
57
+ Provides-Extra: redis
58
+ Requires-Dist: redis>=4.5.0; extra == 'redis'
59
+ Provides-Extra: sql
60
+ Requires-Dist: sqlalchemy>=2.0.0; extra == 'sql'
61
+ Description-Content-Type: text/markdown
62
+
63
+ # LLM Cost Guard
64
+
65
+ [![PyPI version](https://badge.fury.io/py/llm-cost-guard.svg)](https://badge.fury.io/py/llm-cost-guard)
66
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
67
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
68
+
69
+ Real-time cost tracking, budget enforcement, and usage analytics for LLM applications. Supports OpenAI, Anthropic, AWS Bedrock, and more.
70
+
71
+ ## Features
72
+
73
+ - **Real-time Cost Tracking**: Track costs as they happen, not when the bill arrives
74
+ - **Budget Enforcement**: Set limits with configurable actions (warn, throttle, block)
75
+ - **Multi-Provider Support**: OpenAI, Anthropic, AWS Bedrock, Google Vertex AI
76
+ - **LangChain Integration**: Native callback support for LangChain applications
77
+ - **Rate Limiting**: Control request rates per model, provider, or custom tags
78
+ - **Hierarchical Tracking**: Group related LLM calls with spans
79
+ - **Flexible Storage**: In-memory, SQLite, PostgreSQL, Redis, DynamoDB backends
80
+ - **Zero External Dependencies**: Works offline with no external services required
81
+
82
+ ## Installation
83
+
84
+ ```bash
85
+ pip install llm-cost-guard
86
+ ```
87
+
88
+ With optional integrations:
89
+
90
+ ```bash
91
+ # LangChain support
92
+ pip install llm-cost-guard[langchain]
93
+
94
+ # AWS Bedrock support
95
+ pip install llm-cost-guard[bedrock]
96
+
97
+ # All optional dependencies
98
+ pip install llm-cost-guard[all]
99
+ ```
100
+
101
+ ## Quick Start
102
+
103
+ ### Basic Usage
104
+
105
+ ```python
106
+ from llm_cost_guard import CostTracker
107
+
108
+ tracker = CostTracker()
109
+
110
+ # Decorator-based tracking
111
+ @tracker.track
112
+ def my_llm_call():
113
+ response = openai.chat.completions.create(
114
+ model="gpt-4o",
115
+ messages=[{"role": "user", "content": "Hello!"}]
116
+ )
117
+ return response
118
+
119
+ result = my_llm_call()
120
+
121
+ # Check costs
122
+ print(tracker.last_call().total_cost) # $0.0015
123
+ ```
124
+
125
+ ### With Budget Enforcement
126
+
127
+ ```python
128
+ from llm_cost_guard import CostTracker, Budget, BudgetAction
129
+
130
+ tracker = CostTracker(
131
+ budgets=[
132
+ Budget(
133
+ name="daily",
134
+ limit=10.00,
135
+ period="day",
136
+ action=BudgetAction.WARN
137
+ ),
138
+ Budget(
139
+ name="monthly",
140
+ limit=500.00,
141
+ period="month",
142
+ action=BudgetAction.BLOCK
143
+ ),
144
+ ]
145
+ )
146
+
147
+ # Get notified when approaching limits
148
+ @tracker.on_budget_warning
149
+ def handle_warning(budget, current):
150
+ print(f"Warning: Budget '{budget.name}' at {current/budget.limit*100:.0f}%")
151
+
152
+ @tracker.on_budget_exceeded
153
+ def handle_exceeded(budget):
154
+ print(f"Budget '{budget.name}' exceeded!")
155
+ ```
156
+
157
+ ### Manual Recording
158
+
159
+ ```python
160
+ # For custom integrations
161
+ record = tracker.record(
162
+ provider="openai",
163
+ model="gpt-4o",
164
+ input_tokens=1234,
165
+ output_tokens=567,
166
+ tags={"team": "search", "feature": "autocomplete"}
167
+ )
168
+
169
+ print(record.total_cost) # $0.0208
170
+ ```
171
+
172
+ ### Wrapped Clients
173
+
174
+ ```python
175
+ from llm_cost_guard import CostTracker
176
+ from llm_cost_guard.clients import TrackedOpenAI
177
+
178
+ tracker = CostTracker()
179
+ client = TrackedOpenAI(tracker=tracker)
180
+
181
+ # Automatic tracking - no decorators needed
182
+ response = client.chat.completions.create(
183
+ model="gpt-4o",
184
+ messages=[{"role": "user", "content": "Hello!"}]
185
+ )
186
+ ```
187
+
188
+ ### LangChain Integration
189
+
190
+ ```python
191
+ from llm_cost_guard import CostTracker
192
+ from llm_cost_guard.integrations.langchain import CostTrackingCallback
193
+
194
+ tracker = CostTracker()
195
+
196
+ llm = ChatOpenAI(
197
+ model="gpt-4o",
198
+ callbacks=[CostTrackingCallback(tracker)]
199
+ )
200
+
201
+ result = llm.invoke("Hello!")
202
+ print(tracker.last_call().total_cost)
203
+ ```
204
+
205
+ ### Hierarchical Tracking (Spans)
206
+
207
+ ```python
208
+ # Track costs for complex operations like agents
209
+ with tracker.span("customer_support_agent", tags={"user_id": "123"}) as span:
210
+ result = agent.invoke(query)
211
+
212
+ print(span.total_cost) # $0.45 (sum of all calls)
213
+ print(span.call_count) # 5
214
+ print(span.models_used) # ["gpt-4o", "gpt-3.5-turbo"]
215
+ ```
216
+
217
+ ## Configuration
218
+
219
+ ### Storage Backends
220
+
221
+ ```python
222
+ # In-memory (default, development)
223
+ tracker = CostTracker(backend="memory")
224
+
225
+ # SQLite (single-machine persistence)
226
+ tracker = CostTracker(backend="sqlite:///costs.db")
227
+
228
+ # PostgreSQL (production)
229
+ tracker = CostTracker(backend="postgresql://user:pass@host/db")
230
+
231
+ # Redis (distributed, real-time)
232
+ tracker = CostTracker(backend="redis://localhost:6379/0")
233
+ ```
234
+
235
+ ### Rate Limiting
236
+
237
+ ```python
238
+ from llm_cost_guard import CostTracker, RateLimit
239
+
240
+ tracker = CostTracker(
241
+ rate_limits=[
242
+ RateLimit(
243
+ name="requests-per-minute",
244
+ limit=100,
245
+ period="minute",
246
+ scope="global"
247
+ ),
248
+ RateLimit(
249
+ name="user-requests",
250
+ limit=10,
251
+ period="minute",
252
+ scope="tag:user_id"
253
+ )
254
+ ]
255
+ )
256
+ ```
257
+
258
+ ### Fail-Safe Modes
259
+
260
+ ```python
261
+ tracker = CostTracker(
262
+ # Block LLM calls if tracking fails (strict)
263
+ on_tracking_failure="block",
264
+
265
+ # Allow LLM calls but log warning (available)
266
+ # on_tracking_failure="allow",
267
+
268
+ # Use in-memory fallback temporarily
269
+ # on_tracking_failure="fallback",
270
+ )
271
+ ```
272
+
273
+ ## CLI
274
+
275
+ ```bash
276
+ # View current costs
277
+ llm-cost-guard status
278
+
279
+ # Generate report
280
+ llm-cost-guard report --period day --group-by model
281
+
282
+ # Check health
283
+ llm-cost-guard health
284
+
285
+ # List supported models and pricing
286
+ llm-cost-guard models --provider openai
287
+
288
+ # Export data
289
+ llm-cost-guard export --format csv --output costs.csv
290
+ ```
291
+
292
+ ## Supported Providers
293
+
294
+ | Provider | Models |
295
+ |----------|--------|
296
+ | OpenAI | GPT-4o, GPT-4, GPT-3.5, o1, Embeddings, DALL-E |
297
+ | Anthropic | Claude 3.5, Claude 3, Claude 2 |
298
+ | AWS Bedrock | Claude, Titan, Llama, Mistral, Cohere |
299
+ | Google Vertex AI | Gemini 1.5, Gemini 1.0, PaLM 2 |
300
+
301
+ ## Reporting
302
+
303
+ ```python
304
+ # Daily summary
305
+ tracker.daily_report()
306
+
307
+ # Cost by model
308
+ tracker.report_by_model(period="week")
309
+
310
+ # Query with filters
311
+ report = tracker.get_costs(
312
+ start_date="2024-01-01",
313
+ end_date="2024-01-31",
314
+ tags={"team": "search"},
315
+ group_by=["model", "feature"]
316
+ )
317
+
318
+ # Export to DataFrame
319
+ df = tracker.to_dataframe()
320
+ ```
321
+
322
+ ## Security
323
+
324
+ - **No API key logging**: Keys are never stored, logged, or transmitted
325
+ - **No prompt storage by default**: Only metadata (tokens, cost) stored
326
+ - **PII redaction**: Optional redaction for user IDs
327
+ - **Encryption support**: For SQL/Redis backends
328
+
329
+ ```python
330
+ tracker = CostTracker(
331
+ store_prompts=False, # Default: never store prompts
332
+ redact_user_ids=True, # Hash user IDs in storage
333
+ )
334
+ ```
335
+
336
+ ## Custom Pricing
337
+
338
+ For negotiated enterprise rates:
339
+
340
+ ```python
341
+ tracker = CostTracker(
342
+ pricing_overrides={
343
+ "openai/gpt-4": {
344
+ "input_cost_per_1k": 0.02, # Your negotiated rate
345
+ "output_cost_per_1k": 0.04,
346
+ }
347
+ }
348
+ )
349
+ ```
350
+
351
+ ## Contributing
352
+
353
+ Contributions are welcome! Please read our contributing guidelines and submit pull requests.
354
+
355
+ ## License
356
+
357
+ MIT License - see [LICENSE](LICENSE) for details.