noburn 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.
- noburn-0.1.0/.gitignore +6 -0
- noburn-0.1.0/PKG-INFO +112 -0
- noburn-0.1.0/README.md +91 -0
- noburn-0.1.0/pyproject.toml +32 -0
- noburn-0.1.0/src/noburn/__init__.py +4 -0
- noburn-0.1.0/src/noburn/guard.py +569 -0
- noburn-0.1.0/src/noburn/py.typed +0 -0
- noburn-0.1.0/tests/test_guard.py +616 -0
noburn-0.1.0/.gitignore
ADDED
noburn-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: noburn
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Hard LLM spend enforcement for Python — pre-call budget checks and per-user metering.
|
|
5
|
+
Project-URL: Homepage, https://noburn.dev
|
|
6
|
+
Project-URL: Documentation, https://noburn.dev/docs
|
|
7
|
+
Project-URL: Repository, https://github.com/orvi2014/noburn
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: ai,anthropic,budget,cost-control,langchain,llm,openai
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# noburn
|
|
23
|
+
|
|
24
|
+
Hard LLM spend enforcement for Python — pre-call budget checks and per-user metering.
|
|
25
|
+
|
|
26
|
+
Check a planned LLM call against project-, per-user-, and per-run budget caps
|
|
27
|
+
*before* you make it, then record what it actually cost.
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install noburn
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Requires Python ≥ 3.9. No third-party dependencies. Ships type hints (`py.typed`).
|
|
36
|
+
|
|
37
|
+
## Quick start
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
import os
|
|
41
|
+
from noburn import NoburnGuard
|
|
42
|
+
|
|
43
|
+
guard = NoburnGuard(
|
|
44
|
+
api_key=os.environ["NOBURN_API_KEY"],
|
|
45
|
+
project_id=os.environ["NOBURN_PROJECT_ID"],
|
|
46
|
+
budget_cap_usd=10.0, # optional local fallback cap
|
|
47
|
+
on_error="allow", # "allow" (default, fail-open) | "block" (fail-closed)
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
decision = guard.check(
|
|
51
|
+
model="gpt-4o",
|
|
52
|
+
estimated_tokens_in=1000,
|
|
53
|
+
estimated_tokens_out=300,
|
|
54
|
+
end_user_id="user_123", # optional — enforces that user's cap
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
if decision.blocked:
|
|
58
|
+
raise RuntimeError(f"Blocked by noburn: {decision.block_reason}")
|
|
59
|
+
|
|
60
|
+
# ... make your LLM call ...
|
|
61
|
+
|
|
62
|
+
guard.record(
|
|
63
|
+
model="gpt-4o",
|
|
64
|
+
tokens_in=980,
|
|
65
|
+
tokens_out=290,
|
|
66
|
+
cost_usd=0.005,
|
|
67
|
+
was_blocked=False,
|
|
68
|
+
end_user_id="user_123",
|
|
69
|
+
)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`record()` is fire-and-forget — it returns immediately (delivery happens on a
|
|
73
|
+
background daemon thread) and never raises, so it adds no latency to your call
|
|
74
|
+
path.
|
|
75
|
+
|
|
76
|
+
## Agent runs
|
|
77
|
+
|
|
78
|
+
Bound a single agent invocation with its own cap:
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
run = guard.start_run(budget_cap_usd=0.5)
|
|
82
|
+
|
|
83
|
+
decision = guard.check(
|
|
84
|
+
model="gpt-4o",
|
|
85
|
+
estimated_tokens_in=1000,
|
|
86
|
+
estimated_tokens_out=300,
|
|
87
|
+
run_id=run.run_id,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
guard.record(model="gpt-4o", tokens_in=980, tokens_out=290,
|
|
91
|
+
cost_usd=0.005, was_blocked=False, run_id=run.run_id)
|
|
92
|
+
|
|
93
|
+
summary = guard.end_run(run.run_id) # EndRunResult(status=..., spend_usd=..., ...)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Behavior
|
|
97
|
+
|
|
98
|
+
- **`check()` never raises** except `NoburnAuthError` (bad key). Every call asks
|
|
99
|
+
the server for an authoritative decision; if the server is unreachable it
|
|
100
|
+
falls back to a local in-memory check.
|
|
101
|
+
- **`on_error`** controls that fallback when nothing local blocks the call:
|
|
102
|
+
`"allow"` (default) fails open so a noburn outage never breaks your app;
|
|
103
|
+
`"block"` fails closed (`block_reason="noburn_unreachable"`).
|
|
104
|
+
- **`start_run()` raises** on network/auth error (`NoburnTimeoutError` on
|
|
105
|
+
timeout) — a run must be registered before you proceed.
|
|
106
|
+
|
|
107
|
+
> Note: `check()`/`start_run()` use blocking HTTP. In async apps, run them in a
|
|
108
|
+
> thread executor (e.g. `await asyncio.to_thread(guard.check, ...)`).
|
|
109
|
+
|
|
110
|
+
## License
|
|
111
|
+
|
|
112
|
+
MIT
|
noburn-0.1.0/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# noburn
|
|
2
|
+
|
|
3
|
+
Hard LLM spend enforcement for Python — pre-call budget checks and per-user metering.
|
|
4
|
+
|
|
5
|
+
Check a planned LLM call against project-, per-user-, and per-run budget caps
|
|
6
|
+
*before* you make it, then record what it actually cost.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pip install noburn
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Requires Python ≥ 3.9. No third-party dependencies. Ships type hints (`py.typed`).
|
|
15
|
+
|
|
16
|
+
## Quick start
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
import os
|
|
20
|
+
from noburn import NoburnGuard
|
|
21
|
+
|
|
22
|
+
guard = NoburnGuard(
|
|
23
|
+
api_key=os.environ["NOBURN_API_KEY"],
|
|
24
|
+
project_id=os.environ["NOBURN_PROJECT_ID"],
|
|
25
|
+
budget_cap_usd=10.0, # optional local fallback cap
|
|
26
|
+
on_error="allow", # "allow" (default, fail-open) | "block" (fail-closed)
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
decision = guard.check(
|
|
30
|
+
model="gpt-4o",
|
|
31
|
+
estimated_tokens_in=1000,
|
|
32
|
+
estimated_tokens_out=300,
|
|
33
|
+
end_user_id="user_123", # optional — enforces that user's cap
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
if decision.blocked:
|
|
37
|
+
raise RuntimeError(f"Blocked by noburn: {decision.block_reason}")
|
|
38
|
+
|
|
39
|
+
# ... make your LLM call ...
|
|
40
|
+
|
|
41
|
+
guard.record(
|
|
42
|
+
model="gpt-4o",
|
|
43
|
+
tokens_in=980,
|
|
44
|
+
tokens_out=290,
|
|
45
|
+
cost_usd=0.005,
|
|
46
|
+
was_blocked=False,
|
|
47
|
+
end_user_id="user_123",
|
|
48
|
+
)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`record()` is fire-and-forget — it returns immediately (delivery happens on a
|
|
52
|
+
background daemon thread) and never raises, so it adds no latency to your call
|
|
53
|
+
path.
|
|
54
|
+
|
|
55
|
+
## Agent runs
|
|
56
|
+
|
|
57
|
+
Bound a single agent invocation with its own cap:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
run = guard.start_run(budget_cap_usd=0.5)
|
|
61
|
+
|
|
62
|
+
decision = guard.check(
|
|
63
|
+
model="gpt-4o",
|
|
64
|
+
estimated_tokens_in=1000,
|
|
65
|
+
estimated_tokens_out=300,
|
|
66
|
+
run_id=run.run_id,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
guard.record(model="gpt-4o", tokens_in=980, tokens_out=290,
|
|
70
|
+
cost_usd=0.005, was_blocked=False, run_id=run.run_id)
|
|
71
|
+
|
|
72
|
+
summary = guard.end_run(run.run_id) # EndRunResult(status=..., spend_usd=..., ...)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Behavior
|
|
76
|
+
|
|
77
|
+
- **`check()` never raises** except `NoburnAuthError` (bad key). Every call asks
|
|
78
|
+
the server for an authoritative decision; if the server is unreachable it
|
|
79
|
+
falls back to a local in-memory check.
|
|
80
|
+
- **`on_error`** controls that fallback when nothing local blocks the call:
|
|
81
|
+
`"allow"` (default) fails open so a noburn outage never breaks your app;
|
|
82
|
+
`"block"` fails closed (`block_reason="noburn_unreachable"`).
|
|
83
|
+
- **`start_run()` raises** on network/auth error (`NoburnTimeoutError` on
|
|
84
|
+
timeout) — a run must be registered before you proceed.
|
|
85
|
+
|
|
86
|
+
> Note: `check()`/`start_run()` use blocking HTTP. In async apps, run them in a
|
|
87
|
+
> thread executor (e.g. `await asyncio.to_thread(guard.check, ...)`).
|
|
88
|
+
|
|
89
|
+
## License
|
|
90
|
+
|
|
91
|
+
MIT
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "noburn"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Hard LLM spend enforcement for Python — pre-call budget checks and per-user metering."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
keywords = ["llm", "ai", "budget", "cost-control", "openai", "anthropic", "langchain"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 4 - Beta",
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3.9",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Topic :: Software Development :: Libraries",
|
|
23
|
+
]
|
|
24
|
+
dependencies = []
|
|
25
|
+
|
|
26
|
+
[project.urls]
|
|
27
|
+
Homepage = "https://noburn.dev"
|
|
28
|
+
Documentation = "https://noburn.dev/docs"
|
|
29
|
+
Repository = "https://github.com/orvi2014/noburn"
|
|
30
|
+
|
|
31
|
+
[tool.hatch.build.targets.wheel]
|
|
32
|
+
packages = ["src/noburn"]
|