bedrock-kit 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.
@@ -0,0 +1,21 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.so
5
+ .Python
6
+ build/
7
+ dist/
8
+ *.egg-info/
9
+ *.egg
10
+ .pytest_cache/
11
+ .ruff_cache/
12
+ .coverage
13
+ htmlcov/
14
+ .tox/
15
+ .mypy_cache/
16
+ .venv/
17
+ venv/
18
+ env/
19
+ .idea/
20
+ .vscode/
21
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mukunda Rao Katta
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,188 @@
1
+ Metadata-Version: 2.4
2
+ Name: bedrock-kit
3
+ Version: 0.1.0
4
+ Summary: Small, opinionated AWS Bedrock client wrapper: adaptive throttle, cache-aware cost tracking, and structured-output parse-and-repair. Single-cloud, single-purpose.
5
+ Project-URL: Homepage, https://github.com/MukundaKatta/bedrock-kit
6
+ Project-URL: Issues, https://github.com/MukundaKatta/bedrock-kit/issues
7
+ Project-URL: Source, https://github.com/MukundaKatta/bedrock-kit
8
+ Author-email: Mukunda Rao Katta <mukunda.vjcs6@gmail.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: anthropic,aws,bedrock,claude,cost-tracking,llm,mlops,rag,retry,structured-output
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
24
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
+ Requires-Python: >=3.10
26
+ Requires-Dist: pydantic>=2.0
27
+ Provides-Extra: boto
28
+ Requires-Dist: boto3>=1.28; extra == 'boto'
29
+ Provides-Extra: dev
30
+ Requires-Dist: pandas>=2.0; extra == 'dev'
31
+ Requires-Dist: pytest>=8.0; extra == 'dev'
32
+ Requires-Dist: ruff>=0.4; extra == 'dev'
33
+ Provides-Extra: pandas
34
+ Requires-Dist: pandas>=2.0; extra == 'pandas'
35
+ Description-Content-Type: text/markdown
36
+
37
+ # bedrock-kit
38
+
39
+ [![CI](https://github.com/MukundaKatta/bedrock-kit/actions/workflows/ci.yml/badge.svg)](https://github.com/MukundaKatta/bedrock-kit/actions/workflows/ci.yml)
40
+ [![PyPI](https://img.shields.io/pypi/v/bedrock-kit.svg)](https://pypi.org/project/bedrock-kit/)
41
+ [![Python](https://img.shields.io/pypi/pyversions/bedrock-kit.svg)](https://pypi.org/project/bedrock-kit/)
42
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
43
+
44
+ **Small, opinionated AWS Bedrock client wrapper.**
45
+
46
+ Every Bedrock production team rebuilds the same three things: adaptive
47
+ throttle for `ThrottlingException`, per-call cost tracking that handles
48
+ cache-read tokens, and structured-output parsing-with-repair. `bedrock-kit`
49
+ ships those, and nothing else. Single-cloud, single-purpose. No proxy
50
+ server. Wraps the official boto3 client; you can inject a fake for testing.
51
+
52
+ ## Install
53
+
54
+ ```bash
55
+ pip install "bedrock-kit[boto]"
56
+ # optional
57
+ pip install "bedrock-kit[boto,pandas]" # adds CostLedger.to_pandas()
58
+ ```
59
+
60
+ ## Quickstart
61
+
62
+ ```python
63
+ from bedrock_kit import BedrockClient, AdaptiveThrottle, CostLedger
64
+
65
+ ledger = CostLedger()
66
+ client = BedrockClient(
67
+ region="us-east-1",
68
+ retry=AdaptiveThrottle(max_attempts=8, base_delay=1.0, max_delay=30.0),
69
+ cost_ledger=ledger,
70
+ )
71
+
72
+ resp = client.invoke(
73
+ model_id="anthropic.claude-sonnet-4-5",
74
+ messages=[{"role": "user", "content": "Hello"}],
75
+ system="You are concise.",
76
+ max_tokens=512,
77
+ )
78
+
79
+ resp.text # the model's reply
80
+ resp.usage.input_tokens # 12
81
+ resp.usage.cache_read_tokens # 0
82
+ resp.cost_usd # 0.000176
83
+ resp.cache_hit # False
84
+ ledger.total_usd # accumulates across all calls
85
+ ledger.by_model # {"anthropic.claude-sonnet-4-5": 0.000176}
86
+ ```
87
+
88
+ ## Structured output with repair
89
+
90
+ ```python
91
+ from pydantic import BaseModel
92
+ from bedrock_kit import JsonSchema
93
+
94
+ class Sentiment(BaseModel):
95
+ label: str
96
+ confidence: float
97
+
98
+ resp = client.invoke(
99
+ model_id="anthropic.claude-sonnet-4-5",
100
+ messages=[{"role": "user", "content": "Classify: 'this is great!'"}],
101
+ response_schema=JsonSchema(Sentiment, max_repair_attempts=2),
102
+ )
103
+ resp.parsed # Sentiment(label="positive", confidence=0.95)
104
+ ```
105
+
106
+ If the model returns invalid JSON, `bedrock-kit` first does a light local
107
+ repair pass (strip markdown fences, trailing commas, surrounding prose).
108
+ If that still fails, it asks the model to fix its own output, up to
109
+ `max_repair_attempts` times.
110
+
111
+ ## Adaptive throttle
112
+
113
+ ```python
114
+ throttle = AdaptiveThrottle(
115
+ max_attempts=8, # total attempts (incl. first)
116
+ base_delay=1.0, # seconds
117
+ max_delay=30.0,
118
+ jitter=True, # full-jitter (uniform(0, capped_delay))
119
+ )
120
+ ```
121
+
122
+ Retries on Bedrock throttle codes: `ThrottlingException`,
123
+ `TooManyRequestsException`, `ServiceUnavailableException`,
124
+ `ProvisionedThroughputExceededException`, `ModelTimeoutException`. Does
125
+ **not** retry validation, auth, or model-not-found errors - those are
126
+ your bugs to fix, not transient.
127
+
128
+ ## Cost tracking
129
+
130
+ `CostLedger` ships pricing for popular Anthropic Bedrock models. Override
131
+ or extend with `pricing=`:
132
+
133
+ ```python
134
+ from bedrock_kit import CostLedger, Pricing
135
+
136
+ ledger = CostLedger(
137
+ pricing={
138
+ "amazon.nova-pro-v1:0": Pricing(
139
+ input=0.8, output=3.2, cache_read=0.2, cache_write=1.0
140
+ ),
141
+ },
142
+ strict=True, # raise PricingNotFoundError on unknown models
143
+ )
144
+ ```
145
+
146
+ Default pricing is best-effort and dated; verify against
147
+ [aws.amazon.com/bedrock/pricing](https://aws.amazon.com/bedrock/pricing)
148
+ before using these numbers for billing.
149
+
150
+ ## Why not LiteLLM?
151
+
152
+ LiteLLM is great if you need cross-provider routing. `bedrock-kit` is for
153
+ the case where you've already decided on Bedrock, you don't want a 46k-LOC
154
+ multi-provider abstraction, and you want a small surface a security team
155
+ can audit. We don't proxy, don't include a server, don't ship a UI. We're
156
+ < 1000 LOC of Python.
157
+
158
+ ## What it explicitly does NOT do
159
+
160
+ - No multi-provider routing
161
+ - No proxy server, no UI
162
+ - No prompt management
163
+ - No agent loop
164
+ - No image generation
165
+ - No SageMaker, Bedrock Agents, or Knowledge Bases SDK wrapping
166
+ - No streaming or cancellation yet (planned for v0.2)
167
+ - No OpenTelemetry emission yet (planned for v0.2)
168
+
169
+ ## Testing without AWS
170
+
171
+ The default `BedrockClient` makes a real boto3 client. For tests, inject a
172
+ fake that quacks like one:
173
+
174
+ ```python
175
+ from bedrock_kit import BedrockClient, AdaptiveThrottle
176
+
177
+ class FakeClient:
178
+ def converse(self, **kwargs):
179
+ return {"output": {"message": {"content": [{"text": "stub"}]}},
180
+ "stopReason": "end_turn",
181
+ "usage": {"inputTokens": 1, "outputTokens": 1}}
182
+
183
+ client = BedrockClient(client=FakeClient(), retry=AdaptiveThrottle(sleep_fn=lambda _: None))
184
+ ```
185
+
186
+ ## Status
187
+
188
+ v0.1 - alpha. Public API may change before v1.0. Issues and PRs welcome.
@@ -0,0 +1,152 @@
1
+ # bedrock-kit
2
+
3
+ [![CI](https://github.com/MukundaKatta/bedrock-kit/actions/workflows/ci.yml/badge.svg)](https://github.com/MukundaKatta/bedrock-kit/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/bedrock-kit.svg)](https://pypi.org/project/bedrock-kit/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/bedrock-kit.svg)](https://pypi.org/project/bedrock-kit/)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
7
+
8
+ **Small, opinionated AWS Bedrock client wrapper.**
9
+
10
+ Every Bedrock production team rebuilds the same three things: adaptive
11
+ throttle for `ThrottlingException`, per-call cost tracking that handles
12
+ cache-read tokens, and structured-output parsing-with-repair. `bedrock-kit`
13
+ ships those, and nothing else. Single-cloud, single-purpose. No proxy
14
+ server. Wraps the official boto3 client; you can inject a fake for testing.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ pip install "bedrock-kit[boto]"
20
+ # optional
21
+ pip install "bedrock-kit[boto,pandas]" # adds CostLedger.to_pandas()
22
+ ```
23
+
24
+ ## Quickstart
25
+
26
+ ```python
27
+ from bedrock_kit import BedrockClient, AdaptiveThrottle, CostLedger
28
+
29
+ ledger = CostLedger()
30
+ client = BedrockClient(
31
+ region="us-east-1",
32
+ retry=AdaptiveThrottle(max_attempts=8, base_delay=1.0, max_delay=30.0),
33
+ cost_ledger=ledger,
34
+ )
35
+
36
+ resp = client.invoke(
37
+ model_id="anthropic.claude-sonnet-4-5",
38
+ messages=[{"role": "user", "content": "Hello"}],
39
+ system="You are concise.",
40
+ max_tokens=512,
41
+ )
42
+
43
+ resp.text # the model's reply
44
+ resp.usage.input_tokens # 12
45
+ resp.usage.cache_read_tokens # 0
46
+ resp.cost_usd # 0.000176
47
+ resp.cache_hit # False
48
+ ledger.total_usd # accumulates across all calls
49
+ ledger.by_model # {"anthropic.claude-sonnet-4-5": 0.000176}
50
+ ```
51
+
52
+ ## Structured output with repair
53
+
54
+ ```python
55
+ from pydantic import BaseModel
56
+ from bedrock_kit import JsonSchema
57
+
58
+ class Sentiment(BaseModel):
59
+ label: str
60
+ confidence: float
61
+
62
+ resp = client.invoke(
63
+ model_id="anthropic.claude-sonnet-4-5",
64
+ messages=[{"role": "user", "content": "Classify: 'this is great!'"}],
65
+ response_schema=JsonSchema(Sentiment, max_repair_attempts=2),
66
+ )
67
+ resp.parsed # Sentiment(label="positive", confidence=0.95)
68
+ ```
69
+
70
+ If the model returns invalid JSON, `bedrock-kit` first does a light local
71
+ repair pass (strip markdown fences, trailing commas, surrounding prose).
72
+ If that still fails, it asks the model to fix its own output, up to
73
+ `max_repair_attempts` times.
74
+
75
+ ## Adaptive throttle
76
+
77
+ ```python
78
+ throttle = AdaptiveThrottle(
79
+ max_attempts=8, # total attempts (incl. first)
80
+ base_delay=1.0, # seconds
81
+ max_delay=30.0,
82
+ jitter=True, # full-jitter (uniform(0, capped_delay))
83
+ )
84
+ ```
85
+
86
+ Retries on Bedrock throttle codes: `ThrottlingException`,
87
+ `TooManyRequestsException`, `ServiceUnavailableException`,
88
+ `ProvisionedThroughputExceededException`, `ModelTimeoutException`. Does
89
+ **not** retry validation, auth, or model-not-found errors - those are
90
+ your bugs to fix, not transient.
91
+
92
+ ## Cost tracking
93
+
94
+ `CostLedger` ships pricing for popular Anthropic Bedrock models. Override
95
+ or extend with `pricing=`:
96
+
97
+ ```python
98
+ from bedrock_kit import CostLedger, Pricing
99
+
100
+ ledger = CostLedger(
101
+ pricing={
102
+ "amazon.nova-pro-v1:0": Pricing(
103
+ input=0.8, output=3.2, cache_read=0.2, cache_write=1.0
104
+ ),
105
+ },
106
+ strict=True, # raise PricingNotFoundError on unknown models
107
+ )
108
+ ```
109
+
110
+ Default pricing is best-effort and dated; verify against
111
+ [aws.amazon.com/bedrock/pricing](https://aws.amazon.com/bedrock/pricing)
112
+ before using these numbers for billing.
113
+
114
+ ## Why not LiteLLM?
115
+
116
+ LiteLLM is great if you need cross-provider routing. `bedrock-kit` is for
117
+ the case where you've already decided on Bedrock, you don't want a 46k-LOC
118
+ multi-provider abstraction, and you want a small surface a security team
119
+ can audit. We don't proxy, don't include a server, don't ship a UI. We're
120
+ < 1000 LOC of Python.
121
+
122
+ ## What it explicitly does NOT do
123
+
124
+ - No multi-provider routing
125
+ - No proxy server, no UI
126
+ - No prompt management
127
+ - No agent loop
128
+ - No image generation
129
+ - No SageMaker, Bedrock Agents, or Knowledge Bases SDK wrapping
130
+ - No streaming or cancellation yet (planned for v0.2)
131
+ - No OpenTelemetry emission yet (planned for v0.2)
132
+
133
+ ## Testing without AWS
134
+
135
+ The default `BedrockClient` makes a real boto3 client. For tests, inject a
136
+ fake that quacks like one:
137
+
138
+ ```python
139
+ from bedrock_kit import BedrockClient, AdaptiveThrottle
140
+
141
+ class FakeClient:
142
+ def converse(self, **kwargs):
143
+ return {"output": {"message": {"content": [{"text": "stub"}]}},
144
+ "stopReason": "end_turn",
145
+ "usage": {"inputTokens": 1, "outputTokens": 1}}
146
+
147
+ client = BedrockClient(client=FakeClient(), retry=AdaptiveThrottle(sleep_fn=lambda _: None))
148
+ ```
149
+
150
+ ## Status
151
+
152
+ v0.1 - alpha. Public API may change before v1.0. Issues and PRs welcome.
@@ -0,0 +1,69 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.24"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "bedrock-kit"
7
+ version = "0.1.0"
8
+ description = "Small, opinionated AWS Bedrock client wrapper: adaptive throttle, cache-aware cost tracking, and structured-output parse-and-repair. Single-cloud, single-purpose."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "Mukunda Rao Katta", email = "mukunda.vjcs6@gmail.com" }]
13
+ keywords = [
14
+ "aws",
15
+ "bedrock",
16
+ "llm",
17
+ "anthropic",
18
+ "claude",
19
+ "cost-tracking",
20
+ "retry",
21
+ "structured-output",
22
+ "rag",
23
+ "mlops",
24
+ ]
25
+ classifiers = [
26
+ "Development Status :: 3 - Alpha",
27
+ "Intended Audience :: Developers",
28
+ "License :: OSI Approved :: MIT License",
29
+ "Operating System :: OS Independent",
30
+ "Programming Language :: Python :: 3",
31
+ "Programming Language :: Python :: 3 :: Only",
32
+ "Programming Language :: Python :: 3.10",
33
+ "Programming Language :: Python :: 3.11",
34
+ "Programming Language :: Python :: 3.12",
35
+ "Programming Language :: Python :: 3.13",
36
+ "Programming Language :: Python :: 3.14",
37
+ "Topic :: Software Development :: Libraries :: Python Modules",
38
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
39
+ ]
40
+ dependencies = [
41
+ "pydantic>=2.0",
42
+ ]
43
+
44
+ [project.optional-dependencies]
45
+ boto = ["boto3>=1.28"]
46
+ pandas = ["pandas>=2.0"]
47
+ dev = ["pytest>=8.0", "pandas>=2.0", "ruff>=0.4"]
48
+
49
+ [project.urls]
50
+ Homepage = "https://github.com/MukundaKatta/bedrock-kit"
51
+ Issues = "https://github.com/MukundaKatta/bedrock-kit/issues"
52
+ Source = "https://github.com/MukundaKatta/bedrock-kit"
53
+
54
+ [tool.hatch.build.targets.wheel]
55
+ packages = ["src/bedrock_kit"]
56
+
57
+ [tool.hatch.build.targets.sdist]
58
+ include = ["/src", "/tests", "/README.md", "/LICENSE"]
59
+
60
+ [tool.pytest.ini_options]
61
+ testpaths = ["tests"]
62
+ pythonpath = ["src", "."]
63
+
64
+ [tool.ruff]
65
+ target-version = "py310"
66
+ line-length = 100
67
+
68
+ [tool.ruff.lint]
69
+ select = ["E", "F", "I", "UP", "B", "SIM"]
@@ -0,0 +1,35 @@
1
+ """bedrock-kit - small, opinionated AWS Bedrock client wrapper.
2
+
3
+ Adds the things every Bedrock production team rebuilds: adaptive throttle,
4
+ per-call cost tracking with cache-aware accounting, and structured-output
5
+ parse-and-repair. Single-cloud, single-purpose, < 3000 LOC.
6
+ """
7
+
8
+ from bedrock_kit.client import BedrockClient, BedrockResponse, Usage
9
+ from bedrock_kit.cost import CostEntry, CostLedger, Pricing
10
+ from bedrock_kit.exceptions import (
11
+ BedrockKitError,
12
+ JsonParseError,
13
+ PricingNotFoundError,
14
+ ThrottleExhausted,
15
+ )
16
+ from bedrock_kit.retry import AdaptiveThrottle
17
+ from bedrock_kit.schema import JsonSchema
18
+
19
+ __version__ = "0.1.0"
20
+
21
+ __all__ = [
22
+ "AdaptiveThrottle",
23
+ "BedrockClient",
24
+ "BedrockKitError",
25
+ "BedrockResponse",
26
+ "CostEntry",
27
+ "CostLedger",
28
+ "JsonParseError",
29
+ "JsonSchema",
30
+ "Pricing",
31
+ "PricingNotFoundError",
32
+ "ThrottleExhausted",
33
+ "Usage",
34
+ "__version__",
35
+ ]