aws-bedrock-invoke 1.0.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.
- aws_bedrock_invoke-1.0.0/.env.example +12 -0
- aws_bedrock_invoke-1.0.0/.github/workflows/publish.yml +30 -0
- aws_bedrock_invoke-1.0.0/.gitignore +4 -0
- aws_bedrock_invoke-1.0.0/CHANGELOG.md +11 -0
- aws_bedrock_invoke-1.0.0/PKG-INFO +223 -0
- aws_bedrock_invoke-1.0.0/README.md +210 -0
- aws_bedrock_invoke-1.0.0/docker-compose.yml +11 -0
- aws_bedrock_invoke-1.0.0/examples/invoke_json_example.py +26 -0
- aws_bedrock_invoke-1.0.0/examples/invoke_text_example.py +22 -0
- aws_bedrock_invoke-1.0.0/pyproject.toml +27 -0
- aws_bedrock_invoke-1.0.0/src/aws_bedrock_invoke/__init__.py +17 -0
- aws_bedrock_invoke-1.0.0/src/aws_bedrock_invoke/config.py +43 -0
- aws_bedrock_invoke-1.0.0/src/aws_bedrock_invoke/content.py +47 -0
- aws_bedrock_invoke-1.0.0/src/aws_bedrock_invoke/exceptions.py +9 -0
- aws_bedrock_invoke-1.0.0/src/aws_bedrock_invoke/invoker.py +218 -0
- aws_bedrock_invoke-1.0.0/src/aws_bedrock_invoke/parsing.py +43 -0
- aws_bedrock_invoke-1.0.0/src/aws_bedrock_invoke/retry.py +75 -0
- aws_bedrock_invoke-1.0.0/src/aws_bedrock_invoke/utils.py +15 -0
- aws_bedrock_invoke-1.0.0/tests/test_content.py +49 -0
- aws_bedrock_invoke-1.0.0/tests/test_invoker.py +196 -0
- aws_bedrock_invoke-1.0.0/tests/test_parsing.py +29 -0
- aws_bedrock_invoke-1.0.0/tests/test_retry.py +52 -0
- aws_bedrock_invoke-1.0.0/tests/test_utils.py +27 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
AWS_REGION=us-east-1
|
|
2
|
+
AWS_ACCESS_KEY_ID=
|
|
3
|
+
AWS_SECRET_ACCESS_KEY=
|
|
4
|
+
|
|
5
|
+
BEDROCK_RETRY_MAX_ATTEMPTS=4
|
|
6
|
+
BEDROCK_RETRY_BASE_SECONDS=5
|
|
7
|
+
BEDROCK_RETRY_MAX_SECONDS=45
|
|
8
|
+
BEDROCK_RETRY_JITTER=true
|
|
9
|
+
BEDROCK_RETRYABLE_ERROR_CODES=
|
|
10
|
+
|
|
11
|
+
BEDROCK_PROMPT_CACHE_ENABLED=false
|
|
12
|
+
BEDROCK_PROMPT_CACHE_TTL=5m
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Publish Python package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build-and-publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: Set up Python
|
|
16
|
+
uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.12"
|
|
19
|
+
|
|
20
|
+
- name: Install build tools
|
|
21
|
+
run: pip install build
|
|
22
|
+
|
|
23
|
+
- name: Build package
|
|
24
|
+
run: python -m build
|
|
25
|
+
|
|
26
|
+
- name: Publish to PyPI
|
|
27
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
28
|
+
with:
|
|
29
|
+
username: __token__
|
|
30
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.0.0
|
|
4
|
+
|
|
5
|
+
- Added a focused Claude 4.x AWS Bedrock invocation library
|
|
6
|
+
- Added manual progressive retry with env-driven configuration
|
|
7
|
+
- Added additive default retryable Bedrock error-code handling
|
|
8
|
+
- Added optional Bedrock prompt-cache helpers
|
|
9
|
+
- Added JSON and text invocation helpers
|
|
10
|
+
- Added optional public client injection for adapters and tests
|
|
11
|
+
- Added unit tests and real Bedrock smoke coverage
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aws-bedrock-invoke
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Small Python library for invoking Claude 4.x models on AWS Bedrock with manual retries, prompt caching helpers, and JSON parsing.
|
|
5
|
+
Project-URL: Homepage, https://github.com/not-empty/aws-bedrock-invoke-python
|
|
6
|
+
Project-URL: Issues, https://github.com/not-empty/aws-bedrock-invoke-python/issues
|
|
7
|
+
Author-email: Not Empty Foundation <dev@not-empty.org>
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Requires-Dist: boto3>=1.34.0
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# AWS Bedrock Invoke Python
|
|
15
|
+
|
|
16
|
+
AWS Bedrock Invoke Python is a small library for invoking Claude 4.x models on
|
|
17
|
+
AWS Bedrock with one consistent request path.
|
|
18
|
+
|
|
19
|
+
It focuses only on the transport layer:
|
|
20
|
+
|
|
21
|
+
- boto3 client creation
|
|
22
|
+
- optional client injection
|
|
23
|
+
- Bedrock model ID / inference-profile resolution
|
|
24
|
+
- Bedrock prompt-cache helpers
|
|
25
|
+
- manual retry with env-driven configuration
|
|
26
|
+
- response text extraction
|
|
27
|
+
- fenced JSON cleanup and parsing
|
|
28
|
+
|
|
29
|
+
It intentionally does not own business rules such as batching strategies,
|
|
30
|
+
workflow orchestration, application result caching, or prompt authoring.
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install aws-bedrock-invoke
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Scope
|
|
39
|
+
|
|
40
|
+
This library is intentionally narrow:
|
|
41
|
+
|
|
42
|
+
- Claude 4.x on AWS Bedrock only
|
|
43
|
+
- manual retry managed by the library
|
|
44
|
+
- Bedrock prompt-cache support
|
|
45
|
+
- text and JSON invoke helpers
|
|
46
|
+
|
|
47
|
+
This library intentionally does not include:
|
|
48
|
+
|
|
49
|
+
- business-specific batching/windowing
|
|
50
|
+
- application result caching
|
|
51
|
+
- Slack notifications or persistence
|
|
52
|
+
- prompt engineering or workflow orchestration
|
|
53
|
+
|
|
54
|
+
## Quick Start
|
|
55
|
+
|
|
56
|
+
### `invoke_json()`
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from aws_bedrock_invoke import BedrockInvoker, json_text_block
|
|
60
|
+
|
|
61
|
+
invoker = BedrockInvoker.from_env()
|
|
62
|
+
|
|
63
|
+
result = invoker.invoke_json(
|
|
64
|
+
model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
|
65
|
+
profile_arn_fmt="arn:aws:bedrock:{region}:354173731728:inference-profile/{model}",
|
|
66
|
+
system_prompt="Reply with strict JSON.",
|
|
67
|
+
user_content=[
|
|
68
|
+
json_text_block({"question": "hello"}),
|
|
69
|
+
],
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
print(result.parsed_json)
|
|
73
|
+
print(result.response_text)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### `invoke_text()`
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from aws_bedrock_invoke import BedrockInvoker, text_block
|
|
80
|
+
|
|
81
|
+
invoker = BedrockInvoker.from_env()
|
|
82
|
+
|
|
83
|
+
result = invoker.invoke_text(
|
|
84
|
+
model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
|
85
|
+
profile_arn_fmt="arn:aws:bedrock:{region}:354173731728:inference-profile/{model}",
|
|
86
|
+
system_prompt="Answer briefly.",
|
|
87
|
+
user_content=[
|
|
88
|
+
text_block("What is a lien waiver?"),
|
|
89
|
+
],
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
print(result.response_text)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Client Injection
|
|
96
|
+
|
|
97
|
+
Client injection is optional.
|
|
98
|
+
|
|
99
|
+
If you do not provide a client, `BedrockInvoker` builds one from
|
|
100
|
+
`BedrockClientConfig`.
|
|
101
|
+
|
|
102
|
+
If you already have a prepared boto Bedrock client, you can inject it directly.
|
|
103
|
+
This is especially useful for adapters and tests.
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
import boto3
|
|
107
|
+
|
|
108
|
+
from aws_bedrock_invoke import BedrockClientConfig, BedrockInvoker, text_block
|
|
109
|
+
|
|
110
|
+
client = boto3.client(
|
|
111
|
+
"bedrock-runtime",
|
|
112
|
+
region_name="us-east-1",
|
|
113
|
+
aws_access_key_id="...",
|
|
114
|
+
aws_secret_access_key="...",
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
invoker = BedrockInvoker(
|
|
118
|
+
client_config=BedrockClientConfig(
|
|
119
|
+
region="us-east-1",
|
|
120
|
+
aws_access_key_id="...",
|
|
121
|
+
aws_secret_access_key="...",
|
|
122
|
+
),
|
|
123
|
+
client=client,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
result = invoker.invoke_text(
|
|
127
|
+
model="arn:aws:bedrock:us-east-1:123456789012:inference-profile/example",
|
|
128
|
+
system_prompt="Answer briefly.",
|
|
129
|
+
user_content=[text_block("hello")],
|
|
130
|
+
)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Environment Variables
|
|
134
|
+
|
|
135
|
+
### AWS / Bedrock
|
|
136
|
+
|
|
137
|
+
- `AWS_REGION`
|
|
138
|
+
- `AWS_ACCESS_KEY_ID`
|
|
139
|
+
- `AWS_SECRET_ACCESS_KEY`
|
|
140
|
+
|
|
141
|
+
### Retry
|
|
142
|
+
|
|
143
|
+
- `BEDROCK_RETRY_MAX_ATTEMPTS`
|
|
144
|
+
- `BEDROCK_RETRY_BASE_SECONDS`
|
|
145
|
+
- `BEDROCK_RETRY_MAX_SECONDS`
|
|
146
|
+
- `BEDROCK_RETRY_JITTER`
|
|
147
|
+
- `BEDROCK_RETRYABLE_ERROR_CODES`
|
|
148
|
+
|
|
149
|
+
The Bedrock SDK retry behavior is effectively disabled in the client, and the
|
|
150
|
+
library uses its own manual progressive retry loop instead.
|
|
151
|
+
|
|
152
|
+
Default retryable error codes:
|
|
153
|
+
|
|
154
|
+
- `ServiceUnavailableException`
|
|
155
|
+
- `InternalServerException`
|
|
156
|
+
|
|
157
|
+
`BEDROCK_RETRYABLE_ERROR_CODES` is additive. If you set it, the provided codes
|
|
158
|
+
are added on top of those defaults rather than replacing them.
|
|
159
|
+
|
|
160
|
+
Default retry behavior:
|
|
161
|
+
|
|
162
|
+
- `BEDROCK_RETRY_MAX_ATTEMPTS=4`
|
|
163
|
+
- `BEDROCK_RETRY_BASE_SECONDS=5`
|
|
164
|
+
- `BEDROCK_RETRY_MAX_SECONDS=45`
|
|
165
|
+
- `BEDROCK_RETRY_JITTER=true`
|
|
166
|
+
|
|
167
|
+
`on_retry` receives a typed `RetryEvent` with:
|
|
168
|
+
|
|
169
|
+
- `attempt`
|
|
170
|
+
- `max_attempts`
|
|
171
|
+
- `error_code`
|
|
172
|
+
- `error`
|
|
173
|
+
- `sleep_seconds`
|
|
174
|
+
- `model_id`
|
|
175
|
+
- `elapsed_seconds`
|
|
176
|
+
|
|
177
|
+
### Prompt Cache
|
|
178
|
+
|
|
179
|
+
- `BEDROCK_PROMPT_CACHE_ENABLED`
|
|
180
|
+
- `BEDROCK_PROMPT_CACHE_TTL`
|
|
181
|
+
|
|
182
|
+
## Public API
|
|
183
|
+
|
|
184
|
+
- `BedrockInvoker`
|
|
185
|
+
- `BedrockClientConfig`
|
|
186
|
+
- `RetryPolicy`
|
|
187
|
+
- `BedrockPromptCacheConfig`
|
|
188
|
+
- `InvokeResult`
|
|
189
|
+
- `RetryEvent`
|
|
190
|
+
- `json_text_block`
|
|
191
|
+
- `text_block`
|
|
192
|
+
- `resolve_model_id`
|
|
193
|
+
|
|
194
|
+
## Model Resolution
|
|
195
|
+
|
|
196
|
+
If `model` is a full ARN, the library uses it directly.
|
|
197
|
+
|
|
198
|
+
If `model` is a shorthand like `us.anthropic...`, you must provide
|
|
199
|
+
`profile_arn_fmt` on the invoke call.
|
|
200
|
+
|
|
201
|
+
## Testing
|
|
202
|
+
|
|
203
|
+
Run the test suite locally with:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
PYTHONPATH=src python3 -m unittest discover -s tests -v
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Examples
|
|
210
|
+
|
|
211
|
+
Runnable examples live in [examples](/home/disarli/Projects/aws-bedrock-invoke-python/examples):
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
PYTHONPATH=src python3 examples/invoke_json_example.py
|
|
215
|
+
PYTHONPATH=src python3 examples/invoke_text_example.py
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Consumer Integration
|
|
219
|
+
|
|
220
|
+
This repo includes library-level tests and Bedrock smoke examples.
|
|
221
|
+
|
|
222
|
+
Consumer repositories should still add their own integration smoke that uses
|
|
223
|
+
their real prompt builders and payload-shaping logic through this library.
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# AWS Bedrock Invoke Python
|
|
2
|
+
|
|
3
|
+
AWS Bedrock Invoke Python is a small library for invoking Claude 4.x models on
|
|
4
|
+
AWS Bedrock with one consistent request path.
|
|
5
|
+
|
|
6
|
+
It focuses only on the transport layer:
|
|
7
|
+
|
|
8
|
+
- boto3 client creation
|
|
9
|
+
- optional client injection
|
|
10
|
+
- Bedrock model ID / inference-profile resolution
|
|
11
|
+
- Bedrock prompt-cache helpers
|
|
12
|
+
- manual retry with env-driven configuration
|
|
13
|
+
- response text extraction
|
|
14
|
+
- fenced JSON cleanup and parsing
|
|
15
|
+
|
|
16
|
+
It intentionally does not own business rules such as batching strategies,
|
|
17
|
+
workflow orchestration, application result caching, or prompt authoring.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install aws-bedrock-invoke
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Scope
|
|
26
|
+
|
|
27
|
+
This library is intentionally narrow:
|
|
28
|
+
|
|
29
|
+
- Claude 4.x on AWS Bedrock only
|
|
30
|
+
- manual retry managed by the library
|
|
31
|
+
- Bedrock prompt-cache support
|
|
32
|
+
- text and JSON invoke helpers
|
|
33
|
+
|
|
34
|
+
This library intentionally does not include:
|
|
35
|
+
|
|
36
|
+
- business-specific batching/windowing
|
|
37
|
+
- application result caching
|
|
38
|
+
- Slack notifications or persistence
|
|
39
|
+
- prompt engineering or workflow orchestration
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
### `invoke_json()`
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from aws_bedrock_invoke import BedrockInvoker, json_text_block
|
|
47
|
+
|
|
48
|
+
invoker = BedrockInvoker.from_env()
|
|
49
|
+
|
|
50
|
+
result = invoker.invoke_json(
|
|
51
|
+
model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
|
52
|
+
profile_arn_fmt="arn:aws:bedrock:{region}:354173731728:inference-profile/{model}",
|
|
53
|
+
system_prompt="Reply with strict JSON.",
|
|
54
|
+
user_content=[
|
|
55
|
+
json_text_block({"question": "hello"}),
|
|
56
|
+
],
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
print(result.parsed_json)
|
|
60
|
+
print(result.response_text)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### `invoke_text()`
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from aws_bedrock_invoke import BedrockInvoker, text_block
|
|
67
|
+
|
|
68
|
+
invoker = BedrockInvoker.from_env()
|
|
69
|
+
|
|
70
|
+
result = invoker.invoke_text(
|
|
71
|
+
model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
|
72
|
+
profile_arn_fmt="arn:aws:bedrock:{region}:354173731728:inference-profile/{model}",
|
|
73
|
+
system_prompt="Answer briefly.",
|
|
74
|
+
user_content=[
|
|
75
|
+
text_block("What is a lien waiver?"),
|
|
76
|
+
],
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
print(result.response_text)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Client Injection
|
|
83
|
+
|
|
84
|
+
Client injection is optional.
|
|
85
|
+
|
|
86
|
+
If you do not provide a client, `BedrockInvoker` builds one from
|
|
87
|
+
`BedrockClientConfig`.
|
|
88
|
+
|
|
89
|
+
If you already have a prepared boto Bedrock client, you can inject it directly.
|
|
90
|
+
This is especially useful for adapters and tests.
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
import boto3
|
|
94
|
+
|
|
95
|
+
from aws_bedrock_invoke import BedrockClientConfig, BedrockInvoker, text_block
|
|
96
|
+
|
|
97
|
+
client = boto3.client(
|
|
98
|
+
"bedrock-runtime",
|
|
99
|
+
region_name="us-east-1",
|
|
100
|
+
aws_access_key_id="...",
|
|
101
|
+
aws_secret_access_key="...",
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
invoker = BedrockInvoker(
|
|
105
|
+
client_config=BedrockClientConfig(
|
|
106
|
+
region="us-east-1",
|
|
107
|
+
aws_access_key_id="...",
|
|
108
|
+
aws_secret_access_key="...",
|
|
109
|
+
),
|
|
110
|
+
client=client,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
result = invoker.invoke_text(
|
|
114
|
+
model="arn:aws:bedrock:us-east-1:123456789012:inference-profile/example",
|
|
115
|
+
system_prompt="Answer briefly.",
|
|
116
|
+
user_content=[text_block("hello")],
|
|
117
|
+
)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Environment Variables
|
|
121
|
+
|
|
122
|
+
### AWS / Bedrock
|
|
123
|
+
|
|
124
|
+
- `AWS_REGION`
|
|
125
|
+
- `AWS_ACCESS_KEY_ID`
|
|
126
|
+
- `AWS_SECRET_ACCESS_KEY`
|
|
127
|
+
|
|
128
|
+
### Retry
|
|
129
|
+
|
|
130
|
+
- `BEDROCK_RETRY_MAX_ATTEMPTS`
|
|
131
|
+
- `BEDROCK_RETRY_BASE_SECONDS`
|
|
132
|
+
- `BEDROCK_RETRY_MAX_SECONDS`
|
|
133
|
+
- `BEDROCK_RETRY_JITTER`
|
|
134
|
+
- `BEDROCK_RETRYABLE_ERROR_CODES`
|
|
135
|
+
|
|
136
|
+
The Bedrock SDK retry behavior is effectively disabled in the client, and the
|
|
137
|
+
library uses its own manual progressive retry loop instead.
|
|
138
|
+
|
|
139
|
+
Default retryable error codes:
|
|
140
|
+
|
|
141
|
+
- `ServiceUnavailableException`
|
|
142
|
+
- `InternalServerException`
|
|
143
|
+
|
|
144
|
+
`BEDROCK_RETRYABLE_ERROR_CODES` is additive. If you set it, the provided codes
|
|
145
|
+
are added on top of those defaults rather than replacing them.
|
|
146
|
+
|
|
147
|
+
Default retry behavior:
|
|
148
|
+
|
|
149
|
+
- `BEDROCK_RETRY_MAX_ATTEMPTS=4`
|
|
150
|
+
- `BEDROCK_RETRY_BASE_SECONDS=5`
|
|
151
|
+
- `BEDROCK_RETRY_MAX_SECONDS=45`
|
|
152
|
+
- `BEDROCK_RETRY_JITTER=true`
|
|
153
|
+
|
|
154
|
+
`on_retry` receives a typed `RetryEvent` with:
|
|
155
|
+
|
|
156
|
+
- `attempt`
|
|
157
|
+
- `max_attempts`
|
|
158
|
+
- `error_code`
|
|
159
|
+
- `error`
|
|
160
|
+
- `sleep_seconds`
|
|
161
|
+
- `model_id`
|
|
162
|
+
- `elapsed_seconds`
|
|
163
|
+
|
|
164
|
+
### Prompt Cache
|
|
165
|
+
|
|
166
|
+
- `BEDROCK_PROMPT_CACHE_ENABLED`
|
|
167
|
+
- `BEDROCK_PROMPT_CACHE_TTL`
|
|
168
|
+
|
|
169
|
+
## Public API
|
|
170
|
+
|
|
171
|
+
- `BedrockInvoker`
|
|
172
|
+
- `BedrockClientConfig`
|
|
173
|
+
- `RetryPolicy`
|
|
174
|
+
- `BedrockPromptCacheConfig`
|
|
175
|
+
- `InvokeResult`
|
|
176
|
+
- `RetryEvent`
|
|
177
|
+
- `json_text_block`
|
|
178
|
+
- `text_block`
|
|
179
|
+
- `resolve_model_id`
|
|
180
|
+
|
|
181
|
+
## Model Resolution
|
|
182
|
+
|
|
183
|
+
If `model` is a full ARN, the library uses it directly.
|
|
184
|
+
|
|
185
|
+
If `model` is a shorthand like `us.anthropic...`, you must provide
|
|
186
|
+
`profile_arn_fmt` on the invoke call.
|
|
187
|
+
|
|
188
|
+
## Testing
|
|
189
|
+
|
|
190
|
+
Run the test suite locally with:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
PYTHONPATH=src python3 -m unittest discover -s tests -v
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Examples
|
|
197
|
+
|
|
198
|
+
Runnable examples live in [examples](/home/disarli/Projects/aws-bedrock-invoke-python/examples):
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
PYTHONPATH=src python3 examples/invoke_json_example.py
|
|
202
|
+
PYTHONPATH=src python3 examples/invoke_text_example.py
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Consumer Integration
|
|
206
|
+
|
|
207
|
+
This repo includes library-level tests and Bedrock smoke examples.
|
|
208
|
+
|
|
209
|
+
Consumer repositories should still add their own integration smoke that uses
|
|
210
|
+
their real prompt builders and payload-shaping logic through this library.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from aws_bedrock_invoke import BedrockInvoker, json_text_block
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def main() -> None:
|
|
7
|
+
invoker = BedrockInvoker.from_env()
|
|
8
|
+
|
|
9
|
+
result = invoker.invoke_json(
|
|
10
|
+
model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
|
11
|
+
profile_arn_fmt="arn:aws:bedrock:{region}:354173731728:inference-profile/{model}",
|
|
12
|
+
system_prompt="Reply with strict JSON.",
|
|
13
|
+
user_content=[
|
|
14
|
+
json_text_block({"question": "hello"}),
|
|
15
|
+
],
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
print("parsed_json:")
|
|
19
|
+
print(result.parsed_json)
|
|
20
|
+
print()
|
|
21
|
+
print("response_text:")
|
|
22
|
+
print(result.response_text)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if __name__ == "__main__":
|
|
26
|
+
main()
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from aws_bedrock_invoke import BedrockInvoker
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def main() -> None:
|
|
7
|
+
invoker = BedrockInvoker.from_env()
|
|
8
|
+
|
|
9
|
+
result = invoker.invoke_text(
|
|
10
|
+
model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
|
11
|
+
profile_arn_fmt="arn:aws:bedrock:{region}:354173731728:inference-profile/{model}",
|
|
12
|
+
system_prompt="Answer briefly.",
|
|
13
|
+
user_content=[
|
|
14
|
+
{"type": "text", "text": "What is a lien waiver?"},
|
|
15
|
+
],
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
print(result.response_text)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
if __name__ == "__main__":
|
|
22
|
+
main()
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "aws-bedrock-invoke"
|
|
3
|
+
version = "1.0.0"
|
|
4
|
+
authors = [
|
|
5
|
+
{ name="Not Empty Foundation", email="dev@not-empty.org" },
|
|
6
|
+
]
|
|
7
|
+
description = "Small Python library for invoking Claude 4.x models on AWS Bedrock with manual retries, prompt caching helpers, and JSON parsing."
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Programming Language :: Python :: 3",
|
|
12
|
+
"Operating System :: OS Independent",
|
|
13
|
+
]
|
|
14
|
+
dependencies = [
|
|
15
|
+
"boto3>=1.34.0",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[project.urls]
|
|
19
|
+
Homepage = "https://github.com/not-empty/aws-bedrock-invoke-python"
|
|
20
|
+
Issues = "https://github.com/not-empty/aws-bedrock-invoke-python/issues"
|
|
21
|
+
|
|
22
|
+
[build-system]
|
|
23
|
+
requires = ["hatchling"]
|
|
24
|
+
build-backend = "hatchling.build"
|
|
25
|
+
|
|
26
|
+
[tool.hatch.build.targets.wheel]
|
|
27
|
+
packages = ["src/aws_bedrock_invoke"]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from .config import BedrockClientConfig, BedrockPromptCacheConfig
|
|
2
|
+
from .content import json_text_block, text_block
|
|
3
|
+
from .invoker import BedrockInvoker, InvokeResult, RetryEvent
|
|
4
|
+
from .retry import RetryPolicy
|
|
5
|
+
from .utils import resolve_model_id
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"BedrockClientConfig",
|
|
9
|
+
"BedrockInvoker",
|
|
10
|
+
"BedrockPromptCacheConfig",
|
|
11
|
+
"InvokeResult",
|
|
12
|
+
"RetryEvent",
|
|
13
|
+
"RetryPolicy",
|
|
14
|
+
"json_text_block",
|
|
15
|
+
"text_block",
|
|
16
|
+
"resolve_model_id",
|
|
17
|
+
]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _env_truthy(name: str, default: bool = False) -> bool:
|
|
8
|
+
raw = str(os.getenv(name, "") or "").strip().lower()
|
|
9
|
+
if not raw:
|
|
10
|
+
return default
|
|
11
|
+
return raw in {"1", "true", "yes", "on"}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(slots=True)
|
|
15
|
+
class BedrockPromptCacheConfig:
|
|
16
|
+
enabled: bool = False
|
|
17
|
+
ttl: str | None = None
|
|
18
|
+
|
|
19
|
+
@classmethod
|
|
20
|
+
def from_env(cls) -> "BedrockPromptCacheConfig":
|
|
21
|
+
return cls(
|
|
22
|
+
enabled=_env_truthy("BEDROCK_PROMPT_CACHE_ENABLED", default=False),
|
|
23
|
+
ttl=str(os.getenv("BEDROCK_PROMPT_CACHE_TTL", "") or "").strip() or None,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(slots=True)
|
|
28
|
+
class BedrockClientConfig:
|
|
29
|
+
region: str
|
|
30
|
+
aws_access_key_id: str | None = None
|
|
31
|
+
aws_secret_access_key: str | None = None
|
|
32
|
+
connect_timeout: int = 10
|
|
33
|
+
read_timeout: int = 300
|
|
34
|
+
max_pool_connections: int | None = None
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def from_env(cls) -> "BedrockClientConfig":
|
|
38
|
+
region = str(os.getenv("AWS_REGION", "us-east-1") or "").strip()
|
|
39
|
+
return cls(
|
|
40
|
+
region=region,
|
|
41
|
+
aws_access_key_id=str(os.getenv("AWS_ACCESS_KEY_ID", "") or "").strip() or None,
|
|
42
|
+
aws_secret_access_key=str(os.getenv("AWS_SECRET_ACCESS_KEY", "") or "").strip() or None,
|
|
43
|
+
)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from .config import BedrockPromptCacheConfig
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def prompt_cache_to_cache_control(
|
|
10
|
+
config: BedrockPromptCacheConfig | None,
|
|
11
|
+
) -> dict[str, Any] | None:
|
|
12
|
+
if config is None or not config.enabled:
|
|
13
|
+
return None
|
|
14
|
+
cache_control: dict[str, Any] = {"type": "ephemeral"}
|
|
15
|
+
if config.ttl:
|
|
16
|
+
cache_control["ttl"] = config.ttl
|
|
17
|
+
return cache_control
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def json_text_block(
|
|
21
|
+
payload: dict[str, Any],
|
|
22
|
+
*,
|
|
23
|
+
bedrock_prompt_cache: BedrockPromptCacheConfig | None = None,
|
|
24
|
+
) -> dict[str, Any]:
|
|
25
|
+
block: dict[str, Any] = {
|
|
26
|
+
"type": "text",
|
|
27
|
+
"text": json.dumps(payload, ensure_ascii=False),
|
|
28
|
+
}
|
|
29
|
+
cache_control = prompt_cache_to_cache_control(bedrock_prompt_cache)
|
|
30
|
+
if cache_control is not None:
|
|
31
|
+
block["cache_control"] = cache_control
|
|
32
|
+
return block
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def text_block(
|
|
36
|
+
text: str,
|
|
37
|
+
*,
|
|
38
|
+
bedrock_prompt_cache: BedrockPromptCacheConfig | None = None,
|
|
39
|
+
) -> dict[str, Any]:
|
|
40
|
+
block: dict[str, Any] = {
|
|
41
|
+
"type": "text",
|
|
42
|
+
"text": text,
|
|
43
|
+
}
|
|
44
|
+
cache_control = prompt_cache_to_cache_control(bedrock_prompt_cache)
|
|
45
|
+
if cache_control is not None:
|
|
46
|
+
block["cache_control"] = cache_control
|
|
47
|
+
return block
|